理解Kubernetes Pod:容器設計的基本單元

?
1. pod基本概念
Kubernetes 中,Pod 是最小的網絡調度單位, 每個pod可以放多個容器(例如可以放多個docke容器在同一個pod中運行),這些容器共享pod的網絡、存儲、以及容器規(guī)約。每個 Pod 被分配一個唯一的 IP 地址(Pod IP),這個 IP 在集群內是可達的。
在介紹其他概念之前,首先先介紹一下相關的網絡概念,因為這是容易比較迷糊的地方。在k8s中,node有一個ip,pod也有一個ip,然后一個pod中又有很多pod,對應了很多ip,這容易讓人造成誤解。
- node的ip:node的是node對應的物理機(虛擬機,云主機)上的真實ip,比如說,你的一臺物理機在公網上,那么這個node的ip便是一個公網的ip地址,我可以在任何地方拿著這個ip連接到這個node上。
- pod的ip:pod的ip實際上就是一個內網ip,由k8s的網絡插件在pod啟動的時候進行動態(tài)分配。
Pod 運行在 Node 上,其網絡流量進出需經過宿主機(Node),當外部訪問 Pod 時,流量先到達 Node,再由相關組件轉發(fā)到對應的pod
在一個正常工作的 Kubernetes 集群中,Node 節(jié)點之間的網絡必須是互通的 —— 不僅 Node 之間要通,更重要的是,運行在不同 Node 上的 Pod 之間也必須能直接通信(三層路由可達)。
graph TD %% 定義節(jié)點和 Pod subgraph NodeA["NodeA (192.168.1.10)"] direction TB PodA["PodA IP: 10.244.1.5 Port: 8080"] PodX["Podx IP: 10.244.1.x Port: xx"] end subgraph NodeB["NodeB (192.168.1.11)"] direction TB PodB["PodB IP: 10.244.2.8 Listens: 8080"] end %% 定義 Service Service["Service: podB-service ClusterIP: 10.96.xx.xx Port: 80 → targetPort: 8080"] %% 正確通信路徑 —— PodA → PodB PodA -->|?直接訪問 Pod IP<br>curl http://10.244.2.8:8080</br>| PodB %% 推薦路徑 —— PodA → Service → PodB PodA -->|?推薦:通過 Service<br>curl http://podB-service:80</br>| Service Service -->|自動負載均衡| PodB %% 錯誤路徑(虛線 + 紅色風格) PodA -.->|?通常無效<br>curl http://192.168.1.11:8080</br>| NodeB PodA -->|?顯式設置<br>curl http://192.168.1.11:8080</br>| NodeB %% 添加說明注釋 classDef node fill:#e0f7fa,stroke:#0097a7; classDef pod fill:#fff9c4,stroke:#fbc02d; classDef svc fill:#c8e6c9,stroke:#388e3c; classDef invalid stroke:#f44336,stroke-dasharray: 5 5; class NodeA,NodeB node class PodA,PodB pod class Service svc class NodeB invalid
2. pod網絡概念
在同一個 Pod 中的所有容器共享同一個網絡命名空間(network namespace),因此它們擁有相同的 IP 地址(即 Pod IP),并共享同一個端口空間。容器之間可以通過 localhost 互相訪問,但必須避免端口沖突。
當你在一個 Pod 中定義多個容器,Kubernetes 會將這些容器放在同一個 Linux 網絡命名空間中。
這意味著:
- 所有容器看到的是同一個網絡接口(如 eth0)
- 所有容器共享同一個 IP 地址 —— 即 Pod IP
- 所有容器共享同一個端口命名空間 —— 不能有兩個容器監(jiān)聽同一個端口
Pod IP 是集群內可路由的。外部(其他 Pod、Service、Node)訪問該 Pod 時,訪問的是 Pod IP + 某個端口,而這個端口由 Pod 內某個容器監(jiān)聽。

?
3. pod的生命周期和狀態(tài)
pod的生命周期可以分為如下4種,pod的生命周期是單向的,不會回到之前的狀態(tài)。
- Pending
- Running
- Succeeded or Failed
- Unknown
而pod又可以分為如下5種狀態(tài):
| 取值 | 描述 |
|---|---|
?Pending |
Pod 已被 Kubernetes 系統(tǒng)接受,但有一個或者多個容器尚未創(chuàng)建亦未運行。此階段包括等待 Pod 被調度的時間和通過網絡下載鏡像的時間。 |
?Running |
Pod 已經綁定到了某個節(jié)點,Pod 中所有的容器都已被創(chuàng)建。至少有一個容器仍在運行,或者正處于啟動或重啟狀態(tài)。注意Runing狀態(tài)≠pod健康 |
?Succeeded |
Pod 中的所有容器都已成功結束,并且不會再重啟。 |
?Failed |
Pod 中的所有容器都已終止,并且至少有一個容器是因為失敗終止。也就是說,容器以非 0 狀態(tài)退出或者被系統(tǒng)終止,且未被設置為自動重啟。 |
?Unknown |
因為某些原因無法取得 Pod 的狀態(tài)。這種情況通常是因為與 Pod 所在主機通信失敗。 |
那么如何知道pod究竟可不可用呢,那就得看pod的就緒狀態(tài),pod.status.conditions[? type=="Ready"],如果type=Ready就代表pod可用,能接受流量,否則就代表不可用。
4. 探針
前文我們提到了pod分為不同的生命周期,以及對應的pod相關狀態(tài),那么問題來了,我怎么知道pod就行有沒有運行成功呢,有沒有ready呢,這就得靠我們的探針大哥幫忙。
探針的目的就是為了檢測容器相關的狀態(tài),一共有如下四種探針檢查機制:
- exec:執(zhí)行命令,檢查容器是否ok
- grpc:使用grpc檢查容器是否正常
- httpGet:http請求檢查容器是否正常
- tcpSocket:檢查容器tcp端口是否打開,打開則正常
針對于探針的檢查結果,無非就三種結果:成功、失敗、未知(也就是探測失敗,不采取任何行動)。當然,如果你不設置探針,那結果肯定就都是默認成功。
有了探針的檢查結果,那么應該做什么呢?k8s有如下3種探針類型:
- ?
livenessProbe檢查容器是否“活著”(進程是否卡死/假死),失敗則根據(jù)重啟策略重啟容器。 - ?
readinessProbe檢查容器是否“準備好服務”。如果失敗,則容器容器就不能對外提供服務(其實就是自動將該 Pod 從對應的 Endpoints 對象中移除,從而不再將流量路由到這個 Pod,容器的狀態(tài)為NotReady,對應的pod的狀態(tài)Ready=False)。 - ?
startupProbe指示容器中的應用是否已經啟動。如果提供了該類型探針,在成功前,會屏蔽其他類型的探針。當然,如果失敗了,則會根據(jù)對應的策略進行重啟。
Pod 從創(chuàng)建到“真正可用”,必須等待所有容器的 readinessProbe 成功 —— 這是探針對 Pod “可用性”的核心控制點。
以下是千問老師總結的使用要點:
?♂? Readiness = 能不能干活 → 不行就“靠邊站”,別重啟!
Liveness = 還有沒有氣 → 不行就“抬走重來”,必須重啟!
Startup = 剛出生要呵護 → 啟動期特殊保護,長大再考核!
?
5. 創(chuàng)建pod
前面介紹了這么多,現(xiàn)在讓我們使用命令來創(chuàng)建一個pod吧,大家可以在這個Killercoda Interactive Environments進行在線創(chuàng)建。
kubectl run nginxtest --image=nginx:latest --port=80
這樣,我們便創(chuàng)建了一個nginx的pod:

6. 總結
Pod 是 Kubernetes 中最小的可部署、可調度的計算單元,一個 Pod 可以包含一個或多個緊密耦合的容器(共享網絡、存儲、生命周期)。pod的生命周期是不可逆的,而探針能夠不斷去對pod的狀態(tài)進行檢測,從而保證服務的可用性。我們有通過相關命令創(chuàng)建了一個pod,但是大家可以想一想,這個pod如果掛了,還能夠重啟嗎?如果不能重啟,那怎么去解決這個問題呢?讓我們在下一章再進行介紹。
?
作者: 渣渣輝啊
出處:http://www.rzrgm.cn/xiaohuiduan/p/19127125/pod-concept-zmlros

浙公網安備 33010602011771號