docker 资源限制

docker 限制

Docker是一个开源的应用容器引擎,允许开发者打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙盒机制,相互之间不会有任何接口。在进行资源管理和限制方面,Docker提供了多种机制来限制容器的资源使用,包括CPU、内存、磁盘I/O以及网络带宽。下面是一些基本的资源限制方法:

1. CPU资源限制

  • 限制CPU使用率:可以通过--cpus参数来限制容器可以使用的CPU资源。例如,docker run --cpus=".5" nginx命令会限制nginx容器最多只能使用50%的CPU资源。
docker run -d --cpus="0.5" --name test_cpu  ubuntu /bin/sh -c "while true; do :; done"
97ad37f98476ceeaad63fcdea723fef082cf9521afcd3c7b572f93d05aeed1b2

docker stats 97ad37f98476ceeaad63fcdea723fef082cf9521afcd3c7b572f93d05aeed1b2
CONTAINER ID   NAME       CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
97ad37f98476   test_cpu   51.06%    356KiB / 31.34GiB   0.00%     866B / 0B   0B / 0B     1

  • 限制CPU核心:使用--cpuset-cpus参数可以指定容器可以使用的CPU核心。例如,docker run --cpuset-cpus="0-2,4" nginx命令会限制nginx容器只能使用CPU的第1、2、3和第5个核心。
docker run -d   --cpuset-cpus="0-2,4" --cpus="0.5" --name test_cpu  ubuntu /bin/sh -c "while true; do :; done"

docker inspect --format '{{.HostConfig.CpusetCpus}}' test_cpu
0-2,4

ps -eo %cpu,%mem,pid,cmd --sort=-%cpu |grep while
99.9  0.0   24905 /bin/sh -c while true; do :; done
 0.0  0.0   30116 grep while

taskset -pc 24905
pid 24905's current affinity list: 0-2,4

2. 内存资源限制

  • 限制最大内存使用量:通过--memory-m参数可以限制容器使用的最大内存量。例如,docker run -m 256m nginx命令会限制nginx容器最多只能使用256MB的内存。
docker run --rm  -d -m 400m --name test_cpu debian_with_stress /bin/sh -c " stress --vm 1 --vm-bytes 100M --vm-hang 0"
c6d45bcaaba0fb4178a541afdbbc7ab37ce70a7b968b66da4eb4b1b03f2b883e
docker stats c6d45bcaaba0fb4178a541afdbbc7ab37ce70a7b968b66da4eb4b1b03f2b883e
CONTAINER ID   NAME       CPU %     MEM USAGE / LIMIT   MEM %     NET I/O       BLOCK I/O   PIDS
c6d45bcaaba0   test_cpu   0.00%     100.8MiB / 400MiB   25.21%    1.09kB / 0B   0B / 0B     3

  • 限制内存交换区使用量:通过--memory-swap参数可以限制容器使用的内存加上交换区的总量。例如,docker run --memory="256m" --memory-swap="1g" nginx命令会限制nginx容器使用的内存加上交换区的总量不超过1GB。
    我们机器不开通swap谢谢
docker run --rm  -d  --memory="500m" --memory-swap="1g"  --name test_cpu debian_with_stress /bin/sh -c " stress --vm 1 --vm-bytes 400M --vm-hang 0"

3. 磁盘I/O资源限制

正常

 time dd if=/dev/zero of=/tmp/testfile bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.149226 s, 703 MB/s

real	0m0.152s
user	0m0.001s
sys	0m0.037s

  • 限制读写速率:可以通过--device-read-bps--device-write-bps参数来限制容器对特定设备的读写速率。例如,docker run --device-write-bps /dev/sda:1mb nginx命令会限制nginx容器对/dev/sda设备的写速率不超过1MB/s。
docker run --rm -it --device-write-bps /dev/vdb:1mb ubuntu /bin/bash
root@6f08d52efcac:/# time dd if=/dev/zero of=/tmp/testfile bs=1M count=100 oflag=direct

100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 100.008 s, 1.0 MB/s

real	1m40.011s
user	0m0.043s
sys	0m0.000s

  • 限制IOPS:通过--device-read-iops--device-write-iops参数可以限制容器对特定设备的读写操作次数。例如,docker run --device-write-iops /dev/sda:1000 nginx命令会限制nginx容器对/dev/sda设备的写操作不超过每秒1000次。
root@79698c20e560:/# time dd if=/dev/zero of=/mnt/testfile bs=4k count=10000 oflag=direct

10000+0 records in
10000+0 records out
40960000 bytes (41 MB, 39 MiB) copied, 0.687875 s, 59.5 MB/s

real	0m0.690s
user	0m0.018s
sys	0m0.167s

 docker run --rm -it --device-read-iops /dev/vdb:500 --device-write-iops /dev/vdb:500 ubuntu /bin/bash
root@ea535a7335eb:/# time dd if=/dev/zero of=/mnt/testfile bs=4k count=10000 oflag=direct

10000+0 records in
10000+0 records out
40960000 bytes (41 MB, 39 MiB) copied, 19.9105 s, 2.1 MB/s

real	0m19.913s
user	0m0.001s
sys	0m0.470s

time dd if=/mnt/testfile of=/dev/null bs=4k iflag=direct

10000+0 records in
10000+0 records out
40960000 bytes (41 MB, 39 MiB) copied, 19.9077 s, 2.1 MB/s

real	0m19.910s
user	0m0.001s
sys	0m0.292s




磁盘限制

4. 网络带宽限制

Docker原生并不直接支持网络带宽的限制。但是,可以通过第三方工具如tc(traffic control)来实现对容器网络带宽的限制。此外,Docker的网络插件机制允许使用不同的网络驱动来提供额外的网络功能,包括网络带宽限制。

结论

Docker提供了灵活的资源限制选项,帮助用户更好地管理和分配容器资源。通过合理设置这些参数,可以确保容器应用的高效运行,同时避免单个容器占用过多资源而影响系统的稳定性。需要注意的是,合理的资源限制策略应该基于对应用性能需求的理解和测试。


如果你已经准备好尝试使用iptables直接在宿主机上操作以添加端口映射到Docker容器,下面是一个基于Debian镜像的示例。请注意,这个过程涉及到底层的网络配置,如果操作不当可能会影响到宿主机和其他容器的网络连接。请确保你已经备份了重要数据,并且最好在一个测试环境中进行以下操作。

步骤1: 创建并启动Docker容器

首先,创建并启动一个基于Debian镜像的Docker容器,我们假设你已经映射了一些初始端口,比如22和80。

docker run -d --name my-debian-container -p 22:22 -p 80:80 debian

步骤2: 查找Docker容器的网络命名空间

Docker容器的网络命名空间并不直接暴露,但我们可以通过查找容器的进程ID(PID)来间接获取。首先,找到容器的PID:

docker inspect --format '{{ .State.Pid }}' my-debian-container

然后,你可以通过查看/proc/<PID>/ns/net来确认网络命名空间,但这通常不是必需的,因为我们将直接在宿主机上操作iptables

步骤3: 使用iptables添加端口映射规则

现在,我们将使用iptables在宿主机上为Docker容器添加新的端口映射规则。假设我们要添加8080端口的映射:

# 先找到Docker使用的网桥接口,通常是docker0
docker_network_interface=$(ip -o -4 addr show scope global | awk '{print $2}' | grep docker0)

# 添加iptables规则
 iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-debian-container):8080
 iptables -t filter -A DOCKER -d $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-debian-container)/32 ! -i $docker_network_interface -o $docker_network_interface -p tcp -m tcp --dport 8080 -j ACCEPT

8083->8082

# 添加DNAT规则,将宿主机的8083端口流量转发到容器的8082端口
sudo iptables -t nat -A DOCKER -p tcp --dport 8083 -j DNAT --to-destination $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-debian-container):8082

# 添加允许规则,允许流向容器8082端口的流量
docker_network_interface=$(ip -o -4 addr show scope global | awk '{print $2}' | grep docker0)
sudo iptables -t filter -A DOCKER -d $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-debian-container)/32 ! -i $docker_network_interface -o $docker_network_interface -p tcp -m tcp --dport 8082 -j ACCEPT

这里,我们添加了两条iptables规则:

  1. 第一条规则在NAT表的DOCKER链上添加了一条DNAT规则,用于将目标端口8080的流量转发到容器的8080端口。
  2. 第二条规则在filter表的DOCKER链上添加了一条允许规则,用于允许流向容器8080端口的流量。
    加完以后
 iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   32  1712 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   24  1521 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:80
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:22

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:2200 to:172.17.0.2:22
   22  1144 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:8080

iptables -t nat -L DOCKER -n -v | grep 'tcp dpt:' | awk '{print $11}'|awk -F ':' '{print $2}' 
80
2200
8080

ss -tnlp | awk '{print $4}' | awk -F ':' '{print $2}' | grep -vE '^\s*$'
6010
6011
6012
6013
80
22
2200

注意

  • 这个过程可能需要根据你的具体网络配置进行调整。
  • 如果你的Docker使用的不是默认的docker0网桥,你需要相应地调整命令中的网桥接口名称。
  • 这些规则在宿主机重启后不会自动恢复,你可能需要将它们添加到启动脚本中,或使用Docker的网络插件来管理这些规则。

请谨慎操作,并确保你理解每条命令的含义和潜在影响。

  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

(~ ̄▽ ̄)~凤凰涅槃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值