CTS-KB

GKE監視・トラブルシューティング:Pod障害を順番に切り分ける

⏱ 約 4 分で読めます
#Kubernetes#GKE#トラブルシューティング#Cloud Logging#Cloud Monitoring

Kubernetes障害対応で重要なのは、再起動を繰り返す前にどの層で失敗しているかを順番に切り分けることです。最初からGoogle Cloudロードバランサーやアプリコードを決めつけず、現在地、Pod、イベント、ログ、Serviceの順で見ます。

最初の5分で行う確認

# 1. 操作対象
gcloud config get-value project
kubectl config current-context
kubectl config view --minify

# 2. ワークロード全体
kubectl get deployments,replicasets,pods -n YOUR_NAMESPACE -o wide

# 3. 詳細・イベント
kubectl describe pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl get events -n YOUR_NAMESPACE \
  --sort-by=.metadata.creationTimestamp

# 4. 現在と直前のログ
kubectl logs YOUR_POD_NAME -n YOUR_NAMESPACE --tail=200
kubectl logs YOUR_POD_NAME -n YOUR_NAMESPACE --previous --tail=200

複数コンテナPodでは -c YOUR_CONTAINER_NAME を付けます。--previous は再起動前コンテナのログを見るため、CrashLoopBackOffで特に重要です。

状態別の調査入口

状態主な確認先
Pendingrequests、Node容量、taint、affinity、PVC、Quota
ImagePullBackOff / ErrImagePullイメージ名・タグ、Registry権限、imagePullSecret
CrashLoopBackOfflogs --previous、終了コード、設定、依存先、Probe
OOMKilledmemory limit、実使用量、リーク、同時処理数
RunningだがReadyでないreadinessProbe、待受ポート、依存先
Service疎通不可label/selector、EndpointSlice、port/targetPort、NetworkPolicy

状態名は原因そのものではなく、結果です。たとえばCrashLoopBackOffは「何度も起動に失敗し、再試行間隔が伸びている」状態なので、その直前の終了理由を調べます。

Pending

kubectl describe pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl describe resourcequota -n YOUR_NAMESPACE
kubectl get pvc -n YOUR_NAMESPACE
kubectl get nodes

Eventsの FailedScheduling を読みます。Insufficient cpuInsufficient memory、taint不一致、PVC未バインドなどで対処は異なります。requestsを根拠なく下げるのではなく、実使用量とNode構成を確認します。

ImagePullBackOff

kubectl describe pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl get secret gitlab-registry -n YOUR_NAMESPACE \
  -o jsonpath='{.type}{"\n"}'

第12回の手順に沿い、パス、タグ、Deploy Tokenの期限・scope、Secret名とNamespaceを確認します。秘密値をデコードしてチャットやログへ貼らないでください。

CrashLoopBackOff

kubectl logs YOUR_POD_NAME -n YOUR_NAMESPACE --previous --tail=200
kubectl get pod YOUR_POD_NAME -n YOUR_NAMESPACE \
  -o jsonpath='{range .status.containerStatuses[*]}{.name}{" reason="}{.lastState.terminated.reason}{" exit="}{.lastState.terminated.exitCode}{"\n"}{end}'

主な原因は起動コマンドの失敗、必須設定不足、Secretのキー名違い、DB接続失敗、ファイル権限、livenessProbeの過剰な判定です。Probe失敗なら describe pod のイベントにも記録されます。

OOMKilled

メモリ上限超過の場合、再起動して一時的に直っても再発します。

kubectl top pod YOUR_POD_NAME -n YOUR_NAMESPACE --containers
kubectl describe pod YOUR_POD_NAME -n YOUR_NAMESPACE
kubectl logs YOUR_POD_NAME -n YOUR_NAMESPACE --previous

アプリのヒープ上限、キャッシュ、同時実行数、データサイズ、メモリリークを確認し、観測に基づいてrequests・limitsを変更します。

Runningなのに通信できない

kubectl get pods -n YOUR_NAMESPACE --show-labels
kubectl get service,endpointslices -n YOUR_NAMESPACE
kubectl describe service YOUR_SERVICE_NAME -n YOUR_NAMESPACE

EndpointSliceが空なら、Service selectorとPod label、Pod readinessを確認します。転送先があるなら、porttargetPort、コンテナの実待受アドレスを確認します。アプリが 127.0.0.1 だけで待ち受けていると、Pod外から到達できません。

必要ならクラスタ内の一時デバッグPodからServiceへ接続します。ただし本番のKSAやSecretを安易に割り当てません。

kubectl run network-debug \
  -n YOUR_NAMESPACE \
  --image=curlimages/curl \
  --restart=Never \
  --rm -it -- \
  curl -v http://YOUR_SERVICE_NAME:YOUR_PORT/health

使用するデバッグイメージも信頼性と固定タグを確認します。

rolloutの状態を確認する

kubectl rollout status deployment/YOUR_DEPLOYMENT_NAME -n YOUR_NAMESPACE
kubectl rollout history deployment/YOUR_DEPLOYMENT_NAME -n YOUR_NAMESPACE
kubectl describe deployment YOUR_DEPLOYMENT_NAME -n YOUR_NAMESPACE

直前の更新が原因と判断でき、前版が安全ならロールバックします。

kubectl rollout undo deployment/YOUR_DEPLOYMENT_NAME -n YOUR_NAMESPACE

設定の再読込など明確な目的がある場合は再起動できます。

kubectl rollout restart deployment/YOUR_DEPLOYMENT_NAME -n YOUR_NAMESPACE

restart は原因究明ではありません。実行前にログ、終了理由、イベントを記録します。

GKEのCloud Logging・Monitoring

GKEではクラスタ作成時の設定に応じ、ワークロードログ、システムログ、メトリクスをCloud LoggingとCloud Monitoringへ送れます。最低限、次を監視します。

  • Pod再起動数とReady率
  • CPU・メモリ使用量とrequests/limits
  • Deploymentの利用可能レプリカ数
  • Job失敗とCronJobの未実行
  • HTTPエラー率、レイテンシ、依存先エラー
  • NodeやControl planeの通知

ログ量は費用にも直結します。アクセスログやdebugログを無制限に収集せず、ログレベル、除外、保持期間、予算アラートを設計します。ただし障害調査に必要な監査ログやエラーまで消さないよう分類します。

障害記録に残すもの

  • 発生時刻とタイムゾーン
  • 対象プロジェクト、クラスタ、Namespace、ワークロード名
  • 期待状態と実際の状態
  • マニフェストの版とイメージタグ
  • Event、終了理由、秘密値を除いたログ
  • 暫定対応、根本原因、再発防止

トークン、Cookie、Authorizationヘッダー、Secret値、個人情報はマスクします。

参考資料