Pod概念
Pod 是可以在 Kubernetes 中創建和管理的、最小的可部署的計算單元。
Pod是一組(一個或多個)容器;這些容器共享存儲、網絡、以及怎樣運行這些容器的規約。Pod 中的內容總是并置(colocated)的并且一同調度,在共享的上下文中運行。Pod 所建模的是特定于應用的“邏輯主機”,其中包含一個或多個應用容器,這些容器相對緊密地耦合在一起。
核心特性
- 共享上下文:Pod 的共享上下文包括一組 Linux 名字空間、控制組(CGroup)和可能一些其他的隔離方面。在 Pod 的上下文中,各獨立的應用可能會進一步實施隔離。
- 邏輯主機:Pod 類似于共享名字空間并共享文件系統卷的一組容器。
- 容器運行時:為了運行 Pod,你需要提前在每個節點安裝好容器運行時(如 Containerd 或 Docker)。
兩種主要用法
單容器 Pod
最常見的 Kubernetes 使用模式,將 Pod 視為單個容器的包裝器。Kubernetes 直接管理 Pod 而不是容器本身。
多容器 Pod
Pod 可以封裝由緊密耦合且需要共享資源的多個并置容器組成的應用。這些位于同一位置的容器構成一個內聚的服務單元。
將多個并置、同管的容器組織到一個 Pod 是一種相對高級的使用場景。橫向擴展應通過副本機制實現,而非在同一 Pod 中添加多個容器。
Pod 示例
下面是一個 Pod 示例,它由一個運行鏡像 nginx:1.14.2
的容器組成。
# simple-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80
要創建上面顯示的 Pod,運行以下命令:
kubectl apply -f simple-pod.yaml
通過工作負載資源管理 Pod
使用工作負載資源來創建和管理 Pod。Pod 被設計成了相對臨時性的、用后即拋的一次性實體。
直接創建 Pod 的問題
- Pod 是臨時性的,節點故障會導致 Pod 丟失
- 缺乏擴縮容能力
- 沒有自動修復機制
- 無法實現滾動更新
常見的工作負載資源
- Deployment:適用于管理無狀態應用,支持滾動更新和回滾。
- StatefulSet:適用于管理有狀態應用,提供穩定的網絡標識和持久存儲。
- DaemonSet:確保所有(或部分)節點上運行一個 Pod 的副本。
- Job:用于運行一次性任務。
- CronJob:用于運行周期性任務。
這些資源的控制器能夠處理副本的管理、上線,并在 Pod 失效時提供自愈能力。
Deployment示例
**apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentlabels:app: nginx
spec:replicas: 3selector:matchLabels:app: nginxstrategy:type: RollingUpdaterollingUpdate:maxSurge: 25%maxUnavailable: 25%template:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.25.3ports:- containerPort: 80**
Pod 模板
工作負載資源的控制器使用 Pod 模板 來創建和管理 Pod。Pod 模板是包含在工作負載對象中的規范,是目標狀態的一部分。
apiVersion: batch/v1
kind: Job
metadata:name: hello
spec:template:# 這里是 Pod 模板spec:containers:- name: helloimage: busybox:1.28command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']restartPolicy: OnFailure# 以上為 Pod 模板
重要:修改 Pod 模板不會對已經存在的 Pod 直接起作用。控制器會根據新模板創建新的 Pod 來替換舊的 Pod。
Pod 生命周期
Pod 被調度到節點上后會一直保持運行,直到:
- Pod 中的容器執行完畢。
- Pod 對象被刪除。
- Pod 因資源不足而被驅逐。
- 節點失效。
生命周期階段
- Pending(掛起):Pod 已被 Kubernetes 系統接受,但有一個或多個容器尚未創建或運行。
- Running(運行中):Pod 已綁定到一個節點,所有容器都已創建。至少有一個容器仍在運行,或者正處于啟動或重啟過程中。
- Succeeded(成功):Pod 中的所有容器都已成功終止,并且不會再重啟。
- Failed(失敗):Pod 中的所有容器都已終止,并且至少有一個容器是因為失敗終止。
- Unknown(未知):通常是由于無法與 Pod 所在節點的 kubelet 通信所致。
重啟策略
通過 spec.restartPolicy
字段控制
Always
:容器失敗時總是重啟(默認)。OnFailure
:容器以非零狀態退出時重啟。Never
:從不重啟。
Init 容器
Pod 可以包含在應用容器啟動前運行的 Init 容器。Init 容器總是運行到完成為止,并且每個 Init 容器都必須成功啟動,下一個 Init 容器才能運行。如果 Init 容器失敗,Kubernetes 會不斷地重啟 Pod,直到 Init 容器成功為止。
容器探針
-器進程還在運行,并不代表應用是健康的。它可能死鎖、可能正在啟動(但還未就緒)、可能依賴的服務不可用。探針讓 Kubernetes 能夠感知應用內部的真實狀態,并做出相應決策。
探針類型
livenessProbe
:檢測容器是否正在運行。如果失敗,kubelet 會殺死容器,然后根據重啟策略進行處理。readinessProbe
:檢測容器是否已準備好服務請求。如果失敗,端點控制器將從與 Pod 匹配的所有 Service 的端點中移除該 Pod 的 IP 地址。startupProbe
:指示容器內的應用是否已啟動。如果提供了啟動探針,則所有其他探針都會被禁用,直到它成功為止。
探針的三種動作
ExecAction
:在容器內執行指定命令。- 如果命令退出碼為 0,則認為診斷成功。
- 配置 :
livenessProbe: exec: command: - cat - /tmp/healthy
TCPSocketAction
:對指定端口上的容器 IP 地址進行 TCP 檢查。- 如果端口能連通,則認為診斷成功。
- 配置 :
livenessProbe: tcpSocket: port: 8080
HTTPGetAction
:對指定端口和路徑上的容器 IP 地址執行 HTTP Get 請求。- 如果響應的狀態碼在 200 到 399 之間,則認為診斷成功。
- 配置 :
livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: Awesome
Pod 的資源共享和通信
存儲
- 一個 Pod 可以設置一組共享的存儲卷(Volume)。Pod 中的所有容器都可以訪問該共享卷,從而允許這些容器共享數據。卷還允許 Pod 中的持久數據保留下來,即使其中的容器需要重新啟動。
- 容器中的文件系統是臨時的,容器重啟后文件會丟失。
卷
卷是一個目錄,可以被 Pod 中的一個或多個容器訪問。卷的生命周期不屬于容器,它由 Pod 和外部存儲源決定。
類型
- emptyDir
- 生命周期:與 Pod 的生命周期完全一致。Pod 被刪除,數據也隨之刪除。
- 用途:用于 Pod 內容器之間的臨時數據共享(例如,一個容器生產數據,另一個容器消費數據)。節點重啟后數據也會丟失。
- hostPath:
- 生命周期:將節點上的文件系統目錄或文件掛載到 Pod 中。數據持久化在節點上,即使 Pod 被刪除,數據依然存在。
- configMap / secret:
- 生命周期:將 Kubernetes 對象(ConfigMap/Secret)中的數據作為文件或環境變量注入到容器中。
- 持久卷 (persistentVolumeClaim - PVC):
- 生產環境的標準做法。
- 生命周期:獨立于 Pod。Pod 被刪除后,數據依然安全地保存在外部存儲系統中(如云硬盤、NFS、Ceph 等)。
- 工作原理:管理員預先創建持久卷 (PersistentVolume, PV):代表一塊實際的網絡存儲。用戶創建持久卷聲明 (PersistentVolumeClaim, PVC):像一個“申請單”,聲明需要多大的存儲、需要什么訪問模式(如 ReadWriteOnce)。在 Pod 中通過 volumes.persistentVolumeClaim 字段綁定 PVC。
PVC示例
apiVersion: v1
kind: Pod
metadata:name: my-app-with-db
spec:containers:- name: appimage: my-app:latestvolumeMounts:- name: data-storage # 掛載名為 data-storage 的卷mountPath: /var/data # 掛載到容器內的路徑volumes:- name: data-storage # 定義卷的名稱persistentVolumeClaim:claimName: my-pvc # 指定要使用的PVC名稱
網絡
- 每個 Pod 都在每個地址族中獲得一個唯一的 IP 地址。
- Pod 中的每個容器共享網絡名字空間,包括 IP 地址和網絡端口。
- Pod 內的容器可以使用
localhost
互相通信。 - 不同 Pod 中的容器具有不同的 IP 地址,需要通過 Pod IP 進行通信。
網絡實現細節:
-
暫停容器 (Pause Container):
- 當創建一個 Pod 時,Kubernetes 會先創建一個名為
pause
的極小容器。它的唯一作用是持有 Pod 的網絡命名空間 (Network Namespace)。 - Pod 內的其他容器(用戶容器)會通過 Docker 的
--net=container:<id>
參數加入到這個pause
容器的網絡命名空間中,從而實現網絡共享。
- 當創建一個 Pod 時,Kubernetes 會先創建一個名為
-
容器間通信:
- 在同一個 Pod 內,容器可以通過
localhost
和端口號直接通信,就像在同一臺機器上一樣。
- 在同一個 Pod 內,容器可以通過
-
Pod 間通信:
- Pod-to-Pod:通過對方的 Pod IP 直接通信。這是最基礎的通信方式,但 Pod IP 是臨時的,Pod 重啟后會改變。
- Service:為了解決 Pod IP 不固定的問題,Kubernetes 引入了 Service。Service 是一個穩定的抽象層,它有一個固定的 虛擬 IP (VIP) 和 DNS 名稱。Service 通過標簽選擇器 (Selector) 將流量負載均衡到一組后端 Pod 上。
- ClusterIP:默認類型,在集群內部暴露 Service。
- NodePort:通過每個節點的靜態端口暴露 Service。
- LoadBalancer:使用云提供商的負載均衡器對外暴露 Service。
- Ingress:用于管理外部訪問集群內服務的 HTTP/HTTPS 路由規則,提供更高級的功能如基于域名和路徑的路由、SSL 終止等。它本身不是一種 Service,而是位于 Service 之前的入口控制器。
示例:網絡訪問流程
外部用戶 -> (通過 LoadBalancer/NodePort) -> Service (VIP) -> (通過 iptables/IPVS 規則) -> 目標 Pod (在某個節點上)。
K8S官方文檔
參考文章
K8Buard關于Pod存儲官方文檔