【入門編】【完全版】Kubernetesのよくあるエラーとトラブルシューティング集:CrashLoopBackOff等の原因と対処法 – インフラ構成管理(IaC)活用バイブル

【完全版】Kubernetesのよくあるエラーとトラブルシューティング集:CrashLoopBackOff等の原因と対処法

こんにちは!クラウドインフラおよびSRE領域を歩んできた先輩エンジニアです。

Kubernetes(以下k8s)を触り始めたばかりのころ、画面に踊る赤文字や「CrashLoopBackOff」「ImagePullBackOff」といった謎のエラーログを見て、「何が起きているんだ…」と途方に暮れた経験はありませんか?

安心してください。誰もが最初はそこからスタートします。k8sは非常に高度なオーケストレーションツールですが、「エラーの読み方」と「デバッグの定石(型)」さえ身につけてしまえば、決して怖いものではありません。 むしろ、k8sは非常に親切で、何が起きているかのヒントを必ずどこかに残してくれています。

この記事では、k8sの基礎知識と環境構築からスタートし、現場で最も遭遇する「4大トラブル」の原因究明と対策までを徹底的に噛み砕いて解説します。これをマスターすれば、毎日の障害対応やデバッグ作業が劇的に楽になり、自信を持ってコンテナを運用できるようになりますよ!

—

0. まずは基本から:Kubernetesの役割と最速セットアップ

トラブルシューティングに入る前に、k8sが何をしているのか、そして手元で試せる実験環境(HelloWorld)をサクッと整えましょう。

Kubernetes(k8s)の役割とは?

一言で言えば「大量のコンテナ(Dockerなど)を自動で管理・指揮するオーケストラの指揮者」です。
複数台のサーバー(ノード)上で、コンテナの配置、死活監視、自動復旧(セルフヒーリング)、ロードバランシング、スケールアウトなどを自動で行ってくれます。

手元で動かす実験環境(kind のセットアップ)

ローカルで安全に実験するために、Docker上でk8sクラスタを動かせる軽量ツール「kind (Kubernetes in Docker)」を使いましょう。

インストール手順(Mac/Linux例)

kindのインストール (Homebrewを使用する場合)
brew install kind kubectl

ローカルクラスタの作成
kind create cluster –name dev-cluster

クラスタが正常に立ち上がったか確認(これがHelloWorld的な動作確認です)
kubectl cluster-info –context kind-dev-cluster

HelloWorld Podのデプロイ

動作確認のために、簡単なWebサーバー(Nginx)を動かしてみましょう。

nginx-hello.yaml
apiVersion: v1
kind: Pod
metadata:
name: hello-nginx
labels:
app: hello
spec:
containers:

  • name: nginx

image: nginx:latest # 使用するコンテナ画像
ports:

  • containerPort: 80 # コンテナが解放するポート番号

これを適用(反映)します。

kubectl apply -f nginx-hello.yaml

状態確認(STATUSが Running になれば成功です!)
kubectl get pods

さあ、これであなたの手元に実験用のk8s環境が整いました。ここからが本題です!

—

1. CrashLoopBackOffエラーの原因究明と対策

最も頻繁に遭遇し、初心者をもっとも悩ませるのが `CrashLoopBackOff` です。

これはどういう状態?

コンテナが「起動した直後に異常終了(Crash)し、k8sが再起動を試みるが(Loop)、何度も失敗するため再起動の間隔を徐々に広げている(BackOff)」状態です。k8sのセルフヒーリング機能が裏目に出ているように見える現象ですね。

よくある原因

1. 設定値・環境変数の不足(DBの接続情報やAPIキーがない)
2. 起動コマンド・Entrypointのミス(ファイルパスが存在しない、文法エラー)
3. アプリケーションの初期化失敗(DBに接続できずにAppがクラッシュ)
4. メモリ不足(OOMKilled)

プロのデバッグ手順と対策

ステップ1:ログを見る(最優先)

まずはアプリケーションが何と言って死んだのか、ログを聞きに行きましょう。

コンテナの標準出力ログを確認
kubectl logs hello-nginx

【超重要】すでに再起動してしまっている場合、1つ前の死んだコンテナのログを見る
kubectl logs hello-nginx –previous

※この `–previous` フラグを知っているだけで、デバッグ効率は10倍変わります!

ステップ2:詳細なイベントを確認する

ログが出力される前に死んでいる場合は、k8sのイベントログを確認します。

kubectl describe pod hello-nginx

一番下の `Events:` セクションや、`Containers.State` の `Exit Code` を確認してください。

  • Exit Code 137: メモリ溢れ(OOMKilled)による強制終了
  • Exit Code 1/127: アプリケーションのエラー、またはコマンドが見つからない

修正例:環境変数の不足で落ちていた場合

例えば、WordPressコンテナのように「環境変数(DBパスワード等)がないと即死する」仕様のアプリには、正しい環境変数を注入してあげます。

crash-fix-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: wordpress-app
spec:
containers:

  • name: wordpress

image: wordpress:6-php8.1-apache
env:
# 必要な環境変数を明示的に渡すことでCrashLoopBackOffを防ぐ

  • name: WORDPRESS_DB_PASSWORD

value: “secure_password_123”

  • name: WORDPRESS_DB_USER

value: “root”

—

2. ImagePullBackOffエラーの解決策

次に多いのが `ImagePullBackOff` や `ErrImagePull` です。

これはどういう状態?

k8sが指定されたコンテナイメージをレジストリ(Docker HubやECRなど)からダウンロード(Pull)できない状態です。

よくある原因

1. イメージ名やタグのスペルミス(例: `nginx:latst` などのタイポ)
2. プライベートレジストリへの認証失敗(Secretの設定漏れ)
3. レジストリのレートリミット(回数制限)

プロのデバッグ手順と対策

ステップ1:`describe` でイベントを見る

ImagePullエラーの理由は、`kubectl describe` を見れば100%分かります。

kubectl describe pod

`Events:` セクションに以下のようなメッセージが出ていないか探します。
> `Error: ImagePullBackOff`
> `Failed to pull image “my-app:1.0”: rpc error: code = NotFound` → イメージ名ミス
> `pull access denied for …` → 認証失敗

対策:プライベートレジストリの認証情報を設定する

認証が必要なリポジトリから画像を引っ張ってくる場合、`imagePullSecrets` をマニフェストに定義します。

image-pull-fix.yaml
apiVersion: v1
kind: Pod
metadata:
name: private-app
spec:
containers:

  • name: my-container

image: registry.example.com/acme/my-app:v1.0.0 # 正しいイメージURL
# プライベート認証情報を指定
imagePullSecrets:

  • name: my-registry-key # あらかじめ `kubectl create secret docker-registry` で作ったSecret名

—

3. Pending状態から動かないPodのデバッグ手法

Podを作ったのに STATUS が `Pending` のまま一向に動き出さないことがあります。

これはどういう状態?

「Podを配置したいけれど、条件に合うノード(サーバー)が見つからず、スケジューリング(配置計算)が止まっている」状態です。コンテナ自体はまだ起動すらしていません。

よくある原因

1. クラスターのリソース不足(CPUやメモリの空きがない)
2. Requests(要求リソース)の設定が大きすぎる
3. NodeSelectorやAffinityの条件が厳しすぎる
4. PVC(永続ボリューム)がバインドされていない

プロのデバッグ手順と対策

ステップ1:Schedulerのメッセージを読む

このエラーの答えも `kubectl describe pod` にあります。

kubectl describe pod

`Events:` のログに注目しましょう!
> `0/3 nodes are available: 3 Insufficient memory.`
> (3台あるノードのどれもメモリが足りません)

対策:リソースのリクエスト(Requests)を適正化する

初心者がやりがちなのが、`requests`(最低限保証してほしいスペック)に巨大な値を書いてしまうことです。

pending-fix-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-friendly-pod
spec:
containers:

  • name: app

image: nginx
resources:
requests:
# 巨大すぎる値(例: cpu: “32”)を指定するとPendingになる
cpu: “100m” # 0.1コア(現実的な値に設定)
memory: “128Mi” # 128メビバイト
limits:
cpu: “500m” # 最大0.5コアまで許可
memory: “512Mi” # 最大512MBまで許可

※このように `requests` を現実的なサイズに小さく調整することで、Schedulerが「このノードなら置けるぞ!」と判断できるようになります。

—

4. ネットワーク疎通トラブルの切り分け手順

「Podは Running になっているのに、外部からアクセスできない!」「Pod同士が通信できない!」という問題です。

ネットワークトラブルの4大原因

1. Serviceの `selector` と Podの `labels` が一致していない(超高頻度!)
2. アプリケーションが `127.0.0.1`(localhost)でListenしている
3. NetworkPolicy(ファイアウォールルール)で遮断されている
4. DNSの解決失敗

プロの切り分け4ステップ(黄金フロー)

ステップ1:Serviceのターゲットを確認する(最重要)

Serviceが正しくPodを認識しているか確認します。

Serviceに紐づいているPodのIP一覧を表示
kubectl get endpoints

ここで `ENDPOINTS` が `` になっていたら、100% Selectorの記述ミスです!

【正しい設定の例】

service-pod-match.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-backend
labels:
app: my-web # ① ここのラベルと
spec:
containers:

  • name: nginx

image: nginx
ports:

  • containerPort: 80

—
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: my-web # ② ここのセレクターが完全に一致している必要がある!
ports:

  • protocol: TCP

port: 80
targetPort: 80

ステップ2:アプリのListenアドレスを確認する

コンテナ内のアプリが `LISTEN` しているIPアドレスを確認してください。
アプリのコードや設定ファイルで `127.0.0.1` や `localhost` 向けにバインドされていると、Podの外部(他のPodやService)からの通信を拒否してしまいます。
必ず `0.0.0.0`(すべてのネットワークインターフェース)でListenするようにアプリ側を設定しましょう。

ステップ3:デバッグ用Podを打ち込んで疎通テストを行う

「クラスター内部から名前解決やHTTPリクエストができるか」を確かめるため、調査用の臨時Podを立ち上げて直接コマンドを叩くのがエンジニアの常套手段です。

調査用の臨時コンテナ(curlimages/curl)を起動し、シェルに入る
kubectl run net-debug –rm -i –tty –image=curlimages/curl — sh

— 調査用コンテナの中での操作 —
1. DNSの名前解決ができるか?
nslookup web-service

2. Service経由でアクセスできるか?
curl http://web-service:80

確認が終わったら exit で抜ければPodは自動削除されます (–rm)

—

まとめ:トラブルシューティングをマスターしたあなたへ

今回解説したトラブルシュートの基本フローを整理しましょう。

【トラブル解決の4ステップ】
1. kubectl get pods -> Podの全体状態(STATUS)を把握する
2. kubectl describe pod -> Eventsを見てk8s層のエラー(Pending / ImagePull等)を調べる
3. kubectl logs (-p) -> コンテナ内部(アプリ層)のエラーログを見る
4. kubectl run net-debug … -> ネットワーク疎通・DNSを疑う

Kubernetesのトラブルシューティングは、闇雲に試すのではなく「k8sの制御面(コントロールプレーン)の問題か?」「コンテナのアプリの問題か?」「ネットワークの問題か?」を順番に切り分けていくのが最大のコツです。

この「型」さえ知っていれば、どんな複雑なエラーに遭遇しても落ち着いて対処できますよ。

最初は誰でも戸惑うものです。手元の `kind` クラスタでわざとエラーを起こしてみて、今回紹介したコマンドを叩いて遊んでみてください。エラーメッセージが「相棒からのヒント」に見えてきたら、あなたはもう立派なKubernetesエンジニアです!

毎日のインフラ運用が、少しでも楽しく楽になりますように!応援しています!

タイトルとURLをコピーしました