SJ blog
devops
S

信頼度ランク

S 公式ソース確認済み
A 成功実績多数・失敗例少数
B 賛否両論
C 動作未確認・セキュリティリスク高
Z 個人所感

Kubernetes初心者ガイド:なぜPodが落ちるのか

Kubernetesを始めたばかりの人がつまずくポイントを解説。Pod・Deployment・Serviceの関係、CrashLoopBackOff・OOMKilledなどのエラー解読、よくある設定ミスを紹介します。

一言結論

KubernetesのPod障害の大半はCrashLoopBackOff・OOMKilled・ImagePullBackOffの3パターンに集約され、resources.limitsの設定とkubectl logsによるログ確認を習慣にするだけで自己解決できるようになる。

Kubernetes の基本概念

Cluster(クラスター)
  └─ Node(サーバー)
       └─ Pod(コンテナの最小単位)
            └─ Container(実際のアプリ)

Deployment   → Pod の希望状態を管理
Service      → Pod へのネットワーク接続を提供
Ingress      → 外部からのトラフィックをルーティング
ConfigMap    → 設定を管理
Secret       → シークレットを管理

Pod が落ちる主な原因と解読

CrashLoopBackOff

Pod が起動→クラッシュを繰り返している状態。

kubectl get pods
# NAME                   READY   STATUS             RESTARTS   AGE
# my-app-xxx-yyy         0/1     CrashLoopBackOff   5          3m

# ログを確認
kubectl logs my-app-xxx-yyy
kubectl logs my-app-xxx-yyy --previous  # 前回のクラッシュのログ

よくある原因:

  • コンテナが即時終了する(スクリプトが exit 1 で終わるなど)
  • 必要な環境変数や設定が不足
  • 依存サービスに接続できない

OOMKilled — メモリ不足でKillされた

kubectl describe pod my-app-xxx-yyy | grep -A 5 "Last State"
# Last State: Terminated
#   Reason: OOMKilled   ← メモリ不足
#   Exit Code: 137

対策: resources.limits.memory を増やすか、メモリリークを修正。

ImagePullBackOff

# イメージが取得できない
# → タイポ、プライベートレジストリの認証情報不足、イメージが存在しない
kubectl describe pod my-app-xxx-yyy | grep "Events"

よくある設定ミス

リソース制限の未設定

# ❌ 制限なし → ノードのリソースを食い尽くす可能性
containers:
  - name: app
    image: my-app:latest

# ✅ request(最低保証)と limit(上限)を設定
containers:
  - name: app
    image: my-app:latest
    resources:
      requests:
        cpu: "100m"      # 0.1 vCPU
        memory: "128Mi"
      limits:
        cpu: "500m"      # 0.5 vCPU
        memory: "512Mi"

ヘルスチェックの未設定

containers:
  - name: app
    image: my-app:latest
    # ✅ Liveness Probe: 死んだコンテナを再起動
    livenessProbe:
      httpGet:
        path: /health
        port: 3000
      initialDelaySeconds: 30  # 起動待ち
      periodSeconds: 10

    # ✅ Readiness Probe: 準備できるまでトラフィックを送らない
    readinessProbe:
      httpGet:
        path: /ready
        port: 3000
      initialDelaySeconds: 10
      periodSeconds: 5

Service のセレクターミス

# Deployment のラベル
spec:
  template:
    metadata:
      labels:
        app: my-app     # ← このラベルと

# Service のセレクターが一致している必要がある
---
kind: Service
spec:
  selector:
    app: my-app         # ← 一致しないとトラフィックが届かない

Deployment の基本

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3                    # Pod を3つ維持
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1                # 最大で+1台で更新
      maxUnavailable: 0          # ダウンタイムなし
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: app
          image: my-app:1.2.0
          ports:
            - containerPort: 3000
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: database-url

デバッグコマンド集

# Pod の詳細を確認(Events セクションが重要)
kubectl describe pod <pod-name>

# ログを確認
kubectl logs <pod-name> -f  # リアルタイム
kubectl logs <pod-name> -c <container-name>  # 特定コンテナ

# Pod 内でシェルを実行
kubectl exec -it <pod-name> -- /bin/sh

# Pod の環境変数を確認
kubectl exec <pod-name> -- env

# リソース使用量を確認
kubectl top pods
kubectl top nodes

# 全Namespaceのリソース確認
kubectl get all -n my-namespace

まとめ

初心者が最もつまずく箇所:

問題確認コマンドよくある原因
CrashLoopBackOffkubectl logs --previousアプリのクラッシュ・設定不足
OOMKilledkubectl describe podメモリ制限が低すぎ
Pending のままkubectl describe podリソース不足・NodeSelector ミス
Service に届かないkubectl get endpointsセレクターのラベルミス

kubectl describekubectl logs の2つを使いこなすだけで、大半の問題は解決できます。


参考: Kubernetes 公式ドキュメント(日本語)