本頁說明如何準備存活、就緒和啟動探測,方法是在這些探測中設定指令逾時,然後再將 Google Kubernetes Engine (GKE) 叢集升級至 1.35 以上版本。
關於執行探測的逾時
從 GKE 1.35 版開始,Kubernetes 會強制執行活躍度、就緒度和啟動探測的 exec 欄位中指令的逾時。探針規格中的 timeoutSeconds 欄位會定義 Kubernetes 等待探針完成任何動作的時間長度。如果省略這個欄位,預設值為 1,表示任何動作都有一秒的時間完成。
在 1.35 之前的 GKE 版本中,Kubernetes 會忽略執行探測指令 timeoutSeconds 欄位中的值。舉例來說,假設存活探針具有下列屬性:
- 「
timeoutSeconds」欄位的值為5。 exec.command欄位中的指令,需要 10 秒才能完成。
在 1.35 之前的版本中,Kubernetes 會忽略這五秒的逾時時間,並錯誤地將探測回報為成功。在 1.35 以上版本中,Kubernetes 會在五秒後正確地讓探測失敗。
Kubernetes 忽略 exec 探查逾時的行為,可能會導致探查無限期執行,進而隱藏應用程式的問題,或造成無法預測的行為。在 GKE 1.35 以上版本中,Kubernetes 會正確強制執行指令逾時,因此探測行為會與開放原始碼 Kubernetes 一致,且可預測。
強制執行執行探測逾時的影響
這是 GKE 1.35 以上版本中的重大變更,對於在 GKE 上執行的工作負載穩定性和可靠性而言,這項變更不可或缺。將叢集升級至 1.35 以上版本時,如果工作負載的執行探測具有下列其中一項屬性,您可能會發現工作負載出現異常行為:
- 省略
timeoutSeconds欄位:在 1.35 以上版本中,這些探測器有一秒的時間可順利完成指令。如果指令無法在一秒內順利完成,探針就會正確回報失敗。 - 指定較短的逾時時間:在 1.35 以上版本中,逾時時間短於指令完成時間的探查會正確回報失敗。
在 GKE 1.34 版和更早版本中,如果 exec 探查符合下列任一條件,Kubernetes 就會回報錯誤。不過,這些執行探查中的指令仍可執行完畢,因為探查錯誤並非探查失敗。
如果您未指定更準確的逾時時間長度,且指令完成時間超過現有的逾時時間,探測器就會在 1.35 以上版本中回報失敗。探測失敗時,系統會根據探測類型採取下列行為:
- 有效性探測:如果指令逾時導致有效性探測失敗,Kubernetes 會假設應用程式失敗,並重新啟動容器。在 1.35 之前的版本中,逾時可能只會產生警告事件,不會強制重新啟動容器。
如果探查作業一再失敗,Pod 可能會陷入當機迴圈,並顯示
CrashLoopBackOffPod 狀態。 - 就緒探測:如果指令逾時導致就緒探測失敗,Kubernetes 會更新
ReadyPod 狀況,並顯示False狀態。也就是說,在探測成功之前,Kubernetes 不會將任何流量傳送到 Pod。在 GKE 1.35 以上版本中,系統會從 Service 端點移除 Pod。在 1.35 之前的版本中,逾時可能只會產生警告事件,而不會從服務中移除 Pod。 如果支援服務的所有 PodReady條件狀態皆為False,您可能會發現服務中斷。 - 啟動探測:如果啟動探測失敗,Kubernetes 會假設應用程式啟動失敗,並重新啟動容器。如果探針反覆失敗,Pod 可能會陷入當機迴圈,並顯示
CrashLoopBackOffPod 狀態。
已暫停自動升級
如果 GKE 偵測到叢集中的工作負載可能受到這項變更影響,就會暫停自動升級至 1.35 版。如果版本 1.35 是控制層和節點的自動升級目標,且符合下列其中一項條件,GKE 就會繼續自動升級:
- 您已使用逾時值更新工作負載探針,且 GKE 在七天內未偵測到潛在問題。
- 1.34 版已在發布管道中終止支援。
找出受影響的叢集或工作負載
以下各節說明如何找出可能受這項異動影響的叢集或工作負載。
使用 GKE 最佳化建議和深入分析
GKE 會監控叢集,並使用 Recommender 服務找出受執行探查逾時強制執行的叢集。如果 GKE 偵測到叢集有執行探測的工作負載可能會逾時,Cloud de Confiance 控制台會顯示名為「設定工作負載的執行探測逾時」的建議。
取得洞察資料和建議
按照操作說明查看洞察資料和建議。 您可以使用 Cloud de Confiance 控制台取得洞察資料。您也可以使用 Google Cloud CLI 或 Recommender API,並依下列子類型篩選:
EXEC_PROBE_TIMEOUT:執行探測逾時
如果叢集有待處理的建議,GKE 會暫停自動升級至 1.35 版,直到您更新執行探測逾時設定,確保作業不會中斷為止。
使用指令列檢查 Kubernetes 事件
在 GKE 1.34 版和更早版本中,您可以手動檢查叢集中的 Kubernetes 事件,找出完成時間超過現有逾時期間的 exec 探測。Kubernetes 會為這些探測器新增含有 command timed out 訊息的事件。這個方法有助於找出因逾時值過短而發生問題的工作負載。
如要找出受影響的工作負載,請採取下列任一做法:
使用指令碼在多個叢集中尋找工作負載
下列 Bash 指令碼會疊代kubeconfig 檔案中的所有叢集,找出受影響的工作負載。這項指令碼會檢查所有現有且可連線的 Kubernetes 環境,找出 exec 探測逾時錯誤,並將發現項目寫入名為 affected_workloads_report.txt 的文字檔。如要執行這項指令碼,請按照下列步驟操作:
將下列指令碼儲存為
execprobe-timeouts.sh:#!/bin/bash # This script checks for exec probe timeouts across all existing and reachable # Kubernetes contexts and writes the findings to a text file, with one # row for each affected workload, including its cluster name. # --- Configuration --- OUTPUT_FILE="affected_workloads_report.txt" # ------------------- # Check if kubectl and jq are installed if ! command -v kubectl &> /dev/null || ! command -v jq &> /dev/null; then echo "Error: kubectl and jq are required to run this script." >&2 exit 1 fi echo "Fetching all contexts from your kubeconfig..." # Initialize the report file with a formatted header printf "%-40s | %s\n" "Cluster Context" "Impacted Workload" > "$OUTPUT_FILE" # Get all context names from the kubeconfig file CONTEXTS=$(kubectl config get-contexts -o name) if [[ -z "$CONTEXTS" ]]; then echo "No Kubernetes contexts found in your kubeconfig file." exit 0 fi echo "Verifying each context and checking for probe timeouts..." echo "==================================================" # Loop through each context for CONTEXT in $CONTEXTS; do echo "--- Checking context: $CONTEXT ---" # Check if the cluster is reachable by running a lightweight command if kubectl --context="$CONTEXT" get ns --request-timeout=1s > /dev/null 2>&1; then echo "Context '$CONTEXT' is reachable. Checking for timeouts..." # Find timeout events based on the logic from the documentation AFFECTED_WORKLOADS_LIST=$(kubectl --context="$CONTEXT" get events --all-namespaces -o json | jq -r '.items[] | select((.involvedObject.namespace | type == "string") and (.involvedObject.namespace | endswith("-system") | not) and (.message | test("^(Liveness|Readiness|Startup) probe errored(.*): command timed out(.*)|^ * probe errored and resulted in .* state: command timed out.*"))) | .involvedObject.kind + "/" + .involvedObject.name' | uniq) if [[ -n "$AFFECTED_WORKLOADS_LIST" ]]; then echo "Found potentially affected workloads in context '$CONTEXT'." # Loop through each affected workload and write a new row to the report # pairing the context with the workload. while IFS= read -r WORKLOAD; do printf "%-40s | %s\n" "$CONTEXT" "$WORKLOAD" >> "$OUTPUT_FILE" done <<< "$AFFECTED_WORKLOADS_LIST" else echo "No workloads with exec probe timeouts found in context '$CONTEXT'." fi else echo "Context '$CONTEXT' is not reachable or the cluster does not exist. Skipping." fi echo "--------------------------------------------------" done echo "==================================================" echo "Script finished." echo "A detailed report of affected workloads has been saved to: $OUTPUT_FILE"執行指令碼:
bash execprobe-timeouts.sh讀取
affected_workloads_report.txt檔案的內容:cat affected_workloads_report.txt輸出結果會與下列內容相似:
Cluster Context | Impacted Workload -----------------------------------------|---------------------------- gke_my-project_us-central1-c_cluster-1 | Pod/liveness1-exec gke_my-project_us-central1-c_cluster-1 | Deployment/another-buggy-app gke_my-project_us-east1-b_cluster-2 | Pod/startup-probe-test
使用指令列在特定叢集中尋找工作負載
如要在特定叢集中找出受影響的工作負載,可以使用 kubectl 工具檢查 exec 探查逾時錯誤。請針對每個執行 1.34 以下版本的 GKE 叢集,執行下列步驟:
連線至叢集:
gcloud container clusters get-credentials CLUSTER_NAME \ --location=LOCATION更改下列內容:
CLUSTER_NAME:叢集名稱。LOCATION:叢集控制平面的位置,例如us-central1。
檢查是否有事件指出 exec 探針發生逾時錯誤:
kubectl get events --all-namespaces -o json | jq -r '.items[] | select((.involvedObject.namespace | type == "string") and (.involvedObject.namespace | endswith("-system") | not) and (.message | test("^(Liveness|Readiness|Startup) probe errored(.*): command timed out(.*)|^ * probe errored and resulted in .* state: command timed out.*"))) | "\(.involvedObject.kind)/\(.involvedObject.name) Namespace: \(.involvedObject.namespace)"'這項指令會忽略許多系統命名空間中的工作負載。如果存在受影響的工作負載,輸出內容會與下列內容相似:
Pod/liveness1-exec Namespace: default針對執行 1.35 之前 GKE 版本的每個叢集,重複執行上述步驟。
在 Cloud Logging 中找出受影響的叢集和工作負載
前往 Cloud de Confiance 控制台的「Logs Explorer」頁面。
點選「顯示查詢」切換鈕,開啟查詢編輯器。
執行以下查詢:
jsonPayload.message=~" probe errored and resulted in .* state: command timed out" OR jsonPayload.message=~" probe errored: command timed out"輸出內容是探查錯誤清單,這些錯誤是由於指令完成時間超過設定的逾時期限所致。
請先更新受影響的工作負載,再升級至 1.35 版
找出受影響的工作負載後,請更新受影響的探針。
- 檢查每個受影響 Pod 的存活度、就緒度和啟動探測,並判斷適當的
timeoutSeconds值。這個值應夠長,才能在正常情況下順利執行指令。詳情請參閱「設定即時、就緒和啟動探針」。 開啟受影響工作負載的資訊清單檔案,然後新增或修改存活度、就緒或啟動探查的
timeoutSeconds欄位。舉例來說,下列存活探針的timeoutSeconds欄位值為10:spec: containers: - name: my-container image: my-image livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 10將更新後的資訊清單套用至叢集。
按照「使用指令列檢查 Kubernetes 事件」一文的步驟,檢查更新後的探測器是否有錯誤。
更新並測試所有受影響的工作負載後,即可將叢集升級至 GKE 1.35 版。