GKE バージョン 1.35 にアップグレードする前に exec プローブのタイムアウトを構成する


このページでは、Google Kubernetes Engine(GKE)クラスタをバージョン 1.35 以降にアップグレードする前に、これらのプローブのコマンドのタイムアウトを設定して、ライブネス、準備状況、起動プローブを準備する方法について説明します。

exec プローブのタイムアウトについて

GKE バージョン 1.35 以降では、Kubernetes は liveness プローブ、readiness プローブ、startup プローブの exec フィールドのコマンドにタイムアウトを適用します。プローブの仕様の timeoutSeconds フィールドは、Kubernetes がプローブがアクションを完了するまで待機する時間を定義します。このフィールドを省略すると、デフォルト値の 1 が使用されます。これは、すべてのアクションが 1 秒以内に完了することを意味します。

1.35 より前の GKE バージョンでは、Kubernetes は exec プローブ コマンドの timeoutSeconds フィールドの値を無視します。たとえば、次のプロパティを持つ liveness プローブについて考えてみましょう。

  • timeoutSeconds フィールドの値が 5
  • 完了までに 10 秒かかる exec.command フィールドのコマンド。

1.35 より前のバージョンでは、Kubernetes はこの 5 秒のタイムアウトを無視し、プローブが成功したと誤って報告します。バージョン 1.35 以降では、Kubernetes は 5 秒後にプローブを正しく失敗させます。

Kubernetes が exec プローブのタイムアウトを無視するこの動作により、プローブが無期限に実行される可能性があります。これにより、アプリケーションの問題が隠蔽されたり、予測不可能な動作が発生したりする可能性があります。GKE バージョン 1.35 以降では、Kubernetes がコマンド タイムアウトを正しく適用するため、オープンソースの Kubernetes に沿った一貫性のある予測可能なプローブ動作が実現します。

exec プローブのタイムアウトの適用による影響

これは、GKE で実行されるワークロードの安定性と信頼性を確保するために必要な、GKE バージョン 1.35 以降の破壊的変更です。クラスタを 1.35 以降にアップグレードすると、ワークロードに次のいずれかのプロパティを持つ exec プローブがある場合、ワークロードで予期しない動作が発生する可能性があります。

  • timeoutSeconds フィールドを省略する: バージョン 1.35 以降では、これらのプローブはコマンドを正常に完了するまでに 1 秒かかります。コマンドが 1 秒以内に正常に完了しない場合、プローブは失敗を正しく報告します。
  • 短いタイムアウト期間を指定する: バージョン 1.35 以降では、コマンド完了時間よりも短いタイムアウト期間のプローブは、失敗を正しく報告します。

GKE バージョン 1.34 以前では、Kubernetes は次のいずれかの条件を満たす exec プローブでエラーを報告します。ただし、プローブエラーはプローブの失敗ではないため、これらの実行プローブのコマンドは完了まで実行できます。

より正確なタイムアウト期間を指定せず、コマンドの完了に既存のタイムアウト期間よりも時間がかかる場合、プローブはバージョン 1.35 以降で障害を報告します。プローブの種類に応じて、プローブが失敗した場合は次の動作が適用されます。

  • Liveness Probe: コマンドがタイムアウトして livenessProbe が失敗した場合、Kubernetes はアプリケーションが失敗したとみなし、コンテナを再起動します。プローブが繰り返し失敗すると、Pod が CrashLoopBackOff Pod ステータスのクラッシュ ループに陥る可能性があります。
  • Readiness Probe: コマンドがタイムアウトしたために Readiness Probe が失敗した場合、Kubernetes は Ready Pod 条件を False ステータスで更新します。プローブが成功するまで、Kubernetes は Pod にトラフィックを送信しません。Service をバックアップするすべての Pod の Ready 条件のステータスが False の場合、Service の中断が発生する可能性があります。
  • 起動プローブ: 起動プローブが失敗すると、Kubernetes はアプリケーションの起動に失敗したとみなし、コンテナを再起動します。プローブが繰り返し失敗すると、Pod が CrashLoopBackOff Pod ステータスのクラッシュ ループで停止する可能性があります。

自動アップグレードの一時停止

クラスタ内のワークロードがこの変更の影響を受ける可能性があることを検出すると、GKE はバージョン 1.35 への自動アップグレードを一時停止します。バージョン 1.35 がコントロール プレーンとノードの自動アップグレード ターゲットであり、次のいずれかの条件が満たされている場合、GKE は自動アップグレードを再開します。

  • タイムアウト値でワークロード プローブを更新し、GKE が 7 日間潜在的な問題を検出していない。
  • リリース チャンネルでバージョン 1.34 のサポートが終了します。

影響を受けるクラスタまたはワークロードを特定する

以降のセクションでは、この変更の影響を受ける可能性があるクラスタまたはワークロードを特定する方法について説明します。

コマンドラインを使用して Kubernetes イベントを確認する

GKE バージョン 1.34 以前では、クラスタ内の Kubernetes イベントを手動で検査して、既存のタイムアウト期間よりも完了に時間がかかる exec プローブを見つけることができます。Kubernetes は、これらのプローブに対して command timed out メッセージを含むイベントを追加します。この方法は、タイムアウト値が短いためにすでに問題が発生しているワークロードを特定するのに役立ちます。

影響を受けるワークロードを見つけるには、次のいずれかを行います。

スクリプトを使用して複数のクラスタでワークロードを検索する

次の bash スクリプトは、kubeconfig ファイル内のすべてのクラスタを反復処理して、影響を受けるワークロードを検索します。このスクリプトは、既存のすべての到達可能な Kubernetes コンテキストで exec プローブのタイムアウト エラーをチェックし、結果を affected_workloads_report.txt という名前のテキスト ファイルに書き込みます。このスクリプトを実行する手順は次のとおりです。

  1. 次のスクリプトを 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"
    
  2. スクリプトを実行します。

    bash execprobe-timeouts.sh
    
  3. 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 クラスタに対して、次の操作を行います。

  1. クラスタに接続します。

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=LOCATION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • LOCATION: クラスタ コントロール プレーンのロケーション(us-central1 など)。
  2. exec Probe にタイムアウト エラーがあることを示すイベントを確認します。

    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
    
  3. GKE バージョン 1.35 より前のバージョンを実行しているクラスタごとに、上記の手順を繰り返します。

Cloud Logging で影響を受けるクラスタとワークロードを見つける

  1. Google Cloud コンソールで、[ログ エクスプローラ] ページに移動します。

    [ログ エクスプローラ] に移動

  2. クエリエディタを開くには、[クエリを表示] をクリックします。

  3. 次のクエリを実行します。

    jsonPayload.message=~" probe errored and resulted in .* state: command timed out" OR jsonPayload.message=~" probe errored : command timed out"
    

    出力は、構成されたタイムアウト期間よりも完了に時間がかかったコマンドによって発生したプローブエラーのリストです。

1.35 にアップグレードする前に、影響を受けるワークロードを更新する

影響を受けるワークロードを特定したら、影響を受けるプローブを更新する必要があります。

  1. 影響を受ける各 Pod の liveness プローブ、readiness プローブ、startup プローブを確認し、適切な timeoutSeconds 値を決定します。この値は、通常の条件下でコマンドが正常に実行されるのに十分な長さにする必要があります。詳細については、Liveness probe、Readiness probe、Startup Probe の構成をご覧ください。
  2. 影響を受けるワークロードのマニフェスト ファイルを開き、liveness、readiness、startup プローブの timeoutSeconds フィールドを追加または変更します。たとえば、次のライブネス プローブの timeoutSeconds フィールドの値は 10 です。

    spec:
      containers:
      - name: my-container
        image: my-image
        livenessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 10
    
  3. 更新されたマニフェストをクラスタに適用します。

  4. コマンドラインを使用して Kubernetes イベントを確認するの手順に沿って、更新されたプローブのエラーを確認します。

影響を受けるすべてのワークロードを更新してテストしたら、クラスタを GKE バージョン 1.35 にアップグレードできます。