search
LoginSignup
4
Help us understand the problem. What are the problem?

posted at

Kubernetesの通信障害をtcpdumpで解決する

KubernetesとロードバランサーやAPIのエンドポイントなどの外部のデバイスと通信がうまくいっていなかったり、途中で切れたりしたときにtcpdumpを使ってパケットを解析すると、早期の問題解決につながります。Kubernetes環境でないVMでは、VM上でtcpdumpを実行すれば簡単にパケットをとれますが、Kubernetesの場合は少し工夫が必要なのでそのあたりをまとめてみました。

準備

tcpdumpを実行すると、フィルターを使用しても大量のデータを取得してしまいます。時によっては意図せずに、コンプライアンス上やセキュリティー上とるべきでないパケットなんかも見れてしまいます。可能であればテスト環境で問題の再現を行って、テストデータをtcpdumpで取得することをお勧めします。また実際にそのほうが、余分なパケットが少なく必要なデータだけを取得しやすいので解析時間も短くなるはずです。

先ずは複数あるノードから1つtcpdumpを実行するノードを選択し、そのノードに問題が発生しているアプリケーションをデプロイします。

ノードmyk8snode2を使用するので、myk8snode0myk8snode1をcordonします。

kubectl get no
NAME         STATUS   ROLES    AGE   VERSION
myk8snode0   Ready    <none>   10d   v1.24.4
myk8snode1   Ready    <none>   10d   v1.24.4
myk8snode2   Ready    <none>   10d   v1.24.4

kubectl cordon myk8snode0 myk8snode1

もしくはnodeAffinityを使って指定のノードにPodをデプロイします。

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchExpressions:
      - key: kubernetes.io/hostname
        operator: In
        values:
        - myk8snode2

確認すると、Podmyapppod-1bw5d-1234myk8snode2にデプロイされているのがわかります。

kubectl -n myapp get pod -o wide
NAME                  READY   STATUS    RESTARTS        AGE    IP             NODE         NOMINATED NODE   READINESS GATES
myapppod-1bw5d-1234   1/1     Running   1 (1d2h ago)    4d1h   100.111.2.111  myk8snode2   <none>           <none>

次にtcpdumpを実行するためのPodをデプロイします。

apiVersion: v1
kind: Pod
metadata:
  name: nsenter
  namespace: nsenter
spec:
  hostPID: true
  hostNetwork: true
  hostIPC: true
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - myk8snode2
  containers:
    - name: nsenter
      image: ubuntu
      command: ['tail', '-f', '/dev/null']
      securityContext:
        privileged: true

ノード上すべてのPodの通信を取得したいので、管理者権限などが付いたPodです。トラブルシューティング以外の時は使わないほうがいいと思います。

デプロイしたPodにexecします。

kubectl -n nsenter exec -it nsenter -- nsenter --target 1 --mount --uts --ipc --net /bin/bash

これで、Podnsenterからmyk8snode2内の通信を見ることができます。Pod内で

ip link

とかするとノード上の全てのPodのインターフェースを確認できます。

tcpdumpで特定のPodだけのパケットを取得したい場合は、Podのインターフェースを指定する必要があります。
Podmyapppod-1bw5d-1234のインターフェースは、以下のように確認できます。

kubectl exec myapppod-1bw5d-1234 -it -- cat /sys/class/net/eth0/iflink
32

これでnsenterPodからip linkで32を探すと、こんな感じで確認できます。

ip link|grep 32
32: veth32d4edf@if4: .........

ノードmyk8snode2上ではveth32d4edfがPodmyapppod-1bw5d-1234のインターフェースとなります。

tcpdumpの実行

Podnsenterからtcpdumpを実行します。

先ほどのPodmyapppod-1bw5d-1234のパケットのみを取得する場合は、

tcpdump -v -XX -tt -i veth32d4edf port 443 -w /dump/tcpdump.pcap

のような感じで実行すると、Podmyapppod-1bw5d-1234のport 443のパケットを全て取得できます。フィルターを使って、解析に必要な最小限のパケットを取得します。

また、どのPodが問題を起こしているの分からないときや、nginxなどを使ってサービスを公開して外部と通信している場合に通信の全体を見るには

tcpdump -v -XX -tt -i any port 443 -w /dump/tcpdump.pcap

とするとノードmyk8snode2上のすべてのPodのおよび外部との通信のport 443のパケットを取得できます。

解析

先ほど取得したtcpdumpをWiresharkなんかを使って解析します。

ノード上のすべてのインターフェースから取得すると、例えば以下のようなIPを通ったパケットを見ることができます。

  • 外部デバイスのIP
  • ノードのIP
  • ロードバランサーのIP
  • nginx Ingress controllerのIP
  • バックエンドサービスのPodのIP

例えば外部からのリクエストが、nginxを通してバックエンドのサービスのPodmyapppod-1bw5d-1234にどのように送信され、どのIPからRSTを出しているかなどがわかります。これによって通信の遮断の原因がアプリケーションなのか、ロードバランサーなのかもしくは外部のクライアントなのかがわかります。

No.	Time	Source		    Destination	 Protocol Length TTL	Info
349	4.8666 100.111.2.111	10.23.45.12	 TCP      56	 63	    58780 → 443 [RST] Seq=98 Win=0 Len=0

この例だとPodmyapppod-1bw5d-1234のIP100.111.2.111が、外部のエンドポイント10.23.45.12にRSTのパケットを送っています。何らかの原因で、Podとエンドポイントとの通信が正常に終了せず中断されています。考えられる原因としては、タイムアウトなど時間がかかりすぎて中断しているなどあります。

使用しているPodでタイムアウトなどのエラーをしっかりログで出してくれれば、ログ上でエラーを確認できるのでここまでしてパケットの中を見る必要もないです。しかし、すべてのアプリケーションでログが期待できるわけでもないので、ログで分からない場合はこのような方法で通信障害を解析することもできます。

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
What you can do with signing up
4
Help us understand the problem. What are the problem?