文章目錄
- 1、Pod概念
- 2、K8s 中的 Pod 的兩種用法
- 3、定義Pod
- 4、Pod的創建資源
- 5、Pod 模板
- 6、容器探針
- 7、總結干貨
- 8、 K8s Pod 經典面試題速查表
Pod是Kubernetes中最小的單元:
1、Pod概念
Pod 是可以在 Kubernetes中創建和管理的、最小的可部署的計算單元。它由一組、一個或多個容器組成,每個Pod還包含了一個Pause容器,Pause容器是Pod的父容器,主要負責僵尸進程的回收管理,通過Pause容器可以使同一個Pod里面的多個容器共享存儲、網絡、PID、IPC等。
Pod(就像在鯨魚莢或者豌豆莢中)是一組(一個或多個) 容器; 這些容器共享存儲、網絡、以及怎樣運行這些容器的規約。 Pod中的內容總是并置(colocated)的并且一同調度,在共享的上下文中運行。 Pod所建模的是特定于應用的“邏輯主機”,其中包含一個或多個應用容器, 這些容器相對緊密地耦合在一起。在非云環境中,在相同的物理機或虛擬機上運行的應用類似于在同一邏輯主機上運行的云應用。
除了應用容器,Pod 還可以包含在 Pod 啟動期間運行的 Init 容器。 你也可以注入臨時性容器來調試正在運行的 Pod。
Pod 的共享上下文包括一組 Linux 名字空間、控制組(CGroup)和可能一些其他的隔離方面, 即用來隔離容器的技術。 在 Pod 的上下文中,每個獨立的應用可能會進一步實施隔離。
2、K8s 中的 Pod 的兩種用法
Pod 類似于共享名字空間并共享文件系統卷的一組容器。
Kubernetes 集群中的 Pod 主要有兩種用法:
運行單個容器的 Pod。"每個 Pod 一個容器"模型是最常見的 Kubernetes 用例; 在這種情況下,可以將 Pod 看作單個容器的包裝器,并且 Kubernetes 直接管理 Pod,而不是容器。
運行多個協同工作的容器的 Pod。 Pod 可以封裝由緊密耦合且需要共享資源的多個并置容器組成的應用。 這些位于同一位置的容器構成一個內聚單元。
將多個并置、同管的容器組織到一個 Pod 中是一種相對高級的使用場景。 只有在一些場景中,容器之間緊密關聯時你才應該使用這種模式。
3、定義Pod
定義一個Pod:
下面是一個 Pod 示例,它由一個運行鏡像 nginx:1.14.2 的容器組成。
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80
要創建上面顯示的 Pod,請運行以下命令:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
apiVersion: v1 # 必選,API的版本號
kind: Pod # 必選,類型Pod
metadata: # 必選,元數據name: nginx # 必選,符合RFC 1035規范的Pod名稱namespace: default # 可選,Pod所在的命名空間,不指定默認為default,可以使用-n 指定namespace labels: # 可選,標簽選擇器,一般用于過濾和區分Podapp: nginxrole: frontend # 可以寫多個annotations: # 可選,注釋列表,可以寫多個app: nginx
spec: # 必選,用于定義容器的詳細信息initContainers: # 初始化容器,在容器啟動之前執行的一些初始化操作- command:- sh- -c- echo "I am InitContainer for init some configuration"image: busyboximagePullPolicy: IfNotPresentname: init-containercontainers: # 必選,容器列表- name: nginx # 必選,符合RFC 1035規范的容器名稱image: nginx:latest # 必選,容器所用的鏡像的地址imagePullPolicy: Always # 可選,鏡像拉取策略command: # 可選,容器啟動執行的命令- nginx - -g- "daemon off;"workingDir: /usr/share/nginx/html # 可選,容器的工作目錄volumeMounts: # 可選,存儲卷配置,可以配置多個- name: webroot # 存儲卷名稱mountPath: /usr/share/nginx/html # 掛載目錄readOnly: true # 只讀ports: # 可選,容器需要暴露的端口號列表- name: http # 端口名稱containerPort: 80 # 端口號protocol: TCP # 端口協議,默認TCPenv: # 可選,環境變量配置列表- name: TZ # 變量名value: Asia/Shanghai # 變量的值- name: LANGvalue: en_US.utf8resources: # 可選,資源限制和資源請求限制limits: # 最大限制設置cpu: 1000mmemory: 1024Mirequests: # 啟動所需的資源cpu: 100mmemory: 512Mi
# startupProbe: # 可選,檢測容器內進程是否完成啟動。注意三種檢查方式同時只能使用一種。
# httpGet: # httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。
# path: /api/successStart # 檢查路徑
# port: 80readinessProbe: # 可選,健康檢查。注意三種檢查方式同時只能使用一種。httpGet: # httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。path: / # 檢查路徑port: 80 # 監控端口livenessProbe: # 可選,健康檢查#exec: # 執行容器命令檢測方式#command: #- cat#- /health#httpGet: # httpGet檢測方式# path: /_health # 檢查路徑# port: 8080# httpHeaders: # 檢查的請求頭# - name: end-user# value: Jason tcpSocket: # 端口檢測方式port: 80initialDelaySeconds: 60 # 初始化時間timeoutSeconds: 2 # 超時時間periodSeconds: 5 # 檢測間隔successThreshold: 1 # 檢查成功為2次表示就緒failureThreshold: 2 # 檢測失敗1次表示未就緒lifecycle:postStart: # 容器創建完成后執行的指令, 可以是exec httpGet TCPSocketexec:command:- sh- -c- 'mkdir /data/ 'preStop:httpGet: path: /port: 80# exec:# command:# - sh# - -c# - sleep 9restartPolicy: Always # 可選,默認為Always#nodeSelector: # 可選,指定Node節點# region: subnet7imagePullSecrets: # 可選,拉取鏡像使用的secret,可以配置多個- name: default-dockercfg-86258hostNetwork: false # 可選,是否為主機模式,如是,會占用主機端口volumes: # 共享存儲卷列表- name: webroot # 名稱,與上述對應emptyDir: {} # 掛載目錄#hostPath: # 掛載本機目錄# path: /etc/hosts
apiVersion: v1 # 必選,API的版本號
kind: Pod # 必選,類型Pod
metadata: # 必選,元數據name: nginx # 必選,符合RFC 1035規范的Pod名稱# namespace: default # 可選,Pod所在的命名空間,不指定默認為default,可以使用-n 指定namespace labels: # 可選,標簽選擇器,一般用于過濾和區分Podapp: nginxrole: frontend # 可以寫多個annotations: # 可選,注釋列表,可以寫多個app: nginx
spec: # 必選,用于定義容器的詳細信息
# initContainers: # 初始化容器,在容器啟動之前執行的一些初始化操作
# - command:
# - sh
# - -c
# - echo "I am InitContainer for init some configuration"
# image: busybox
# imagePullPolicy: IfNotPresent
# name: init-containercontainers: # 必選,容器列表- name: nginx # 必選,符合RFC 1035規范的容器名稱image: nginx:1.15.2 # 必選,容器所用的鏡像的地址imagePullPolicy: IfNotPresent # 可選,鏡像拉取策略, IfNotPresent: 如果宿主機有這個鏡像,那就不需要拉取了. Always: 總是拉取, Never: 不管是否存儲都不拉去command: # 可選,容器啟動執行的命令 ENTRYPOINT, arg --> cmd- nginx - -g- "daemon off;"workingDir: /usr/share/nginx/html # 可選,容器的工作目錄
# volumeMounts: # 可選,存儲卷配置,可以配置多個
# - name: webroot # 存儲卷名稱
# mountPath: /usr/share/nginx/html # 掛載目錄
# readOnly: true # 只讀ports: # 可選,容器需要暴露的端口號列表- name: http # 端口名稱containerPort: 80 # 端口號protocol: TCP # 端口協議,默認TCPenv: # 可選,環境變量配置列表- name: TZ # 變量名value: Asia/Shanghai # 變量的值- name: LANGvalue: en_US.utf8
# resources: # 可選,資源限制和資源請求限制
# limits: # 最大限制設置
# cpu: 1000m
# memory: 1024Mi
# requests: # 啟動所需的資源
# cpu: 100m
# memory: 512Mi
# startupProbe: # 可選,檢測容器內進程是否完成啟動。注意三種檢查方式同時只能使用一種。
# httpGet: # httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。
# path: /api/successStart # 檢查路徑
# port: 80
# readinessProbe: # 可選,健康檢查。注意三種檢查方式同時只能使用一種。
# httpGet: # httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。
# path: / # 檢查路徑
# port: 80 # 監控端口
# livenessProbe: # 可選,健康檢查#exec: # 執行容器命令檢測方式#command: #- cat#- /health#httpGet: # httpGet檢測方式# path: /_health # 檢查路徑# port: 8080# httpHeaders: # 檢查的請求頭# - name: end-user# value: Jason
# tcpSocket: # 端口檢測方式
# port: 80
# initialDelaySeconds: 60 # 初始化時間
# timeoutSeconds: 2 # 超時時間
# periodSeconds: 5 # 檢測間隔
# successThreshold: 1 # 檢查成功為2次表示就緒
# failureThreshold: 2 # 檢測失敗1次表示未就緒
# lifecycle:
# postStart: # 容器創建完成后執行的指令, 可以是exec httpGet TCPSocket
# exec:
# command:
# - sh
# - -c
# - 'mkdir /data/ '
# preStop:
# httpGet:
# path: /
# port: 80# exec:# command:# - sh# - -c# - sleep 9restartPolicy: Always # 可選,默認為Always,容器故障或者沒有啟動成功,那就自動該容器,Onfailure: 容器以不為0的狀態終止,自動重啟該容器, Never:無論何種狀態,都不會重啟#nodeSelector: # 可選,指定Node節點# region: subnet7
# imagePullSecrets: # 可選,拉取鏡像使用的secret,可以配置多個
# - name: default-dockercfg-86258
# hostNetwork: false # 可選,是否為主機模式,如是,會占用主機端口
# volumes: # 共享存儲卷列表
# - name: webroot # 名稱,與上述對應
# emptyDir: {} # 掛載目錄
# #hostPath: # 掛載本機目錄
# # path: /etc/hosts
4、Pod的創建資源
Pod 通常不是直接創建的,而是使用工作負載資源創建的。
用于管理 Pod 的工作負載資源:
- Deployment
- StatefulSet
- DaemonSet
通常你不需要直接創建 Pod,甚至單實例 Pod。相反,你會使用諸如 Deployment 或 Job 這類工作負載資源來創建 Pod。 如果 Pod 需要跟蹤狀態,可以考慮 StatefulSet 資源。
每個 Pod 都旨在運行給定應用程序的單個實例。如果希望橫向擴展應用程序 (例如,運行多個實例以提供更多的資源),則應該使用多個 Pod,每個實例使用一個 Pod。 在 Kubernetes 中,這通常被稱為副本(Replication)。 通常使用一種工作負載資源及其控制器來創建和管理一組 Pod 副本。
Pod 天生地為其成員容器提供了兩種共享資源:網絡和存儲。
說明:
重啟 Pod 中的容器不應與重啟 Pod 混淆。 Pod 不是進程,而是容器運行的環境。 在被刪除之前,Pod 會一直存在。
5、Pod 模板
工作負載資源的控制器通常使用 Pod 模板(Pod Template) 來替你創建 Pod 并管理它們。
Pod 模板是包含在工作負載對象中的規范,用來創建 Pod。這類負載資源包括 Deployment、 Job 和 DaemonSet 等。
工作負載的控制器會使用負載對象中的 PodTemplate 來生成實際的 Pod。 PodTemplate 是你用來運行應用時指定的負載資源的目標狀態的一部分。
創建 Pod 時,你可以在 Pod 模板中包含 Pod 中運行的容器的環境變量。
6、容器探針
probe 是由 kubelet 對容器執行的定期診斷。 要執行診斷,kubelet 既可以在容器內執行代碼,也可以發出一個網絡請求。
檢查機制
使用探針來檢查容器有四種不同的方法。 每個探針都必須準確定義為這四種機制中的一種:
- exec
在容器內執行指定命令。如果命令退出時返回碼為 0 則認為診斷成功。 - grpc
使用 gRPC 執行一個遠程過程調用。 目標應該實現 gRPC 健康檢查。 如果響應的狀態是 “SERVING”,則認為診斷成功。 - httpGet
對容器的 IP 地址上指定端口和路徑執行 HTTP GET 請求。如果響應的狀態碼大于等于 200 且小于 400,則診斷被認為是成功的。 - tcpSocket
對容器的 IP 地址上的指定端口執行 TCP 檢查。如果端口打開,則診斷被認為是成功的。 如果遠程系統(容器)在打開連接后立即將其關閉,這算作是健康的。
注意:
和其他機制不同,exec 探針的實現涉及每次執行時創建/復制多個進程。 因此,在集群中具有較高 pod 密度、較低的 initialDelaySeconds 和 periodSeconds 時長的時候, 配置任何使用 exec 機制的探針可能會增加節點的 CPU 負載。 這種場景下,請考慮使用其他探針機制以避免額外的開銷。
探測結果
每次探測都將獲得以下三種結果之一:
- Success(成功)
容器通過了診斷。 - Failure(失敗)
容器未通過診斷。 - Unknown(未知)
診斷失敗,因此不會采取任何行動。
探測類型
針對運行中的容器,kubelet 可以選擇是否執行以下三種探針,以及如何針對探測結果作出反應:
- livenessProbe
指示容器是否正在運行。如果存活態探測失敗,則 kubelet 會殺死容器, 并且容器將根據其重啟策略決定未來。如果容器不提供存活探針, 則默認狀態為 Success。 - readinessProbe
指示容器是否準備好為請求提供服務。如果就緒態探測失敗, EndpointSlice 控制器將從與該 Pod 匹配的所有 Service 的 EndpointSlice 中刪除該 Pod 的 IP 地址。 初始延遲之前的就緒態的狀態值默認為 Failure。 如果容器不提供就緒態探針,則默認狀態為 Success。 - startupProbe
指示容器中的應用是否已經啟動。如果提供了啟動探針,則所有其他探針都會被 禁用,直到此探針成功為止。如果啟動探測失敗,kubelet 將殺死容器, 而容器依其重啟策略進行重啟。 如果容器沒有提供啟動探測,則默認狀態為 Success。
如欲了解如何設置存活態、就緒態和啟動探針的進一步細節, 可以參閱配置存活態、就緒態和啟動探針。
何時該使用存活態探針?
如果容器中的進程能夠在遇到問題或不健康的情況下自行崩潰,則不一定需要存活態探針; kubelet 將根據 Pod 的 restartPolicy 自動執行修復操作。
如果你希望容器在探測失敗時被殺死并重新啟動,那么請指定一個存活態探針, 并指定 restartPolicy 為 “Always” 或 “OnFailure”。
何時該使用就緒態探針?
如果要僅在探測成功時才開始向 Pod 發送請求流量,請指定就緒態探針。 在這種情況下,就緒態探針可能與存活態探針相同,但是規約中的就緒態探針的存在意味著 Pod 將在啟動階段不接收任何數據,并且只有在探針探測成功后才開始接收數據。
如果你希望容器能夠自行進入維護狀態,也可以指定一個就緒態探針, 檢查某個特定于就緒態的因此不同于存活態探測的端點。
如果你的應用程序對后端服務有嚴格的依賴性,你可以同時實現存活態和就緒態探針。 當應用程序本身是健康的,存活態探針檢測通過后,就緒態探針會額外檢查每個所需的后端服務是否可用。 這可以幫助你避免將流量導向只能返回錯誤信息的 Pod。
如果你的容器需要在啟動期間加載大型數據、配置文件或執行遷移, 你可以使用啟動探針。 然而,如果你想區分已經失敗的應用和仍在處理其啟動數據的應用,你可能更傾向于使用就緒探針。
說明:
請注意,如果你只是想在 Pod 被刪除時能夠排空請求,則不一定需要使用就緒態探針; 當 Pod 被刪除時,EndpointSlice 中對應的端點會更新其狀況: 該端點的 ready 狀況將被設置為 false,因此負載均衡器不會再將該 Pod 用于常規流量。 關于 kubelet 如何處理 Pod 刪除的更多信息,請參見 Pod 終止。
何時該使用啟動探針?
對于所包含的容器需要較長時間才能啟動就緒的 Pod 而言,啟動探針是有用的。 你不再需要配置一個較長的存活態探測時間間隔,只需要設置另一個獨立的配置選定, 對啟動期間的容器執行探測,從而允許使用遠遠超出存活態時間間隔所允許的時長。
如果你的容器啟動時間通常超出
initialDelaySeconds+failureThreshold×periodSeconds 總值,你應該設置一個啟動探測,對存活態探針所使用的同一端點執行檢查。 periodSeconds 的默認值是 10 秒。你應該將其 failureThreshold 設置得足夠高, 以便容器有充足的時間完成啟動,并且避免更改存活態探針所使用的默認值。 這一設置有助于減少死鎖狀況的發生。
7、總結干貨
Pod 是 Kubernetes 的最小執行單元,是“一組共享網絡和存儲的容器”,通常通過控制器來管理
序號 | 內容 |
---|---|
1 | Pod 內部可以包含一個或多個容器(常見情況是 1 個容器)。 |
1 | Pod 里的容器 共享網絡和存儲卷。 |
2 | 同一網絡命名空間:Pod 內的容器共享 IP、Port。 |
3 | 共享存儲卷:多個容器能訪問相同的持久存儲。 |
4 | 緊密耦合:Pod 內容器一般完成一個整體任務。 |
5 | 單容器 Pod:最常見,一個容器一個 Pod。 |
6 | 調度器:將 Pod 分配到合適的節點。 |
7 | 控制器:保證 Pod 的副本數和狀態(如 Deployment、DaemonSet)。 |
8 | 親和/反親和:Pod 可以指定與節點或其他 Pod 的調度關系。 |
9 | Pod 的 IP 不穩定(Pod 刪除重建后會變) |
Pod 的狀態描述
狀態 | 描述 |
---|---|
Pending: | Pod 已提交,等待調度。 |
Running: | Pod 已調度到節點上,至少一個容器運行中。 |
Succeeded: | 所有容器成功退出(狀態碼 0)。 |
Failed: | 至少一個容器異常退出。 |
CrashLoopBackOff: | 容器不斷重啟,說明有錯誤。 |
Pod 相關命令速查
# 查看 Pod
kubectl get pods -o wide# 查看 Pod 詳細信息
kubectl describe pod <pod-name># 查看 Pod 日志
kubectl logs -f <pod-name> [-c 容器名]# 進入 Pod 容器
kubectl exec -it <pod-name> -c <容器名> -- /bin/bash
8、 K8s Pod 經典面試題速查表
1?? 基礎概念類
Q1: 為什么 Kubernetes 引入 Pod,而不是直接用容器?
👉 因為有些場景需要多個容器緊密協作(例如主應用 + 日志收集 + 代理),Pod 提供:
共享網絡命名空間(一個 IP,多個容器);
共享存儲卷;
作為 調度和伸縮的最小單位。
Q2: Pod 和容器的區別是什么?
👉 容器是應用的運行實例;
Pod 是 Kubernetes 調度的基本單位,可以包含一個或多個容器;
Pod 提供共享網絡和存儲,是容器的邏輯集合。
Q3: Pod 的類型有哪些?
👉單容器 Pod(最常見);
多容器 Pod(Sidecar、Ambassador、Adapter 模式);
靜態 Pod(由 kubelet 直接管理,不受 API Server 控制)。
2?? 生命周期與狀態類
Q4: Pod 有哪些狀態?
👉 Pending → Running → Succeeded/Failed → CrashLoopBackOff(異常重啟)。
Q5: 什么是 Init 容器,有什么作用?
👉 Init 容器在主容器啟動前運行,用于:
執行初始化任務(配置下載、檢查依賴服務);
保證主容器在準備好環境后再啟動。
Q6: Pod CrashLoopBackOff 怎么排查?
👉 常見原因:
應用啟動失敗(配置錯誤、缺少依賴)。
存儲掛載失敗。
探針檢查失敗(liveness/readiness probe)。 👉 排查命令:
kubectl describe pod <pod-name>
kubectl logs <pod-name> -c <container>
3?? 調度與控制類
Q7: Pod 如何被調度到節點?
👉 調度器會根據:
資源請求/限制(CPU、內存);
節點選擇器(nodeSelector, nodeAffinity);
Pod 親和性/反親和性;
Taints & Tolerations(污點與容忍)。
Q8: Pod 與 Deployment/ReplicaSet 的關系?
👉Pod:最小運行單位;
ReplicaSet:保證 Pod 的副本數;
Deployment:聲明式管理 ReplicaSet,支持滾動更新、回滾。
4?? 網絡與存儲類
Q9: Pod 如何通信?
👉同一 Pod 內:容器共享 localhost;
同一 Node 內不同 Pod:通過 Pod IP 通信;
跨 Node Pod:依賴 CNI 插件(Flannel, Calico, Cilium);
外部訪問 Pod:通過 Service(ClusterIP、NodePort、LoadBalancer)。
Q🔟: Pod 為什么需要 Service?
👉 Pod 的 IP 不是固定的,重啟后會變化。 Service 提供一個 穩定的虛擬 IP(ClusterIP),解決 Pod
動態變化帶來的訪問問題。
5?? 高級與實戰類
Q11: Pod 重啟策略有哪些?
👉 在 Pod Spec 中 restartPolicy:
Always(默認,適用于長期運行的服務);
OnFailure(任務型,失敗才重啟);
Never(一次性任務)。
Q12: 怎么排查 Pod 處于 Pending 狀態?
👉 常見原因:
沒有可用的 Node(資源不足);
PVC 未綁定(存儲不足);
Node 上的 Taint 無法被容忍。
👉 排查命令:
kubectl describe pod <pod-name>
kubectl get events --sort-by=.metadata.creationTimestamp
Q13: 靜態 Pod 和普通 Pod 的區別?
👉靜態 Pod:由 kubelet 直接管理,通常用于運行核心組件(kube-apiserver 等),存放在
/etc/kubernetes/manifests。普通 Pod:由 API Server 管理,通過 etcd 存儲。
“人的一生會經歷很多痛苦,但回頭想想,都是傳奇”。