圖解kubernetes Pod生命週期事件生成器

PLEG(PodLifecycleEventGenerator)主要是用於週期性檢測Pod的運行狀態,從而對比Pod先後狀態生成事件從而觸發kubelet進行Pod容器狀態的校證,讓咱們一塊兒來初探下其內部實現機制算法

1. 圖解設計

1.1 Pod事件生成

image.png Pod事件生成主要是根據對應Pod先後的狀態對比來實現,首先經過runtime來獲取當前節點的全部Pod的列表,並將對應的狀態進行保存,這樣在下一個輪訓週期就能夠經過先後狀態的對比去發現狀態發生改變的Pod的容器,而且產生對應的事件微信

1.2 事件通知與狀態同步

image.png Pod事件生成以後會經過管道將對應的事件同步給狀態同步線程,狀態同步線程感知到Pod的變動事件後,會與Pod的目標狀態進行對比同步,並調用Runtime來進行最終校證操做的執行,同時在下個輪詢週期中又會從新從Runtime獲取狀態,從而不斷校證Pod的狀態,直至目標狀態數據結構

2. Pod記錄

Pod記錄其實就是一個map,並經過podRecord來保存先後輪詢週期Runtime返回的Pod的信息ide

type podRecord struct {
	old     *kubecontainer.Pod
	current *kubecontainer.Pod
}

type podRecords map[types.UID]*podRecord

3. Pod事件生成器

3.1 獲取Pod狀態

首先經過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
	}

3.2 對比Pod信息生成事件

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)
			}
		}
	}

3.3對比容器狀態事件生成

Pod的事件主要是經過底層容器的狀態來生成的,會最終對比每一個容器的先後狀態,從而獲取變動事件ui

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))
	}
}

4. 總體事件流程總覽

image.png 在k8s中有不少相似PLEG的設計,總的設計目標都是爲了經過事件的變動和實際指望狀態,不斷的進行調整,從而達到最終的指望狀態, 之後我儘可能只給出組件最核心的一點代碼,梳理清除整個流程中核心的數據結構與算法線程

k8s源碼閱讀電子書地址: https://www.yuque.com/baxiaoshi/tyado3 > 微信號:baxiaoshi2020 > 關注公告號閱讀更多源碼分析文章 21天大棚 > 更多文章關注 www.sreguide.com > 本文由博客一文多發平臺 OpenWrite 發佈設計

相關文章
相關標籤/搜索