KubernetesでのPodのパケットキャプチャの方法について

Red HatのNFVPEというチームに所属しています林(と)1と申します。

赤帽エンジニアAdvent Calendar 2018の18日目の本記事では12/10-13日に行なわれましたKubeCon + CloudNativeCon North America 2018(KubeCon NA 2018)で発表した"Troubleshooting On-Premise Kubernetes Network: Underlay, Overlay and Pod"についてご紹介致します。ちなみに発表のスライドはこのページの下の方にpdfがあります。

話の主な内容

主にオンプレミス環境でKubernetes(またはOpenShift)を運用する際に問題となるようなネットワークのトラブルシューティングについての始めの一歩として

  • インストール時に出やすいエラーとその対処
  • Podのインターフェイスの情報の取得
  • Podのトラフィックをタッピング

の3点を説明しました。本日はその中で紹介したPodのトラフィックをキャプチャするにはどうすればいいかについて説明します。

Podのトラフィックをタッピングするにはどうすればいいか?

ネットワークのトラブルで多く使われるトラブルシューティングの一つにパケットのキャプチャがあります。Kubernetesではiptablesを多用するために、各所でヘッダの内容が異なるため、デバッグする際にはそのケース毎にキャプチャしたい箇所はノードのインターフェースだったり、(ovsを含む)bridgeだったりと異なると思います。

その中でもPod内部のインターフェイス(=eth0)をキャプチャするのは非常にやっかいです。なぜかというと以下の理由があります。

  • コンテナイメージにwireshark等のソフトがインストールされているケースがほぼ無い
  • よしんば入っていたとしてもPodのPrivilegeによってwiresharkの実行ができない

現在ですと以下の手順を踏んでnsenterコマンドを用いることでパケットのキャプチャが可能ですがこれもまた手数の多さが問題となります。

  • kubectl get pod <pod名> -o json等で対象のPodの動作しているノード、ContainerIDを確認する
  • 対象のノードで docker inspectcrictl inspectコマンドを実行してPIDを取得する
  • 対象のノードにwiresharkをインストールする(インストールされていない場合)
  • sudo nseneter -t <pid> -n -- wireshark でキャプチャする

そこでkokotapというソフトを開発しました。 このソフトでは対象のPodのインターフェイスをLinuxのtc-mirred という機能を使ってミラーを行ない、 VxLANで他のノードに飛ばすことを行ないます。

例えば以下のようなコマンドを実行するとPod(centos)のトラフィックをミラーする'mirror'インターフェイスをkube-masterに作成することが可能です。これでコンテナにソフトが入っていなくてもパケットをキャプチャすることが可能になります。

[centos@kube-master ~]$ ./kokotap --pod=centos --mirrortype=both \
    --dest-node=kube-master --vxlan-id=100 | kubectl create -f -
pod/kokotap-centos-sender created
pod/kokotap-centos-receiver-kube-master created
[centos@kube-master ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
(snip)
17: mirror: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN qlen 1000
    link/ether 7e:3a:cb:bf:95:28 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::7c3a:cbff:febf:9528/64 scope link 
       valid_lft forever preferred_lft forever

また対象のホストをIPアドレスで指定することでKubernetesの管理対象になっていないノードにもミラーのトラフィックを飛ばすことが可能です。この場合は受信側のVxLANインターフェイスを自分で作成する必要があります。

ミラー(送信側)作成

[centos@kube-master ~]$ ./kokotap --pod=centos --mirrortype=both \
    --dest-ip=10.1.1.1 --vxlan-id=100 | kubectl create -f -
pod/kokotap-centos-sender created
pod/kokotap-centos-receiver-kube-master created

ミラー(受信側)作成

[centos@10.1.1.1 ~]$ sudo ip link add mirror type vxlan id 192.168.1.1 dev eth0 dstport 4789
[centos@10.1.1.1 ~]$ sudo ip link set up mirror
[centos@10.1.1.1 ~]$ wireshark -i mirror

デモ動画

以下の動画で上のコマンドの実行例が確認できます。


kokotap demo movie at KubeConNA 2018

まとめ

本記事ではKubeCon 2018 NAで発表した"Troubleshooting On-Premise Kubernetes Network: Underlay, Overlay and Pod"の中のPodのトラフィックをキャプチャするにはどうすればいいかを紹介しました。 Kubernetesを使ったさいのアプリケーションのデバッグやネットワークのデバッグの助けとなれば幸いです。


  1. 弊社には同姓の社員がいるのでとりあえずこんな形で区別してみました。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。