不会飞的章鱼

熟能生巧,勤能补拙;念念不忘,必有回响。

Kubernetes编排原理——“控制器”设计思想

首先,我们以之前实践过的nginx-deployment.yaml文件为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment # API对象的类型
metadata:
name: nginx-deployment
spec:
selector:
matchLabels: # 过滤规则的定义
app: nginx
replicas: 2 # 定义Pod副本个数为2
template:
metadata: labels: # 元数据
app: nginx # labels,一组键值对的标签
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

这个Deployment定义的编排动作是:请确保携带了app:nginx标签的Pod的个数永远等于spec.replicas指定的个数-> 2。

这就意味着,如果在这个集群中,携带app:nginx标签的Pod个数大于等于2,就会有旧的Pod被删除;反之就会有新的Pod被创建。

那么,究竟是Kubernetes项目的哪个组件在执行这些操作呢?——kube-controller-manager组件。

实际上,这个组件就是一系列控制器的集合,看下pkg/controller目录

实际上,这些控制器之所以被统一放在pkg/controller目录下,就是因为它们都遵循Kubernetes项目中的一个通用编排模式——控制循环(control loop)。

比如,现在有一种待编排的对象X,它有一个对应的控制器。那么,我就可以用一段Go语言风格伪代码来描述:

1
2
3
4
5
6
7
8
9
for {
实际状态 := 获取集群中对象X的实际状态
期望状态 := 获取集群中对象X的期望状态
if 实际状态 == 期望状态 {
什么都不做
} else {
执行编排动作,将实际状态调整为期望状态
}
}

我们以Deployment为例,简单介绍它对控制器模型的实现:

  • 1,Deployment控制器从etcd中获取所有携带了app:nginx标签的Pod,然后统计它们的数量,这就是实际状态;
  • 2,Deployment对象的Replicas字段的值就是期望状态;
  • 3,Deployment控制器比较两个状态,然后根据结果确定是创建Pod,还是删除已有的Pod

因此,一个Kubernetes对象的主要编排逻辑在第三步对比阶段完成。这个操作通常称作调谐(reconcile)。调谐的过程则称作调谐循环(reconcile loop)或者同步循环(sync loop)

调谐的最终结果往往是对被控制对象的某种写操作。比如,增加/删除 Pod,或者更新Pod的某个字段。

至此,我们可以对Deployment以及其他类似的控制器做一个简单总结:

类似于Deployment这样的控制器,由上半部分的控制器定义(包括期望状态)和下半部分的被控制对象的模板组成的。这就是为什么在所有API对象的Metadata里,都会有一个名为ownerReference的字段,用于保存当前这个API对象的拥有者的信息。

------ 本文结束------
如果本篇文章对你有帮助,可以给作者加个鸡腿~(*^__^*),感谢鼓励与支持!