极客时间《云原生训练营》学习笔记。

Kubernetes 基础架构-API设计原则

API设计原则

所有 API 都应是声明式的

  • 相对于命令式操作,声明式操作对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。
  • 声明式操作更易被用户使用,可以使系统向用户隐藏实现的细节,同时也保留了系统未来持续优化的可能性。
  • 此外,声明式的 API 还隐含了所有的 API 对象都是名词性质的,例如 Service、Volume 这些 API 都是名词,这些名词描述了用户所期望得到的一个目标对象。

例如 我四减二的这样一个操作,你可能发一个减二过去对吧?那你下一次还发一个减二,他怎么知道你是要减二,还是说你上一次的重试呢?它是分不清楚的?那么所谓的声明是的话,他的这个请求发出去的时候。不是减二的这个操作,而是说我的期望值是2那这样的话。那些处理的细节隐藏起来了,用户更容易使用

API 对象是彼此互补而且可组合的

  • 这实际上鼓励 API 对象尽量实现面向对象设计时的要求,即“高内聚,松耦合”,对业务相关的概念有一个合适的分解,提高分解出来的对象的可重用性。

其实是一个设计的取舍 一般来说,我们我觉得在设计里面最重要的一个原则就是高内聚松耦合, 例如: deployment的控制是什么呢?它控制的是一次滚动发布的或者是滚动升级的这样一个动作 replicaset 控制的是什么呢?他控制的是说我需要多少个副本, 他们两个的职责其实是不一样的,你如果把这两个职责放到一个对象上去,那这个对象其实他就会变得很复杂

高层 API 以操作意图为基础设计

  • 如何能够设计好 API,跟如何能用面向对象的方法设计好应用系统有相通的地方,高层设计一定是从业务出发,而不是过早的从技术实现出发。
  • 因此,针对 Kubernetes 的高层 API 设计,一定是以 Kubernetes 的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。

低层 API 根据高层 API 的控制需要设计

  • 设计实现低层 API 的目的,是为了被高层 API 使用,考虑减少冗余、提高重用性的目的,低层 API 的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。

尽量避免简单封装,不要有在外部 API 无法显式知道的内部隐藏的机制

  • 简单的封装,实际没有提供新的功能,反而增加了对所封装 API 的依赖性。
  • 例如 StatefulSet 和 ReplicaSet,本来就是两种 Pod 集合,那么 Kubernetes 就用不同 API 对象 来定义它们,而不会说只用同一个 ReplicaSet,内部通过特殊的算法再来区分这个 ReplicaSet 是 有状态的还是无状态。

API 操作复杂度与对象数量成正比

  • API 的操作复杂度不能超过 O(N),否则系统就不具备水平伸缩性了。

API 对象状态不能依赖于网络连接状态

  • 由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证 API 对象状态能应 对网络的不稳定,API 对象的状态就不能依赖于网络连接状态。

尽量避免让操作机制依赖于全局状态

  • 因为在分布式系统中要保证全局状态的同步是非常困难的。

Kubernetes 如何通过对象的组合完成业务描述

image-20211212214456891

引用依赖, 比如说 pod对象中有一个nodename属性的名字指向了 node对象,ingress属性中有个service的名字指向了service, 这种情况叫引用依赖。

基于命名规范, 两个对象的关系是写在程序里面的,比如 deployment对象的 PodTemplate字符串的 hash值,是replicaset 名字的一部分。

基于标签,基于标签的过滤条件。比如 pod 怎么和 service产生关系的呢? service是根据 selector 的标签值来关联的

image-20211212220056817