本頁說明如何準備存活、就緒和啟動探測,以便在將 Google Kubernetes Engine (GKE) 叢集升級至 1.35 以上版本前,為這些探測中的指令設定逾時。
關於 exec 探測的逾時
從 GKE 1.35 版開始,Kubernetes 會強制執行執行中、就緒和啟動探測器 exec
欄位中指令的逾時。探測規格中的 timeoutSeconds
欄位會定義 Kubernetes 等待探測完成任何動作的時間長度。如果省略這個欄位,預設值為 1
,表示任何動作都有一秒的時間完成。
在 1.35 之前的 GKE 版本中,Kubernetes 會忽略 exec 探查指令 timeoutSeconds
欄位中的值。舉例來說,假設存活探針具有下列屬性:
timeoutSeconds
欄位中的5
值。exec.command
欄位中的指令需要 10 秒才能完成。
在 1.35 之前的版本中,Kubernetes 會忽略這五秒的逾時時間,並錯誤地回報探查成功。在 1.35 以上版本中,Kubernetes 會在五秒後正確地讓探查失敗。
Kubernetes 忽略 exec 探查逾時的行為,可能會導致探查無限期執行,進而隱藏應用程式的問題,或導致無法預測的行為。在 GKE 1.35 以上版本中,Kubernetes 會正確強制執行指令逾時,因此探查行為會與開放原始碼 Kubernetes 一致,且可預測。
強制執行 exec 探查逾時的影響
這是 GKE 1.35 以上版本中的重大變更,有助於提升 GKE 工作負載的穩定性和可靠性。將叢集升級至 1.35 以上版本時,如果工作負載具有下列其中一項屬性的 exec 探查,您可能會發現工作負載出現異常行為:
- 省略
timeoutSeconds
欄位:在 1.35 以上版本中,這些探測器有一秒的時間可成功完成指令。如果指令無法在一秒內順利完成,探測器就會正確回報失敗。 - 指定較短的逾時時間:在 1.35 以上版本中,逾時時間短於指令完成時間的探查會正確回報失敗。
在 GKE 1.34 版和更早版本中,如果 exec 探針符合下列任一條件,Kubernetes 就會回報錯誤。不過,這些 exec 探針中的指令仍可執行完畢,因為探針錯誤並非探針失敗。
如果您未指定更準確的逾時時間,且指令完成時間超過現有的逾時時間,探測器會在 1.35 以上版本中回報失敗。視探測類型而定,探測失敗時的行為如下:
- 有效性探測:如果指令逾時導致有效性探測失敗,Kubernetes 會假設應用程式失敗,並重新啟動容器。如果探測器反覆失敗,Pod 可能會陷入當機迴圈,並顯示
CrashLoopBackOff
Pod 狀態。 - 就緒探測:如果指令逾時導致就緒探測失敗,Kubernetes 會更新
Ready
Pod 狀況,並顯示False
狀態。Kubernetes 會等到探測作業成功後,再將流量傳送至 Pod。如果支援服務的所有 Pod 都有Ready
條件的False
狀態,您可能會發現服務中斷。 - 啟動探測:如果啟動探測失敗,Kubernetes 會假設應用程式啟動失敗,並重新啟動容器。如果探針反覆失敗,Pod 可能會陷入當機迴圈,並處於
CrashLoopBackOff
Pod 狀態。
已暫停自動升級
如果 GKE 偵測到叢集中的工作負載可能會受到這項變更影響,就會暫停自動升級至 1.35 版。如果版本 1.35 是控制層和節點的自動升級目標,且符合下列任一條件,GKE 就會繼續自動升級:
- 您已使用逾時值更新工作負載探查,且 GKE 在七天內未偵測到潛在問題。
- 1.34 版在發布管道中終止支援。
找出受影響的叢集或工作負載
以下各節說明如何找出可能受這項異動影響的叢集或工作負載。
使用指令列檢查 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 中找出受影響的叢集和工作負載
前往 Google Cloud 控制台的「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 版。