実行中のPodのデバッグ

このページでは、ノード上で動作している(またはクラッシュしている)Podをデバッグする方法について説明します。

始める前に

  • あなたのPodは既にスケジュールされ、実行されているはずです。Pod がまだ実行されていない場合は、Troubleshoot Applications から始めてください。

  • いくつかの高度なデバッグ手順では、Podがどのノードで動作しているかを知り、そのノードでコマンドを実行するためのシェルアクセス権を持っていることが必要です。kubectl を使用する標準的なデバッグ手順の実行には、そのようなアクセスは必要ではありません。

Podログを調べます

まず、影響を受けるコンテナのログを見ます。

kubectl logs ${POD_NAME} ${CONTAINER_NAME}

コンテナが以前にクラッシュしたことがある場合、以前のコンテナのクラッシュログにアクセスすることができます。

kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}

container execによるデバッグ

もしcontainer imageがデバッグユーティリティを含んでいれば、LinuxやWindows OSのベースイメージからビルドしたイメージのように、kubectl exec で特定のコンテナ内でコマンドを実行することが可能です。

kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}

例として、実行中のCassandra Podからログを見るには、次のように実行します。

kubectl exec cassandra -- cat /var/log/cassandra/system.log

例えばkubectl exec-i-t引数を使って、端末に接続されたシェルを実行することができます。

kubectl exec -it cassandra -- sh

詳しくは、実行中のコンテナのシェルを取得するを参照してください。

エフェメラルコンテナによるデバッグ

FEATURE STATE: Kubernetes v1.23 [beta]

エフェメラルコンテナは、コンテナがクラッシュしたり、コンテナイメージにデバッグユーティリティが含まれていないなどの理由でkubectl execが不十分な場合に、対話的にトラブルシューティングを行うのに便利です(ディストロ・イメージの場合など)。

エフェメラルコンテナを使用したデバッグ例

実行中のPodにエフェメラルコンテナを追加するには、kubectl debugコマンドを使用することができます。 まず、サンプル用のPodを作成します。

kubectl run ephemeral-demo --image=k8s.gcr.io/pause:3.1 --restart=Never

このセクションの例では、デバッグユーティリティが含まれていないpauseコンテナイメージを使用していますが、この方法はすべてのコンテナイメージで動作します。

もし、kubectl execを使用してシェルを作成しようとすると、このコンテナイメージにはシェルが存在しないため、エラーが表示されます。

kubectl exec -it ephemeral-demo -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown

代わりに、kubectl debug を使ってデバッグ用のコンテナを追加することができます。 引数に-i/--interactiveを指定すると、kubectlは自動的にエフェメラルコンテナのコンソールにアタッチされます。

kubectl debug -it ephemeral-demo --image=busybox --target=ephemeral-demo
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #

このコマンドは新しいbusyboxコンテナを追加し、それにアタッチします。targetパラメーターは、他のコンテナのプロセス名前空間をターゲットにします。これはkubectl runが作成するPodでprocess namespace sharingを有効にしないため、指定する必要があります。

新しく作成されたエフェメラルコンテナの状態はkubectl describeを使って見ることができます。

kubectl describe pod ephemeral-demo
...
Ephemeral Containers:
  debugger-8xzrl:
    Container ID:   docker://b888f9adfd15bd5739fefaa39e1df4dd3c617b9902082b1cfdc29c4028ffb2eb
    Image:          busybox
    Image ID:       docker-pullable://busybox@sha256:1828edd60c5efd34b2bf5dd3282ec0cc04d47b2ff9caa0b6d4f07a21d1c08084
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 12 Feb 2020 14:25:42 +0100
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:         <none>
...

終了したらkubectl deleteを使ってPodを削除してください。

kubectl delete pod ephemeral-demo

Podのコピーを使ったデバッグ

Podの設定オプションによって、特定の状況でのトラブルシューティングが困難になることがあります。 例えば、コンテナイメージにシェルが含まれていない場合、またはアプリケーションが起動時にクラッシュした場合は、kubectl execを実行してトラブルシューティングを行うことができません。 このような状況では、kubectl debug を使用してデバッグを支援するために設定値を変更したPodのコピーです。

新しいコンテナを追加しながらPodをコピーします

新しいコンテナを追加することは、アプリケーションが動作しているが期待通りの動作をせず、トラブルシューティングユーティリティをPodに追加したい場合に便利な場合があります。 例えば、アプリケーションのコンテナイメージはbusybox上にビルドされているが、busyboxに含まれていないデバッグユーティリティが必要な場合があります。このシナリオは kubectl run を使ってシミュレーションすることができます。

kubectl run myapp --image=busybox --restart=Never -- sleep 1d

このコマンドを実行すると、myappのコピーにmyapp-debugという名前が付き、デバッグ用の新しいUbuntuコンテナが追加されます。

kubectl debug myapp -it --image=ubuntu --share-processes --copy-to=myapp-debug
Defaulting debug container name to debugger-w7xmf.
If you don't see a command prompt, try pressing enter.
root@myapp-debug:/#

デバッグが終わったら、Podの後始末をするのを忘れないでください。

kubectl delete pod myapp myapp-debug

Podのコマンドを変更しながらコピーします

デバッグフラグを追加するためや、アプリケーションがクラッシュするためなど、コンテナのコマンドを変更すると便利な場合があります。 アプリケーションのクラッシュをシミュレートするには、kubectl runを使用して、すぐに終了するコンテナを作成します。

kubectl run --image=busybox myapp -- false

kubectl describe pod myapp を使用すると、このコンテナがクラッシュしていることがわかります。

Containers:
  myapp:
    Image:         busybox
    ...
    Args:
      false
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1

kubectl debugを使うと、コマンドをインタラクティブシェルに変更したこのPodのコピーを作成することができます。

kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh
If you don't see a command prompt, try pressing enter.
/ #

これで、ファイルシステムのパスのチェックやコンテナコマンドの手動実行などのタスクを実行するために使用できる対話型シェルが完成しました。

デバッグが終わったら、Podの後始末をするのを忘れないでください。

kubectl delete pod myapp myapp-debug

コンテナイメージを変更してPodをコピーします

状況によっては、動作不良のPodを通常のプロダクション用のイメージから、デバッグ・ビルドや追加ユーティリティを含むイメージに変更したい場合があります。

例として、kubectl runを使用してPodを作成します。

kubectl run myapp --image=busybox --restart=Never -- sleep 1d

ここで、kubectl debugを使用してコピーを作成し、そのコンテナイメージをubuntuに変更します。

kubectl debug myapp --copy-to=myapp-debug --set-image=*=ubuntu

set-imageの構文は、kubectl set imageと同じcontainer_name=imageの構文を使用します。*=ubuntuは、全てのコンテナのイメージをubuntuに変更することを意味します。

デバッグが終わったら、Podの後始末をするのを忘れないでください。

kubectl delete pod myapp myapp-debug

ノード上のシェルによるデバッグ

いずれの方法でもうまくいかない場合は、Podが動作しているノードを探し出し、ホストの名前空間で動作する特権Podを作成します。 ノード上で kubectl debug を使って対話型のシェルを作成するには、以下を実行します。

kubectl debug node/mynode -it --image=ubuntu
Creating debugging pod node-debugger-mynode-pdx84 with container debugger on node mynode.
If you don't see a command prompt, try pressing enter.
root@ek8s:/#

ノードでデバッグセッションを作成する場合、以下の点に注意してください:

  • kubectl debugはノードの名前に基づいて新しい Pod の名前を自動的に生成します。
  • コンテナはホストのIPC、Network、PIDネームスペースで実行されます。
  • ノードのルートファイルシステムは/hostにマウントされます。

デバッグが終わったら、Podの後始末をするのを忘れないでください。

kubectl delete pod node-debugger-mynode-pdx84