Kubernetes Kubernetes

失敗する Pod をデバッグする:describe、logs、exec、port-forward

Pod が Pending のまま、クラッシュする、応答しない原因を突き止めるための、繰り返し使えるチェックリスト。

12 min learn.level.初級

遅かれ早かれ、Pod が起動しない、再起動を繰り返す、または動作しているのに応答しないという事態に遭遇します。解決策は、ほとんどの場合、いくつかの kubectl コマンドを正しい順序で使えば見えてきます。このガイドでは、その順序を示します。ステータスを読む、イベントを尋ねる、ログを読む、コンテナの中に入る、そしてネットワークパスをたどる、です。

まずステータスを読む

まずステータスの列から始めます。

kubectl get pods -o wide

最も一般的な状態と、最初に見る場所は次のとおりです。

  • Pending。 Pod がノードに割り当てられていません。通常、CPU やメモリが足りない、クォータを使い果たした、ボリュームをバインドできないなどです。describe がどれかを教えてくれます。
  • ContainerCreating。 ノードがコンテナを準備しています。このままの状態が続く場合は、ボリュームの欠落や、イメージの pull の遅さを確認してください。
  • ErrImagePull / ImagePullBackOff。 イメージを pull できません。ほとんどは、名前やタグのタイプミス、またはプライベートレジストリの認証情報の欠落が原因です。
  • CrashLoopBackOff。 コンテナが起動し、終了し、増加する遅延とともに繰り返し再起動されます。アプリケーションが失敗しているので、そのログを読みます。
  • CreateContainerConfigError。 Pod が、存在しない ConfigMap、Secret、またはキーを参照しています。
  • Running だが READY 0/1。 コンテナは起動していますが、readiness probe に失敗しています。
  • OOMKilled(describe に表示)。コンテナがメモリ制限を超えました。

Kubernetes に理由を尋ねる:describe とイベント

kubectl describe pod POD_NAME

下部の Events セクションまでスクロールします。タイムラインのように読めます。Scheduled、Pulling、Failed、BackOff です。0/3 nodes are available: insufficient cpu や Failed to pull image "ngnix:1.25" のようなメッセージは、たいてい問題を直接指しています。その上では、各コンテナの State と Last State で、終了コードと理由を確認します。namespace 全体で何が起きていたかのビューは次のとおりです。

kubectl get events --sort-by=.metadata.creationTimestamp

コンテナの出力を読む

kubectl logs POD_NAME
kubectl logs POD_NAME -c CONTAINER_NAME
kubectl logs POD_NAME --all-containers
kubectl logs POD_NAME --previous
kubectl logs POD_NAME -f --since=10m --tail=100

Pod に複数のコンテナがある場合は -c、ストリーミングには -f、出力を制限するには --since と --tail、そして最後にクラッシュしたインスタンスのログを読むには --previous を使います。クラッシュループではこれが必要です。試すには、意図的に失敗するコンテナを持つ Deployment を作成します。

kubectl create deployment crashy --image=busybox:1.36 -- \
  sh -c 'echo starting; echo "fatal: DB_URL is not set" >&2; exit 1'
kubectl get pods -l app=crashy
kubectl logs deployment/crashy --previous

ステータスは CrashLoopBackOff になり、ログが理由を示します。kubectl delete deployment crashy で片付けます。

ログは Pod に属していることに注意してください。Pod が削除されたり置き換えられたりすると、そのログも一緒にクリーンアップされます。履歴が必要な場合は、Fluentd や Fluent Bit のようなログコレクターが、ログを耐久性のある場所に送る必要があります。

中に入る:exec、port-forward、cp

kubectl exec -it POD_NAME -- sh
kubectl exec POD_NAME -- env
kubectl port-forward pod/POD_NAME 8080:80
curl http://localhost:8080
kubectl cp POD_NAME:/path/to/file ./file

exec はコンテナ内でコマンドを実行し、port-forward はローカルポートを Pod のポートに接続し(svc/NAME でも動作します)、cp はファイルをコピーして出し入れします。多くの本番用イメージは最小限で、シェルも curl もありません。その場合、kubectl debug -it POD_NAME --image=busybox:1.36 --target=CONTAINER_NAME で、Pod の namespace を共有する一時的なデバッグ用コンテナをアタッチできます。

稼働中のコンテナ内で行った変更、たとえば設定ファイルの編集は、Pod が置き換えられるとすぐに失われます。exec は調査に使い、修正はイメージ、マニフェスト、または ConfigMap に対して行ってください。

リクエストの経路を逆にたどる

Pod は正常に見えるのにアプリケーションに到達できない場合は、内側から外側へと経路をたどります。

  1. Pod は実行中で READY ですか。まず Pod を直します。
  2. Service のセレクターは Pod のラベルと一致していますか。kubectl get pods --show-labels と kubectl describe service NAME が一致しているはずです。
  3. Service にエンドポイントがありますか。kubectl get endpointslices -l kubernetes.io/service-name=NAME は、Pod の IP を一覧表示するはずです。空のリストは、セレクターの不一致か、準備完了の Pod がないことを意味します。
  4. ポートは一致していますか。Service の targetPort は、コンテナが実際にリッスンしているポートである必要があります。
  5. 別の Pod から動作しますか。kubectl run tmp --rm -it --image=busybox:1.36 --restart=Never -- wget -qO- http://NAME。これは DNS と Service をテストし、クラスターの外にあるものを除外します。
  6. NetworkPolicy がブロックしている可能性はありますか。kubectl get networkpolicy で一覧表示します。
  7. 最後に、その前段にある Ingress や外部ロードバランサーを確認します。

各ステップが問題を 1 つの層に絞り込むため、推測するより速くなります。

人気のガイド