はじめに
Kubernetes (K8s) にデプロイされたコンテナ (Pod) のネットワークが、何かおかしい時、皆さんはどうされてますか?
kubectl exec
でコンテナに入り込んで、ping を打ちたかったりしませんか?
ところが...!そのコンテナには ping はおろか、curl や ip コマンドも仕込まれていなかったり...!?
「マジかー・・・ping 仕込んだコンテナイメージ用意するかぁ・・・」とかなっていれば、ちょっと待ってください!
そんな悲しい状況下で、便利に使えるコンテナイメージがあります!
netshoot というコンテナイメージなのですが、ping はもちろん、curl や ip コマンド、はたまた iperf などのネットワークのトラブルシュートに使える様々な便利ツールが詰め込まれています。
前提
今回、直接の依存関係はありませんが、TUNA-JP Advent Calendar 2023
への寄稿ということで、強引に Tanzu に絡ませるべく、vSphere with Tanzu を使ってデプロイした TKG クラスタ上で、お試ししています。
- vSphere 8.0 Update 2
- kubectl v1.26.4+vmware.wcp.0
- Kubernetes v1.25.7+vmware.3-fips.1
また、「何かおかしいな?」の題材として、下記のような nginx のコンテナを TKG クラスタ上にデプロイしています。
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-85cf7975fb-cmrzr 1/1 Running 0 10m 10.244.1.5 project01-cluster01-node-pool-1-hsn8z-74b594979f-l8g62 <none> <none>
nginx-85cf7975fb-fscq9 1/1 Running 0 10m 10.244.2.5 project01-cluster01-node-pool-1-hsn8z-74b594979f-thnv8 <none> <none>
nginx-85cf7975fb-jjsfl 1/1 Running 0 10m 10.244.2.4 project01-cluster01-node-pool-1-hsn8z-74b594979f-thnv8 <none> <none>
使い方
GitHub の README が非常に分かりやすいので、そこまで難しいことは無いと思いますが、K8s 上での使い方に関しては、Netshoot with Kubernetes
のセクションを参照ください。
コンテナへのアタッチ
まず kubectl debug
コマンドを使って、稼働中の nginx の Pod に netshoot のコンテナをアタッチしてみます。
$ kubectl debug nginx-85cf7975fb-cmrzr -it --image=nicolaka/netshoot
Defaulting debug container name to debugger-ggtqg.
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (containers "nginx", "debugger-jmvt4", "debugger-ggtqg" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (containers "nginx", "debugger-jmvt4", "debugger-ggtqg" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or containers "nginx", "debugger-jmvt4", "debugger-ggtqg" must set securityContext.runAsNonRoot=true), seccompProfile (pod or containers "nginx", "debugger-jmvt4", "debugger-ggtqg" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
If you don't see a command prompt, try pressing enter.
dP dP dP
88 88 88
88d888b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P
88' `88 88ooood8 88 Y8ooooo. 88' `88 88' `88 88' `88 88
88 88 88. ... 88 88 88 88 88. .88 88. .88 88
dP dP `88888P' dP `88888P' dP dP `88888P' `88888P' dP
Welcome to Netshoot! (github.com/nicolaka/netshoot)
Version: 0.11
nginx-85cf7975fb-cmrzr ~
Ctrl+D や exit
で、ターミナルを抜けると、自動でアタッチしたコンテナも削除してくれるので便利です。
また、プロンプトがアタッチした先の Pod 名になっているのと、Pod の IP アドレスを確認すると、ちゃんと狙った Pod の IP アドレス (前提のセクションで確認した 10.244.1.5
) になっていることが確認できます。
nginx-85cf7975fb-cmrzr ~ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
2: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether ee:24:6e:32:2d:dd brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.1.5/24 brd 10.244.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::ec24:6eff:fe32:2ddd/64 scope link
valid_lft forever preferred_lft forever
ping
とりあえず、まずは ping を打ってみましょう。
外部のルータの IP アドレス 172.19.30.254
を狙ってみます。
nginx-85cf7975fb-cmrzr ~ ping -c 3 172.19.30.254
PING 172.19.30.254 (172.19.30.254) 56(84) bytes of data.
64 bytes from 172.19.30.254: icmp_seq=1 ttl=63 time=1.60 ms
64 bytes from 172.19.30.254: icmp_seq=2 ttl=63 time=1.10 ms
64 bytes from 172.19.30.254: icmp_seq=3 ttl=63 time=0.919 ms
--- 172.19.30.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.919/1.206/1.599/0.287 ms
ss (netstat)
nginx で 80番ポート (HTTP) で待ち受けているはずなので、ちゃんと Listen できているのか確認してみます。
nginx-85cf7975fb-cmrzr ~ ss -tupln
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 128 [::]:80 [::]:*
プロセス名まで追えていない (PID Namespace が違う?) ですが、80番ポートで、何かが動いていることは確認できました。
iproute2
ルーティングのテーブルの確認のために、ip route
や ip neighbor
コマンドを叩いてみます。
nginx-85cf7975fb-cmrzr ~ ip r
default via 10.244.1.1 dev eth0
10.244.1.0/24 dev eth0 proto kernel scope link src 10.244.1.5
nginx-85cf7975fb-cmrzr ~ ip n
10.244.1.1 dev eth0 lladdr 0e:e3:be:9c:67:2d REACHABLE
今回の環境では Antrea CNI によって管理される Open vSwitch (OVS) に渡されるので、大した情報はありませんが、「ルーティングテーブルは正しい?」などを確認する際に便利そうです。
termshark
tcpdump でも良いですが、CLI ながら Wireshark に似た UI でパケットキャプチャできる Termshark を起動しています。
nginx-85cf7975fb-cmrzr ~ termshark -i eth0
Termshark is initializing - please wait...
(The termshark UI will start when packets are detected on eth0...)
...(略)...
ここでは詳しくは紹介しませんが、Termshark めっちゃ便利です!びっくりしました。
iperf
もう一つ別のコンテナなり、対向してくれる端末が必要ですが、お試しで iperf を使って、スループットを計測してみます。
まず、対向する端末、例えば、もう一つ別の nginx の Pod に netshoot のコンテナをアタッチしておいて、iperf サーバーを起動しておきます。
nginx-85cf7975fb-fscq9 ~ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 128 KByte (default)
------------------------------------------------------------
...(略)...
次に、もう一方の netshoot コンテナから、iperf クライアントを実行して、スループットを計測します。
nginx-85cf7975fb-cmrzr ~ iperf -c 10.244.2.5
------------------------------------------------------------
Client connecting to 10.244.2.5, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[ 1] local 10.244.1.5 port 40660 connected with 10.244.2.5 port 5001
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-10.12 sec 259 MBytes 214 Mbits/sec
デフォルト設定であることもあって、大して良いスループットでは無いですね...
チューニングの余地はありそうですが、ここでは割愛します。
もし、オプション指定のチューニングや、結果の集計について、ご興味があれば、下記の記事も覗いていただけると嬉しいです。
まとめ
パッとすぐに使いそうなコマンドや操作のみを取り上げましたが、netshoot には、まだまだ他にも便利なツールが同梱されています!
「あ、こんなツールあるんだ〜」と勉強になるものもあると思いますので、「いくつ知ってるかな?」気分で覗いみても面白いと思います。