tc はカーネルがパケットをネットワークインタフェースに送る前にキューイングしてトラフィックを制御する qdisc (queueing discipline) を設定するコマンドあるいはサブシステム。Kubernetes CNI の bandwidth plugin も tc によって実現されており次の annotatiton によって Pod の帯域を制限できる。
annotations:
kubernetes.io/ingress-bandwidth: 1M
kubernetes.io/egress-bandwidth: 1M
Amazon Linux 2023 の t2.micro EC2 インスタンスで実行してみる。
$ ip link
...
2: enX0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
$ sudo yum -y install iproute-tc
$ tc -json qdisc show dev enX0 | jq
[
{
"kind": "fq_codel",
"handle": "0:",
"root": true,
"refcnt": 2,
"options": {
"limit": 10240,
"flows": 1024,
"quantum": 9015,
"target": 4999,
"interval": 99999,
"memory_limit": 33554432,
"ecn": true,
"drop_batch": 64
}
}
]
fq_codel は systemd を使う OS やルーターのファームウェアなどで広く使われているアルゴリズムで、トラフィックがバーストしたとしてもキューの最小遅延時間が options の target になるように制御する。limit はパケットの上限、memory_limit はバイト数の上限となっており、これらを超過すると以後のパケットは捨てられる。handle は parent を指定するときに使われる qdisc の識別子。
netem (Network Emulator) で遅延を発生させ、tbf (Token Bucket Filter) で帯域を制限してみる。
$ sudo tc qdisc add dev enX0 root handle 1: netem delay 100ms
$ sudo tc qdisc add dev enX0 parent 1: tbf rate 50mbit burst 512kbit latency 400ms
$ tc -json qdisc show dev enX0 | jq
[
{
"kind": "netem",
"handle": "1:",
"root": true,
"refcnt": 2,
"options": {
"limit": 1000,
"delay": {
"delay": 0.1,
"jitter": 0,
"correlation": 0
},
"ecn": false,
"gap": 0
}
},
{
"kind": "tbf",
"handle": "800b:",
"parent": "1:",
"options": {
"rate": 6250000,
"burst": 65531,
"lat": 400000
}
}
]
他のインスタンスと iperf や ping で通信することで帯域制限と遅延がはたらいていることが確認できる。tbf の burst が少ないと途中で Transfer が 0 になってしまったので増やした。
# iperf3 -s # another instance
$ sudo yum install -y iperf3
$ iperf3 -c 172.31.25.78
Connecting to host 172.31.25.78, port 5201
[ 5] local 172.31.16.172 port 51834 connected to 172.31.25.78 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 5.50 MBytes 46.1 Mbits/sec 0 1.11 MBytes
[ 5] 1.00-2.00 sec 5.38 MBytes 45.1 Mbits/sec 0 1.41 MBytes
[ 5] 2.00-3.00 sec 6.75 MBytes 56.6 Mbits/sec 0 1.70 MBytes
[ 5] 3.00-4.00 sec 5.38 MBytes 45.1 Mbits/sec 0 2.00 MBytes
[ 5] 4.00-5.00 sec 6.62 MBytes 55.6 Mbits/sec 0 2.30 MBytes
[ 5] 5.00-6.00 sec 5.50 MBytes 46.2 Mbits/sec 0 2.59 MBytes
[ 5] 6.00-7.00 sec 5.25 MBytes 44.0 Mbits/sec 0 2.88 MBytes
[ 5] 7.00-8.00 sec 6.62 MBytes 55.6 Mbits/sec 0 3.16 MBytes
[ 5] 8.00-9.00 sec 5.25 MBytes 44.0 Mbits/sec 0 3.16 MBytes
[ 5] 9.00-10.00 sec 6.50 MBytes 54.5 Mbits/sec 0 3.16 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 58.8 MBytes 49.3 Mbits/sec 0 sender
[ 5] 0.00-10.50 sec 58.5 MBytes 46.7 Mbits/sec receiver
$ ping 172.31.25.78
PING 172.31.25.78 (172.31.25.78) 56(84) bytes of data.
64 bytes from 172.31.25.78: icmp_seq=1 ttl=127 time=101 ms
64 bytes from 172.31.25.78: icmp_seq=2 ttl=127 time=100 ms
64 bytes from 172.31.25.78: icmp_seq=3 ttl=127 time=100 ms
qdisc を削除すると元に戻る。
$ sudo tc qdisc del dev enX0 root
$ ping 172.31.25.78
PING 172.31.25.78 (172.31.25.78) 56(84) bytes of data.
64 bytes from 172.31.25.78: icmp_seq=1 ttl=127 time=0.461 ms
64 bytes from 172.31.25.78: icmp_seq=2 ttl=127 time=0.476 ms
64 bytes from 172.31.25.78: icmp_seq=3 ttl=127 time=0.626 ms
参考
tcコマンドでNetworkの帯域と遅延を制御してみてみた - Qiita
How to Use the Linux Traffic Control
Chapter 32. Linux traffic control Red Hat Enterprise Linux 9 | Red Hat Customer Portal