cmd/kubelet/kubelet.go
進程入口函數(shù)全庸,調(diào)用 server.go Run
Run
初始化 KubeClient乞娄、EventClient衅码、CAdvisorInterface咧最、ContainerManager
等
Run
中的函數(shù) RunKubelet
繼續(xù)啟動 kubelet
翩腐,做一些配置檢查
RunKubelet
中的函數(shù) startKubelet
最終啟動 kubelet
慈鸠,當(dāng)然之前需要初始化 Kubelet
蓝谨,CreateAndInitKubelet
->NewMainKubelet
// start the kubelet
go wait.Until(func() { k.Run(podCfg.Updates()) }, 0, wait.NeverStop)
這塊有兩個分支,一支為 k.Run
林束,另一支為 podCfg.Updates()
- k.Run 函數(shù)從 podCfg.Updates() 返回的 channel 中獲取到 updates 的 pod 信息
- podCfg 負責(zé)將從 file / url / apiserver 獲得的 pod updates 信息融合到一個 channel 中
k.Run 開始 syncLoop 之前(開始處理 updates 信息之前)像棘,會啟動一系列周期 goroutine
,如
- volumeManager
- syncNodeStatus(從 apiserver 獲得 metadata.name==kl.nodename 的
node 信息壶冒,更新本地 node 信息缕题,隨后又 update apiserver 上的對應(yīng) node 的信息) - syncNetworkStatus
- updateRuntimeUp
- syncNetworkUtil(刷 iptables 這兩個規(guī)則 KUBE-MARK-DROP、KUBE-MARK-MASQ)
- podKiller (刪除沒被 podWorker 正確處理的 pod)
還會啟動一些 manager胖腾,如
- go kl.volumeManager.Run(kl.sourcesReady, wait.NeverStop)
- statusManager.Start() (syncPeriod=10s
syncBatch
周期烟零,或者從 podStatusChannel 中獲取更新信息,直接syncPod
咸作;syncPod
首先去本地 cache 確認是否需要更新锨阿,不需要更新直接返回,需要更新繼續(xù)將本地 pod status 更新到 apiserver记罚,如果 pod DeletionTimestamp 不為 nil墅诡,則該 pod 被標記刪除,如果該 pod 仍有在運行的 container桐智,則返回末早;否則調(diào)用 apiserver 刪除 api烟馅,將 pod 從 etcd 中刪除,成功后然磷,本地 cache 通過 pod uid 將該 pod 刪除郑趁。至于syncBatch
,從 podStatuses map 中獲取到所有需要 update姿搜、reconcile 的 status寡润,逐一調(diào)用syncPod
處理這些 status。其中podStatuses
的信息來源為舅柜,SetPodStatus
->updateStatusInternal
梭纹,首先將 status 和 cache 比,相同且沒有設(shè)置 forceUpdate 的話致份,就不用更新了栗柒;否則生成新的versionedPodStatus
,version + 1知举,存入本地 cache,即 podStatuses太伊。若 podStatusChannel 未滿雇锡,則將該 statuspodStatusSyncRequest{pod.UID, newStatus}
放入其中
,否則交由 syncBatch 處理僚焦,因為該 status 已經(jīng)在 podStatuses 中了) - probeManager.Start()
- pleg.Start() (pod lifecycle event generator)
syncLoop
重頭戲
- syncTicker(1s)
- housekeepingTicker(2s)
- pleg.Watch()
- 如果有 runtimeErrors锰提,則 skip sync and sleep 5s;否則
syncLoopIteration(updates, handler)
芳悲,這里的 updates 不是 status 是PodUpdate
立肘,可能從 configCh(PodUpdate) 來的更新:ADD
、UPDATE
名扛、REMOVE
谅年、RECONCILE
、DELETE
肮韧,交由各個handle
去處理融蹂;從 plegCh 來的事件HandlePodSyncs
;從 syncCh 來的 tick弄企,HandlePodSyncs
超燃;從 livenessManager 來的 updates,HandlePodSyncs
拘领;housekeepingCh 來的 tick意乓,sourcesReady.AllReady() 時,HandlePodCleanups()约素;最后這個 handler 傳入的其實就是Kubelet
神奇的在 pkg 下的 kubelet.go 又看到一個 syncPod
fun届良,這個是 real syncPod笆凌,之前那個是 status_manager 的 syncPod,是 sync status of pod 的伙窃;那么來解讀一下 kubelet.go 的 syncPod 吧
- 若 SyncPodKill: 則 kill pod 并 kl.statusManager.SetPodStatus(pod, apiPodStatus)
- SyncPodCreate: metrics 記錄第一次被 apiserver 看到的時間菩颖;生成 apiPodStatus (
generateAPIPodStatus
);如果 pod 仍未啟動为障,則記錄啟動時延 - 判斷是否能 runPod晦闰,不能則給出 Reason 和 Message
- 更新 status
kl.statusManager.SetPodStatus(pod, apiPodStatus)
- 創(chuàng)建 pcm (pod container manager)
- 為 pod 啟動做一系列動作,如創(chuàng)建 data 目錄鳍怨,掛卷(AttachAndMount)等
-
result := kl.containerRuntime.SyncPod(pod, apiPodStatus, podStatus, pullSecrets, kl.backOff)
使用 container 啟動 pod (不過 SyncPod 是 Runtime 接口的一個方法呻右,再找實現(xiàn)就不知道在哪里了,求問 go 里面怎么找接口實現(xiàn)鞋喇,一臉懵逼)
pod 的創(chuàng)建似乎和 cgroups 有關(guān)声滥,這塊后繼需要再了解一下
想想 kubelet 組件的作用不就是 create、update侦香、delete pod 么
多處都使用到 HandlePodSyncs
落塑,有時間繼續(xù)解析
另外 NewMainKubelet
這個也是重頭,主要是創(chuàng)建 Kubelet
罐韩,就是都要用到的 kl
憾赁,初始化一系列東西
** 看這些主要是為了理出比較明確的 node 和 pod 的 status **
現(xiàn)在并沒有看到 local 的 pod 信息在那寫入的,當(dāng)然 file 算一種散吵,不過類似 OOM 這種運行時錯誤的上報沒有發(fā)現(xiàn)龙考;如果 pod 一開始就不能 Admit 當(dāng)然是會立刻生成 status 的
先寫到這 to be cont.