1. 程式人生 > 其它 >kubernetes之pod基本概念總結

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. 容器設計模式

考慮這樣一個問題,容器見的關係是一成不變的嗎?

舉一些例子:

  1. 在pod中的一些容器的啟動,必須依賴某一個正在執行的容器,也就是說這個容器必須比其他容器先啟動
  2. 在pod中的容器必須同時協作,也就是說所有容器必須並行執行
  3. 一個pod需要給外部的其他pod提供介面
  4. 外部訪問pod時,又怎樣確保響應報文的一致性
  5. ..........

常見容器設計模式:

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裡的容器的視角來說,它們的流量進出可以看做是通過根容器完成的