※本ページにはプロモーション(広告)が含まれています
【2026年最新版】KubernetesでPodがCrashLoopBackOffになる原因と対処法【完全ガイド】
KubernetesクラスターでPodが起動→クラッシュ→再起動を繰り返す「CrashLoopBackOff」状態になってしまった——そんな状況で困っていませんか?本記事では、CrashLoopBackOffの原因特定から、リソース制限・Probe設定・ConfigMap/Secretの設定ミス・イメージタグの問題まで、実践的な対処法を完全解説します。
この記事でわかること
- CrashLoopBackOffとは何か・どんな状態か
- kubectl logs / describe pod でのログ確認と原因特定
- resource limits(CPU/メモリ)の適切な設定方法
- Liveness/Readiness Probeの調整による誤検知の解消
- ConfigMap・Secretの設定ミスの特定と修正
- コンテナイメージタグの問題と解決
- 依存サービス(データベース等)の起動順序問題
CrashLoopBackOffとは何か
CrashLoopBackOffとは、KubernetesのPodが以下のサイクルを繰り返している状態です。
- Podが起動(
Running状態になる) - コンテナ内のプロセスがエラーで終了(exit code 0以外)
- KubernetesがPodを再起動(バックオフ遅延付き)
- また起動して失敗し、再起動を繰り返す
「BackOff」の部分は、再起動のたびに待機時間が指数関数的に増加すること(10秒 → 20秒 → 40秒 → 最大5分)を示します。
# Podの状態確認
kubectl get pods -n namespace-name
# 出力例
NAME READY STATUS RESTARTS AGE
my-app-7d8f9b5c4-xk2m9 0/1 CrashLoopBackOff 5 8m
RESTARTS カウントが増え続け、STATUS が CrashLoopBackOff になっているのが特徴です。
ステップ1: kubectl logs / describe pod で原因を特定する
ログを確認する(最重要)
# 現在のPodのログを確認
kubectl logs my-app-7d8f9b5c4-xk2m9 -n namespace-name
# 前回クラッシュしたコンテナのログ(--previous フラグ)
kubectl logs my-app-7d8f9b5c4-xk2m9 -n namespace-name --previous
# ログをリアルタイムで追う
kubectl logs -f my-app-7d8f9b5c4-xk2m9 -n namespace-name
# 複数コンテナがある場合はコンテナ名を指定
kubectl logs my-app-7d8f9b5c4-xk2m9 -c container-name -n namespace-name
重要: CrashLoopBackOffでは、Podが終了してから次の起動まで時間があります。--previous フラグで前回クラッシュ時のログを見ることが特に重要です。
kubectl describe pod でイベントを確認
kubectl describe pod my-app-7d8f9b5c4-xk2m9 -n namespace-name
出力の最下部にある「Events」セクションに重要な情報が含まれています。
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10m default-scheduler Successfully assigned default/my-app to node01
Normal Pulling 10m kubelet Pulling image "my-app:latest"
Normal Pulled 10m kubelet Successfully pulled image "my-app:latest"
Normal Created 10m (x3 over 9m) kubelet Created container my-app
Normal Started 10m (x3 over 9m) kubelet Started container my-app
Warning BackOff 2m (x8 over 8m) kubelet Back-off restarting failed container
exit code から原因を推定する
| Exit Code | 意味 | よくある原因 |
|---|---|---|
| 1 | アプリケーションエラー | 設定ミス、DB接続失敗、コードのバグ |
| 2 | シェル組み込みコマンドの誤用 | entrypointスクリプトのエラー |
| 126 | コマンドが実行不可 | 権限不足、実行ファイルが存在しない |
| 127 | コマンドが見つからない | entrypointのパスが誤っている |
| 137 | OOMKill(メモリ不足で強制終了) | memory limitが低すぎる |
| 143 | SIGTERMで終了 | Liveness Probeによる強制再起動 |
原因1: resource limits(リソース制限)の問題
OOMKillによるCrashLoopBackOff
memory limitが低すぎると、コンテナがメモリを使いすぎた際にOOM Killer(Out of Memory Killer)に強制終了されます。exit code 137 が特徴です。
# OOMKillを確認
kubectl describe pod my-app-7d8f9b5c4-xk2m9 | grep -i oom
# または Events セクションで
# Reason: OOMKilling Message: Memory limit reached.
resource limits の適切な設定
# deployment.yaml の resource 設定例
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-app
image: my-app:1.0.0
resources:
requests:
memory: "128Mi" # 最低限必要なメモリ(スケジューリングに使用)
cpu: "250m" # 最低限必要なCPU(250ミリコア = 0.25コア)
limits:
memory: "512Mi" # 上限メモリ(超えるとOOMKill)
cpu: "500m" # 上限CPU(超えるとスロットリング、終了はしない)
ベストプラクティス:
- まず
limitsなしでデプロイし、実際のメモリ使用量をkubectl top podsで計測 - 計測値の1.5〜2倍を
limits.memoryに設定 requestsとlimitsを極端に乖離させない(QoS ClassがBurstableになる)
実際のリソース使用量を確認する
# metrics-server が必要
kubectl top pods -n namespace-name
kubectl top nodes
原因2: Liveness/Readiness Probe の設定ミス
Liveness Probeによる誤検知
Liveness Probeが厳しすぎると、アプリが起動中(初期化処理中)にKubernetesがコンテナを異常と判断して強制再起動します。これがCrashLoopBackOffの一因になります。
# Probe設定の確認
kubectl describe pod my-app-7d8f9b5c4-xk2m9 | grep -A 10 "Liveness\|Readiness"
Probe設定の改善例
containers:
- name: my-app
livenessProbe:
httpGet:
path: /healthz
port: 8080
# 最初のチェックまでの待機時間(デフォルト0秒 → 30秒に増やす)
initialDelaySeconds: 30
# チェック間隔(デフォルト10秒)
periodSeconds: 10
# タイムアウト(デフォルト1秒 → 5秒に増やす)
timeoutSeconds: 5
# 失敗と判定するまでの連続失敗回数(デフォルト3回)
failureThreshold: 3
# 成功判定の連続成功回数(Livenessは1が推奨)
successThreshold: 1
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
successThreshold: 1
# Kubernetes 1.18+ ではStartup Probeを使用(起動時間が長いアプリに最適)
startupProbe:
httpGet:
path: /healthz
port: 8080
# 最大で failureThreshold × periodSeconds 秒待機(ここでは300秒)
failureThreshold: 30
periodSeconds: 10
Startup Probe の活用: 起動に時間がかかるアプリ(Java Spring Boot、データ移行処理など)では、Startup Probeを使うことでLiveness Probeが起動中に誤検知するのを防げます。
原因3: ConfigMap・Secretの設定ミス
よくある設定ミスパターン
- 参照しているConfigMap/Secretが存在しない
- キー名のスペルミス
- Secretの値がBase64エンコードされていない
- 名前空間が異なる
ConfigMap/Secret の確認コマンド
# ConfigMapの一覧確認
kubectl get configmap -n namespace-name
# ConfigMapの内容確認
kubectl describe configmap app-config -n namespace-name
# Secretの一覧確認
kubectl get secret -n namespace-name
# Secretの内容確認(値はBase64エンコードされて表示される)
kubectl get secret app-secret -o yaml -n namespace-name
# Secretの値をデコードして確認
kubectl get secret app-secret -o jsonpath='{.data.DATABASE_URL}' | base64 --decode
PodのEnvから設定値が正しく渡されているか確認
# Podが起動中(Running)の瞬間に環境変数を確認
kubectl exec my-app-pod -- env
# デバッグ用に一時的にsleepするコンテナでオーバーライド
kubectl run debug-pod --image=my-app:1.0.0 --command -- sleep 3600 -n namespace-name
kubectl exec -it debug-pod -- /bin/sh
# コンテナ内で環境変数や設定ファイルを確認
存在しないConfigMapを参照している場合の対処
# ConfigMapが存在しない場合のエラー例(kubectl describe より)
# Warning Failed kubelet Error: configmap "app-config" not found
# ConfigMapを作成する
kubectl create configmap app-config \
--from-literal=DATABASE_HOST=db.example.com \
--from-literal=APP_ENV=production \
-n namespace-name
# または YAMLファイルから適用
kubectl apply -f configmap.yaml -n namespace-name
原因4: コンテナイメージタグの問題
ImagePullBackOff と CrashLoopBackOff の違い
イメージ自体が取得できない場合は ImagePullBackOff、イメージ取得後に起動に失敗する場合は CrashLoopBackOff になります。
latest タグの問題
:latest タグは常に最新のイメージを指しますが、意図しないバージョンのイメージがデプロイされることがあります。
# NG: latestタグは本番環境に不向き
image: my-app:latest
# OK: 特定のバージョンタグを使用
image: my-app:1.2.3
# OK: イメージのSHA256ダイジェストで固定
image: my-app@sha256:abc123...
imagePullPolicy の設定
containers:
- name: my-app
image: my-app:1.0.0
# Always: 毎回レジストリから取得(latestタグの場合はデフォルト)
# Never: ローカルキャッシュのみ使用
# IfNotPresent: ローカルにない場合のみ取得(バージョンタグの場合はデフォルト)
imagePullPolicy: IfNotPresent
プライベートレジストリの認証問題
# レジストリ認証のSecretを作成
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=password \
--docker-email=user@example.com \
-n namespace-name
# Deploymentに imagePullSecrets を追加
spec:
template:
spec:
imagePullSecrets:
- name: regcred
containers:
- name: my-app
image: registry.example.com/my-app:1.0.0
原因5: 依存サービスの起動順序問題
データベース接続エラーによるCrashLoopBackOff
アプリがデータベースに接続を試み、DBが起動していない(またはReadyでない)場合に接続エラーで終了することがあります。
Init Containers を使った起動順序制御
spec:
# Init Containerはメインコンテナ起動前に完了する必要がある
initContainers:
- name: wait-for-db
image: busybox:1.35
# DBが応答するまでループしてチェック
command: ['sh', '-c',
'until nc -z db-service 5432; do echo waiting for database; sleep 2; done']
containers:
- name: my-app
image: my-app:1.0.0
アプリ側での接続リトライ実装
Kubernetesのベストプラクティスとして、アプリ自体が接続リトライロジックを実装することが推奨されています。Init Containerに依存するよりも、アプリが接続失敗を適切にハンドリングしてリトライする設計が理想的です。
よく使うデバッグコマンド集
# Podの詳細情報(Events含む)
kubectl describe pod -n
# 前回のクラッシュログ
kubectl logs --previous -n
# リアルタイムログ
kubectl logs -f -n
# Deploymentのロールアウト状態
kubectl rollout status deployment/my-app -n
# Deploymentの変更履歴
kubectl rollout history deployment/my-app -n
# 1つ前のバージョンにロールバック
kubectl rollout undo deployment/my-app -n
# 特定バージョンにロールバック
kubectl rollout undo deployment/my-app --to-revision=2 -n
# Podの環境変数確認(コンテナ内で実行)
kubectl exec -- env -n
# 起動に失敗するPodをデバッグ用コマンドでオーバーライド
kubectl debug pod/ -it --copy-to=debug-pod --container=my-app -- /bin/sh -n
# Nodeのリソース使用状況確認
kubectl top nodes
kubectl top pods -n
Deployment設定のデバッグフロー
| 確認ステップ | コマンド | 確認ポイント |
|---|---|---|
| 1. Pod状態確認 | kubectl get pods |
RESTARTS数、STATUS |
| 2. ログ確認 | kubectl logs --previous |
エラーメッセージ |
| 3. イベント確認 | kubectl describe pod |
OOMKill、Probe失敗 |
| 4. リソース確認 | kubectl top pods |
memory/CPU使用量 |
| 5. ConfigMap/Secret確認 | kubectl get configmap,secret |
存在確認、キー名 |
| 6. ロールバック | kubectl rollout undo |
直前のバージョンで動作確認 |
この記事に関連するおすすめ商品
Kubernetes完全ガイド(書籍)
約3,800円〜
Pod・Deployment・Service設計から本番運用まで体系的に解説
Docker/コンテナ技術 入門書
約2,500円〜
コンテナ化の基礎からKubernetesへの発展まで丁寧に解説
ミニPC(Kubernetesクラスター自作用)
約25,000円〜
自宅Kubernetesクラスター構築に最適な省電力ミニPC
※ 価格は変動します。最新価格はリンク先でご確認ください
よくある質問(FAQ)
Q1. CrashLoopBackOffのPodに kubectl exec で入って調査できますか?
コンテナがクラッシュして停止状態のため、通常の kubectl exec は使えません。代わりに kubectl debug コマンドでデバッグ用コンテナをPodにサイドカーとして追加できます(Kubernetes 1.18以降)。または、Deploymentのコマンドを一時的に sleep infinity に変更してデプロイし、起動状態で調査する方法も有効です。
Q2. RESTARTSが増え続けているがエラーログが空の場合はどうすれば良いですか?
アプリが起動直後にシグナルを受け取って即終了している可能性があります。kubectl describe pod の Events で exit code を確認し、137(OOMKill)や143(SIGTERM)であれば、それぞれリソース増量やLiveness Probe設定を見直してください。
Q3. 本番環境でCrashLoopBackOffが発生した場合、どうやって早急に復旧しますか?
最初は kubectl rollout undo deployment/app-name で直前の安定バージョンにロールバックしてサービスを復旧し、その後でゆっくり原因調査することを推奨します。調査より復旧を優先するのが鉄則です。
Q4. HelmチャートをアップグレードしたらCrashLoopBackOffになりました
helm rollback [release-name] [revision] で直前のリビジョンに戻してください。helm history [release-name] でリビジョン一覧を確認できます。変更差分は helm diff upgrade プラグインで事前確認する運用を推奨します。
Q5. 特定のNodeでのみCrashLoopBackOffになる場合は?
Nodeの問題(ディスク不足、カーネルバージョンの差異、Nodeのリソース逼迫)が疑われます。kubectl describe node [node-name] でNodeの状態を確認し、問題のあるNodeを kubectl cordon [node-name] でスケジューリング対象から除外して調査してください。
Q6. CrashLoopBackOff状態のPodが自動的に回復することはありますか?
クラッシュの原因が一時的なもの(依存サービスの一時的な停止、ネットワークの瞬断)であれば、バックオフ待機後の再起動で自然に回復することがあります。ただし設定やコードの問題が原因の場合は手動修正が必要です。
Q7. Horizontal Pod Autoscaler(HPA)とCrashLoopBackOffの関係は?
CrashLoopBackOff状態のPodはReady状態にならないため、HPAのスケールアップ対象にはなりません。HPAがレプリカ数を増やしても全Podが同じ理由でCrashLoopBackOffになることが多く、まず根本原因の解消を優先してください。
まとめ
KubernetesのCrashLoopBackOff問題は、適切なデバッグ手順を踏むことで確実に原因を特定し解決できます。対処の優先順位をまとめます。
- ログ確認(最優先):
kubectl logs --previousでクラッシュ時のログを確認 - イベント確認:
kubectl describe podでOOMKill、Probe失敗、ConfigMap不存在などを確認 - exit code から原因推定: 137=OOMKill、143=SIGTERM、1=アプリエラー
- リソース調整: memory limitを実際の使用量に基づいて適切に設定
- Probe設定見直し: initialDelaySecondsを増やし、Startup Probeを活用
- ConfigMap/Secret確認: 参照しているリソースが存在し、キー名が正しいか確認
- ロールバック: 本番障害は調査前にまずロールバックで復旧
体系的なデバッグ手順を確立することで、次回以降のCrashLoopBackOff発生時も素早く対応できます。定期的なProbe設定のレビューとリソース使用量のモニタリングで予防的な運用を心がけてください。
minto.tech スマホ(Android/iPhone)・PC(Mac/Windows)の便利情報をお届け! 月間アクセス160万PV!スマートフォン、タブレット、パソコン、地デジに関する素朴な疑問や、困ったこと、ノウハウ、コツなどが満載のお助け記事サイトはこちら!