如何在Docker容器中对网络流量进行速率限制?

24
我想为点对点应用程序设置一个 Docker 容器。该应用程序没有应用程序级别的速率限制,因此我试图在容器级别上设置限制。我希望对所有端口的出站和入站连接进行速率限制,但不包括该应用程序 Web UI 使用的端口。
3个回答

23
我很惊讶发现这个问题的答案如此难以找到。各种论坛上的大多数回答都是错误的(我用两个iperf3节点测试过,发现那些解决方案不起作用或只限制了一个方向的流量(仅入站或仅出站)。对于一个具有比传统客户端/服务器应用程序更对称数据使用的P2P应用程序,因此必须在两个方向上限制流量。

我发现限制Docker容器的网络带宽(入站和出站)的最佳方法是在运行容器内部使用Linux自己的流量控制设置。在启动P2P应用程序之前,在容器内执行tc命令。

例如,您可以创建以下启动脚本,将其复制到docker映像中,并将其作为ENTRYPOINT调用。

Dockerfile(片段):

COPY start-my-p2p.sh /
RUN chmod +x /start-my-p2p.sh    
ENTRYPOINT /start-my-p2p.sh   

在您的 start-my-p2p.sh 文件中添加类似以下内容(tc 命令可能是您一直在互联网上搜索的内容):

将类似以下内容放入您的 start-my-p2p.sh 中(tc 命令可能是您一直在搜索互联网上的内容):

#/bin/sh

# Limit all incoming and outgoing network to 1mbit/s
tc qdisc add dev eth0 handle 1: ingress
tc filter add dev eth0 parent 1: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate 1mbit burst 10k drop flowid :1
tc qdisc add dev eth0 root tbf rate 1mbit latency 25ms burst 10k`

# Now start your p2p application
myp2pservice -d 

重要提示:在启动容器时,您需要使用--cap-add=NET_ADMIN参数:

docker run --rm -it --cap-add=NET_ADMIN -p6969:p6969 myimage

第一行失败,显示:“独占标志开启,无法修改”。 - David Taub

2
在 Docker 主机上应用 tc 策略。
# find container pid
container_id=$(docker inspect some_container -f '{{.State.Pid}}')
mkdir -p /var/run/netns
# link network namespace for `some_container`
ln -sfT /proc/$container_id/ns/net /var/run/netns/some_container
# view the interface of the container
ip netns exec some_container ip -br -c link
# add traffic control policy to the interface in network namespace `some_container`
# tc -n some_container qdisc add dev eth0 tbf rate 1024kbps 1024b limit 1024b
# update tc 2023/05/19
tc -n some_container qdisc add dev eth0 handle 10: root tbf limit 1024 burst 2048 rate 1024

最后一行返回“tbf:未知参数”1024b”,因此我尝试使用“tc -n some_container qdisc add dev eth0 tbf rate“10.0Mbit”burst“55000”latency“50ms””,但这会返回“错误:句柄不能为零。”我真的不喜欢“tc”,因为它的语法过于复杂,而且在出错时只返回无用的消息。 :| - mgutt
tc 很强大,但不易使用。但 tc 是用于流量控制的工具。另一种方法是使用 iptables 在网络命名空间中进行流量控制。 - obarisk
最后一个 tc -n 命令给出了 RTNETLINK answers: No such file or directory 的错误信息。eth0 是主机还是容器的接口? - undefined
所有关于主机的操作都需要 root 权限来操作网络命名空间。 使用 tc -n 命令可以在网络命名空间上运行 tc。 可以通过 ip netns ls 命令来检查网络命名空间。 - undefined

1
你可以使用iptables limits模块。例如,您可以使用选项“-m limit --limit 10/s”向PREROUTING表添加规则,以限制特定端口每秒只接收10个连接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接