天天看點

Kubernetes Pod啟動流程

pod啟動流程

Kubernetes Pod啟動流程

runc有兩種,一種docker,一種containerd,上面是以containerd來說明,更加輕量。

使用者去建立pod,那麼pod的請求會發給apiserver,apiserver接收到請求之後,會把對象存儲到etcd裡面,存儲完成之後,排程器就去watch到pod的建立時間,并且完成排程,綁定pod。

綁定之後,也就是更新,繼續去etcd裡面做持久化,持久化完成之後,kubelet就watch到已經綁定的pod。

kubelet在啟動pod的時候,它啟動的不是一個容器程序,而是多個容器程序,不僅僅啟動了應用程序,同時還啟動了pause容器鏡像的執行個體,容器程序啟動了之後可以把它和某個網絡namespace産生關聯關系,把它放在某個網絡namespace下面,在這個獨立的網絡namesapce下面,它可以有獨立的網絡配置,如果直接将容器程序放到網絡namesapce裡面會出現什麼樣的問題呢?

你的容器程序可靠嗎?會不會有錯誤,會不會異常退出,oom,空指針,等等,當出現這些問題的時候,容器程序就退出了,退出之後容器程序就和這個網絡namespace之間的綁定關系就消失了,如果不做一些措施的話,那是不是每次容器程序退出都需要重新為這個容器程序配置網絡,那麼這樣的效率不會很高,如果容器頻繁重新開機,那麼就會導緻節點上面多了很多不必要的系統操作。

有什麼辦法讓容器程序退出的時候,網絡,存儲這些東西都不發生變化,這就是為什麼需要pause容器。

在容器啟動之前,網絡就需要就緒,網絡是要在容器之前就緒的,這就需要額外的容器程序先啟動起來。這個也是pause的功能。

pause容器裡面entrypoint其實就是pause,它永遠sleep,它是一個不會退出,不消耗資源的一個穩定的程序,那麼所有的網絡就可以挂載在這個pause上面,當容器應用程序啟動的時候,我隻需要将應用程序的網絡namespace挂載在pause上面就行了。

即使容器出現各種問題重新開機,沒關系,因為網絡是挂載在其下面的。是以它就提供了非常穩定的基座。

更加詳細的啟動過程

再回過頭來看pod啟動,pod啟動的時候最先啟動pause容器,啟動之後containerd就會去調用cni的插件去setup pod,其實它會将ADD的指令告訴cni插件幫我setup網絡,cni這邊setup網絡之後會去将pod資訊傳回給runtime,然後這個資訊會傳回給kubelet,那麼這個時候其實pod就有IP了,這個時候才會去進行下面的使用者應用容器的啟動。

可以看到在啟動容器的時候,網絡是已經就緒的,是以有網絡需求就可以滿足了,整個啟動完之後就會将狀态回寫到Apiserver裡面,那麼整個的啟動過程就完成了。

Kubernetes Pod啟動流程

上面是更加細的流程框圖,如果讀代碼可以按照上面的思路作為指導去梳理代碼的走讀流程。

可以看到最左邊是kubelet 中間是CRI 右邊是CNI

CheckAdmit:kubelet在sync pod也就是做pod同步的時候,首先也會去做準入,比如它要去啟動pod,如果節點資源不夠,你非要将nodename設定為該節點,因為和節點産生綁定關系,那麼就需要啟動這個容器了,啟動的時候我要去check一下,也需要去做準入的,要去看你的cpu的需求滿足不滿足,如果不滿足就直接報錯了,out of cpu的error,寫回到這個pod狀态裡面。

Check network plugin:然後會去監聽目前節點上網絡插件的情況,如果網絡插件不就緒,那麼pod是啟動不起來的,是以這裡也會直接報錯。

Update cgroup:namspace cgroup這些技術要去啟動容器程序的時候,要将容器對應的cgroup檔案配置好。

Makepoddir:pod需要存儲日志,容器的日志需要在主機上有個目錄,它會去将資料目錄建立起來。

WaitForattachandmount:你的pod是需要一些存儲,比如configmap輕量級存儲隻需要将檔案下載下傳下來,然後mount到容器當中就行了,如果是更高要求的存儲,比如網絡存儲,那麼需要去建立volume,然後和這個節點産生attach關系,然後再mount到容器裡面,其實就是等待存儲就緒。

面試的時候:CRI CNI CSI,它們之間關系是怎麼樣的呢?在啟動pod的時候誰先啟動,誰後啟動,上面可以很清晰看到CSI就在kubelet這部分運作,就是在pod後續加載還沒有啟動的時候,我就得先去将存儲挂載好,并且mount進來。

如果這一步不過的話,它會一直卡在這裡,接下來才會去做syncpod。

syncpod裡面就是來計算sandbox和容器變化,如果sandox發生變化了,就是已經在運作的容器和我pod本身不比對了,那就是重建了,這裡面其實就是computerpodaction的動作,如果這個pod已經不存在了,你的容器還在,那麼就需要将容器kill掉。

然後你要啟動一個新的容器,那麼會去經曆啟動的動作。之前講了第一步就是createpodsandbox,它會去生成這些sandbox的config,它有一些mainfest,要将這些配置檔案生成出來。然後pod的日志目錄要建立好,然後要去調用runtime的sandbox。

繼續閱讀