kubernetes的最重要的设计理念就是声明式API,所谓的声明式API 就是用户通过API定义对象的最终状态,然后剩下的就交给k8s去处理。
Controller manager是真正负责资源管理的组件,它主要是负责容器的副本数管理、节点状态维护、节点网段分配等功能。 它是Kubernetes负责实现生命式API和控制器模式的核心。以ReplicaSet为例,它会周期的检测理想的“目标容器数”和真实的“当前容器数”是否相同,如果不相等,则会将实际的容器数调整到目标容器数,当设置一个ReplicaSet的副本数为10的时候,如果实际的容器数小于10则会执行调用Apiserver创建Pod,对应的,如果当前容器数大于10,则会执行删除Pod操作。整个过程如下图所示:
但其实上面的说法不是特别准确,如果一直死循环比对将会导致资源的浪费,为此k8s里面还有另外一个高级功能 listwatch机制。当用户通过k8s 的apiserver 将资源对象保存或者更新到etcd 后,便会触发一个add、update或者delete 的event事件,这个些事件会放到controller 内部的工作队列 workqueue里面,然后通过这个死循环控制器,对比新老对象的差异,从而执行对应的动作,如下所示,你可以理解只有在有必要比对的时候才会去执行比对动作。
k8s里面有很多的控制器,比如控制副本的replicasset 控制器、控制Deployment的Deployment控制器,控制statefulset的statefulset的控制器,以及service 控制器等。每种控制器分别watch 自己关心的资源,比如一个replicasset的控制器在启动的时候就会watch rs 和pod的状态如下所示。
rsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: rsc.addRS, UpdateFunc: rsc.updateRS, DeleteFunc: rsc.deleteRS, }) podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: rsc.addPod, UpdateFunc: rsc.updatePod, DeleteFunc: rsc.deletePod, })
状态发生变化后,就会加入到上面的workqueue,执行比对操作。controller manager整套逻辑的执行是不需要用户参与,这个才是声明式的核心。