我们讲解了Pod这个API对象的各个字段,接下来就是Kuberenetes的编排功能

Pod这个复杂的API对象,其实是对容器的进一步抽象和封装而已

而且,比起原本的容器的一个简单的镜像,容器这个沙盒的概念,对于描述应用来说,太过于简单,就好比一个光滑的球,没法去抓

所以Pod,就是在这个球上面加了好多的抓取垫,方便人去搬运使用

而Kubernetes操作这些集装箱的逻辑,都由控制器完成,在之前,我们曾经说过Deployment这个基本的控制器对象

接下来,我们回顾一下这个名为nginx-deployment的例子

apiVersion: apps/v1

kind: Deployment

metadata:

  name: nginx-deployment

spec:

  selector:

    matchLabels:

      app: nginx

  replicas: 2

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      – name: nginx

        image: nginx:1.7.9

        ports:

        – containerPort: 80

这个Deployement定义的编排很简单,就是确保app=nginx标签的pod的个数,等于spec.replicas指定的个数,就是2个

这就意味着,如果这个集群,携带的app=nginx标签的pod个数大于2个时候,就会有旧的Pod删除,不然就会有新的Pod创建

这就是Kube-controller-manager,这就是一系列控制器的集合

在kubernetes项目的pkg/controller目录

$ cd kubernetes/pkg/controller/

$ ls -d */              

deployment/             job/                    podautoscaler/          

cloud/                  disruption/             namespace/              

replicaset/             serviceaccount/         volume/

cronjob/                garbagecollector/       nodelifecycle/          replication/            statefulset/            daemon/

在这个目录下面的每一个控制,都以独有的方式负责某种编排功能,Deployement就是其中一种

这些控制器统一放在pkg/controller目录下,就是一个通用的编排模式,控制循环

control loop

现在有一种需要编排的对象X,有一个对应的控制器,那么简单来说的编排流程如下

for {

  实际状态 := 获取集群中对象X的实际状态(Actual State)

  期望状态 := 获取集群中对象X的期望状态(Desired State)

  if 实际状态 == 期望状态{

    什么都不做

  } else {

    执行编排动作,将实际状态调整为期望状态

  }

}

利用一个无限的for循环,来进行整个控制循环

而实际的容器装填,来自于K8s的集群本身,比如K8S根据心跳汇报的容器状态和节点状态,以及一些自定义的信息,来进行判断实际状态

而期望的状态,来自于用户自定义的YAML文件,Deployment对象在Replicas字段的值,这些值放在Etcd中

在Deployment为例,看下对控制器模型的实现

首先是从Etcd中获取了所有带有app:nginx的标签的Pod,然后统计数量

然后获取到了replicas的值,就是期望状态

然后进行判断,是创建Pod还是删除Pod

整个过程,一般叫做调谐 Reconcile,或者叫做 Reconcile Loop(调谐循环)或者Sync Loop(同步循环)

调谐的最终目的,就是对被控制对象的写操作,无论是追加还是删除Pod,或者是更新Pod的某个字段,都是K8S中面向API对象编程的一个体现

而被控制的对象,来自于一个模板,比如Deployment的template字段,可以看出,Deployment这个template字段中的内容,和一个标准的Pod对象的API定义,丝毫不差,这个Deployment管理处的Pod,都是根据这个template字段内容创建出来的

那么我们总结一下Deployment的模板

图片

类似Deployment这样的一个控制器,实际上都是上半部分控制器定义,也就是期望状态

和下半部分的模板定义构成的

这就是为何,在所有API对象的metedata中,都有一个字段ownerReference,保存这个API对象的拥有者

对于,我们这个nginx-deployment来说,这个Pod的ownerReference是哪位呢?

在本篇文章中,我们以Deployment为例,分享了Kubernetes项目如何通过一个称为控制器模式的设计方式,统一的实现对不同的对象或者资源进行编排的操作

在K8s中,还有很多不同类型的容器编排功能,比如StatefulSet DaemonSet等,都是具有一个或者多个控制器的存在,并遵循这个控制循环的流程完成各自的编排控制

但是本质上,和Deployment相似,都是控制循环的最后执行结果,创建,更新一些Pod,要么就是删除一些已经存在的Pod

但是在这个统一的实现下,不同的控制器的实现思路,实现逻辑是不同的,从而达到不同的编排效果

控制器模式和事件驱动有什么区别吗?

控制器模式是一个无限循环的模型,而事件是单一的,每一次控制器的触发都对应着是一次事件

其次,有人说是select 和 epoll 的区别

或者说

事件驱动,对于控制器来说,是一种被动触发,只要触发了事件就行,至于成功与否,并不在意

控制器模式,对于控制器来说,是主动的,本身在不断的获取信息,知道是否能够生效

而且对于整个K8S系统来说,只有一个Deployment-Controller来管理这个系统的所有Deployment

发表评论

邮箱地址不会被公开。 必填项已用*标注