Kubernetes環境で意図的にネットワーク遅延やパケットロスをを注入しようとしている。Linuxではtc-netem(8)を使って実現できる。コンテナ側でtcコマンドを叩こうとすると、コンテナのケイパビリティとしてNET_ADMINなどを与え直す必用があり、面倒などでノード側で特定のPodに異常を注入したい。 まずは、Kubernetesで任意のPodと対応するノード側のVethインタフェースを特定する。 ```shell-session # -- コンテナ側 --  ~ kubectl iexec user Namespace: sock-shop | Pod: ✔ user-db-795bfb6cd4-mwdfv $ 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 3: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue state UP group default link/ether 2e:2f:1d:e5:d5:38 brd ff:ff:ff:ff:ff:ff inet 10.48.0.17/24 brd 10.48.0.255 scope global eth0 valid_lft forever preferred_lft forever $ cat /sys/class/net/eth0/iflink 20 # Node側 ## GKEではtoolboxコンテナが用意されているのでログイン $ toolbox shell-session $ grep ^ /sys/class/net/vet*/ifindex | grep :20 /sys/class/net/veth18bcba24/ifindex:20 $ ip link | grep veth18bcba24 20: veth18bcba24@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue master cbr0 state UP mode DEFAULT group default ``` 次にtcコマンドを使って、遅延を注入する。ここでは50msとする。同様にパケットロスを注入することもできる。 ```shell-session # パケット遅延を追加する $ tc qdisc add dev veth18bcba24 root netem delay 50ms; sleep 600; tc qdisc del dev veth18bcba24 root # パケットロスを発生させる $ tc qdisc add dev veth18bcba24 root netem loss 2%; sleep 600; tc qdisc del dev veth18bcba24 root ``` 遅延の注入時に別ノード上のpodから対象podのIPアドレスへpingをしていると、途中からほぼ50msの遅延が追加されていることがわかる。 ```shell-session $ ping 10.48.0.17 ... 64 bytes from 10.48.0.17: icmp_seq=58 ttl=62 time=0.322 ms 64 bytes from 10.48.0.17: icmp_seq=59 ttl=62 time=0.245 ms 64 bytes from 10.48.0.17: icmp_seq=60 ttl=62 time=0.274 ms 64 bytes from 10.48.0.17: icmp_seq=61 ttl=62 time=50.448 ms 64 bytes from 10.48.0.17: icmp_seq=62 ttl=62 time=50.422 ms 64 bytes from 10.48.0.17: icmp_seq=63 ttl=62 time=50.503 ms 64 bytes from 10.48.0.17: icmp_seq=64 ttl=62 time=50.449 ms ... ``` 対象podと同一ノード上の別のpodへpingをしていたところRTTに変化がなかったので、特定のpodのみdelayを注入できているはず。 PodとNode側のvethインタフェースの紐付けは下記を参考にした。 [Kubernetes (gke) get name of pod network interface](https://stackoverflow.com/questions/51239781/kubernetes-gke-get-name-of-pod-network-interface) 仮想ネットワーク環境でtcを使っている例は次の通り。 [Emulating Bad Networks](https://samwho.dev/blog/emulating-bad-networks/) [Zalando Engineering Blog - PgBouncer on Kubernetes and how to achieve minimal latency](https://engineering.zalando.com/posts/2020/06/postgresql-connection-poolers.html)