CrashLoopBackOff イベントのトラブルシューティング


このページでは、Google Kubernetes Engine(GKE)で CrashLoopBackOff イベントが発生している Pod の問題を解決する方法について説明します。

このページは、コンテナのクラッシュの原因となる構成エラーやコード関連のバグなどのアプリレベルの問題を特定するアプリ デベロッパーを対象としています。また、リソースの枯渇、ノードの中断、liveness プローブの構成ミスなど、コンテナの再起動のプラットフォーム レベルの根本原因を特定する必要があるプラットフォーム管理者とオペレーターも対象としています。 Trusted Cloud by S3NS のコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーロールとタスクをご覧ください。

CrashLoopBackOff イベントについて理解する

Pod が CrashLoopBackOff 状態のままになると、Pod 内のコンテナが繰り返し起動、クラッシュ、終了します。この CrashLoop により、Kubernetes は restartPolicy に従ってコンテナの再起動を試みます。再起動が失敗するたびに、次の試行までの BackOff 遅延は指数関数的に増加し(10 秒、20 秒、40 秒など)、最大で 5 分になります。

このイベントはコンテナ内の問題を示していますが、貴重な診断シグナルでもあります。CrashLoopBackOff イベントは、ノードへの割り当てやコンテナ イメージの pull など、Pod の作成の多くの基本的な手順がすでに完了していることを確認します。この情報により、クラスタ インフラストラクチャではなく、コンテナのアプリまたは構成に調査を集中できます。

CrashLoopBackOff 状態は、Kubernetes(特に kubelet)が Pod の再起動ポリシーに基づいてコンテナの終了を処理する方法が原因で発生します。通常、サイクルは次のパターンに従います。

  1. コンテナが起動します。
  2. コンテナが終了します。
  3. kubelet は停止したコンテナを監視し、Pod の restartPolicy に従って再起動します。
  4. このサイクルが繰り返され、コンテナは指数バックオフ遅延の増加後に再起動されます。

この動作の鍵となるのは、Pod の restartPolicy です。デフォルトのポリシー Always は、このループの最も一般的な原因です。これは、コンテナが正常に終了した後でも、何らかの理由で終了すると、コンテナを再起動するためです。OnFailure ポリシーは、ゼロ以外の終了コードでのみ再起動するため、ループが発生する可能性は低くなります。また、Never ポリシーでは再起動が完全に回避されます。

CrashLoopBackOff イベントの症状を特定する

CrashLoopBackOff ステータスの Pod は、CrashLoopBackOff イベントの主な指標です。

ただし、CrashLoopBackOff イベントのわかりにくい症状が発生する可能性があります。

  • ワークロードの正常なレプリカがゼロ。
  • 正常なレプリカの急激な減少。
  • 水平 Pod 自動スケーリングが有効になっているワークロードのスケーリングが遅いか、スケーリングに失敗する。

system ワークロード(ロギング エージェントや指標エージェントなど)のステータスが CrashLoopBackOff の場合、次の症状も発生する可能性があります。

  • 一部の GKE 指標が報告されない。
  • 一部の GKE ダッシュボードとグラフにギャップがあります。
  • Pod レベルのネットワーキングでの接続の問題。

これらのわかりにくい症状が見られた場合は、次のステップとして CrashLoopBackOff イベントが発生したかどうかを確認する必要があります。

CrashLoopBackOff イベントを確認する

CrashLoopBackOff イベントを確認して調査するには、Kubernetes イベントとコンテナのアプリログから証拠を収集します。この 2 つのソースは、問題について異なるが補完的な見解を提供します。

  • Kubernetes イベントは、Pod がクラッシュしていることを確認します。
  • コンテナのアプリログを見ると、コンテナ内のプロセスが失敗した理由を確認できます。

この情報を表示するには、次のいずれかのオプションを選択します。

コンソール

Kubernetes イベントとアプリログを表示するには、次の操作を行います。

  1. Trusted Cloud コンソールで、[ワークロード] ページに移動します。

    [ワークロード] に移動

  2. 調査するワークロードを選択します。[概要] タブまたは [詳細] タブに、ワークロードのステータスに関する詳細情報が表示されます。

  3. [管理対象 Pod] セクションで、問題のある Pod の名前をクリックします。

  4. Pod の詳細ページで、次の項目を調べます。

    • Kubernetes イベントの詳細を表示するには、[イベント] タブに移動します。
    • コンテナのアプリログを表示するには、[ログ] タブに移動します。このページには、アプリ固有のエラー メッセージやスタック トレースが表示されます。

kubectl

Kubernetes イベントとアプリログを表示するには、次の操作を行います。

  1. クラスタで実行されているすべての Pod のステータスを表示します。

    kubectl get pods
    

    出力は次のようになります。

    NAME       READY  STATUS             RESTARTS  AGE
    POD_NAME   0/1    CrashLoopBackOff   23        8d
    

    出力で、次の列を確認します。

    • Ready: 準備完了したコンテナの数を確認します。この例では、0/1 は、想定される 1 つのコンテナのうち 0 個が準備完了状態であることを示しています。この値は問題の明確な兆候です。
    • Status: ステータスが CrashLoopBackOff の Pod を探します。
    • Restarts: 値が大きいほど、Kubernetes がコンテナの起動を繰り返し試みて失敗していることを示します。
  2. 失敗した Pod を特定したら、その Pod の状態に関連するクラスタレベルのイベントを確認します。

    kubectl describe pod POD_NAME -n NAMESPACE_NAME
    

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

    • POD_NAME: kubectl get コマンドの出力で特定した Pod の名前。
    • NAMESPACE_NAME: Pod の Namespace

    出力は次のようになります。

    Containers:
    container-name:
    ...
      State:          Waiting
        Reason:       CrashLoopBackOff
      Last State:     Terminated
        Reason:       StartError
        Message:      failed to create containerd task: failed to create shim task: context deadline exceeded: unknown
        Exit Code:    128
        Started:      Thu, 01 Jan 1970 00:00:00 +0000
        Finished:     Fri, 27 Jun 2025 16:20:03 +0000
      Ready:          False
      Restart Count:  3459
    ...
    Conditions:
    Type                        Status
    PodReadyToStartContainers   True
    Initialized                 True
    Ready                       False
    ContainersReady             False
    PodScheduled                True
    ...
    Events:
    Type     Reason   Age                     From     Message
    ----     ------   ----                    ----     -------
    Warning  Failed   12m (x216 over 25h)     kubelet  Error: context deadline exceeded
    Warning  Failed   8m34s (x216 over 25h)   kubelet  Error: context deadline exceeded
    Warning  BackOff  4m24s (x3134 over 25h)  kubelet  Back-off restarting failed container container-name in pod failing-pod(11111111-2222-3333-4444-555555555555)
    

    出力で、次のフィールドを調べて CrashLoopBackOff イベントの兆候を確認します。

    • State: コンテナの状態は、理由 CrashLoopBackOffWaiting と表示される可能性があります。
    • Last State: 以前に終了したコンテナの状態。Terminated ステータスを探し、終了コードを確認して、クラッシュ(ゼロ以外の終了コード)または予期しない正常終了(ゼロの終了コード)が発生したかどうかを確認します。
    • Events: クラスタ自体が行ったアクション。コンテナの起動に関するメッセージを探します。その後に、liveness プローブの失敗や Back-off restarting failed container などのバックオフ警告が続いているかどうかを確認します。
  3. Pod が失敗した理由の詳細を確認するには、アプリのログを表示します。

    kubectl logs POD_NAME --previous
    

    --previous フラグは、終了した前のコンテナからログを取得します。このログには、クラッシュの原因を示す特定のスタック トレースやエラー メッセージが含まれています。現在のコンテナが新しすぎて、ログが記録されていない可能性があります。

    出力で、プロセスが終了する原因となるアプリ固有のエラーを探します。カスタムメイドのアプリを使用している場合は、アプリを作成したデベロッパーがこれらのエラー メッセージを解釈するのに最も適しています。プリビルド アプリを使用している場合、多くの場合、アプリ独自のデバッグ手順が提供されています。

クラッシュループしている Pod のインタラクティブ ハンドブックを使用する

CrashLoopBackOff イベントを確認したら、インタラクティブ ハンドブックを使用してトラブルシューティングを開始します。

  1. Trusted Cloud コンソールで、[GKE Interactive Playbook - Crashlooping Pods] ページに移動します。

    クラッシュ ループしている Pod に移動する

  2. [クラスタ] リストで、トラブルシューティングするクラスタを選択します。クラスタが見つからない場合は、[フィルタ] フィールドにクラスタの名前を入力します。

  3. [Namespace] リストで、トラブルシューティングする Namespace を選択します。Namespace が見つからない場合は、[フィルタ] フィールドに Namespace を入力します。

  4. 各セクションを確認して、次の質問に答えます。

    1. アプリのエラーを特定する: 再起動中のコンテナ
    2. メモリ不足の問題を調査する: アプリに関する構成ミスやエラーの有無
    3. ノードの中断を調査する: ノードリソース上で中断があると、コンテナは再起動されますか?
    4. livenessProbe 失敗の調査: liveness プローブがコンテナを停止させていますか?
    5. 変更イベントの相関関係: コンテナのクラッシュが始まった時刻の前後に何が起きていたでしょうか。
  5. 省略可: 今後 CrashLoopBackOff イベントが発生した場合に通知を受け取るには、[今後の対応のヒント] セクションで [アラートを作成する] を選択します。

ハンドブックを使用しても問題が解決しない場合は、ガイドの残りの部分を読んで、CrashLoopBackOff イベントの解決方法について詳しく確認してください。

CrashLoopBackOff イベントを解決する

以降のセクションでは、CrashLoopBackOff イベントの最も一般的な原因の解決方法について説明します。

リソースの枯渇を解決する

CrashLoopBackOff イベントは、多くの場合、メモリ不足(OOM)の問題が原因で発生します。kubectl describe の出力に次の内容が表示されている場合は、これが原因であることを確認できます。

Last State: Terminated
  Reason: OOMKilled

OOM イベントの診断と解決方法については、OOM イベントのトラブルシューティングをご覧ください。

livenessProbe の失敗を解決する

livenessProbe は、kubelet によって実行される定期的なヘルスチェックです。プローブが指定された回数(デフォルトは 3 回)失敗すると、kubelet はコンテナを再起動します。プローブの失敗が続くと、CrashLoopBackOff イベントが発生する可能性があります。

ライブネス プローブが原因かどうかを確認する

ライブネス プローブの失敗が CrashLoopBackOff イベントをトリガーしているかどうかを確認するには、kubelet ログをクエリします。これらのログには、プローブの失敗と後続の再起動を示す明示的なメッセージが含まれていることがよくあります。

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

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

  2. クエリペインで、次のクエリを入力して、ライブネス プローブに関連する再起動をフィルタします。

    resource.type="k8s_node"
    log_id("kubelet")
    jsonPayload.MESSAGE:"failed liveness probe, will be restarted"
    resource.labels.cluster_name="CLUSTER_NAME"
    

    CLUSTER_NAME は、使用するクラスタの名前に置き換えます。

  3. 出力を確認します。Liveness Probe の失敗が CrashLoopBackOff イベントの原因である場合、クエリは次のようなログメッセージを返します。

    Container probe failed liveness probe, will be restarted
    

ライブネス プローブが CrashLoopBackOff イベントの原因であることを確認したら、一般的な原因のトラブルシューティングに進みます。

liveness プローブの構成を確認する

プローブの構成ミスは、CrashLoopBackOff イベントの頻繁な原因です。プローブのマニフェストで次の設定を確認します。

  • プローブタイプを確認する: プローブの構成は、アプリが健全性をレポートする方法と一致している必要があります。たとえば、アプリにヘルスチェック URL(/healthz など)がある場合は、httpGet プローブタイプを使用します。コマンドの実行によってヘルスが決定される場合は、exec プローブタイプを使用します。たとえば、ネットワーク ポートが開いてリッスンしているかどうかを確認するには、tcpSocket プローブタイプを使用します。
  • プローブ パラメータを確認する:
    • パス(httpGet プローブタイプの場合): HTTP パスが正しく、アプリがそのパスでヘルスチェックを提供していることを確認します。
    • ポート: プローブで構成されたポートが実際にアプリで使用され、公開されていることを確認します。
    • コマンド(exec プローブタイプの場合): コマンドがコンテナ内に存在し、成功時に終了コード 0 を返し、構成された timeoutSeconds 期間内に完了することを確認します。
    • タイムアウト: timeoutSeconds の値が、特に起動時や負荷がかかっているときに、アプリが応答するのに十分であることを確認します。
    • 初期遅延(initialDelaySeconds: プローブが開始される前にアプリが起動するのに十分な初期遅延があるかどうかを確認します。

詳細については、Kubernetes ドキュメントの livenessProbe、readinessProbe、startupProbe の構成をご覧ください。

CPU とディスク I/O の使用率を検査する

リソース競合によりプローブ タイムアウトが発生し、これが liveness プローブの失敗の主な原因となります。リソース使用率が liveness プローブの失敗の原因であるかどうかを確認するには、次の解決策を試してください。

  • CPU 使用率を分析する: プローブ間隔中に、影響を受けるコンテナとそれが実行されているノードの CPU 使用率をモニタリングします。追跡する重要な指標は kubernetes.io/container/cpu/core_usage_time です。コンテナまたはノードの CPU 使用率が高いと、アプリがプローブに時間内に応答できなくなる可能性があります。
  • ディスク I/O をモニタリングする: ノードのディスク I/O 指標を確認します。compute.googleapis.com/guest/disk/operation_time 指標を使用すると、ディスク オペレーションに要した時間を評価できます。この時間は、読み取りと書き込みで分類されます。ディスク I/O が多いと、コンテナの起動、アプリの初期化、アプリ全体のパフォーマンスが大幅に低下し、プローブのタイムアウトが発生する可能性があります。

大規模な導入に対応する

多数の Pod が同時にデプロイされるシナリオ(ArgoCD などの CI/CD ツールによる場合など)では、新しい Pod の急増によりクラスタ リソースが過負荷になり、コントロール プレーンのリソースが枯渇する可能性があります。リソースが不足すると、アプリの起動が遅延し、アプリの準備が整う前に liveness プローブが繰り返し失敗する可能性があります。

この問題を解決するには、次のことを試してください。

  • 段階的なデプロイを実装する: ノードリソースの過負荷を避けるため、Pod をバッチでデプロイしたり、長期間にわたってデプロイしたりする戦略を実装します。
  • ノードの再構成またはスケーリング: 段階的なデプロイが実現できない場合は、高速または大容量のディスク、または Persistent Volume Claim を使用してノードをアップグレードし、I/O 需要の増加に適切に対応することを検討してください。クラスタの自動スケーリングが適切に構成されていることを確認します。
  • 待機して観察する: クラスタのリソースが極端に不足していない場合、ワークロードは大幅な遅延(30 分以上かかる場合もあります)の後に最終的にデプロイされることがあります。

一時的なエラーに対処する

アプリの起動時や初期化時に一時的なエラーや遅延が発生し、プローブが最初に失敗することがあります。アプリが最終的に復元する場合は、ライブネス プローブのマニフェストの initialDelaySeconds フィールドまたは failureThreshold フィールドで定義されている値を増やすことを検討してください。

アドレス プローブのリソース消費

まれに、liveness プローブの実行自体が大量のリソースを消費し、リソース制約がトリガーされて、OOM kill によりコンテナが終了することがあります。プローブ コマンドが軽量であることを確認します。軽量なプローブは迅速かつ確実に実行される可能性が高く、アプリの実際の健全性を正確に報告する忠実度が高くなります。

アプリの構成ミスを解決する

アプリの構成ミスにより、多くの CrashLoopBackOff イベントが発生します。アプリが停止した理由を把握するには、まず終了コードを調べます。このコードによって、トラブルシューティングのパスが決まります。

  • 終了コード 0 は正常な終了を示しますが、長時間実行されるサービスでは予期しないものであり、コンテナのエントリ ポイントまたはアプリの設計に問題があることを示しています。
  • ゼロ以外の終了コードはアプリのクラッシュを示し、構成エラー、依存関係の問題、コードのバグに焦点を当てます。

終了コードを確認する

アプリの終了コードを確認する手順は次のとおりです。

  1. Pod の説明を取得します。

    kubectl describe pod POD_NAME -n NAMESPACE_NAME
    

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

    • POD_NAME: 問題のある Pod の名前。
    • NAMESPACE_NAME: Pod の Namespace
  2. 出力で、関連するコンテナの Last State セクションにある Exit Code フィールドを確認します。終了コードが 0 の場合は、正常な終了のトラブルシューティング(終了コード 0)をご覧ください。終了コードが 0 以外の数値の場合は、アプリのクラッシュのトラブルシューティング(ゼロ以外の終了コード)をご覧ください。

正常終了(終了コード 0)のトラブルシューティング

通常、終了コード 0 は、コンテナのプロセスが正常に終了したことを意味します。これはタスクベースの Job で望ましい結果ですが、Deployment、StatefulSet、ReplicaSet などの長時間実行されるコントローラでは問題を示す可能性があります。

これらのコントローラは、Pod が常に実行されるように機能するため、終了は修正されるべき障害として扱われます。kubelet は、Pod の restartPolicy(デフォルトは Always)に準拠し、正常に終了した後でもコンテナを再起動することで、この動作を強制します。このアクションによりループが作成され、最終的に CrashLoopBackOff ステータスがトリガーされます。

予期しない正常終了の最も一般的な原因は次のとおりです。

  • コンテナ コマンドが永続プロセスを開始しない: コンテナは、初期プロセス(command または entrypoint)が実行されている間のみ実行されます。このプロセスが長時間実行されるサービスでない場合、コマンドが完了するとすぐにコンテナが終了します。たとえば、["/bin/bash"] のようなコマンドは、実行するスクリプトがないため、すぐに終了します。この問題を解決するには、コンテナの初期プロセスが継続的に実行されるプロセスを開始するようにします。

  • 作業キューが空になるとワーカーアプリが終了する: 多くのワーカーアプリは、キューでタスクを確認し、キューが空の場合はクリーンに終了するように設計されています。この問題を解決するには、Job コントローラ(完了まで実行されるタスク用に設計されている)を使用するか、アプリのロジックを変更して永続サービスとして実行します。

  • 構成の欠落または無効な構成が原因でアプリが終了する: コマンドライン引数、環境変数、重要な構成ファイルなど、必要な起動手順が欠落している場合、アプリがすぐに終了することがあります。

    この問題を解決するには、まずアプリのログで、構成の読み込みやパラメータの欠落に関連する特定のエラー メッセージを確認します。次に、次のことを確認します。

    • アプリの引数または環境: 必要なコマンドライン引数と環境変数がすべて、アプリで想定されているとおりにコンテナに正しく渡されていることを確認します。
    • 構成ファイルの存在: 必要な構成ファイルがコンテナ内の想定されるパスに存在することを確認します。
    • 構成ファイルの内容: 構文エラー、必須フィールドの欠落、値の誤りがないか、構成ファイルの内容と形式を検証します。

    この問題の一般的な例は、ConfigMap ボリュームでマウントされたファイルから読み取るようにアプリが構成されている場合です。ConfigMap がアタッチされていない、空である、キーの名前が間違っている場合、構成がないときに終了するように設計されたアプリは、終了コード 0 で停止する可能性があります。このような場合は、次の設定を確認します。 - Pod のボリューム定義の ConfigMap 名が実際の名前と一致している。- ConfigMap 内のキーは、マウントされたボリューム内のファイル名としてアプリが想定する内容と一致します。

アプリのクラッシュ(ゼロ以外の終了コード)のトラブルシューティング

コンテナがゼロ以外のコードで終了すると、Kubernetes はコンテナを再起動します。エラーの原因となった根本的な問題が解決されない場合、アプリは再びクラッシュし、サイクルが繰り返されて、最終的に CrashLoopBackOff 状態になります。

ゼロ以外の終了コードは、アプリ自体でエラーが発生したことを示す明確なシグナルです。これにより、デバッグ作業はアプリの内部動作と環境に向けられます。この終了は、次のような問題が原因で発生することがよくあります。

  • 構成エラー: ゼロ以外の終了コードは、アプリの構成または実行環境の問題を示していることがよくあります。アプリで次の一般的な問題がないか確認します。

    • 構成ファイルが見つからない: アプリが必要な構成ファイルを見つけられないか、アクセスできない可能性があります。
    • 無効な構成: 構成ファイルに構文エラー、不正な値、互換性のない設定が含まれていると、アプリがクラッシュする可能性があります。
    • 権限の問題: アプリに、構成ファイルの読み取りまたは書き込みに必要な権限がない可能性があります。
    • 環境変数: 環境変数が正しくないか、欠落していると、アプリが誤動作したり、起動に失敗したりする可能性があります。
    • 無効な entrypoint または command: コンテナの entrypoint フィールドまたは command フィールドで指定されたコマンドが正しくない可能性があります。この問題は、実行可能ファイルへのパスが間違っているか、ファイル自体がコンテナ イメージに存在しない場合に、新しくデプロイされたイメージで発生する可能性があります。この構成ミスにより、128 終了コードが返されることがよくあります。
    • 制御されていないイメージの更新(:latest タグ): ワークロード イメージで :latest タグを使用している場合、新しい Pod は、破壊的変更を導入する更新されたイメージ バージョンを pull する可能性があります。

      一貫性と再現性を確保するため、本番環境では常に特定の不変のイメージタグ(v1.2.3 など)または SHA ダイジェスト(sha256:45b23dee08... など)を使用してください。この方法により、毎回同じイメージ コンテンツが確実に取得されます。

  • 依存関係の問題: 依存している他のサービスに接続できない場合、またはそれらにアクセスするための認証に失敗した場合や権限が不足している場合、アプリがクラッシュする可能性があります。

    • 外部サービスが利用できない: アプリが依存している外部サービス(データベースや API など)に、ネットワーク接続の問題やサービス停止が原因でアクセスできない可能性があります。この問題をトラブルシューティングするには、Pod に接続します。詳細については、Kubernetes ドキュメントの実行中の Pod のデバッグをご覧ください。

      Pod に接続したら、コマンドを実行してファイルやデータベースへのアクセスを確認したり、ネットワークをテストしたりできます。たとえば、curl などのツールを使用して、サービスの URL にアクセスできます。この操作を行うと、問題の原因がネットワーク ポリシー、DNS、サービス自体にあるかどうかを判断できます。

    • 認証の失敗: 認証情報が正しくないため、アプリが外部サービスで認証できない可能性があります。コンテナのログで、401 Unauthorized(認証情報が無効)や 403 Forbidden(権限が不足)などのメッセージを確認します。これらのメッセージは、多くの場合、Pod のサービス アカウントに外部 Trusted Cloud by S3NSサービス呼び出しを行うために必要な IAM ロールがないことを示しています。

      GKE Workload Identity 連携を使用する場合は、プリンシパル ID にタスクに必要な権限があることを確認します。GKE Workload Identity Federation を使用してプリンシパルに IAM ロールを付与する方法については、認可とプリンシパルを構成するをご覧ください。また、GKE メタデータ サーバーのリソース使用量が上限を超えていないことを確認する必要があります。

    • タイムアウト: 外部サービスからのレスポンスを待機しているときにアプリがタイムアウトし、クラッシュにつながる可能性があります。

  • アプリ固有のエラー: 構成と外部依存関係が正しいと思われる場合は、エラーがアプリのコード内にある可能性があります。アプリログを調べて、次の一般的な内部エラーがないか確認します。

    • 未処理の例外: アプリログには、未処理の例外やコード関連のバグを示すスタック トレースやエラー メッセージが含まれている場合があります。
    • デッドロックまたはライブロック: アプリがデッドロック状態に陥っている可能性があります。この状態では、複数のプロセスが互いの完了を待機しています。この場合、アプリは終了しない可能性がありますが、無期限に応答を停止します。
    • ポートの競合: 別のプロセスですでに使用されているポートにバインドしようとすると、アプリが起動に失敗する可能性があります。
    • 互換性のないライブラリ: アプリが、ランタイム環境に存在しないライブラリや、ランタイム環境と互換性のないライブラリに依存している可能性があります。

    根本原因を特定するには、コンテナのログで特定のエラー メッセージまたはスタック トレースを調べます。この情報は、アプリコードを修正するか、リソース上限を調整するか、環境の構成を修正するかを判断する際に役立ちます。ログの詳細については、GKE ログについてをご覧ください。

次のステップ

  • このドキュメントで問題を解決できない場合は、サポートを受けるで、次のトピックに関するアドバイスなど、詳細なヘルプをご覧ください。