0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kubernetes⑥(全7回)|minikube|トラブルシュートと運用 — エラー対応とデバッグの実践

0
Last updated at Posted at 2026-02-18

シリーズ記事一覧

📑 目次

  1. この記事について
  2. この記事のゴール
  3. 前提条件
  4. デバッグコマンド5つ
  5. よくあるエラーパターン
  6. 運用テクニック
  7. まとめ

1. この記事について

1-1. シリーズ概要

Docker Compose経験者が「素のKubernetes」を
1週間で実践レベルまで習得する
ことを目指す学習記録です。

1-2. シリーズ構成

テーマ 内容
第1回 全体像と環境構築 Docker Composeとの対比、minikube導入
第2回 Pod と Deployment コンテナ起動〜スケーリング〜ローリングアップデート
第3回 Service と Ingress ネットワークと外部公開
第4回 ConfigMap / Secret / PV 設定管理と永続化
第5回 模擬プロジェクト 全概念を組み合わせて実践
第6回(本記事) トラブルシュートと運用 エラー対応、ログ確認、運用テクニック
第7回 総まとめ 振り返りと

1-3. 対象読者

  • 第5回を読み終えた方(k8sでアプリを構築できる状態)
  • kubectl get pods で Running 以外のステータスを見たことがある方
  • 「動かない時にどう調べるの?」を知りたい方

2. この記事のゴール

# ゴール 確認方法
デバッグコマンド5つを使い分けられる 状況に応じて適切なコマンドを選択できる
主要なエラーパターン7つの原因と対処法を説明できる STATUSを見て初動対応が判断できる
ロールバック・スケーリング等の運用操作ができる 安全なデプロイと緊急対応の使い分けを語れる
dry-run / diff で事前確認する習慣を語れる 本番適用前の安全策を説明できる

3. 前提条件

3-1. 環境情報

項目 バージョン / 詳細
OS Windows 11 + WSL2 Ubuntu
minikube インストール済み(第1回で構築)
kubectl インストール済み(第1回で構築)

3-2. 前提知識

  • 第5回の模擬プロジェクトの構成を理解していること
  • Docker Composeでの docker-compose logsdocker exec の経験

4. デバッグコマンド5つ

k8sのトラブルシュートは「浅い確認から深い調査へ」の順番で進めます。
5つのコマンドを覚えれば、ほとんどの問題の原因を特定できます。

深さ コマンド 何がわかる
浅い kubectl get pods 症状の把握(STATUS)
kubectl describe pod 詳細情報・Events(カルテ)
kubectl logs アプリが出したエラーメッセージ
kubectl exec Pod内に入って現場確認
深い kubectl get events クラスタ全体で何が起きたか

4-1. トラブルシュートの基本フロー

問題が発生したら、この5つを上から順に実行します。

4-2. Docker Composeとの対比

デバッグ操作 Docker Compose k8s
状態確認 docker-compose ps kubectl get pods
ログ確認 docker-compose logs api kubectl logs POD
詳細情報 docker inspect CONTAINER kubectl describe pod POD
コンテナに入る docker exec -it CONTAINER bash kubectl exec -it POD -- bash
イベント確認 (なし) kubectl get events
前回クラッシュのログ (なし) kubectl logs --previous

🔰 k8sでは describeevents が追加された分、Docker Composeよりも情報が豊富です。

4-3. コマンド①:kubectl get pods

kubectl get pods -n k8s-todo

出力の読み方:

NAME                     READY   STATUS             RESTARTS   AGE
api-5d8f7b-abc           1/1     Running            0          10m
db-0                     0/1     CrashLoopBackOff   3          5m
web-3a4b5c-ghi           0/1     ImagePullBackOff   0          2m
web-3a4b5c-jkl           0/1     Pending            0          2m
カラム 意味 注目ポイント
NAME Pod名 StatefulSetは連番、Deploymentはランダム
READY 準備完了 / 全コンテナ数 0/1 = readinessProbe失敗
STATUS Pod状態 Running以外は要調査
RESTARTS 再起動回数 1以上 = クラッシュ発生
AGE 経過時間 若いPodが多い = 再起動が頻発

4-3-1. よく使うオプション

オプション 用途 コマンド
全Namespace 全体を俯瞰 kubectl get pods --all-namespaces
ラベル絞り込み 特定アプリだけ kubectl get pods -l app=api -n k8s-todo
ウォッチ リアルタイム監視 kubectl get pods -n k8s-todo --watch
詳細表示 IPやNode情報 kubectl get pods -n k8s-todo -o wide

4-4. コマンド②:kubectl describe pod

kubectl describe pod db-0 -n k8s-todo

出力の注目箇所:

Containers:
  postgres:
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
    Restart Count:  3

Events:
  Type     Reason     Age   Message
  ----     ------     ----  -------
  Normal   Scheduled  5m    Successfully assigned k8s-todo/db-0
  Normal   Started    4m    Started container postgres
  Warning  BackOff    3m    Back-off restarting failed container
確認箇所 何がわかる
Containers → State コンテナの現在の状態
Containers → Last State 前回の終了状態(Exit Code重要)
Events 最も重要。時系列で何が起きたか

🍽️
kubectl get pods = 「体温計で熱があるか確認」。
kubectl describe = 「問診票を読む」。Eventsがカルテ

4-5. コマンド③:kubectl logs

# 現在のログ
kubectl logs db-0 -n k8s-todo

# ★ 前回クラッシュしたコンテナのログ(CrashLoopBackOff時に必須)
kubectl logs db-0 -n k8s-todo --previous

# リアルタイム追跡
kubectl logs -f api-5d8f7b-abc -n k8s-todo

# 最新50行だけ
kubectl logs db-0 -n k8s-todo --tail=50
オプション 用途 いつ使う
(なし) 現在のコンテナのログ 通常のログ確認
--previous 前回クラッシュしたコンテナのログ ★ CrashLoopBackOff時
-f リアルタイム追跡 動作確認中
--tail=N 最新N行だけ ログが大量な時

🔰 CrashLoopBackOffの時は必ず --previous をつける、
現在のコンテナは再起動直後で何もログがないため。

4-6. コマンド④:kubectl exec

# Pod内でシェルを起動
kubectl exec -it db-0 -n k8s-todo -- bash

# 単発コマンド
kubectl exec db-0 -n k8s-todo -- env | grep DATABASE

# Pod内からネットワーク疎通確認
kubectl exec -it api-POD -n k8s-todo \
  -- sh -c 'wget -qO- http://redis-service:6379 || echo "接続失敗"'
用途 コマンド例
環境変数確認 kubectl exec POD -- env
ファイル確認 kubectl exec POD -- cat /etc/nginx/conf.d/default.conf
DNS解決確認 kubectl exec POD -- nslookup redis-service
ネットワーク疎通 kubectl exec POD -- wget -qO- http://service:port
DB接続確認 kubectl exec POD -- pg_isready -h db-0.db-headless

🍽️
kubectl exec = 「厨房に入って直接状況を確認する」。
ログだけではわからない問題を調査できる。
(設定ファイルの中身、ネットワーク疎通)

4-7. コマンド⑤:kubectl get events

# Namespace内のイベント(時系列)
kubectl get events -n k8s-todo --sort-by='.lastTimestamp'

# Warningのみ表示
kubectl get events -n k8s-todo --field-selector type=Warning
使い所 説明
describeでは見えない問題 スケジューリング失敗、リソース不足
複数Podにまたがる問題 Node全体の問題を発見
時系列で原因追跡 どの順序で何が起きたか

5. よくあるエラーパターン

まず5-1の早見表でSTATUSから対応を引き、5-2以降で各パターンの詳細な調査手順を解説します。

5-1. エラーステータス早見表

kubectl get pods の STATUS を見て、次に何をすべきかを引く辞書です。

STATUS 意味 最初に見る場所 よくある原因
CrashLoopBackOff 起動→クラッシュ→再起動
のループ
logs --previous 設定ミス, 環境変数不足, DB接続失敗
ImagePullBackOff イメージ取得
に失敗
describe → Events イメージ名/タグのタイプミス, レジストリ認証
Pending スケジュール
されない
describe → Events リソース不足, PVCバインド失敗
Running (0/1) 動いてるが
準備未完了
describe → Probe readinessProbe失敗, 依存サービス未起動
CreateContainerConfigError コンテナ作成前に
エラー
describe → Events ConfigMap/Secret参照ミス
OOMKilled メモリ不足で
強制終了
describe → Last State limitsが小さすぎる
Evicted Nodeから
追い出された
describe → Events Nodeのディスク/メモリ枯渇

🍽️
レストランで例えると、STATUS は「入口の看板」。
看板を見れば、厨房(logs)を覗くべきか、
受付の記録(Events)を見るべきかがすぐわかる。

5-2. パターン1:CrashLoopBackOff

最も頻繁に遭遇するエラーです。
Podが起動→クラッシュを繰り返し、
再起動間隔が指数的に増加します(10秒→20秒→40秒→...→最大5分)。

5-2-1. 原因と対処

原因 見つけ方 対処
環境変数の不足 logs --previous で「ENV not set」 ConfigMap/Secretの参照を確認
DB接続失敗 logs --previous で「connection refused」 DB Podの起動状態を確認
設定ファイルの構文エラー logs --previous で「syntax error」 ConfigMapの中身を確認
権限エラー logs --previous で「permission denied」 SecurityContext、ファイル権限を確認

5-2-2. 調査手順

# ① STATUSとRESTARTS確認
kubectl get pods -n k8s-todo

# ② Eventsで何が起きたか
kubectl describe pod db-0 -n k8s-todo | tail -20

# ③ ★最重要:前回クラッシュのログ
kubectl logs db-0 -n k8s-todo --previous

5-2-3. Exit Codeの読み方

Exit Code 意味 よくある原因
0 正常終了 コマンドがデーモンになっていない
1 アプリケーションエラー 設定ミス、依存サービス未起動
127 コマンドが見つからない PATHの問題
137 OOMKilled または SIGKILL メモリ不足
143 SIGTERM(正常停止) 通常のPod停止

🍽️
Exit Code = 「シェフがなぜ倒れたかの診断結果」。
1 = 食材が足りなかった。
127 = 調理器具が見つからなかった。
137 = キッチンが狭すぎた。

5-3. パターン2:ImagePullBackOff

イメージの取得に失敗した状態です。

5-3-1. 原因と対処

原因 Events のメッセージ例 対処
イメージ名のタイプミス Failed to pull image "ngnix:1.21" イメージ名を修正
タグが存在しない manifest unknown Docker Hubで存在するタグを確認
プライベートレジストリ認証 unauthorized: authentication required imagePullSecrets を設定
ネットワーク問題 dial tcp: lookup ... timeout Nodeのネットワーク確認

5-3-2. 調査手順

# ① describeでEventsを確認
kubectl describe pod web-POD -n k8s-todo

出力例(Events部分):

Events:
  Warning  Failed   Failed to pull image "ngnix:1.21": not found
                      ↑ タイプミス! 正しくは nginx
# ② イメージ名・タグの修正後に再apply
kubectl apply -f web/deployment.yaml

🍽️
ImagePullBackOff = 「食材の発注書に書いた名前が間違っていて、業者から届かない」

5-4. パターン3:Pending

Podがどのノードにもスケジュールされない状態です。

5-4-1. 原因と対処

原因 Events のメッセージ例 対処
CPU/メモリ不足 Insufficient cpu / memory requestsを下げる or Nodeを追加
PVCがバインドされない unbound immediate PersistentVolumeClaims StorageClass名・容量を確認
nodeSelector不一致 didn't match Pod's node affinity ラベルを確認

5-4-2. 調査手順

# ① describeでスケジューリング失敗の理由
kubectl describe pod web-POD -n k8s-todo

# ② Nodeのリソース状況確認
kubectl describe node | grep -A 5 "Allocated resources"

# ③ PVCの状態確認(Pending の場合がある)
kubectl get pvc -n k8s-todo

出力例(PVCがPendingの場合):

NAME            STATUS    VOLUME   CAPACITY   STORAGECLASS   AGE
db-data-db-0    Pending                       standard       30s

🍽️
Pending = 「シェフは採用したけど、調理台が空いてなくて働けない」

5-5. パターン4:Running だが READY 0/1

Podは動いているが、readinessProbeが失敗してServiceの振り分け対象に入らない状態です。

5-5-1. 原因と対処

原因 調査方法 対処
ヘルスチェックのパス間違い describe → readinessProbe設定 path/portを修正
アプリ起動に時間がかかる logsで起動ログ確認 initialDelaySecondsを増やす
依存サービスが未起動 execでPod内から疎通確認 DB/Redisの起動状態を確認

5-5-2. 調査手順

# ① readinessProbeの設定確認
kubectl describe pod api-POD -n k8s-todo | grep -A 10 "Readiness"

# ② Pod内からヘルスチェックを手動実行
kubectl exec -it api-POD -n k8s-todo \
  -- wget -qO- http://localhost:8080/healthz

出力例(Probe失敗時):

Readiness:  http-get http://:8080/healthz delay=5s timeout=3s
  ...
  Warning  Unhealthy  Readiness probe failed: Get "http://10.244.0.8:8080/healthz": dial tcp 10.244.0.8:8080: connect: connection refused

5-6. パターン5:CreateContainerConfigError

コンテナの作成前に設定エラーで止まっている状態です。

5-6-1. 原因と対処

原因 Events のメッセージ例 対処
ConfigMapが存在しない configmap "app-config" not found ConfigMapを先に作成
Secretが存在しない secret "db-secret" not found Secretを先に作成
参照するキーが存在しない key "DB_PASSWORD" not found キー名のタイプミスを確認

5-6-2. 調査手順

# ① ConfigMap/Secretが存在するか確認
kubectl get configmap,secret -n k8s-todo

# ② describeでどのリソースが見つからないか特定
kubectl describe pod api-POD -n k8s-todo

出力例(Events部分):

Events:
  Warning  Failed  Error: configmap "app-config" not found

🍽️ CreateContainerConfigError = 「レシピカードが見つからなくて、料理を始められない」

5-7. パターン6:OOMKilled

メモリの limits を超えてカーネルに強制終了された状態です。

5-7-1. 原因と対処

原因 見つけ方 対処
limitsが小さすぎる describe で OOMKilled + Exit Code 137 limitsを増やす
アプリのメモリリーク top で使用量が増え続ける アプリ側の修正

5-7-2. 調査手順

# ① describeでOOMKilledを確認
kubectl describe pod api-POD -n k8s-todo

出力例:

Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137
# ② 現在のメモリ使用量を確認
kubectl top pod -n k8s-todo

🔰 kubectl top を使うにはMetrics Serverが必要です(有効化手順はセクション6-2参照)。

5-7-3. 対処例

# limitsを増やす
resources:
  requests:
    memory: "256Mi"     # 128Mi → 256Mi
  limits:
    memory: "512Mi"     # 256Mi → 512Mi

5-8. パターン7:Evicted

Nodeのリソース(ディスク、メモリ)が枯渇して、Podが追い出された状態です。

5-8-1. 原因と対処

原因 対処
ディスク不足 Nodeのディスク拡張 or 不要なイメージ削除
メモリ不足 requests/limitsの見直し or Node追加

5-8-2. 調査手順

# ① Evictedされたpodの確認
kubectl get pods -n k8s-todo | grep Evicted

# ② 原因確認
kubectl describe pod EVICTED-POD -n k8s-todo

出力例:

Status:   Failed
Reason:   Evicted
Message:  The node was low on resource: ephemeral-storage

5-9. 調査が行き詰まったら

上記の手順で期待どおりの出力が出ないこともあります。
その場合の対処法です。

状況 次のアクション
kubectl logs --previous でログが空 コンテナ起動前のエラー → describe のEventsを再確認
kubectl describe のEventsが空 時間が経ってイベント消失 → kubectl get events --sort-by='.lastTimestamp'
出力が本記事の例と異なる エラーメッセージをそのままコピーしてWeb検索
複数Podが同時に異常 Pod単体ではなくNode/クラスタの問題 → kubectl get nodeskubectl describe node

🍽️
調査の行き詰まり = 「症状を見ても診断がつかない時は、検査範囲を広げる」。
Pod → Node → クラスタ全体へ視野を広げる。


6. 運用テクニック

ここまではトラブル発生時の対応を学びました。
ここからはトラブルを未然に防ぐための日常運用テクニックです。

6-1. ローリングアップデートとロールバック

第2回で学んだローリングアップデートに、
失敗時のロールバックを加えた運用フローです。

6-1-1. ロールバック操作

# デプロイ履歴を確認
kubectl rollout history deployment/api -n k8s-todo

出力例:

REVISION  CHANGE-CAUSE
1         <none>
2         <none>
# 直前のリビジョンに戻す
kubectl rollout undo deployment/api -n k8s-todo

# 特定のリビジョンに戻す
kubectl rollout undo deployment/api -n k8s-todo --to-revision=1

# デプロイの進行状況を監視
kubectl rollout status deployment/api -n k8s-todo
# → "deployment "api" successfully rolled out"

6-1-2. CHANGE-CAUSEの記録

# apply時にアノテーションを記録
kubectl annotate deployment/api -n k8s-todo \
  kubernetes.io/change-cause="Update API image to v2.1"

# 履歴に表示される
kubectl rollout history deployment/api -n k8s-todo
# REVISION  CHANGE-CAUSE
# 1         Initial deployment
# 2         Update API image to v2.1

🍽️
ロールバック = 「新メニューが不評だったら、前のメニューにすぐ戻す」。
k8sはデプロイ履歴を保持しているため、1コマンドで戻せる。

6-2. リソース監視

# Metrics Server有効化(minikube)
minikube addons enable metrics-server

# PodのCPU/メモリ使用量
kubectl top pods -n k8s-todo

# NodeのCPU/メモリ使用量
kubectl top nodes

出力例:

NAME                   CPU(cores)   MEMORY(bytes)
api-5d8f7b-abc         2m           32Mi
api-5d8f7b-def         3m           35Mi
db-0                   5m           48Mi
redis-7d9f8b-xyz       1m           8Mi
web-3a4b5c-ghi         1m           12Mi

requests/limitsと比較して、
余裕があるか・逼迫しているかを判断します。

🍽️
kubectl top = 「各調理台の使用状況をモニタリング」。
水道の使用量が上限に近づいたら水圧が下がる前に対処。

6-3. ラベルを活用した運用操作

# ラベルで絞り込んでログ確認
kubectl logs -l app=api -n k8s-todo

# ⚠️ ラベルで絞り込んで一括削除(該当Pod全台が再起動される)
kubectl delete pods -l app=api -n k8s-todo

# ラベルで絞り込んでリソース確認
kubectl get all -l app=db -n k8s-todo

🔰-l app=api のようにラベルで絞り込むのがk8s運用の基本、
Pod名はランダムで覚えられないが、ラベルは一定。

6-4. 一時デバッグPodの活用

クラスタ内のネットワーク疎通やDNS解決を確認する時に、一時的なPodを使います。

# busybox(軽量Linux)で一時Pod起動
kubectl run debug \
  --image=busybox \
  --rm -it \
  --restart=Never \
  -n k8s-todo \
  -- sh
# → "If you don't see a command prompt, try pressing enter."
# → / #    ← busyboxのプロンプトが表示されたら成功

# Pod内で使えるコマンド例:
nslookup api-service             # DNS解決確認
wget -qO- http://api-service:80  # HTTP疎通確認
nc -zv redis-service 6379        # TCP疎通確認
exit                             # 終了(--rmなのでPod自動削除)
イメージ サイズ 使えるツール 用途
busybox ~1.5 MB wget, nslookup, nc, sh 汎用デバッグ(まずこれを使う)
curlimages/curl ~10 MB curl HTTPリクエスト詳細確認
nicolaka/netshoot ~400 MB curl, dig, nmap, tcpdump 本格的なネットワーク診断

🍽️
一時デバッグPod = 「覆面調査員を店舗に送り込んで、客目線で問題を確認する」

6-5. ConfigMap / Secret の変更管理

ConfigMap更新後、参照方式によって反映タイミングが異なります。

参照方式 更新後の反映 追加操作
環境変数(envFrom) 反映されない rollout restart が必要
ファイルマウント 自動反映(数十秒〜数分) アプリの再読み込みが必要な場合あり
# ConfigMap更新
kubectl apply -f configmap.yaml

# 環境変数参照の場合、安全に再起動
kubectl rollout restart deployment/api -n k8s-todo

6-5-1. rollout restart とは

ローリングアップデートと同じ方式で安全に再起動する操作です。

操作 動作 ダウンタイム
kubectl delete pod 指定Podを即座に削除 一瞬あり
rollout restart ローリング方式で順番に再起動 なし

6-6. スケーリング

# APIを2台から4台に増やす
kubectl scale deployment/api -n k8s-todo --replicas=4

# 確認
kubectl get pods -l app=api -n k8s-todo

# 1台に戻す
kubectl scale deployment/api -n k8s-todo --replicas=1
方法 メリット 使う場面
kubectl scale 即座に反映 緊急対応、一時的な変更
YAML修正 + apply git管理される 通常の運用(推奨)

🔰 本番では必ずYAML修正 + applykubectl scale は緊急時のみ。

6-7. 本番適用前の安全確認 ― dry-run / diff

6-7-1. dry-run で事前確認

# YAMLの構文チェック(クラスタに反映しない)
kubectl apply -f deployment.yaml --dry-run=client
# → "deployment.apps/api configured (dry run)"  ← 成功

# サーバーサイドのバリデーション(Quota超過等も検出)
kubectl apply -f deployment.yaml --dry-run=server
# → "deployment.apps/api configured (server dry run)"  ← 成功

# 差分確認(何が変わるか)
kubectl diff -f deployment.yaml
# → 変更箇所が diff 形式で表示される(変更なしなら出力なし)
オプション チェック内容 クラスタへの影響
--dry-run=client YAML構文のみ なし
--dry-run=server 構文 + API Serverのバリデーション(Quota等) なし
kubectl diff 現在のリソースとの差分表示 なし

🍽️ dry-run = 「注文を確定する前に、伝票の内容を確認する」。diff = 「前回の注文と何が変わったかを比較」

6-8. 運用コマンドまとめ

操作 コマンド
ロールバック kubectl rollout undo deployment/NAME
デプロイ履歴 kubectl rollout history deployment/NAME
安全な再起動 kubectl rollout restart deployment/NAME
リソース監視 kubectl top pods / nodes
ラベル絞り込み kubectl get pods -l app=api
一時デバッグPod kubectl run debug --image=busybox --rm -it --restart=Never -- sh
事前確認 kubectl apply --dry-run=server -f FILE
差分確認 kubectl diff -f FILE
スケーリング kubectl scale deployment/NAME --replicas=N

7. まとめ

7-1. 本記事で学んだこと

# 学んだこと キーポイント 該当セクション
デバッグコマンド5つ get → describe → logs → exec → events の順で調査 4
CrashLoopBackOff logs --previous が最重要。Exit Codeで原因分類 5-2
ImagePullBackOff describeのEventsでイメージ名・タグのタイプミスを発見 5-3
Pending リソース不足 or PVC未バインド。describeで原因特定 5-4
Running 0/1 readinessProbe失敗。execでPod内から疎通確認 5-5
CreateContainerConfigError ConfigMap/Secretの存在・キー名を確認 5-6
OOMKilled limitsを増やす。top で使用量を監視 5-7
ロールバック rollout undo で1コマンドで戻せる 6-1
dry-run / diff 本番適用前の安全策 6-7

7-2. 次回予告

第7回:総まとめ — 振り返り・次のステップ

最終回では、第1回〜第6回で学んだ全内容を振り返ります。

  • 全体の振り返り — 7記事で学んだ概念の整理と関係性マップ
  • マイグレーション戦略 — Docker Compose → Kubernetes への移行指針
  • 次のステップ — Helm / ArgoCD / Operator 等への道筋

(つづく)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?