天天看點

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

文章來源:圖解源碼,原文連結

kubernetes中的容器建立無疑是個複雜的過程,涉及内部各種元件的統一協作,還有對接外部的CRI運作時,本文嘗試初探一下容器建立流程中的各種細節,了解其各種元件協作流程,進而在後續出現問題的時候,也好能大概有點排查方向

1. 基礎築基

1.1 容器管理線程模型

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

kubelet中的線程模型屬于master/slave模型,通過單master來監聽各種事件源,并為每個Pod建立一個goroutine來進行Pod業務邏輯的處理,master和slave之間通過一個狀态管道來進行通信

1.2 基于事件驅動的狀态最終一緻性

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

在通過yaml建立Pod之後,kubernetes會根據目前的事件和目前的Pod狀态,來不斷進行調整,進而達到最終目标狀态的一緻性

1.3 元件協作流程

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

kubelet的結構體聲明就高達300多行代碼,可見其複雜程度,但是我們按照容器建立這個流程,我們去觀察其核心流程,其實主要可以概括為三部分:kubelet、containerRuntime、CRI容器運作時

2.Kubelet建立容器流程

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

2.1 擷取Pod進行準入檢查

kubelet的事件源主要包含兩個部分:靜态Pod和Apiserver,我們這裡隻考慮普通的Pod,則會直接将Pod加入到PodManager來進行管理,并且進行準入檢查

準入檢查主要包含兩個關鍵的控制器:驅逐管理與預選檢查驅逐管理主要是根據目前的資源壓力,檢測對應的Pod是否容忍目前的資源壓力;預選檢查則是根據目前活躍的容器和目前節點的資訊來檢查是否滿足目前Pod的基礎運作環境,例如親和性檢查,同時如果目前的Pod的優先級特别高或者是靜态Pod,則會嘗試為其進行資源搶占,會按照QOS等級逐級來進行搶占進而滿足其運作環境

2.2 建立事件管道與容器管理主線程

kubelet接收到一個新建立的Pod首先會為其建立一個事件管道,并且啟動一個容器管理的主線程消費管道裡面的事件,并且會基于最後同步時間來等待目前kubelet中最新發生的事件(從本地的podCache中擷取),如果是一個建立的Pod,則主要是通過PLEG中更新時間操作,廣播的預設空狀态來作為最新的狀态

2.3 同步最新狀态

當從本地的podCache中擷取到最新的狀态資訊和從事件源擷取的Pod資訊後,會結合目前目前statusManager和probeManager裡面的Pod裡面的容器狀态來更新,進而擷取目前感覺到的最新的Pod狀态

2.4 準入控制檢查

之前的準入檢查是Pod運作的資源硬性限制的檢查,而這裡的準入檢查則是軟狀态即容器運作時和版本的一些軟體運作環境檢查,如果這裡檢查失敗,則會講對應的容器狀态設定為Blocked

2.5 更新容器狀态

在通過準入檢查之後,會調用statusManager來進行POd最新狀态的同步,此處可能會同步給apiserver

2.6 Cgroup配置

在更新完成狀态之後會啟動一個PodCOntainerManager主要作用則是為對應的Pod根據其QOS等級來進行Cgroup配置的更新

2.7Pod基礎運作環境準備

接下來kubelet會為Pod的建立準備基礎的環境,包括Pod資料目錄的建立、鏡像秘鑰的擷取、等待volume挂載完成等操作建立Pod的資料目錄主要是建立 Pod運作所需要的Pod、插件、Volume目錄,并且會通過Pod配置的鏡像拉取秘鑰生成秘鑰資訊,到此kubelet建立容器的工作就已經基本完成

3.ContainerRuntime

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

前面我們提到過針對Pod的操作,最終都是基于事件和狀态的同步而完成,在containerRUntime并不會區分對應的事件是建立還是更新操作,隻是根據目前的Pod的資訊與目标狀态來進行對比,進而建構出對應的操作,達到目标狀态

3.1 計算Pod容器變更

計算容器變更主要包括:Pod的sandbox是否變更、短聲明周期容器、初始化容器是否完成、業務容器是否已經完成,相應的我們會得到一個幾個對應的容器清單:需要被kill掉的容器清單、需要啟動的容器清單,注意如果我們的初始化容器未完成,則不會進行将要運作的業務容器加入到需要啟動的容器清單,可以看到這個地方是兩個階段

3.2 初始化失敗嘗試終止

如果之前檢測到之前的初始化容器失敗,則會檢查目前Pod的所有容器和sandbox關聯的容器如果有在運作的容器,會全部進行Kill操作,并且等待操作完成

3.3 未知狀态容器補償

當一些Pod的容器已經運作,但是其狀态仍然是Unknow的時候,在這個地方會進行統一的處理,全部kill掉,進而為接下來的重新啟動做清理操作,此處和3.2隻會進行一個分支,但核心的目标都是清理那些運作失敗或者無法擷取狀态的容器

3.4 建立容器沙箱

在啟動Pod的容器之前,首先會為其建立一個sandbox容器,目前Pod的所有容器都和Pod對應的sandbox共享同一個namespace進而共享一個namespace裡面的資源,建立Sandbox比較複雜,後續會繼續介紹

3.5 啟動Pod相關容器

Pod的容器目前分為三大類:短生命周期容器、初始化容器、業務容器,啟動順序也是從左到右依次進行,如果對于的容器建立失敗,則會通過backoff機制來延緩容器的建立,這裡我們順便介紹下containerRuntime啟動容器的流程

3.5.1 檢查容器鏡像是否拉取

鏡像的拉取首先會進行對應容器鏡像的拼接,然後将之前擷取的拉取的秘鑰資訊和鏡像資訊,一起交給CRI運作時來進行底層容器鏡像的拉取,當然這裡也會各種backoff機制,進而避免頻繁拉取失敗影響kubelet的性能

3.5.2 建立容器配置

建立容器配置主要是為了容器的運作建立對應的配置資料,主要包括:Pod的主機名、域名、挂載的volume、configMap、secret、環境變量、挂載的裝置資訊、要挂載的目錄資訊、端口映射資訊、根據環境生成執行的指令、日志目錄等資訊

3.5.3 調用runtimeService完成容器的建立

調用runtimeService傳遞容器的配置資訊,調用CRI,并且最終調用容器的建立接口完成容器的狀态

3.5.4 調用runtimeService啟動容器

通過之前建立容器傳回的容器ID,來進行對應的容器的啟動,并且會為容器建立對應的日志目錄

3.5.5 執行容器的回調鈎子

如果容器配置了PostStart鈎子,則會在此處進行對應鈎子的執行,如果鈎子的類型是Exec類則會調用CNI的EXec接口完成在容器内的執行

4. 運作沙箱容器

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

4.1 拉取sandbox鏡像

首先會拉取sandbox鏡像

4.2 建立沙箱容器

4.2.1 應用SecurityContext

在建立容器之前會先根據SecurityContext裡面的配資資訊,來進行容器SecurityContext的配置,主要包括特權等級、隻讀目錄、運作賬戶組等資訊

4.2 其餘基礎資訊

除了應用SecurityContext還會進行斷開、OOMScoreAdj、Cgroup驅動等資訊的映射

4.3 建立容器

根據上面的各種配置資訊來進行容器的建立

4.3 建立checkpoint

checkpoint主要是将目前sandbox的配置資訊進行序列化,并且存儲其目前的快照資訊

4.4 啟動sandbox容器

啟動sandbox容器則會直接調用StartContainer同時傳入之前建立容器傳回的ID完成容器的啟動,并且此時會重寫覆寫容器的dns配置檔案

4.5 容器網絡設定

容器的網絡配置主要是調用CNI插件來完成容器網絡的配置,這裡就先不展開了

5. Pod容器啟動總結

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

kubelet是容器管理的核心大管家,其負責各種準入控制、狀态管理、探測管理、volume管理、QOS管理、CSI對接的統一排程,并且為Runtime運作時準備基礎的資料和并回報Pod目前的最新狀态

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結

Runtime層則将kubelet組裝的資料,按照CRI運作時的目标配置和kubelet管理的資源配置資訊來進行資源的重組,并且根據Pod的容器的狀态來決策容器的啟停、建立等操作,并完成容器的基礎配置環境的建構,并最終調用CRI完成容器的建立,而CRI運作時,則會講傳遞過來的各種資料進行進一步的組合,并應用到主機和對應的namespace資源限制,并根據自己的容器服務組織資料,調用容器服務完成容器的最終建立

本文是一個基礎版本,後續會在該版本上,繼續疊加各種細節,感興趣的朋友可以幫忙轉發關注下,謝謝大家

k8s源碼閱讀電子書位址: https://www.yuque.com/baxiaoshi/tyado3

END Kubernetes  線上直播班

建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結
建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結
建立元件“ovalshape”失敗_圖解:kubernetes Pod 建立流程1. 基礎築基2.Kubelet建立容器流程3.ContainerRuntime4. 運作沙箱容器5. Pod容器啟動總結