💭

Podのデバッグ方法をまとめ+AKS向けのコマンド例

2022/10/09に公開

はじめに

k8sで使われるイメージの多くはDistoressイメージを用いるためシェルすらないものが多く、従って直接アクセスしてのデバッグが難しいです。
デバッグのためにnslookupやdigあるいはcurlなどのコマンドを使いたい場合は、一時的にこれらのコマンドを持つコンテナをクラスター内で実行することでデバッグが実現可能です。


基本的な方法 DNSコマンドを持つイメージを積んだpodを生成する

DNS周りでデバッグする時は公式ドキュメントkubernets.ioでは以下のようなyaml使って、dnsコマンド一式入ったpodを配置してexecすると記載されてます。
以下が例になります。

以下の定義をもつpodを。

apiVersion: v1
kind: Pod
metadata:
  name: dnsutils
  namespace: default
spec:
  containers:
  - name: dnsutils
    image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
  restartPolicy: Always

コマンドでapplyしてデバッグコマンドを実行する。

kubectl apply -f dnsutils.yaml
kubectl exec -i -t dnsutils -- nslookup kubernetes.default

https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/


kubectl debugによるデバッグ

k8sの一般的なdebug方法としてはkubectl debugがあります。
やることは基本的な方法と変わらず、任意のコンテナを操作するというものですが、2つパターンがありそれぞれ基本的な方法に対してメリットがあります。

ephemeral containerをアタッチする

kubectl debugコマンドではephemeral(一時的な)コンテナをpodにアタッチして任意のコマンドを実行すること可能です。
この場合、podを単純に生成する方法と違い消し忘れのリスクはありません。

kubectl debug target-pod -it --image=registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 -- nslookup kubernetes.default

この方法は開発環境のクラスタであれば問題ないのですが、本番環境の場合リスクが稼働中の環境に手をつけることによりPodの状態が改変される問題があります。操作を誤った際にログが飛んだり、パラメータが変わったことにより動かなくなったりするなど様々リスクが考えられます。
また、podのステータスとしてephemeralContainersが追加されるので要件によっては望ましくないということも考えられます。

Workload API reference
https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/

kubectl debug 対象をコピーしたPod内でコンテナを操作する

まずは、kubectl debugコマンドによりpodにアタッチして任意のコマンドを実行する方法です。
この場合Podを破壊するリスクがなく非常に安全ですが、コピーはそのまま残るので消し忘れのリスクが発生します。

kubectl debug target-pod -it --image=registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 \
  --share-processes --copy-to debug-target-pod -- sh

まとめ

消し忘れリスク Pod変更リスク 用途
デバッグPod生成 ✖️ ✖️ とりあえず基本
エフェメラル ⭕️ ✖️ 開発環境でサクッと
コピーPod生成&サイドカー注入 ✖️ ⭕️ 👮🚓🕵️「捜査の基本は現場保存だ!」本番向け。

おまけ1 kubectl debugでnodeもできますよ。

podを生成し特権コンテナによるデバッグセッションが開けます。
AKSを今練習で触っておりレファレンスにSSH使うなこっちを使いなさいと書いてましたが、他のマネージドサービスもおそらくSSHアクセス嫌うのでこの方法を推奨していると思います。
この場合デバッグ用のpodがcompletedになるので消しましょう。

kubectl debug node/<node-name> -it --image=registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 -- nslookup kubernetes.default

https://learn.microsoft.com/ja-jp/azure/aks/node-access

おまけ2 AKS用のチートシート

AKSでデバッグするときは mcr.microsoft.com/azure-cli のイメージ使うといいみたいです。

curlも積んでます。

ephemeralパターン

Pod

kubectl debug <target-pod> -it --image=mcr.microsoft.com/azure-cli

Node

kubectl debug node/<target-node> -it --image=mcr.microsoft.com/azure-cli

Pod copyパターン

kubectl debug <target-pod> -it --image=mcr.microsoft.com/azure-cli \
  --share-processes --copy-to <prefix>-<target-pod>

終了後のステータス

1番上はcopy podにデバッグ用サイドカーを入れたパターンです。
2番目はnode向けのデバッグコンテナが入ったpodです。不正利用防ぐためにcompletedにしてるのでしょう。

ephemeralコンテナは対象pod内部に存在するので、対象podに対して以下のコマンドを発行すればステータスを確認できます。

k get pod <podname> -o jsonpath='{ .status.ephemeralContainerStatuses}' | jq

おしまい

Discussion