容器、tc、iperf3

使用 tc 实现对容器应用的限流,并使用 iperf3 测网速。

实验环境

  • Ubuntu 16.04,Kernel 版本 4.4.0-142-generic
  • Docker 19.03.11
  • 正常带宽 100 Mbits/s

实验设备

使用 tc 对容器 c1、c3、c4 进行网络带宽限速,使用 iperf 测量网络带宽


实验环境准备

在宿主机1和2上安装 iperf3

1
apt-get install iperf3

宿主机1

在宿主机1上,先启动容器 c1、c2、c3,这里为了简单起见,使用 nginx:alpine 镜像。

1
2
3
4
5
6
7
8
9
10
11
docker run -d \
-p 8081:80 -p 8082:8082 \
--name c1 \
nginx:alpine
# -d 后台运行
# -p 映射端口至宿主机,宿主机端口:容器内部应用端口
# --name 容器的名称
# nginx:alpine 容器镜像

docker run -d -p 8083:80 -p 8084:8084 --name c2 nginx:alpine
docker run -d --name c3 nginx:alpine

查看容器是否正常启动:

1
docker ps

接下来,需要获取这些容器的 Pid

1
docker inspect c1 | grep -i pid

可以看到参数 Pid,我这里为 17734 ,Pid 可能有所不同,下面是测得的各个容器的 pid

容器名 Pid
c1 17734
c2 17882
c3 18004

接下来,使用 tc 对相关容器网络进行带宽限速,这里将带宽限制为 4 Mbits/s。以下操作在宿主机1上完成

1
2
3
4
5
sudo nsenter -t 17734 -n \
tc qdisc add dev eth0 root tbf \
rate 4mbit \
peakrate 8mbit \
burst 64kb latency 50ms minburst 1540

宿主机2

在宿主机2上执行类似的操作

1
docker run -d --name c4 nginx:alpine

测得其 pid 为 14023

1
docker inspect c4 | grep -i pid

测试带宽

额外打开两个终端登录至宿主机1,接下来启动 iperf3 server,注意 pid,分别为 c1 和 c2 的

1
2
3
4
5
6
7
8
9
10
11
# 终端1
sudo nsenter \
-t 17734 \
-n \
iperf3 -s\
-p 8082
# nsenter 进入进程的相关命名空间中(Linux Namespace)
# -t 目标进程 Pid
# -n 指定进入到网络命名空间中 (Network Namespace)
# 接下来是要在命名空间中执行的命令:iperf3 -s server 模式启动
# -p 监听端口为 8082
1
2
# 终端2
sudo nsenter -t 17882 -n iperf3 -s -p 8084

其实你可以认为,使用 nsenter 执行的程序与容器进程共享指定的命名空间(比如共享容器网络栈)

同一宿主机

接下来,使用以下命令,使用 c3 容器测试两个容器 c1 和 c2 的网络带宽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 测 c1
sudo nsenter -t 18004 -n \
iperf3 \
-c 10.211.55.62 \
-b 100m \
-t 10 \
-p 8082 \
-R

# -c server ip
# -b 测试间隔
# -t 测试时长(s)
# -p server port
# -R 测 client 从 server 下载数据的速度

输出如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Connecting to host 10.211.55.62, port 8082
Reverse mode, remote host 10.211.55.62 is sending
[ 4] local 172.17.0.4 port 51598 connected to 10.211.55.62 port 8082
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 544 KBytes 4.46 Mbits/sec
[ 4] 1.00-2.00 sec 468 KBytes 3.83 Mbits/sec
[ 4] 2.00-3.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 3.00-4.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 4.00-5.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 5.00-6.00 sec 468 KBytes 3.84 Mbits/sec
[ 4] 6.00-7.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 7.00-8.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 8.00-9.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 9.00-10.00 sec 468 KBytes 3.84 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 4.75 MBytes 3.98 Mbits/sec 0 sender
[ 4] 0.00-10.00 sec 4.75 MBytes 3.98 Mbits/sec receiver

带宽为 3.98,基本和 tc 限制的相符。接下来测试 c2

1
2
3
4
5
6
7
sudo nsenter -t 18004 -n \
iperf3 \
-c 10.211.55.62 \
-b 100m \
-t 10 \
-p 8084 \
-R

输出如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[  4] local 172.17.0.4 port 36244 connected to 10.211.55.62 port 8084
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 10.8 MBytes 90.1 Mbits/sec 0 327 KBytes
[ 4] 1.00-2.00 sec 12.0 MBytes 101 Mbits/sec 0 680 KBytes
[ 4] 2.00-3.00 sec 11.9 MBytes 99.6 Mbits/sec 0 827 KBytes
[ 4] 3.00-4.00 sec 12.0 MBytes 101 Mbits/sec 0 827 KBytes
[ 4] 4.00-5.00 sec 11.9 MBytes 99.5 Mbits/sec 0 827 KBytes
[ 4] 5.00-6.00 sec 11.9 MBytes 99.7 Mbits/sec 0 827 KBytes
[ 4] 6.00-7.00 sec 12.0 MBytes 101 Mbits/sec 0 827 KBytes
[ 4] 7.00-8.00 sec 11.9 MBytes 99.6 Mbits/sec 0 827 KBytes
[ 4] 8.00-9.00 sec 11.9 MBytes 99.7 Mbits/sec 0 827 KBytes
[ 4] 9.00-10.00 sec 12.0 MBytes 101 Mbits/sec 0 827 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 118 MBytes 99.1 Mbits/sec 0 sender
[ 4] 0.00-10.00 sec 118 MBytes 99.1 Mbits/sec receiver

iperf Done.

发现下行带宽没有限速,符合预期

不同宿主机

在宿主机2上进行相同的实验,命令和输出结果如下

1
2
3
4
5
6
7
sudo nsenter -t 14023 -n \
iperf3 \
-c 10.211.55.62 \
-b 100m \
-t 10 \
-p 8082 \
-R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Reverse mode, remote host 10.211.55.62 is sending
[ 4] local 172.17.0.2 port 38670 connected to 10.211.55.62 port 8082
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 544 KBytes 4.46 Mbits/sec
[ 4] 1.00-2.00 sec 468 KBytes 3.84 Mbits/sec
[ 4] 2.00-3.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 3.00-4.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 4.00-5.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 5.00-6.00 sec 468 KBytes 3.84 Mbits/sec
[ 4] 6.00-7.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 7.00-8.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 8.00-9.00 sec 467 KBytes 3.82 Mbits/sec
[ 4] 9.00-10.00 sec 468 KBytes 3.84 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 4.76 MBytes 3.99 Mbits/sec 0 sender
[ 4] 0.00-10.00 sec 4.76 MBytes 3.99 Mbits/sec receiver
1
2
3
4
5
6
7
sudo nsenter -t 14023 -n \
iperf3 \
-c 10.211.55.62 \
-b 100m \
-t 10 \
-p 8084 \
-R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Reverse mode, remote host 10.211.55.62 is sending
[ 4] local 172.17.0.2 port 42706 connected to 10.211.55.62 port 8084
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 12.1 MBytes 101 Mbits/sec
[ 4] 1.00-2.00 sec 11.9 MBytes 99.7 Mbits/sec
[ 4] 2.00-3.00 sec 11.9 MBytes 99.6 Mbits/sec
[ 4] 3.00-4.00 sec 11.9 MBytes 99.6 Mbits/sec
[ 4] 4.00-5.00 sec 12.0 MBytes 101 Mbits/sec
[ 4] 5.00-6.00 sec 11.9 MBytes 99.6 Mbits/sec
[ 4] 6.00-7.00 sec 12.0 MBytes 101 Mbits/sec
[ 4] 7.00-8.00 sec 11.9 MBytes 99.6 Mbits/sec
[ 4] 8.00-9.00 sec 11.9 MBytes 99.7 Mbits/sec
[ 4] 9.00-10.00 sec 12.0 MBytes 101 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 119 MBytes 100 Mbits/sec 50 sender
[ 4] 0.00-10.00 sec 119 MBytes 100 Mbits/sec receiver

实战测试

测试一下使用 wget 的下载速度,此部分操作都在宿主机1上进行

1
2
3
4
5
6
7
8
9
10
cd /tmp

# 生成一个大文件
truncate -s 50m large.dmg

# 拷贝到容器 c1 内部
docker cp large.dmg c1:/usr/share/nginx/html

# 尝试下载
wget http://0.0.0.0:8081/large.dmg

下载时网速被限制

1
large.dmg.1            18%[===>            ]   9.27M   467KB/s    eta 89s

实验环境清理

在宿主机1上

1
2
docker rm -f c{1..3}
rm /tmp/large.dmg*

在宿主机2上

1
docker rm -f c4

Ref