Pod
Pod 是可以在 Kubernetes 中建立和管理的最小可部署計算單元。
Pod(就像鯨魚群或豆莢一樣)是一組一個或多個容器,它們共享儲存和網路資源,並有一個執行容器的規範。Pod 的內容總是共同定位和共同排程,並在共享上下文中執行。Pod 建模了一個特定於應用的“邏輯主機”:它包含一個或多個相對緊密耦合的應用容器。在非雲環境中,在同一物理機或虛擬機器上執行的應用程式類似於在同一邏輯主機上執行的雲應用程式。
除了應用容器,Pod 還可以包含在 Pod 啟動期間執行的初始化容器。你還可以注入臨時容器來除錯正在執行的 Pod。
什麼是 Pod?
注意
你需要在叢集中的每個節點上安裝一個容器執行時,以便 Pod 可以在那裡執行。Pod 的共享上下文是一組 Linux 名稱空間、cgroups 以及可能還有其他隔離方面——與隔離容器的機制相同。在 Pod 的上下文中,各個應用程式可能會應用進一步的子隔離。
Pod 類似於一組共享名稱空間和共享檔案系統卷的容器。
Kubernetes 叢集中的 Pod 主要有兩種用途:
執行單個容器的 Pod。“每個 Pod 一個容器”模型是最常見的 Kubernetes 用例;在這種情況下,你可以將 Pod 視為單個容器的包裝器;Kubernetes 管理 Pod,而不是直接管理容器。
執行多個需要協同工作的容器的 Pod。Pod 可以封裝由多個共置容器組成的應用程式,這些容器緊密耦合並需要共享資源。這些共置容器構成一個單一的、內聚的單元。
在單個 Pod 中對多個共置和共同管理的容器進行分組是一種相對高階的用例。你只應在容器緊密耦合的特定情況下使用此模式。
你不需要執行多個容器來提供複製(為了彈性或容量);如果你需要多個副本,請參閱工作負載管理。
使用 Pod
以下是一個 Pod 示例,它由一個執行 nginx:1.14.2
映象的容器組成。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
要建立上面顯示的 Pod,請執行以下命令:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
Pod 通常不直接建立,而是使用工作負載資源建立。有關 Pod 如何與工作負載資源一起使用的更多資訊,請參閱使用 Pod。
用於管理 Pod 的工作負載資源
通常你不需要直接建立 Pod,即使是單例 Pod 也不需要。相反,請使用Deployment或Job等工作負載資源來建立它們。如果你的 Pod 需要跟蹤狀態,請考慮使用StatefulSet資源。
每個 Pod 都旨在執行給定應用程式的單個例項。如果你想水平擴充套件你的應用程式(透過執行更多例項來提供更多整體資源),你應該使用多個 Pod,每個例項一個。在 Kubernetes 中,這通常被稱為複製。複製的 Pod 通常由工作負載資源及其控制器作為一組建立和管理。
有關 Kubernetes 如何使用工作負載資源及其控制器來實現應用程式擴縮和自動修復的更多資訊,請參閱Pod 和控制器。
使用 Pod
你很少直接在 Kubernetes 中建立單個 Pod,即使是單例 Pod 也很少。這是因為 Pod 被設計為相對短暫、可丟棄的實體。當一個 Pod 被建立時(由你直接或由控制器間接),新的 Pod 被排程到叢集中的一個節點上執行。Pod 會一直保留在該節點上,直到 Pod 執行完成、Pod 物件被刪除、Pod 因資源不足而被驅逐,或者節點發生故障。
注意
重新啟動 Pod 中的容器不應與重新啟動 Pod 混淆。Pod 不是一個程序,而是執行容器的環境。Pod 會一直存在,直到被刪除。Pod 的名稱必須是有效的DNS 子域名值,但這可能會導致 Pod 主機名出現意想不到的結果。為了獲得最佳相容性,名稱應遵循更嚴格的DNS 標籤規則。
Pod 作業系統
Kubernetes v1.25 [穩定]
你應該將 .spec.os.name
欄位設定為 windows
或 linux
,以指示你希望 Pod 執行的作業系統。這兩個是 Kubernetes 目前支援的唯一作業系統。將來,此列表可能會擴充套件。
在 Kubernetes v1.34 中,.spec.os.name
的值不會影響 kube-scheduler 如何為 Pod 選擇一個節點來執行。在任何有多個作業系統執行節點的叢集中,你應該在每個節點上正確設定 kubernetes.io/os 標籤,並使用基於作業系統標籤的 nodeSelector
定義 Pod。kube-scheduler 根據其他標準將你的 Pod 分配給一個節點,並且可能成功也可能不成功地選擇一個合適的節點位置,其中節點作業系統適合該 Pod 中的容器。Pod 安全標準也使用此欄位來避免強制執行與作業系統無關的策略。
Pod 和控制器
你可以使用工作負載資源為你建立和管理多個 Pod。資源的控制器負責在 Pod 故障時進行復制、部署和自動修復。例如,如果一個節點發生故障,控制器會注意到該節點上的 Pod 已停止工作,並建立替代 Pod。排程器會將替代 Pod 放置到健康的節點上。
以下是一些管理一個或多個 Pod 的工作負載資源的示例:
Pod 模板
工作負載資源的控制器從Pod 模板建立 Pod,並代表你管理這些 Pod。
PodTemplate 是建立 Pod 的規範,幷包含在諸如 Deployment、Job 和 DaemonSet 等工作負載資源中。
每個工作負載資源的控制器都使用工作負載物件中的 PodTemplate
來建立實際的 Pod。PodTemplate
是你用於執行應用程式的任何工作負載資源的期望狀態的一部分。
建立 Pod 時,你可以在 Pod 模板中包含環境變數,用於在 Pod 中執行的容器。
下面的示例是一個簡單 Job 的清單,其中包含一個啟動一個容器的 template
。該 Pod 中的容器列印一條訊息,然後暫停。
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# This is the pod template
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# The pod template ends here
修改 Pod 模板或切換到新 Pod 模板對已存在的 Pod 沒有直接影響。如果你更改了工作負載資源的 Pod 模板,該資源需要建立使用更新模板的替換 Pod。
例如,StatefulSet 控制器確保執行中的 Pod 與每個 StatefulSet 物件的當前 Pod 模板匹配。如果你編輯 StatefulSet 以更改其 Pod 模板,StatefulSet 將開始基於更新的模板建立新的 Pod。最終,所有舊 Pod 都將被新 Pod 替換,並且更新完成。
每個工作負載資源都實現了自己的 Pod 模板更改處理規則。如果你想了解更多關於 StatefulSet 的資訊,請閱讀 StatefulSet 基礎教程中的更新策略。
在節點上,kubelet 不直接觀察或管理 Pod 模板和更新的任何細節;這些細節都被抽象掉了。這種抽象和關注點分離簡化了系統語義,並使得在不更改現有程式碼的情況下擴充套件叢集行為成為可能。
Pod 更新和替換
如上一節所述,當工作負載資源的 Pod 模板更改時,控制器會根據更新後的模板建立新的 Pod,而不是更新或修補現有 Pod。
Kubernetes 不會阻止你直接管理 Pod。可以直接更新正在執行的 Pod 的某些欄位。但是,Pod 更新操作(如 patch
和 replace
)有一些限制:
Pod 的大部分元資料是不可變的。例如,你不能更改
namespace
、name
、uid
或creationTimestamp
欄位。如果設定了
metadata.deletionTimestamp
,則不能向metadata.finalizers
列表新增新條目。Pod 更新不能更改
spec.containers[*].image
、spec.initContainers[*].image
、spec.activeDeadlineSeconds
、spec.terminationGracePeriodSeconds
、spec.tolerations
或spec.schedulingGates
以外的欄位。對於spec.tolerations
,你只能新增新條目。更新
spec.activeDeadlineSeconds
欄位時,允許兩種型別的更新:- 將未分配的欄位設定為正數;
- 將欄位從正數更新為更小的非負數。
Pod 子資源
上述更新規則適用於常規 Pod 更新,但其他 Pod 欄位可以透過子資源進行更新。
- Resize:
resize
子資源允許更新容器資源(spec.containers[*].resources
)。有關更多詳細資訊,請參閱調整容器資源大小。 - Ephemeral Containers:
ephemeralContainers
子資源允許將臨時容器新增到 Pod 中。有關更多詳細資訊,請參閱臨時容器。 - Status:
status
子資源允許更新 Pod 狀態。這通常僅由 Kubelet 和其他系統控制器使用。 - Binding:
binding
子資源允許透過Binding
請求設定 Pod 的spec.nodeName
。這通常僅由排程器使用。
Pod Generation
metadata.generation
欄位是唯一的。系統將自動設定它,使得新 Pod 的metadata.generation
為 1,並且 Pod 規範中可變欄位的每次更新都會將metadata.generation
增加 1。
Kubernetes v1.34 [beta]
(預設啟用:true)observedGeneration
是一個在 Pod 物件的status
部分中捕獲的欄位。如果啟用了特性門PodObservedGenerationTracking
,Kubelet 會設定status.observedGeneration
來跟蹤 Pod 狀態到當前 Pod 狀態。Pod 的status.observedGeneration
將反映報告 Pod 狀態時 Pod 的metadata.generation
。
注意
status.observedGeneration
欄位由 kubelet 管理,外部控制器不應修改此欄位。不同的狀態欄位可能與當前同步迴圈的 metadata.generation
相關聯,或者與上一個同步迴圈的 metadata.generation
相關聯。關鍵區別在於 spec
中的更改是直接反映在 status
中,還是正在執行程序的間接結果。
直接狀態更新
對於直接反映分配規範的狀態欄位,observedGeneration
將與當前 metadata.generation
(N 代)相關聯。
此行為適用於:
- Resize Status:資源調整大小操作的狀態。
- Allocated Resources:調整大小後分配給 Pod 的資源。
- Ephemeral Containers:當新增新的臨時容器並且它處於
Waiting
狀態時。
間接狀態更新
對於作為執行規範的間接結果的狀態欄位,observedGeneration
將與上一個同步迴圈的 metadata.generation
(N-1 代)相關聯。
此行為適用於:
- 容器映象:
ContainerStatus.ImageID
反映前一代的映象,直到拉取新映象並更新容器。 - 實際資源:在進行中的調整大小期間,實際使用的資源仍然屬於前一代的請求。
- 容器狀態:在進行中的調整大小期間,需要重啟策略反映前一代的請求。
- activeDeadlineSeconds & terminationGracePeriodSeconds & deletionTimestamp:這些欄位對 Pod 狀態的影響是先前觀察到的規範的結果。
資源共享和通訊
Pod 允許其組成容器之間共享資料和通訊。
Pod 中的儲存
Pod 可以指定一組共享儲存卷。Pod 中的所有容器都可以訪問共享卷,從而允許這些容器共享資料。卷還允許 Pod 中的持久資料在一個容器需要重新啟動時仍然存在。有關 Kubernetes 如何實現共享儲存並使其可用於 Pod 的更多資訊,請參閱儲存。
Pod 網路
每個 Pod 為每個地址族分配一個唯一的 IP 地址。Pod 中的每個容器共享網路名稱空間,包括 IP 地址和網路埠。在 Pod 內部(僅在此情況下),屬於 Pod 的容器可以使用 localhost
相互通訊。當 Pod 中的容器與Pod 外部實體通訊時,它們必須協調如何使用共享網路資源(例如埠)。在 Pod 內部,容器共享一個 IP 地址和埠空間,並且可以透過 localhost
相互查詢。Pod 中的容器還可以使用標準程序間通訊(如 SystemV 訊號量或 POSIX 共享記憶體)相互通訊。不同 Pod 中的容器具有不同的 IP 地址,並且在沒有特殊配置的情況下無法透過 OS 級別 IPC 進行通訊。希望與在不同 Pod 中執行的容器互動的容器可以使用 IP 網路進行通訊。
Pod 內的容器將系統主機名視為與 Pod 的配置 name
相同。有關此內容的更多資訊,請參閱網路部分。
Pod 安全設定
要在 Pod 和容器上設定安全限制,可以使用 Pod 規範中的 securityContext
欄位。該欄位讓你能夠精細控制 Pod 或單個容器可以執行的操作。例如:
- 丟棄特定的 Linux 能力以避免 CVE 的影響。
- 強制 Pod 中的所有程序以非 root 使用者或特定的使用者或組 ID 執行。
- 設定特定的 seccomp 配置檔案。
- 設定 Windows 安全選項,例如容器是否作為 HostProcess 執行。
注意
你還可以使用 Pod 的 securityContext 為 Linux 容器啟用特權模式。特權模式會覆蓋 securityContext 中的許多其他安全設定。除非你無法透過 securityContext 中的其他欄位授予等效許可權,否則請避免使用此設定。在 Kubernetes 1.26 及更高版本中,你可以透過在 Pod 規範的 security context 上設定windowsOptions.hostProcess
標誌,以類似特權模式執行 Windows 容器。有關詳細資訊和說明,請參閱建立 Windows HostProcess Pod。- 要了解可以使用的核心級安全限制,請參閱Pod 和容器的 Linux 核心安全限制。
- 要了解有關 Pod 安全上下文的更多資訊,請參閱配置 Pod 或容器的安全上下文。
靜態 Pod
靜態 Pod 由特定節點上的 kubelet 守護程序直接管理,而API 伺服器不觀察它們。雖然大多數 Pod 由控制平面管理(例如,Deployment),但對於靜態 Pod,kubelet 直接監督每個靜態 Pod(並在其失敗時重新啟動)。
靜態 Pod 始終繫結到特定節點上的一個 Kubelet。靜態 Pod 的主要用途是執行自託管的控制平面:換句話說,使用 kubelet 監督各個控制平面元件。
Kubelet 會自動嘗試為每個靜態 Pod 在 Kubernetes API 伺服器上建立一個映象 Pod。這意味著在節點上執行的 Pod 在 API 伺服器上可見,但無法從那裡控制。有關更多資訊,請參閱指南建立靜態 Pod。
多容器 Pod
Pod 旨在支援多個協作程序(作為容器),它們構成一個有凝聚力的服務單元。Pod 中的容器會自動共置並共同排程到叢集中的同一物理或虛擬機器上。容器可以共享資源和依賴項,相互通訊,並協調何時以及如何終止。
Kubernetes 叢集中的 Pod 主要有兩種用途:
- 執行單個容器的 Pod。“每個 Pod 一個容器”模型是最常見的 Kubernetes 用例;在這種情況下,你可以將 Pod 視為單個容器的包裝器;Kubernetes 管理 Pod,而不是直接管理容器。
- 執行多個需要協同工作的容器的 Pod。Pod 可以封裝由多個共置容器組成的應用程式,這些容器緊密耦合並需要共享資源。這些共置容器構成一個單一、有凝聚力的服務單元——例如,一個容器將共享卷中儲存的資料提供給公眾,而一個單獨的Sidecar 容器重新整理或更新這些檔案。Pod 將這些容器、儲存資源和臨時的網路身份封裝在一起,作為一個單一單元。
例如,你可能有一個容器作為共享卷中檔案的 Web 伺服器,以及一個單獨的Sidecar 容器,它從遠端源更新這些檔案,如下圖所示:
有些 Pod 既有初始化容器,也有應用容器。預設情況下,初始化容器在應用容器啟動之前執行並完成。
你還可以擁有Sidecar 容器,它們為主應用程式 Pod 提供輔助服務(例如:服務網格)。
Kubernetes v1.33 [stable]
(預設啟用:true)預設啟用的 SidecarContainers
功能門控允許你為初始化容器指定 restartPolicy: Always
。將 Always
重啟策略設定為確保你設定它的容器被視為在 Pod 的整個生命週期內保持執行的Sidecar。你明確定義為 Sidecar 容器的容器在主應用程式 Pod 啟動之前啟動,並保持執行直到 Pod 關閉。
容器探針
探針是 kubelet 定期對容器執行的診斷。為了執行診斷,kubelet 可以呼叫不同的操作:
ExecAction
(在容器執行時幫助下執行)TCPSocketAction
(由 kubelet 直接檢查)HTTPGetAction
(由 kubelet 直接檢查)
你可以在 Pod 生命週期文件中閱讀有關探針的更多資訊。
下一步
- 瞭解 Pod 的生命週期。
- 瞭解 RuntimeClass 以及如何使用它配置具有不同容器執行時配置的不同 Pod。
- 瞭解 PodDisruptionBudget 以及如何使用它來管理中斷期間的應用程式可用性。
- Pod 是 Kubernetes REST API 中的頂級資源。Pod 物件定義詳細描述了該物件。
- 分散式系統工具包:複合容器模式解釋了具有多個容器的 Pod 的常見佈局。
- 閱讀有關Pod 拓撲分散約束的資訊
要了解 Kubernetes 將通用 Pod API 封裝在其他資源(例如StatefulSets或Deployments)中的原因,你可以閱讀相關的現有技術,包括: