PLEG(PodLifecycleEventGenerator)主要是用於週期性檢測Pod的運行狀態,從而對比Pod先後狀態生成事件從而觸發kubelet進行Pod容器狀態的校證,讓咱們一塊兒來初探下其內部實現機制算法
Pod事件生成主要是根據對應Pod先後的狀態對比來實現,首先經過runtime來獲取當前節點的全部Pod的列表,並將對應的狀態進行保存,這樣在下一個輪訓週期就能夠經過先後狀態的對比去發現狀態發生改變的Pod的容器,而且產生對應的事件數據結構
Pod事件生成以後會經過管道將對應的事件同步給狀態同步線程,狀態同步線程感知到Pod的變動事件後,會與Pod的目標狀態進行對比同步,並調用Runtime來進行最終校證操做的執行,同時在下個輪詢週期中又會從新從Runtime獲取狀態,從而不斷校證Pod的狀態,直至目標狀態ide
Pod記錄其實就是一個map,並經過podRecord來保存先後輪詢週期Runtime返回的Pod的信息線程
type podRecord struct { old *kubecontainer.Pod current *kubecontainer.Pod } type podRecords map[types.UID]*podRecord
首先經過runtime來獲取當前節點的全部pod的狀態設計
// Get all the pods. podList, err := g.runtime.GetPods(true) if err != nil { klog.Errorf("GenericPLEG: Unable to retrieve pods: %v", err) return }
eventsByPodID := map[types.UID][]*PodLifecycleEvent{} for pid := range g.podRecords { // 獲取以前的Pod信息 oldPod := g.podRecords.getOld(pid) pod := g.podRecords.getCurrent(pid) // 獲取當前Pod的全部容器集合 allContainers := getContainersFromPods(oldPod, pod) for _, container := range allContainers { // events := computeEvents(oldPod, pod, &container.ID) for _, e := range events { // 更新pod的events事件 updateEvents(eventsByPodID, e) } } }
Pod的事件主要是經過底層容器的狀態來生成的,會最終對比每一個容器的先後狀態,從而獲取變動事件code
func generateEvents(podID types.UID, cid string, oldState, newState plegContainerState) []*PodLifecycleEvent { if newState == oldState { return nil } klog.V(4).Infof("GenericPLEG: %v/%v: %v -> %v", podID, cid, oldState, newState) switch newState { case plegContainerRunning: return []*PodLifecycleEvent{{ID: podID, Type: ContainerStarted, Data: cid}} case plegContainerExited: return []*PodLifecycleEvent{{ID: podID, Type: ContainerDied, Data: cid}} case plegContainerUnknown: return []*PodLifecycleEvent{{ID: podID, Type: ContainerChanged, Data: cid}} case plegContainerNonExistent: switch oldState { case plegContainerExited: // We already reported that the container died before. return []*PodLifecycleEvent{{ID: podID, Type: ContainerRemoved, Data: cid}} default: return []*PodLifecycleEvent{{ID: podID, Type: ContainerDied, Data: cid}, {ID: podID, Type: ContainerRemoved, Data: cid}} } default: panic(fmt.Sprintf("unrecognized container state: %v", newState)) } }
在k8s中有不少相似PLEG的設計,總的設計目標都是爲了經過事件的變動和實際指望狀態,不斷的進行調整,從而達到最終的指望狀態, 之後我儘可能只給出組件最核心的一點代碼,梳理清除整個流程中核心的數據結構與算法blog
k8s源碼閱讀電子書地址: https://www.yuque.com/baxiaoshi/tyado3事件