トラブルシューティング:Kubernetes Pod が Pending または CrashLoopBackOff でスタックする理由
Kubernetes は、コンテナ化されたアプリケーションのデプロイと管理方法に革命をもたらし、比類のないスケーラビリティと回復力を提供します。しかし、適切にオーケストレーションされた環境であっても、Pod は Running 状態に到達できない問題に遭遇することがあります。Pod の最も一般的でフラストレーションのたまる状態の 2 つは、Pending と CrashLoopBackOff です。Pod がこれらの状態にスタックする理由を理解し、効果的に診断する方法を学ぶことは、健全で信頼性の高いアプリケーションを維持するために不可欠です。
この記事では、Pod が Pending または CrashLoopBackOff 状態でスタックする一般的な原因を掘り下げていきます。リソースの制約、イメージのプル失敗から、アプリケーションレベルのエラー、設定ミスによるプローブまで、さまざまな問題を調査します。さらに重要なことに、これらのデプロイメントの頭痛の種を迅速に診断および解決するための実践的な kubectl コマンドを使用したステップバイステップガイドを提供し、アプリケーションがスムーズに実行されるようにします。
Pod の状態の理解:Pending vs. CrashLoopBackOff
トラブルシューティングに入る前に、これらの 2 つの状態が何を意味するかを理解することが重要です。
Pod の状態:Pending
Pending 状態の Pod は、Kubernetes スケジューラが Pod を受け入れたものの、まだワーカーノードに正常にスケジュールされていないか、すべてのコンテナが作成/初期化されていないことを意味します。これは通常、Pod がワーカーノードでのジャーニーを開始するのを妨げる問題を示しています。
Pod の状態:CrashLoopBackOff
CrashLoopBackOff 状態の Pod は、Pod 内のコンテナが繰り返し起動、クラッシュ、再起動を繰り返していることを意味します。Kubernetes は、ノードに過負荷をかけないように、再起動間に指数関数的なバックオフ遅延を実装しています。この状態は、コンテナ自体またはその直接の環境内で実行されているアプリケーションの問題をほぼ常に指します。
Pending 状態の Pod のトラブルシューティング
Pod が Pending の場合、最初に調べるべきはスケジューラと、それが配置されようとしているノードです。一般的な原因と診断手順は次のとおりです。
1. ノードのリソース不足
Pod が Pending になる最も頻繁な理由の 1 つは、クラスター内のどのノードも Pod の requests を満たすのに十分な利用可能なリソース(CPU、メモリ)を持っていないことです。スケジューラは適切なノードを見つけることができません。
診断手順:
-
Pod の説明を表示:
kubectl describe podコマンドがここで最も役立ちます。多くの場合、Pod がスケジュールできない理由を詳細に示すイベントが表示されます。
bash kubectl describe pod <pod-name> -n <namespace>
「FailedScheduling」のようなイベントと、「0/3 nodes are available: 3 Insufficient cpu」または「memory」のようなメッセージを探します。 -
ノードリソースの確認: ノードの現在のリソース使用量と容量を確認します。
bash kubectl get nodes kubectl top nodes # (metrics-server が必要)
解決策:
- クラスター容量の増強: Kubernetes クラスターにノードを追加します。
- Pod リソースリクエストの調整: Pod マニフェストの CPU およびメモリの
requestsが高すぎる場合は、それらを減らします。
yaml resources: requests: memory: "128Mi" cpu: "250m" - 他の Pod の退去: リソースを解放するために、ノードから優先度の低い Pod を手動で退去させます(注意して使用してください)。
2. イメージプルエラー
Kubernetes が Pod をノードにスケジュールできたとしても、ノードがコンテナイメージをプルできない場合、Pod は Pending のままになります。
一般的な原因:
- イメージ名/タグの誤り: イメージ名にタイプミスがあるか、存在しないタグを使用しています。
- プライベートレジストリ認証: プライベートレジストリ用の
ImagePullSecretsが欠落しているか、誤っています。 - ネットワークの問題: ノードがイメージレジストリに到達できません。
診断手順:
-
Pod の説明を表示: 再び、
kubectl describe podが鍵となります。「Failed」、「ErrImagePull」、「ImagePullBackOff」のようなイベントを探します。
bash kubectl describe pod <pod-name> -n <namespace>
例:Failed to pull image "my-private-registry/my-app:v1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for my-private-registry/my-app, repository does not exist or may require 'docker login' -
ImagePullSecrets の確認: Pod または ServiceAccount で
imagePullSecretsが正しく設定されているか確認します。
bash kubectl get secret <your-image-pull-secret> -o yaml -n <namespace>
解決策:
- イメージ名/タグの修正: デプロイメントマニフェストでイメージ名とタグを再確認します。
- ImagePullSecrets の設定:
docker-registryシークレットを作成し、それを Pod または ServiceAccount にリンクしていることを確認します。
bash kubectl create secret docker-registry my-registry-secret \n --docker-server=your-registry.com \n --docker-username=your-username \n --docker-password=your-password \n --docker-email=your-email -n <namespace>
次に、Pod 仕様に追加します。
```yaml
spec:
imagePullSecrets:- name: my-registry-secret
containers:
...
```
- name: my-registry-secret
- ネットワーク接続: ノードからイメージレジストリへのネットワーク接続を確認します。
3. ボリューム関連の問題
Pod が PersistentVolumeClaim (PVC) を必要とし、対応する PersistentVolume (PV) をプロビジョニングまたはバインドできない場合、Pod は Pending のままになります。
診断手順:
-
Pod の説明を表示: ボリューム関連のイベントを探します。
bash kubectl describe pod <pod-name> -n <namespace>
イベントにはFailedAttachVolume、FailedMount、または類似のメッセージが表示される場合があります。 -
PVC および PV の状態を確認: PVC および PV の状態を検査します。
bash kubectl get pvc <pvc-name> -n <namespace> kubectl get pv
Pending状態でスタックしている PVC や、バインドされていない PV を探します。
解決策:
- StorageClass の確認: 特に動的プロビジョニングを使用している場合、
StorageClassが定義され、利用可能であることを確認します。 - PV の可用性の確認: 静的プロビジョニングを使用している場合、PV が存在し、PVC の基準に一致していることを確認します。
- アクセスモードの確認: アクセスモード(例:
ReadWriteOnce、ReadWriteMany)が互換性があることを確認します。
CrashLoopBackOff 状態の Pod のトラブルシューティング
CrashLoopBackOff 状態は、アプリケーションレベルの問題を示しています。コンテナは正常に起動しましたが、その後エラーで終了し、Kubernetes が繰り返し再起動することを促します。
1. アプリケーションエラー
最も一般的な原因は、アプリケーション自体が起動に失敗するか、起動直後に致命的なエラーに遭遇することです。
一般的な原因:
- 依存関係/設定の欠落: アプリケーションが、依存する重要な設定ファイル、環境変数、または外部サービスを見つけられません。
- コマンド/引数の誤り: コンテナ仕様で指定された
commandまたはargsが誤っているか、即時終了につながります。 - アプリケーションロジックエラー: アプリケーションコードのバグにより、起動時にクラッシュします。
診断手順:
-
Pod ログの表示: これが最も重要な手順です。ログには、アプリケーションをクラッシュさせた正確なエラーメッセージが表示されることがよくあります。
bash kubectl logs <pod-name> -n <namespace>
Pod が繰り返しクラッシュしている場合、ログには直近の失敗した試行の出力が表示されることがあります。クラッシュしたコンテナの以前のインスタンスからのログを表示するには、-p(previous)フラグを使用します。
bash kubectl logs <pod-name> -p -n <namespace> -
Pod の説明を表示:
ContainersセクションのRestart Countを確認します。これはコンテナがクラッシュした回数を示します。また、Last StateのExit Codeも確認します。
bash kubectl describe pod <pod-name> -n <namespace>
終了コード0は通常、正常なシャットダウンを意味しますが、ゼロ以外の終了コードはエラーを示します。一般的なゼロ以外の終了コードには、1(一般的なエラー)、137(SIGKILL、多くは OOMKilled)、139(SIGSEGV、セグメンテーション違反)などがあります。
解決策:
- アプリケーションログのレビュー: ログに基づいて、アプリケーションコードまたは設定をデバッグします。必要なすべての環境変数、
ConfigMaps、Secretsが正しくマウント/注入されていることを確認します。 - ローカルでのテスト: 同じ環境変数とコマンドでコンテナイメージをローカルで実行して、問題を再現およびデバッグしてみてください。
2. Liveness および Readiness プローブの失敗
Kubernetes は、Liveness および Readiness プローブを使用して、アプリケーションのヘルス状態と可用性を判断します。Liveness プローブが継続的に失敗すると、Kubernetes はコンテナを再起動し、CrashLoopBackOff につながります。
診断手順:
-
Pod の説明を表示:
ContainersセクションのLivenessおよびReadinessプローブの定義とそのLast Stateを確認します。
bash kubectl describe pod <pod-name> -n <namespace>
「Liveness probe failed: HTTP probe failed with statuscode: 500」などのプローブ失敗を示すメッセージを探します。 -
アプリケーションログのレビュー: 場合によっては、アプリケーションログがプローブエンドポイントが失敗した理由のコンテキストを提供します。
解決策:
- プローブ設定の調整: プローブの
path、port、command、initialDelaySeconds、periodSeconds、またはfailureThresholdを修正します。 - プローブエンドポイントの正常性の確保: プローブがターゲットとするアプリケーションエンドポイントが実際に正常であり、期待どおりに応答していることを確認します。アプリケーションの起動に時間がかかりすぎている可能性があり、より大きな
initialDelaySecondsが必要になる場合があります。
3. リソース制限超過
コンテナが一貫して memory.limit よりも多くのメモリを使用しようとしたり、cpu.limit を超えたために CPU スロットリングが発生したりすると、カーネルはプロセスを終了させることがあり、多くの場合 OOMKilled(Out Of Memory Killed)イベントが発生します。
診断手順:
-
Pod の説明を表示:
Last StateまたはEventsセクションでOOMKilledを探します。Exit Code: 137は、多くの場合OOMKilledイベントを示します。
bash kubectl describe pod <pod-name> -n <namespace> -
kubectl topの確認:metrics-serverがインストールされている場合、kubectl top podを使用して Pod の実際の使用リソースを確認します。
bash kubectl top pod <pod-name> -n <namespace>
解決策:
- リソース制限の増強: アプリケーションが実際にリソースを必要とする場合は、Pod マニフェストの
memoryおよび/またはcpulimitsを増やします。これには、ノードでのより多くの容量が必要になる場合があります。
yaml resources: requests: memory: "256Mi" cpu: "500m" limits: memory: "512Mi" # ここを増やす cpu: "1000m" # ここを増やす - アプリケーションの最適化: アプリケーションをプロファイルして、リソース消費を特定および削減します。
4. 権限の問題
コンテナが必要なファイル、ディレクトリ、またはネットワークリソースにアクセスするための必要な権限を持っていない場合、コンテナはクラッシュする可能性があります。
診断手順:
- ログのレビュー: アプリケーションログに権限拒否エラー(
EACCES)が表示される場合があります。 - Pod の説明を表示: 使用されている
ServiceAccountと、マウントされているsecurityContext設定を確認します。
解決策:
securityContextの調整: 必要に応じてrunAsUser、fsGroup、またはallowPrivilegeEscalationを設定します。- ServiceAccount の権限: Pod に関連付けられた
ServiceAccountが、RoleBindingsおよびClusterRoleBindingsを介してバインドされた必要なRolesおよびClusterRolesを持っていることを確認します。 - ボリュームの権限: マウントされたボリューム(例:
emptyDir、hostPath、ConfigMap、Secret)が、コンテナのユーザーに対して正しい権限を持っていることを確認します。
一般的な診断手順とツール
Pod の問題に直面した場合に実行するコマンドのクイックチェックリストを次に示します。
- 概要の取得: Pod の状態を確認します。
bash kubectl get pods -n <namespace> kubectl get pods -n <namespace> -o wide - Pod の詳細情報: Pod のイベント、状態、条件を理解するために最も重要なコマンドです。
bash kubectl describe pod <pod-name> -n <namespace> - コンテナログ: アプリケーションが報告している内容を確認します。
bash kubectl logs <pod-name> -n <namespace> kubectl logs <pod-name> -p -n <namespace> # 前のインスタンス kubectl logs <pod-name> -f -n <namespace> # ログをフォロー - クラスター全体のイベント: 場合によっては、問題は特定の Pod ではなく、クラスター全体のイベント(例:ノードの圧力)であることがあります。
bash kubectl get events -n <namespace> - インタラクティブデバッグ: コンテナが起動するがすぐにクラッシュする場合、短い間
execして接続するか、設定されていれば別のデバッグコンテナに接続できる場合があります。
bash kubectl exec -it <pod-name> -n <namespace> -- bash
(注意:これはコンテナがアタッチするのに十分な時間実行され続ける場合にのみ機能します。)
Pod の問題を回避するためのベストプラクティス
予防は常に治療に勝ります。これらのベストプラクティスに従うことで、Pending および CrashLoopBackOff のインシデントを大幅に減らすことができます。
- 現実的なリソースリクエストと制限の設定: 妥当な
requestsとlimitsから始め、アプリケーションのプロファイリングと監視に基づいて調整します。 - 特定のイメージタグの使用: 本番環境では
latestタグを避けてください。再現性のために、不変のタグ(例:v1.2.3、commit-sha)を使用します。 - 堅牢なプローブの実装: アプリケーションのヘルス状態を正確に反映する
livenessおよびreadinessプローブを設定します。initialDelaySecondsで起動時間を考慮します。 - 集中ログと監視: Prometheus、Grafana、ELK スタック、またはクラウドネイティブなロギングサービスなどのツールを使用して、Pod ログとメトリクスを収集および分析します。
- マニフェストのバージョン管理: Kubernetes マニフェストをバージョン管理システム(例:Git)に保存して、変更を追跡し、ロールバックを容易にします。
- 徹底的なテスト: 本番環境にデプロイする前に、開発およびステージング環境でコンテナイメージと Kubernetes デプロイメントをテストします。
- 正常なシャットダウン: アプリケーションが
SIGTERMシグナルを正常に処理し、終了前にリソースを解放できるようにします。
結論
Kubernetes 環境で Pending または CrashLoopBackOff でスタックする Pod に遭遇することは、よくあるシナリオです。最初は daunting に見えますが、これらの状態は貴重な手がかりを提供します。Pod の説明、ログ、クラスターイベントを体系的に調べることで、リソースの制約、イメージのプル失敗、またはアプリケーションレベルのバグのいずれであっても、根本原因を特定できます。このガイドで概説されている診断手順とベストプラクティスを武器に、Kubernetes デプロイメントを健全に保ち、アプリケーションを確実に実行するための十分な準備が整いました。デバッグを楽しんでください!