概要
KubernetesのPodを出入りするネットワークパケットを収集して分析する方法を紹介します。
Kubernetesでは1つのPod内に複数のコンテナを起動することができ(Sidecarと呼びます)、Pod内のコンテナは同じNICを共有します。
この仕組みを利用して、対象のPodにパケット収集用コンテナを追加し、そのコンテナの中でパケット収集処理を実行します。
今回は下記の流れでパケットの収集と分析を行います。
- パケット収集用コンテナにて、収集処理を実行して結果をファイル出力する。
- ホストにて、
kubectl cp
コマンドを使って収集結果ファイルをホストにコピーする。 - ホストにて、Wiresharkを使ってコピーしたファイルを分析する。
Wiresharkは事前にインストールしてください。
パケット収集用コンテナをPodに追加
パケット収集用コンテナに使うDockerイメージは何でも良いのですが、今回はnicolaka/netshootを使います。(ネットワーク関連の様々なコマンドがインストール済みであり、ネットワーク分析用として有名なイメージです。)
例えば下記のようなyamlファイルを作る事で、netshootという名前のパケット収集用コンテナを含むPodをDeploymentとして作成できます。
---
apiVersion: apps/v1
kind: Deployment
...
spec:
...:
template:
...:
spec:
containers:
# アプリケーションコンテナ(収集対象)
- name: ...
image: ...
...:
# パケット収集用コンテナ
- name: netshoot
image: nicolaka/netshoot
imagePullPolicy: IfNotPresent
command: ["/bin/bash"]
args: ["-c", "while true; do ping localhost; sleep 60; done"]
command
およびargs
の箇所では、コンテナを起動させ続けるために永続的なコマンドを実行するよう定めています。
パケットを収集
netshootコンテナを含むPodをKubernetesにデプロイしたのち、下記コマンドでnetshootコンテナにログインします。
kubectl exec <Pod名> -c netshoot -it -- /bin/bash
今回のようにPod内に複数のコンテナがある場合は、
-c
オプションでログインしたいコンテナの名前を指定できます。
Namespaceがdefault以外の場合は、
-n <Namespace名>
オプションを追加します。
ログインしたnetshootコンテナの中でifconfigコマンドを実行し、パケット収集対象のNICを探します。
ifconfig
出力結果が下記の場合は、eth0という名前のNICを対象にすれば良いとわかります。
eth0 Link encap:Ethernet HWaddr 4E:1D:AF:72:EF:4B
inet addr:10.1.0.88 Bcast:10.1.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:19 errors:0 dropped:0 overruns:0 frame:0
TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1398 (1.3 KiB) TX bytes:42 (42.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:11832 errors:0 dropped:0 overruns:0 frame:0
TX packets:11832 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:993888 (970.5 KiB) TX bytes:993888 (970.5 KiB)
loはループバック用のNICです。
アプリケーションコンテナでもifconfigコマンドが実行可能であれば、アプリケーションコンテナにログインしてifconfigコマンドを実行すると、同一のeth0というNICがある事を確認できます。
tcpdumpコマンドを実行して、パケット収集処理を起動します。
tcpdump -i eth0 -w tcpdump.out
-i
オプションで対象のNICを、-w
オプションで収集結果の出力先ファイル名を指定します。
パケット収集処理を起動したままの状態で、ホストからアプリケーションにアクセスして動作させます。
アプリケーションの動作が一通り完了したら、netshootコンテナの中でCtrl + C
を入力してパケット収集処理を停止します。
netshootコンテナの中でlsコマンドおよびpwdコマンドを使って、収集結果ファイルの絶対パスを確認します。
出力結果が下記の場合は、
/root/tcpdump.out
に収集結果ファイルがあることがわかります。
bash-5.1# ls
motd tcpdump.out
bash-5.1# pwd
/root
収集結果を分析
ホスト側でkubectl cp
コマンドを実行して、収集結果ファイルをホストにコピーします。
kubectl cp <Pod名>:/root/tcpdump.out tcpdump.out -c netshoot
-c
オプションでコピー対象のコンテナを指定します。
Namespaceがdefault以外の場合は、
<Namespace名>/<Pod名>:/root/tcpdump.out
とします。
Wiresharkを起動し、コピーしたファイルを開くと、パケットの内容を確認できます。
上記の例について、パケット分析の詳細は割愛しますが、概要は下記の通りとなります。
- Kubernetesにはfront1とback1という2つのPodがあり、今回はfront1のパケットを収集している。
- ホストからfront1へHTTPリクエスト
- front1からback1へHTTPリクエスト
- back1からfront1へHTTPレスポンス
- front1からホストへHTTPレスポンス