Kubernetes CrashLoopBackOffとは？ そして、修復する方法

本文の内容は、2022年8月25日に<span>Javier Martínez</span>が投稿したブログ(https://sysdig.com/blog/debug-kubernetes-crashloopbackoff/)を元に日本語に翻訳・再構成した内容となっております。<br /><br /><strong>CrashLoopBackOffは、Podで発生している再起動ループを表すKubernetesステートです。</strong>Pod内のコンテナが起動されますが、クラッシュして再起動されることを何度も繰り返します。<br /><br />Kubernetesは、エラーを修正するチャンスを与えるために、再起動の間のバックオフ時間を長くして待機します。このように、CrashLoopBackOffはそれ自体がエラーではなく、Podが正しく起動できないようなエラーが起きていることを示しています。<br /><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01.png" alt="Kubernetes Crashloopbackoff, an illustrated representation. A Pod is in a loop between Running, Failed, and Waiting." width="1200" height="660" class="img-lightbox aligncenter size-full wp-image-53160 u-drop-shadow entered lazyloaded" data-lazy-srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-350x193.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-1170x644.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-768x422.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-175x96.png 175w, / 1w" data-lazy-sizes="(max-width: 1200px) 100vw, 1200px" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01.png" data-ll-status="loaded" sizes="(max-width: 1200px) 100vw, 1200px" srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-350x193.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-1170x644.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-768x422.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-01-175x96.png 175w, / 1w" /><em>KubernetesのCrashloopBackoff、図解で表すと。PodはRunning、Failed、Waitingの間でループしている。</em><br /><br />なお、再起動するのは、<span> </span><code>restartPolicy</code><span> </span>が<span> </span><code>Always</code>（デフォルト）または<code>OnFailure</code>に設定されているためです。そして、<a href="https://www.linkedin.com/pulse/kubelet%25E3%2582%2592%25E3%2583%25A2%25E3%2583%258B%25E3%2582%25BF%25E3%2583%25AA%25E3%2583%25B3%25E3%2582%25B0%25E3%2581%2599%25E3%2582%258B%25E6%2596%25B9%25E6%25B3%2595-takao-shimizu/?trackingId=a%2BLF4VZlRBm2koXNcbDUpA%3D%3D">kubelet</a>はこの設定を読み込んでPod内のコンテナを再起動し、ループを発生させています。この動作は本当に便利です。足りないリソースの読み込みが完了するまでの時間を確保し、問題を検出してデバッグすることができるからです - 詳しくは後述します。<br /><br />CrashLoopの部分はこれで説明しましたが、<strong>BackOffの時間</strong>についてはどうでしょうか？基本的には、再起動の間に指数関数的に発生する遅延（10秒、20秒、40秒、...）で、上限は5分です。Podの状態がCrashLoopBackOffと表示されている場合、現在Podを再び再起動する前に表示された時間だけ待機していることを意味します。そして、それが修正されない限り、おそらく再び失敗します。<br /><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02.png" alt="Kubernetes Crashloopbackoff, an illustrated representation. A Pod is in a loop. It tries to run, but it fails, so it goes to a Failed state. If waits a bit to help you debug, then it tries to run again. If the issue is not fixed, we are in a loop. It fails again." width="1200" height="600" class="img-lightbox aligncenter size-full wp-image-53161 u-no-shadow entered lazyloaded" data-lazy-srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-175x88.png 175w, / 1w" data-lazy-sizes="(max-width: 1200px) 100vw, 1200px" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02.png" data-ll-status="loaded" sizes="(max-width: 1200px) 100vw, 1200px" srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-02-175x88.png 175w, / 1w" /><em>KubernetesのCrashloopbackoff、図解表現。あるPodがループしている。実行しようとするが、失敗するのでFailedの状態になる。デバッグのために少し待つと、また実行しようとする。問題が解決されないと、ループ状態になります。また失敗する。</em><br /><br />この記事で、把握できることは：<br /><br /><ol><li>CrashLoopBackOffとは何ですか？</li><li>CrashLoopBackOffの問題を検出する方法</li><li>CrashLoopBackOffが発生する一般的な原因</li><li>CrashLoopBackOffをデバッグするためのKubernetesツール</li><li>Prometheusを使ったCrashLoopBackOffの検出方法</li></ol><br /><h2>クラスター内のCrashLoopBackOffを検出するには？</h2>ほとんどの場合、<span> </span><code>kubectl get pods</code>でPodをリストアップして、この状態のPodを1つ以上発見したはずです。<br /><br /><pre class="prettyprint">$ kubectl get pods
NAME                     READY     STATUS             RESTARTS   AGE
flask-7996469c47-d7zl2   1/1       Running            1          77d
flask-7996469c47-tdr2n   1/1       Running            0          77d
nginx-5796d5bc7c-2jdr5   0/1       CrashLoopBackOff   2          1m
nginx-5796d5bc7c-xsl6p   0/1       CrashLoopBackOff   2          1m</pre><br />出力から、最後の2つのPodを確認することができます。<br /><br /><ul><li><span> </span><code>READY</code><span> </span>状態ではありません<span> (</span><code>0/1</code><span>)</span></li><li>それらの<strong>status</strong>は<span> </span><code>CrashLoopBackOff</code>を表示しています。</li><li><span> </span><code>RESTARTS</code><span> </span>列には、1つ以上の再起動の表示があります。</li></ul>これらの3つのシグナルは、私たちが説明したように、Podが失敗しており、再起動されていることを指しています。再起動と再起動の間には、<span> </span><code>CrashLoopBackOff </code>として表される猶予期間があります。<br /><br />また、<span> </span><code>Running</code><span> </span>や<span> </span><code>Failed</code><span> </span>の状態にある短い時間の中で、Podを見つけることができる「幸運」もあるかもしれません。<br /><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03.png" alt="A timeline of a CrashloopBackoff. Everytime it fails, the BackoffTime and the Restart Count are increased" width="1200" height="600" class="img-lightbox aligncenter size-full wp-image-53162 u-no-shadow entered lazyloaded" data-lazy-srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-175x88.png 175w, / 1w" data-lazy-sizes="(max-width: 1200px) 100vw, 1200px" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03.png" data-ll-status="loaded" sizes="(max-width: 1200px) 100vw, 1200px" srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-03-175x88.png 175w, / 1w" /><em>CrashloopBackoffのタイムライン。失敗するたびにBackoffTimeとRestart Countが増加する</em><br /><br /><h2>CrashLoopBackOffが発生する一般的な理由</h2>CrashLoopBackOffは、Podをクラッシュさせている実際のエラーではないことに注意することが重要です。<span> </span><code>STATUS</code><span> </span>カラムにループが発生していることを表示しているだけであることを思い出してください。コンテナに影響を与える根本的なエラーを見つける必要があります。<br /><br />実際のアプリケーションにリンクしているエラーには、次のようなものがあります：<br /><br /><ul><li><strong>設定ミス：</strong>設定ファイルのタイプミスのようなものです。</li><li><strong>リソースが利用できない：</strong>マウントされていないPersistedVolumeのようなもの。</li><li><strong>コマンドライン引数が間違っている：</strong>見つからないか、正しくないもの。</li><li><strong>バグと例外：</strong>これは、アプリケーションに特有のもので、何でもありです。</li></ul>そして最後に、ネットワークとパーミッションからのエラーです：<br /><br /><ul><li><strong>既存のポートをバインド</strong>しようとした。</li><li>メモリ制限が低すぎるため、コンテナは <a href="https://www.linkedin.com/pulse/kubernetes-oom%25E3%2581%258A%25E3%2582%2588%25E3%2581%25B3cpu%25E3%2582%25B9%25E3%2583%25AD%25E3%2583%2583%25E3%2583%2588%25E3%2583%25AB%25E3%2581%25AE%25E3%2583%2588%25E3%2583%25A9%25E3%2583%2596%25E3%2583%25AB%25E3%2582%25B7%25E3%2583%25A5%25E3%2583%25BC%25E3%2583%2586%25E3%2582%25A3%25E3%2583%25B3%25E3%2582%25B0%25E6%2596%25B9%25E6%25B3%2595-takao-shimizu/?trackingId=mb7lK2D0TSa%2BUJLDYhveNQ%3D%3D">Out Of Memory で強制終了</a>した。</li><li><a href="https://sysdig.com/blog/whats-new-kubernetes-1-16/#950">liveness probes</a>のエラーは、Podが準備完了であることをレポートしていない。</li><li><strong>読み取り専用のファイルシステム</strong>、または一般的なパーミッションが不足している。</li></ul>繰り返しますが、これはあくまで可能性のある原因のリストであり、他にもたくさんある可能性があります。<br /><br />それでは、さらに深く掘り下げて、本当に原因を見つける方法を見ていきましょう。<br /><br /><h2>CrashLoopBackOff状態のデバッグ、トラブルシュート、修復方法</h2>前のセクションで、Pod が CrashLoopBackOff 状態になる理由がたくさんあることを理解しました。さて、どれが影響しているのかを知るにはどうしたらよいでしょうか？デバッグに使用できるいくつかのツールと、それをどの順番で使用するかを確認しましょう。<br /><br />これが最善の策になるかもしれません：<br /><br /><ol><li><strong>Pod description</strong>をチェックする。</li><li><strong>Podのログ</strong>をチェックする。</li><li><strong>イベント</strong>をチェックする。</li><li><strong>デプロイメント</strong>をチェックする。</li></ol><h4><br />1. Pod descriptionを確認する - kubectl describe pod</h4><span> </span><code>kubectl describe pod</code><span> </span>コマンドは、特定のPodとそのコンテナの詳細情報を提供します。<br /><br /><pre class="prettyprint">$ kubectl describe pod the-pod-name
Name:         the-pod-name
Namespace:    default
Priority:     0
…
State:          Waiting
Reason:       CrashLoopBackOff
Last State:     Terminated
Reason:       Error
…
Warning  BackOff                1m (x5 over 1m)   kubelet, ip-10-0-9-132.us-east-2.compute.internal  Back-off restarting failed container
…</pre><br />describeの出力から、以下の情報を抽出することができます。<br /><br /><ul><li>現在のPodの<span> </span><code>State</code><span> </span>は<span> </span><code>Waiting</code>です。</li><li>Waiting状態の理由は <strong>"CrashLoopBackOff "</strong>です。</li><li>最後の（または前の）状態は <strong>"Terminated "</strong>です。</li><li>最後の終了の理由は <strong>"Error"</strong>。</li></ul>これまで説明してきたループの挙動と一致していますね。<br /><br /><span> </span><code>kubectl describe pod</code><span> </span>を使うことで、以下のような設定ミスがないか確認できます。<br /><br /><ul><li>Podの定義</li><li>コンテナ</li><li>コンテナ用に引き出されたイメージ</li><li>コンテナに割り当てられたリソース</li><li>引数の誤りや欠落</li><li>...</li></ul><br /><pre class="prettyprint">…
Warning  BackOff                1m (x5 over 1m)   kubelet, ip-10-0-9-132.us-east-2.compute.internal  Back-off restarting failed container
…</pre><br />最後の行に、このPodに関連する直近のイベントのリストが表示されていますが、その中の1つに<span> </span><code>Back-off restarting failed container</code>があります。これは、再起動ループに関連するイベントです。複数の再起動が起こったとしても、1行だけであるべきです。<br /><br /><h4>2. ログを確認する - kubectl logs</h4>特定のPodのログを確認することができます：<br /><br /><pre class="prettyprint">kubectl logs mypod</pre><br />あるいは、そのPodに含まれるコンテナのログも見ることができます：<br /><br /><pre class="prettyprint">kubectl logs mypod -c mycontainer</pre><br />影響を受けるPodに間違った値がある場合、ログに有用な情報が表示されている可能性があります。<br /><br /><h4>3. イベントを確認する - kubectl get events</h4>リストで表示することができます：<br /><br /><pre class="prettyprint">kubectl get events</pre><br />また、1つのPodのイベントを全てリストアップすることも可能です：<br /><br /><pre class="prettyprint">kubectl get events --field-selector involvedObject.name=mypod</pre><br />この情報は<span> </span><code>describe pod</code><span> </span>の出力の下部にも表示されることに注意してください。<br /><br /><h4>4. デプロイメントを確認する - kubectl describe deployment</h4>以下のコマンドで情報を取得することができます：<br /><br /><pre class="prettyprint">kubectl describe deployment mydeployment</pre><br />もし、望ましいPodの状態を定義しているでデプロイメントがあれば、その中にCrashLoopBackOffの原因となっている設定ミスが含まれている可能性があります。<br /><br /><h4>すべてをまとめる</h4>次の例では、コマンドの引数でエラーが見つかったログを掘り下げる方法を見ることができます。<br /><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04.png" alt="Debugging a Crashloopbackoff. It shows three terminals with the relationship between several debug commands." width="1200" height="600" class="img-lightbox aligncenter size-full wp-image-53163 u-no-shadow entered lazyloaded" data-lazy-srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-175x88.png 175w, / 1w" data-lazy-sizes="(max-width: 1200px) 100vw, 1200px" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04.png" data-ll-status="loaded" sizes="(max-width: 1200px) 100vw, 1200px" srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-04-175x88.png 175w, / 1w" /><em>CrashloopBackoffのデバッグ。これは、いくつかのデバッグコマンドの関係で3つの端末を示しています。</em><br /><br /><h2>PrometheusでCrashLoopBackOffを検出する方法</h2><a href="https://sysdig.jp/blog/prometheus-query-examples/">クラウド監視にPrometheus</a>を使用している場合、CrashLoopBackOffが発生したときにアラートを出すのに役立つヒントを紹介します。<br /><br />以下の式を使用することで、CrashLoopBackOff<span> </span><code>status</code><span> </span>にあるクラスター内のコンテナを迅速にスキャンできます（<a href="https://docs.sysdig.com/en/docs/installation/sysdig-agent/agent-configuration/enable-kube-state-metrics/">Kube State Metrics</a>が必要です）。<br /><br /><pre class="prettyprint">kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"} == 1</pre><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-05.png" alt="PromQL example of CrashLoopBackOff detection based on pod status waiting." width="1200" height="600" class="img-lightbox aligncenter size-full wp-image-53163 u-no-shadow entered lazyloaded" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-05.png" data-ll-status="loaded" /><br />また、Podで起きている再起動の量をトレースすることも可能です：<br /><br /><pre class="prettyprint">rate(kube_pod_container_status_restarts_total[5m]) &gt; 0</pre><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-06.png" alt="PromQL example of CrashLoopBackOff detection based on restart rate" width="1200" height="600" class="img-lightbox aligncenter size-full wp-image-53163 u-no-shadow entered lazyloaded" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-06.png" data-ll-status="loaded" /><br /><br /><strong>注意：</strong> クラスターで起きているすべてのリスタートがCrashLoopBackOffのステータスに関連しているわけではありません。<br /><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07.png" alt="Correlation between restarts and crashloopbackoff. Not all restarts are caused by a crashloopbackoff." width="1200" height="600" class="img-lightbox size-full wp-image-53164 u-no-shadow entered lazyloaded" data-lazy-srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-175x88.png 175w, / 1w" data-lazy-sizes="(max-width: 1200px) 100vw, 1200px" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07.png" data-ll-status="loaded" sizes="(max-width: 1200px) 100vw, 1200px" srcset="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07.png 1200w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-350x175.png 350w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-1170x585.png 1170w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-768x384.png 768w, https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-07-175x88.png 175w, / 1w" /><br /><em>CrashLoopBackOffの期間ごとに再起動があるはずですが（1）、CrashLoopBackOffとは関係ない再起動がある可能性もあります（2）。</em><br /><br />その後、以下のようなPrometheus Alerting Ruleを作成し、いずれかのPodがこの状態になった場合に通知を受けることができます。<br /><br /><pre class="prettyprint">- alert: CrashLoopBackOffAlert
  expr: rate(kube_pod_container_status_restarts_total[5m]) &gt; 0
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: Pod is in CrashLoopBackOff state
  description: Pod {{ $labels.pod }} in {{ $labels.namespace }} has a container {{ $labels.container }} which is causing a CrashLoopBackOff</pre><br /><br /><h2>まとめ</h2>今回は、CrashLoopBackOffはそれ自体がエラーではなく、Podで発生している再試行ループを通知しているだけであることを確認しました。<br /><br />どのような状態を通過するのか、そしてそれを<span> </span><code>kubectl</code><span> </span>コマンドで追跡する方法について見てきました。<br /><br />また、この状態を引き起こす可能性のある一般的な設定ミスや、デバッグに使用できるツールについても見てきました。<br /><br />最後に、PodでCrashLoopBackOffイベントを追跡しアラートを出す際に、Prometheusがどのように役立つかを確認しました。<br /><br />直感的なメッセージではありませんが、CrashLoopBackOffは意味のある便利な概念であり、何も恐れることはありません。<br /><hr /><h3>Sysdig MonitorでCrashLoopBackOffのデバッグを高速化する</h3>Sysdig Monitorの新しいKubernetesトラブルシューティング製品であるAdvisorは、トラブルシューティングを最大10倍高速化します。Advisorは、問題の優先順位付けされたリストと関連するトラブルシューティングデータを表示し、最大の問題領域を浮上させ、解決までの時間を加速させることができます。<br /><br /><img src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-08.gif" alt="How to debug a crashloopbackoff with Sysdig Monitor Advisor" width="1438" height="899" class="img-lightbox aligncenter size-full wp-image-53165 u-drop-shadow entered lazyloaded" data-lazy-src="https://sysdig.com/wp-content/uploads/What-is-Crashloopbackoff-08.gif" data-ll-status="loaded" /><em>Sysdig Monitor Advisorを使用してクラッシュループバックオフをデバッグする方法</em>