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。
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 服務啟動。
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']
Probes (探針)
為了確保應用的穩定性,Kubernetes 提供了 Liveness Probe、Readiness Probe 和 Startup Probe,用於監控和管理 Pod 中的容器狀態,如果出現異常將透過自我檢測和修復來避免把流量導到不健康的 Pod。
常見的檢查方式
- Exec 檢查:執行容器內的一個命令,並檢查返回值,回傳 0 代表成功,其餘皆為失敗。
- TCP 檢查:嘗試連接到容器的某個 TCP 埠, 連接埠開啟代表成功,否則代表失敗。
- HTTP 檢查:發送 HTTP 請求到容器內的指定端點,狀態大於等於 200 且小於 400 皆為成功,其餘皆失敗。
- gRPC 檢查:可以透過對容器 IP 為紙上的指定連接埠發起 gRPC 請求,這裡需要注意的是使用 gRPC 作為 action 時需要特別指定連接埠。
Liveness Probe
Liveness Probe 用於檢查容器是否仍然存活。如果檢查失敗,Kubernetes 將重啟該容器,避免因應用停滯而導致服務不可用。
Readiness Probe
Readiness Probe 用於檢查容器是否已準備好接受流量。如果檢查失敗,Kubernetes 將從該容器的服務端點中移除,確保流量只分配給可用的容器。
Startup Probe
Startup Probe 用於檢查容器的啟動狀態,適用於需要較長時間啟動的應用程式。該探針允許 Kubernetes 在啟動期間給予容器更多時間,避免過早判定為失敗並進行重啟。
探針比較
探針類型 | 功能 | 失敗後行為 |
---|---|---|
Liveness Probe | 檢查容器是否存活,若失敗表明應用已陷入無法恢復的狀態。 | Kubernetes 重啟容器。 |
Readiness Probe | 檢查容器是否準備好接受流量,若失敗表明應用暫時無法處理請求。 | Kubernetes 從服務端點中移除容器,暫停流量分配。 |
Startup Probe | 檢查容器的啟動過程是否完成,適用於啟動時間較長的應用程式。 | 在超過失敗閾值前,Kubernetes 不會認定容器失敗或重啟。 |
範例
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe: # 檢查容器是否準備好接受流量的探針
tcpSocket: # 使用 TCP 檢查的方式
port: 8080 # 檢查的目標 TCP 埠
initialDelaySeconds: 5 # 探針檢查的初始延遲時間(單位:秒),容器啟動後 5 秒開始進行檢查
periodSeconds: 10 # 每次探針檢查的間隔時間(單位:秒)
livenessProbe: # 檢查容器是否仍然存活的探針
tcpSocket: # 使用 TCP 檢查的方式
port: 8080 # 檢查的目標 TCP 埠
initialDelaySeconds: 15 # 探針檢查的初始延遲時間(單位:秒),容器啟動後 15 秒開始進行檢查
periodSeconds: 20 # 每次探針檢查的間隔時間(單位:秒)
總結
Pod 的生命週期、容器類型、鉤子以及探針設定是 Kubernetes 中非常重要的概念,它們幫助我們更好地監控和管理應用的健康狀態。通過正確地使用 liveness 和 readiness 和 startup 探針,以及適當設置 Init Container 和鉤子,我們可以提升應用的穩定性和可靠性。