在容器网络命名空间中通过tc直接操作veth设备实现流量限速最可靠:先查容器pid和对应宿主机veth接口,再用tbf或htb配置egress限速,结合cgroup可统一调度多容器流量,最后用iperf3实测验证。

直接在容器网络命名空间里操作 tc,是实现流量精细化调度最可靠的方式。Docker 本身不提供带宽限速功能,但它的网络隔离机制(独立 network namespace + veth-pair)恰好为 Linux 原生 tc 工具提供了理想落点——你能精准控制单个容器的出向流量,不影响宿主机或其他容器。
找准容器对应的 veth 设备
每个容器启动时,Docker 会在宿主机创建一对 veth 设备,一端连 docker0 或自定义网桥,另一端挂载进容器网络命名空间。关键不是找“容器内看到的 eth0”,而是找到宿主机上那条与之配对的 veth 接口。
- 先获取容器 PID:
docker inspect -f '{{.State.Pid}}' <container_name_or_id></container_name_or_id> - 查该 PID 下的网络设备名:
ls -la /proc/<pid>/root/sys/class/net/</pid>,通常能看到类似eth0的设备 - 回到宿主机,用
ip link show找到名称匹配的 veth* 接口(如vethabc123),它就是你要限速的目标网卡
在 veth 上配置 HTB 或 TBF 队列
HTB 更适合多容器分级限速,TBF 更简单直接。以下以限制出口带宽为 2Mbps 的 TBF 为例:
- 清空已有规则(避免冲突):
tc qdisc del dev vethabc123 root 2>/dev/null || true - 添加限速规则:
tc qdisc add dev vethabc123 root tbf rate 2mbit burst 32kbit latency 400ms - 验证是否生效:
tc qdisc show dev vethabc123,应看到 tbf 行
注意:tc 控制的是发包方向(egress),即容器向外发送的数据;对入向(ingress)限速需借助 ifb 虚拟设备,一般不必要。
结合网络命名空间做动态策略绑定
若需按业务类型统一调度(比如所有日志服务限速、所有 API 容器保底带宽),可将容器加入特定 cgroup,并用 tc filter 绑定 classid。
- 创建 cgroup:
sudo cgcreate -g net_cls:/log-containers - 设置 classid:
echo 0x00010001 | sudo tee /sys/fs/cgroup/net_cls/log-containers/net_cls.classid - 把容器 PID 加入该组:
echo <pid> | sudo tee /sys/fs/cgroup/net_cls/log-containers/cgroup.procs</pid> - 在宿主机网卡(如 eth0)上配置 htb + filter:
tc filter add dev eth0 parent 1: protocol ip handle 1: cgroup
这样所有属于 log-containers 组的容器流量,都会被归类到同一限速类中,便于统一管理。
用 iperf3 验证限速效果
别只信 tc 输出,实测才靠谱。建议在容器内运行 iperf3 服务端,在宿主机或另一台机器跑客户端测试:
- 容器内启动服务端:
iperf3 -s -p 5001 - 宿主机发起测试:
iperf3 -c <container_ip> -p 5001 -t 30 -i 2</container_ip> - 观察实际吞吐是否稳定在设定值附近(允许 ±10% 波动)
如果结果远低于预期,检查是否误限了宿主机物理网卡,或容器用了 host 网络模式(此时 veth 不存在,需改限 eth0)。











