Author: xidianwangtao@gmail.com
摘要:我认为,Node Controller是Kubernetes几十个Controller中最为重要的Controller之一,其重要程度在Top3,然而这可能也是最为复杂的一个Controller,因此对其的源码分析,我将做一个系列文章,希望能帮助自己有一个深入的理解。本博文主要对Node Controller触发的Taint Controller进行源码分析,看看NoExecuteTaintManager是如何进行Taint Pod Evictions的。
NewNoExecuteTaintManager
在Kubernetes Node Controller源码分析之创建篇中提到:
- PodInformer添加Event Handler时,通过调用
taintManager.PodUpdated(oldPod *v1.Pod, newPod *v1.Pod)
往tc.podUpdateQueue添加updateItem。 - NodeInformer添加Event Handler时,通过调用
taintManager.NodeUpdated(oldNode *v1.Node, newNode *v1.Node)
往tc.nodeUpdateQueue添加updateItem。 - 当创建NodeController时,如果runTaintManager为true(通过kube-controller-manager的–enable-taint-manager中指定,默认为true),则会通过
NewNoExecuteTaintManager
来实例化一个Taint Manager。
pkg/controller/node/nodecontroller.go:195
func NewNodeController(..) (*NodeController, error) {
...
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
...
if nc.taintManager != nil {
nc.taintManager.PodUpdated(nil, pod)
}
},
...
}
...
} else {
nodeEventHandlerFuncs = cache.ResourceEventHandlerFuncs{
AddFunc: func(originalObj interface{}) {
...
if nc.taintManager != nil {
nc.taintManager.NodeUpdated(nil, node)
}
},
...
}
}
...
if nc.runTaintManager {
nc.taintManager = NewNoExecuteTaintManager(kubeClient)
}
...
return nc, nil
}
因此,创建NodeController时已经配置了监听pod和node的事件,并会将相关数据发送到tc.podUpdateQueue和tc.nodeUpdateQueue,然后由Taint Manager从中取出数据进行处理。在此之前,我们先来看看NewNoExecuteTaintManager是如何实例化一个Taint Manager的。
pkg/controller/node/taint_controller.go:152
func NewNoExecuteTaintManager(c clientset.Interface) *NoExecuteTaintManager {
...
tm := &NoExecuteTaintManager{
client: c,
recorder: recorder,
// taintedNodes记录每个Node对应的Taint信息。
taintedNodes: make(map[string][]v1.Taint),
// nodeUpdateQueue中取出的updateItem会发送到nodeUpdateChannel,Tait Manager从该Channel中取出对应的node update info。
nodeUpdateChannel: make(chan *nodeUpdateItem, nodeUpdateChannelSize),
// podUpdateQueue中取出的updateItem会发送到podUpdateChannel,Tait Manager从该Channel中取出对应的pod update info。
podUpdateChannel: make(chan *podUpdateItem, podUpdateChannelSize),
// Node Controller监听到的node update info会发送到nodeUpdateQueue。
nodeUpdateQueue: workqueue.New(),
// Node Controller监听到的pod update info会发送到podUpdateQueue。
podUpdateQueue: workqueue.New(),
}
// CreateWorkerQueue creates a new TimedWorkerQueue for workers that will execute deletePodHandler.
tm.taintEvictionQueue = CreateWorkerQueue(deletePodHandler(c, tm.emitPodDeletionEvent))
return tm
}
相关的代码分析见里面的代码注释。需要强调的是,我们在这里给tm.taintEvictionQueue注册了函数deletePodHandler
,用来通过Taint Eviction时删除pod时调用。Taint Manager Run的时候会通过tc.taintEvictionQueue.AddWork()
时创建Worker来执行deletePodHandler
。
func deletePodHandler(c clientset.Interface, emitEventFunc func(types.Namespac