kubernetes之pod基本概念總結
1. 什麼是pod
一些關於pod的表述很專業,例如
Pod 是可以在 Kubernetes 中建立和管理的、最小的可部署的計算單元
pod是kubernetes專案中的最小API物件
pod是kubernetes專案的原子排程單位
官方描述:https://kubernetes.io/zh/docs/concepts/workloads/pods/
2. 為什麼需要pod
對於這些對pod概念的總結大多殊路同歸。
在理解概念前不妨先想一個問題:
明明有了容器,為什麼還需要pod?
最質樸的回答往往是:
為了解決容器不足,或者說容器無法滿足需求。
確實是這樣,先分析一下容器的本質:
namespace做隔離
Cgroup做限制
rootfs做檔案系統
三者相輔相成組成容器基本模型
但是,巨集觀的來說,容器的本質是系統中的一個程序。只不過這個程序啟動時被附加了以上等等一下特殊的屬性。
所謂容器只是一個恰當的說法。
就如系統中的大多數程序來說,不是單個程序獨自工作,而是以“程序組”的方式“原則性”的組織在一起,互相協作,完成複雜任務。當然,它們之間也會共享一些資源,例如pid,namespace,儲存等等。
在實際開發和運維中也是隨處可見的這種問題,應用之間有深切的聯絡和依賴。
比如說,我要將一個應用容器化,這個應用由負責各個功能的5個程序組成,這時候,問題來了。
正是容器的侷限性:單程序模型
單程序不是指容器中只能執行一個程序,而是容器無法去管理多個程序
例如,容器中有pid=1的程序,還有一個pid=5的程序,當這個pid=5的程序異常退出時,後續的垃圾回收等處理工作又由誰去做呢?
所以,這個應用的5個模組就必須分別製成5個容器,而且必須在同一個機器上執行。
隨之而來的又是一個問題:
也就是容器排程問題,例如有兩個容器排程節點node1和node2,可用記憶體分別為5G和4.5G,
每個容器分1G記憶體。由於5個容器必須在一臺機器,正常全部排程到node1剛剛好,沒有任何問題。
但是,因為是以容器為單位排程,有這樣一些特殊情況。當前4個容器被排程到node2上時,空間只有0.5G,不足以執行最後一個容器,它有隻能在node1執行,這就是以容器為排程單位的缺點。
當然也有解決方案:如Mesos中的資源囤積(resource hoarding),也就是所有排程任務都到達了才進行排程,也有谷歌Omega論文提出樂觀排程,就是先不管衝突,而是在衝突之後通過一系列回滾機制解決衝突。
但這些都沒有很完善的解決容器排程問題,但是在kubernetes中,這些問題都迎刃而解。
因為不在按照傳統思維的將容器作為排程單位
kubernetes中的專案排程器是統一按照pod的資源需求做排程計算
也就是開始總結的那句話: pod是kubernetes專案的原子排程單位
3. pod結構
如圖所示,一個pod包含了兩類容器:
- 使用者容器
- Pause容器,也常常被稱為“根容器”(貌似老版本叫做infra容器)
使用者容器好理解,但是Pause容器,也就是根容器,他是做什麼用的呢?
pause容器主要為每個使用者容器提供以下功能:
① PID名稱空間:Pod中的不同應用程式可以看到其他應用程式的程序ID。
② 網路名稱空間:Pod中的多個容器能夠訪問同一個IP和埠範圍。
③ IPC名稱空間:Pod中的多個容器能夠使用SystemV IPC或POSIX訊息佇列進行通訊。
④ UTS名稱空間:Pod中的多個容器共享一個主機名;Volumes(共享儲存卷):
⑤ Pod中的各個容器可以訪問在Pod級別定義的Volumes。
4. 容器設計模式
考慮這樣一個問題,容器見的關係是一成不變的嗎?
舉一些例子:
- 在pod中的一些容器的啟動,必須依賴某一個正在執行的容器,也就是說這個容器必須比其他容器先啟動
- 在pod中的容器必須同時協作,也就是說所有容器必須並行執行
- 一個pod需要給外部的其他pod提供介面
- 外部訪問pod時,又怎樣確保響應報文的一致性
- ..........
常見容器設計模式:
Init(初始化)容器
Sidecar(邊車)容器
Adapter(介面卡)容器
Ambassador(外交官)容器
關於容器設計模式可以參考論文:https://www.usenix.org/conference/hotcloud16/workshop-program/presentation/burns
5. pod實現原理
一定要明白一點:pod只是一個邏輯上的概念
因為kubernetes真正處理的還是宿主機作業系統上容器的Namespace和Cgroup,也就是說沒有所謂的pod邊界或隔離環境。
所以說,pod就是一組共享了某些資源的容器
在一個pod中所有容器是共享一個Network Namespace
的,根據宣告的不同來實現不同的資源共享
但是容器間的複雜關係在容器上難以解決,所以kubernetes專案裡,pod的實現借用了一箇中間容器,也就是常常說的根容器(也叫pause容器或infra容器,現在好像都統稱pause容器,infra容器已經不再使用)。
在pod中,根容器永遠是第一個建立的容器,使用者後面定義的容器會加入進pod的Network Namespace
,從而在檢視上容器都在pod裡。
不妨在k8s中看看這個容器映象:
[root@master ~]# docker images | grep pause
registry.aliyuncs.com/google_containers/pause 3.2 80d28bedfe5d 15 months ago 683kB
#當然,主機上有多少個pod就能docker ps 過濾看到多少pause容器
pause映象大小隻有683k,它是由組合語言寫的映象
在一個pod中的容器,他們的Namespace檔案,是一樣的
也就意味著:
- pod內的容器可以使用localhost進行通訊
- 根容器能看到的網路資源,其他容器都能看到,也就是pod的網路資源和pod內的容器共享
- 一個pod有一個ip地址,和pod對應的Network namespace的ip一致
- pod的生命週期只與根容器有關,與pod內的容器無關
- 從pod裡的容器的視角來說,它們的流量進出可以看做是通過根容器完成的