一冯勉、概念
Kubelet Bootstrap Checkpoint是kubelet對(duì)特定的Pods的進(jìn)行備份奔则、恢復(fù)的kubelet內(nèi)置模塊先嬉。
- Kubelet Bootstrap Checkpoint是對(duì)當(dāng)前Node上帶有Annotation:
node.kubernetes.io/bootstrap-checkpoint=true
的Pods的Checkpoint到文件系統(tǒng)機(jī)制泵肄。 - 當(dāng)kubelet重啟時(shí),會(huì)檢查checkpoint目錄下各個(gè)Pods對(duì)應(yīng)的checkpoint文件焕蹄,加載所有的checkpoint文件逾雄,轉(zhuǎn)換成Pod Object,然后啟動(dòng)這些Pods。
二嘲驾、啟用
- Kubelet啟動(dòng)參數(shù)中配置
--bootstrap-checkpoint-path
,默認(rèn)為""
迹卢,意味著默認(rèn)Disable辽故。 - 給需要Bootstrap Checkpoint的Pods加上Annotation:
node.kubernetes.io/bootstrap-checkpoint=true
。
三腐碱、工作機(jī)制
kubelet啟動(dòng)時(shí)誊垢,在NewMainKubelet中會(huì)檢查--bootstrap-checkpoint-path
是否不為空,如果不為空症见,就會(huì)創(chuàng)建checkpointManager喂走。
注:目前Bootstrap Checkpoint只是對(duì)本節(jié)點(diǎn)的特定Pods進(jìn)行Checkpoint,并不包括其他Kubernetes Object的Checkpoint谋作。
3.1 創(chuàng)建或更新pod
當(dāng)kubelet開(kāi)啟了checkpoint功能芋肠,用戶(hù)提交了創(chuàng)建pod的請(qǐng)求,經(jīng)過(guò)kube-scheduler調(diào)度后遵蚜,kubelet在開(kāi)始pod的創(chuàng)建流程帖池。kubelet在HandlePodAddtions()
方法中遍歷所有pod,使用podManager.AddPod()
接口[AddPod()
其實(shí)就是UpdatePod()
]吭净,此方法調(diào)用了checkpoint.WritePod()
接口睡汹,首先會(huì)檢查pod的annotation是否開(kāi)啟了checkpoint(node.kubernetes.io/bootstrap-checkpoint=true
),對(duì)于滿(mǎn)足條件的pod寂殉,寫(xiě)入對(duì)應(yīng)的checkpoint文件中(Pod_UID.yaml)囚巴,最后再調(diào)用dispatchWorker去創(chuàng)建pod。
同理友扰,當(dāng)pod.Spec有更新彤叉,kubelet按照如下調(diào)用鏈:HandlePodUpdates() ==> podManager.UpdatedPod() ==> checkpoint.WritePod()
記錄pod的checkponit文件。
如果checkpoint.WritePod()發(fā)生Error村怪,可以在kubelet日志中看到姆坚,但是并不會(huì)引發(fā)流程異常,也就是說(shuō)实愚,Pod還會(huì)繼續(xù)創(chuàng)建起來(lái)兼呵,只是checkpoint失敗。
3.2 刪除pod
刪除過(guò)程同樣類(lèi)似腊敲,HandlePodRemoves() ==> podManager.DeletePod() ==> checkpoint.DeletePod()
击喂,checkpoint在刪除pod時(shí),會(huì)把pod對(duì)應(yīng)的checkpoint文件也刪除碰辅。刪除不會(huì)像創(chuàng)建或者更新那樣懂昂,先檢查pod的annotation配置。
這樣做的目的是没宾,如果pod的annotation在某次更新操作后被刪除凌彬,那么該pod的checkpoint文件將會(huì)產(chǎn)生殘留沸柔。之后pod被刪除,而kubelet發(fā)生了重啟铲敛,將從checkpoint文件褐澎,把該pod恢復(fù)错览。當(dāng)然熄云,這個(gè)pod會(huì)在與kube-apiserver同步后得知被刪除兽叮,然后kubelet會(huì)再次刪除它茫虽。因此硕糊,刪除pod時(shí)遮晚,即使pod不存在checkpoint文件谷扣,調(diào)用os.Remove()
返回的IsNotExists
錯(cuò)誤并不會(huì)上報(bào)竿开。
3.3 Kubelet重啟
當(dāng)kubelet發(fā)生冷重啟時(shí)焙畔,會(huì)先檢查--bootstrap-checkpoint-path
是否配置掸读,如果是,就會(huì)調(diào)用checkpoint.LoadPods()
根據(jù)配置的目錄下的所有Pod_UID.yaml格式的文件宏多,并通過(guò)FNV Hash算法進(jìn)行CheckSum檢查寺枉。
檢查通過(guò)后,將checkpoint yaml文件內(nèi)容轉(zhuǎn)換成Pod API Object绷落,然后把這些Pod對(duì)象通過(guò)kubetypes.PodUpdate()
類(lèi)型的channel一直傳遞給Kubelet.syncLoopIteration()
姥闪,最終由dispatchWork
給Kubelet podWorkers
去創(chuàng)建對(duì)應(yīng)的Pod實(shí)例。
四砌烁、應(yīng)用場(chǎng)景
4.1 self-hosted-kubernetes
對(duì)于k8s托管的kube-apiserver筐喳,kube-controller-manager,kube-scheduler函喉,kubelet避归,etcd,adds-on組件進(jìn)行升級(jí)管呵、維護(hù)的場(chǎng)景梳毙。關(guān)于self-hosted-kubernetes
的更多內(nèi)容請(qǐng)參考Proposal: Self-hosted Control Plane,bootkube捐下,kubeadm upgrade等都與此相關(guān)账锹。這也是社區(qū)設(shè)計(jì)這一特性的主要?jiǎng)訖C(jī)。下圖是bootkube的原理圖坷襟。
那么奸柬,對(duì)于用戶(hù)來(lái)說(shuō),部署普通應(yīng)用時(shí)給Pod加上Annotation:node.kubernetes.io/bootstrap-checkpoint=true
來(lái)給該P(yáng)od提供bootstrap checkpoint會(huì)帶來(lái)什么好處嗎婴程?
對(duì)于用戶(hù)而言廓奕,如果kube-apiserver能正常訪(fǎng)問(wèn),那么bootstrap checkpoint確實(shí)沒(méi)有什么用處,因?yàn)閑tcd中已經(jīng)有Pods API Object信息了桌粉,checkpoint就顯得多此一舉了蒸绩。如果checkpoint文件和etcd中數(shù)據(jù)存在不一致的情況,反而會(huì)導(dǎo)致Pod先通過(guò)checkpoint恢復(fù)后铃肯,很快又根據(jù)etcd中Object Info進(jìn)行重建的問(wèn)題患亿。
但是,對(duì)于Node上一些特殊的常駐Agent缘薛,比如cmdb agent窍育,需要定期上報(bào)Node的狀態(tài)等信息卡睦,以DaemonSet Pod方式運(yùn)行在Node上宴胧,如果在對(duì)Kubernetes進(jìn)行升級(jí)時(shí)方式不對(duì)或者不順暢,Node系統(tǒng)重啟并長(zhǎng)時(shí)間無(wú)法與kube-apiserver進(jìn)行通信(比如apiserver升級(jí)失敱矶汀)恕齐,這將導(dǎo)致Node上無(wú)法運(yùn)行DaemonSet Pod,那么這個(gè)Node上的cmdb agent就無(wú)法正常上報(bào)信息瞬逊。對(duì)于這種情況显歧,如果我們給這個(gè)DaemonSet Pod設(shè)置了對(duì)應(yīng)Annotation和啟用了Kubelet Bootstrap Checkpoint,那么kubelet可以在不依賴(lài)kube-apiserver的情況下确镊,通過(guò)本地的checkpoint文件恢復(fù)之前備份的Pods士骤。
因此,給一些per-node上的關(guān)鍵用戶(hù)組件使用Bootstrap Checkpoint是有價(jià)值的蕾域。