使用 Pod 失敗策略處理可重試與不可重試的 Pod 失敗
Kubernetes v1.31 [穩定]
(預設啟用:true)本文件向您展示如何使用 Pod 失敗策略,結合預設的 Pod 退避失敗策略,以改善對 Job 內容器或 Pod 層級失敗處理的控制。
Pod 失敗策略的定義可以幫助您
開始之前
您應該已經熟悉 Job 的基本用法。
您需要有一個 Kubernetes 叢集,並且必須設定 kubectl 命令列工具以與您的叢集通訊。建議在至少有兩個節點且不充當控制平面主機的叢集上執行本教學課程。如果您還沒有叢集,可以使用 minikube 建立一個,或者您可以使用以下 Kubernetes playground 之一
您的 Kubernetes 伺服器必須是 v1.25 或更新版本。若要檢查版本,請輸入kubectl version
。使用 Pod 失敗策略避免不必要的 Pod 重試
透過以下範例,您可以學習如何在 Pod 失敗指示不可重試的軟體錯誤時,使用 Pod 失敗策略來避免不必要的 Pod 重新啟動。
首先,根據組態建立 Job
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-failjob
spec:
completions: 8
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/bash:5
command: ["bash"]
args:
- -c
- echo "Hello world! I'm going to exit with 42 to simulate a software bug." && sleep 30 && exit 42
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailJob
onExitCodes:
containerName: main
operator: In
values: [42]
透過執行
kubectl create -f job-pod-failure-policy-failjob.yaml
大約 30 秒後,整個 Job 應終止。執行以下命令檢查 Job 的狀態
kubectl get jobs -l job-name=job-pod-failure-policy-failjob -o yaml
在 Job 狀態中,會顯示以下條件
FailureTarget
條件:具有設定為PodFailurePolicy
的reason
欄位,以及包含有關終止的更多資訊的message
欄位,例如Container main for pod default/job-pod-failure-policy-failjob-8ckj8 failed with exit code 42 matching FailJob rule at index 0
。Job 控制器會在 Job 被視為失敗時立即新增此條件。如需詳細資訊,請參閱 終止 Job Pod。Failed
條件:與FailureTarget
條件相同的reason
和message
。Job 控制器會在 Job 的所有 Pod 終止後新增此條件。
為了比較,如果停用 Pod 失敗原則,Pod 將會重試 6 次,至少需要 2 分鐘。
清理
刪除您建立的 Job
kubectl delete jobs/job-pod-failure-policy-failjob
叢集會自動清理 Pod。
使用 Pod 失敗原則來忽略 Pod 中斷
透過以下範例,您可以學習如何使用 Pod 失敗原則來忽略 Pod 中斷,避免 Pod 重試計數器朝 .spec.backoffLimit
限制遞增。
注意
時機對於此範例非常重要,因此您可能需要在執行前閱讀步驟。為了觸發 Pod 中斷,在 Pod 於節點上執行時(自 Pod 排程起 90 秒內)排空節點非常重要。根據設定檔建立 Job
apiVersion: batch/v1 kind: Job metadata: name: job-pod-failure-policy-ignore spec: completions: 4 parallelism: 2 template: spec: restartPolicy: Never containers: - name: main image: docker.io/library/bash:5 command: ["bash"] args: - -c - echo "Hello world! I'm going to exit with 0 (success)." && sleep 90 && exit 0 backoffLimit: 0 podFailurePolicy: rules: - action: Ignore onPodConditions: - type: DisruptionTarget
透過執行
kubectl create -f job-pod-failure-policy-ignore.yaml
執行此命令以檢查 Pod 排程到的
nodeName
nodeName=$(kubectl get pods -l job-name=job-pod-failure-policy-ignore -o jsonpath='{.items[0].spec.nodeName}')
排空節點以在 Pod 完成前 (90 秒內) 驅逐 Pod
kubectl drain nodes/$nodeName --ignore-daemonsets --grace-period=0
檢查
.status.failed
以確認 Job 的計數器未遞增kubectl get jobs -l job-name=job-pod-failure-policy-ignore -o yaml
解除節點封鎖
kubectl uncordon nodes/$nodeName
Job 恢復並成功。
為了比較,如果停用 Pod 失敗原則,Pod 中斷將導致整個 Job 終止(因為 .spec.backoffLimit
設定為 0)。
清理
刪除您建立的 Job
kubectl delete jobs/job-pod-failure-policy-ignore
叢集會自動清理 Pod。
使用 Pod 失敗原則以根據自訂 Pod 狀況避免不必要的 Pod 重試
透過以下範例,您可以學習如何使用 Pod 失敗原則,根據自訂 Pod 狀況來避免不必要的 Pod 重新啟動。
首先,根據組態建立 Job
apiVersion: batch/v1 kind: Job metadata: name: job-pod-failure-policy-config-issue spec: completions: 8 parallelism: 2 template: spec: restartPolicy: Never containers: - name: main image: "non-existing-repo/non-existing-image:example" backoffLimit: 6 podFailurePolicy: rules: - action: FailJob onPodConditions: - type: ConfigIssue
透過執行
kubectl create -f job-pod-failure-policy-config-issue.yaml
請注意,此映像檔設定錯誤,因為它不存在。
執行以下命令來檢查 Job 的 Pod 狀態
kubectl get pods -l job-name=job-pod-failure-policy-config-issue -o yaml
您將看到類似以下的輸出
containerStatuses: - image: non-existing-repo/non-existing-image:example ... state: waiting: message: Back-off pulling image "non-existing-repo/non-existing-image:example" reason: ImagePullBackOff ... phase: Pending
請注意,Pod 仍處於
Pending
階段,因為它無法提取設定錯誤的映像檔。原則上,這可能是一個暫時性問題,映像檔可能會被提取。但是,在本例中,映像檔不存在,因此我們透過自訂狀況來指出此事實。新增自訂狀況。首先,執行以下命令準備修補程式
cat <<EOF > patch.yaml status: conditions: - type: ConfigIssue status: "True" reason: "NonExistingImage" lastTransitionTime: "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" EOF
其次,執行以下命令選擇 Job 建立的其中一個 Pod
podName=$(kubectl get pods -l job-name=job-pod-failure-policy-config-issue -o jsonpath='{.items[0].metadata.name}')
然後,執行以下命令將修補程式套用至其中一個 Pod
kubectl patch pod $podName --subresource=status --patch-file=patch.yaml
如果成功套用,您將收到如下通知
pod/job-pod-failure-policy-config-issue-k6pvp patched
執行以下命令刪除 Pod,使其轉換為
Failed
階段kubectl delete pods/$podName
執行以下命令檢查 Job 的狀態
kubectl get jobs -l job-name=job-pod-failure-policy-config-issue -o yaml
在 Job 狀態中,查看 Job 的
Failed
狀況,其中欄位reason
等於PodFailurePolicy
。此外,message
欄位包含有關 Job 終止的更詳細資訊,例如:Pod default/job-pod-failure-policy-config-issue-k6pvp has condition ConfigIssue matching FailJob rule at index 0
。
注意
在生產環境中,步驟 3 和 4 應由使用者提供的控制器自動化。清理
刪除您建立的 Job
kubectl delete jobs/job-pod-failure-policy-config-issue
叢集會自動清理 Pod。
替代方案
您可以完全依賴 Pod 退避失敗原則,透過指定 Job 的 .spec.backoffLimit
欄位。但是,在許多情況下,要在設定較低的 .spec.backoffLimit
值以避免不必要的 Pod 重試,以及設定足夠高的值以確保 Job 不會因 Pod 中斷而終止之間找到平衡點,是很有問題的。