Advanced - Pod Lifecycle
在 Kubernetes 中,Pod 是最小的可部署單位,它代表一組容器的集合。 Pod 的生命週期包含多個階段,每個階段都反映了 Pod 的狀態和行為。 以下將介紹 Pod 的生命週期、主要的容器類型以及相關的探針(Probes)。
Pod Lifecycle
Pod 的生命週期中有以下重要的部分:
- Init Container (初始化容器):
- Init Container 是在 Main Container 啟動之前執行的特殊容器 ,負責完成初始化任務。
- 這些任務包括檢查條件是否滿足、準備必要的資源(如配置文件或數據初始化)。
- Init Container 必須執行成功,才能啟動後續的 Main Container。
- Main Container (主容器):
- Main Container 是 Pod 的核心,執行應用程序的主要工作負載。
- Pod 通常至少包含一個 Main Container,負責提供主要的服務或執行任務。
- Post Start / Pre Stop Hook (生命週期鉤):
- Kubernetes 提供了容器級別的鉤子,用於在容器啟動後或終止前執行一些任務。
- Post Start Hook:
- 在容器啟動後立即執行,用於執行初始化操作。
- Pre Stop Hook:
- 在容器終止前執行,用於清理資源或執行優雅關閉操作。
- Liveness / Readiness Probe (健康檢查機制):
- 探針是用於監控容器健康狀態的機制,確保應用穩定性和高可用性。
- Liveness Probe
- 用於檢查容器是否仍然存活。
- 如果檢查失敗,Kubernetes 會自動重啟該容器。
- Readiness Probe
- 用於檢查容器是否準備好接受流量。
- 如果檢查失敗,Kubernetes 會從該容器的服務端點中移除。
Pod Phase (階段)
Pod 可以分為以下主要階段:
- Pending:
- 當 Pod 被創建後 ,進入 Pending 狀態。
- 在這個階段,Kubernetes 正在尋找適合的節點(Node)來調度 Pod,並拉取所需的容器映像。
- Running:
- 當 Pod 已被調度到某個節點,且所有的容器都成功啟動時,Pod 進入 Running 狀態。
- 此時,Pod 開始執行其定義的工作負載。
- Succeeded:
- 當 Pod 中所有的容器都正常執行完畢並成功退出,Pod 進入 Succeeded 狀態。
- 這通常發生於執行一次性任務的 Pod,例如批次作業。
- Failed:
- 如果 Pod 中任何容器異常退出且未被重啟策略恢復,Pod 進入 Failed 狀態。
- Unknown:
- 當 Kubernetes 無法與執行 Pod 的節點通訊時,Pod 進入 Unknown 狀態。
Restart Policies
Pod 支援三種重啟策略:
- Always: 無論退出狀態如何,總是重啟容器(預設值)。
- OnFailure: 只有在容器異常退出時才重啟。
- Never: 容器退出後不重啟。
restartPolicy 僅適用於 kubelet 在同一節點上重新啟動容器。
Kubelet 將根據指數增加的延遲(10s, 20s, 40s)重新啟動不健康的容器,延遲上限為 5 分鐘,並在容器成功執行 10 分鐘後重置延遲。
控制器與重啟策略
- Job:
- 用於一次性任務,例如批量計算。
- 任務結束後,Pod 會被此類控制器清除。
- 支援的重啟策略為
OnFailure或Never。
- Replication Controller / ReplicaSet / Deployment:
- 這些控制器旨在確保 Pod 持續運行。
- 僅支援
Always作為重啟策略。
- DaemonSet:
- 在每個節點上只會運行一個 Pod。
- 重啟策略必須是
Always。
範例
就像我們之前建立 Deployment 一樣,主要是為了確保 Pod 持續運行,所以重啟策略設定為 Always。
always_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: v1-deployment
labels:
type: demo-v1
spec:
replicas: 1
selector:
matchLabels:
type: demo-v1
template:
metadata:
labels:
type: demo-v1
spec:
restartPolicy: Always
containers:
- name: v1
image: hello-world:v1.0.0
imagePullPolicy: Always
ports:
- containerPort: 8080
Container Types
在 Pod 中,可以包含多種類型的容器,每種類型都有其特定的用途。
Main Container
Main Container 是 Pod 的核心,負責執行應用程序的主要工作負載。通常,Pod 至少包含一個 Main Container。
Init Container
Init Container 是在 Main Container 啟動之前執行的特殊容器。它們的作用包括:
- 等待其他服務準備好:
- 這種作法特別適用於解決服務器之間的依賴,例如有一個應用需要資料庫的服務,但啟動主服務的時候並不能保證被依賴的資料庫是否就緒, 這個時候我們可以簡單使用一個 Init Container,來監測資料庫服務是否 OK,確認 OK 就可以退出,並交由主服務開始啟動。
- 執行初始化任務:
- 比如叢集檢測所有已經存在的成員節點,為主容器準備好叢集的設定資訊,這樣主容器啟動後就能用這些設定加入叢集。
提示
Init Container 必須執行成功,才能啟動 Main Container。
範例
- 首先我們想實現一個 google 首頁的服務,我們可以透過 InitContainers 來抓取首頁當成我們的首頁, 當他成功抓取之後並產出 index.html 後會隨即退出,再透過 volume 將資料夾掛載到主容器,實現初始化並共享資源,最後讓 nginx 服務啟動。
init-container.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
volumes:
- name: workdir
emptyDir: {}
initContainers:
- name: install
image: busybox
command: # 抓取google首頁當作index.html
- wget
- "-O"
- "/work-dir/index.html"
- https://www.google.com
volumeMounts: # 透過volume掛載到主容器上
- name: workdir
mountPath: /work-dir
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts: # 透過volume我們可以讀到init container抓到的東西
- name: workdir
mountPath: /usr/share/nginx/html
Hooks: Post Start & Pre Stop
Pod 支援兩種容器級別的鉤子(Hooks),他們是在初始化容器執行完畢後由 kubelet 發 起,用於在容器啟動或停止時執行任務。
Post Start Hook
- 這個鉤子在容器建立後立刻執行。但是並不能保證鉤子將在容器 Enterpoint(入口點)之前運行,因為他不會傳遞任何參數給作業程序。
- 主要用於資源部屬、環境準備等。
- 不過需要注意如果鉤子花費太多時間,以至於不能運行或者遇到問題,容器將不能達到 Running 狀態。
Pre Stop Hook
- 是一個在容器結束運行前立刻被呼叫的鉤子。他是同步的,可以延遲終止過程,必須在容器被正式終止前完成執行。
- 主要用於優雅的關閉應用、通知其他系統等。
- 如果鉤子在執行期間掛起,Pod 階段將停留在 Running 狀態,並且永遠不會達到 Failed 狀態。
範例
以下的例子就是在 Pod 創立和刪除時會 echo 出來。
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ['/bin/sh', '-c', 'echo Container started']
preStop:
exec:
command: ['/bin/sh', '-c', 'echo Container stopping']