docker资源限制

容器底层技术

Docker底层技术包括:namespace主要是隔离作用,cgroups主要是资源限制,联合文件主要用于 镜像分层存储和管理

在这里插入图片描述

namespace

namespace是将内核的全局资源做封装,使得每个namespace都有一份独立的资源,因此不同的进程在各自的namespace内对同一种资源的使用不会互相干扰

  1. UTS namespace提供了主机名和域名的隔离,这样每个容器就拥有独立的主机名和域名了,在网络上就可以被视为一个独 立的节点,在容器中对hostname的命名不会对宿主机造成任何影响。
  2. IPC namespace实现了进程间通信的隔离,包括常见的几种进程间通信机制,如信号量,消息队列和共享内存。
  3. PID namespace完成的是进程号的隔离,同样的一个进程在不同的PID Namespace里面可以拥有不同的PID。
  4. Mount namespace是用来隔离各个进程看到的挂载点视图。在不同namespace中的进程看到的文件系统层次是不一样 的。
  5. User namespace主要是隔离用户的用户组ID。也就是说,一个进程的User ID和Group ID在User namespace内外可以是不同的。
  6. Network namespace是用来隔离网络设备,IP地址端口等网络栈的namespace。Network namespace可以让每个容器 拥有自己独立的网络设备(虚拟的),而且容器内的应用可以绑定到自己的端口,每个namesapce内的端口都不会互相冲突

cgroups

cgroups是control groups的缩写,最初由google的工程师提出,后来被整合进Linux内核。cgroups是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:CPU、内存、IO等)的机制。在默认情况下,Docker容器并不会对容器内部进程使用的内存大小进行任何限制。对于直接使用Docker的用户而言,这非常危险。如果哪个业务容器,出现了内存泄漏;那么它可能会危害到整个主机系统,导致业务应用容器所在的主机出现OOM

cgroups到底长什么样子呢?我们可以在/sys/fs/cgroup中找到它,创建一个新容器,并使用-m限制容器能够使用的内存大小

[root@docker ~] docker run --name cycentos1 -itd -m 200M centos:7

随着容器的创建启动,在/sys/fs/cgroup/memory/docker/目录中,Linux会创建该容器的cgroup目录,目录中包含了对容器所使 用资源的限制

[root@docker ~] cat /sys/fs/cgroup/memory/docker/cc5e321eed337a9575c4e302752e56d12c27b44bd
08a357c94d0cd3ae83fdfa6/memory.limit_in_bytes

在/sys/fs/cgroup/目录中还包含其他的资源限制

[root@docker ~] ls /sys/fs/cgroup/
blkio cpuacct cpuset freezer memory net_cls,net_prio perf_event systemd
cpu cpu,cpuacct devices hugetlb net_cls net_prio pids

资源管理

每个容器在运行时,都需要内存、CPU、IO等资源,用户可以根据需求为容器分配资源。 对于容器而言,容器中的资源大小与Docker host资源大小是一致的,因为它们都共享同一个 内核。如果运行多个容器,某个容器在运行过程中异常占用大量的资源,那么势必会对其他容 器造成影响

构建stress镜像,stress是一个容器压力测试工具,也能帮助我们学习docker的资源限制

[root@docker ~] vim Dockerfile
FROM ubuntu:trusty
RUN apt-get update && apt-get install -y stress
ENTRYPOINT ["/usr/bin/stress","--verbose"]
[root@docker ~] docker build -t stress .

内存限制

-m, --memory=“<数字>[<单位>]” 内存使用限制。数字需要使用整数,对应的单位是b,k,m,g中的一个。最小取值是4M
–memory-swap=“<数字>[<单位>]” 总内存使用限制(物理内存 + 交换分区,数字需要使用整数,对应的单位是b,k,m,g中的一个
–memory-reservation=“<数字>[<单位>]” 内存软限制。数字需要使用整数,对应的单位是b,k,m,g中的一个
–kernel-memory=“<数字>[<单位>]” 内核内存限制。数字需要使用正整数,对应的单位是b,k,m,g中的一个。最小值取是4M
–oom-kill-disable=false 内存耗尽时是否杀掉容器
–memory-swappiness=“” 调节容器内存使用交换分区的选项,取值为0和100之间的整数(含0和100)
–oom-score-adj 容器被OOM killer杀死的优先级,范围是[-1000,1000],默认为0

内存限制

1、容器对内存的使用限制一般会使用-m或者–memory,这个参数仅限制对物理内存的使用

[root@docker~] dockerrun-it--namea1--rm-m50Mstress--vm1--vm-bytes30M

2、在容器中也可以使用swap,这就需要用到–memory-swap参数,–memory-swap是指容器所用的物理内存加sawp的总和,需要配合-m使用

[root@docker~] dockerrun-it--namea1--rm-m50M--memory-swap=100Mstress--vm 1--vm-bytes70M

3、Memoryreservation是一种软性限制,用于节制容器内存使用

[root@docker~] dockerrun-it-m100M--memory-reservation50Mcentos:7

4、我们可以通过设置–oom-kill-disable选项来禁止OOMkiller杀死容器内进程

[root@docker~] dockerrun-it-m100M--oom-kill-disablecentos:7

cpu限制

常用的容器CPU限制参数如表:

-c,–cpu-share=0 CPU份额(相对权重)
–cpu-period=0 完全公平算法中的period值
–cpu-quota=0 完美公平算法中的quota值
–cpuset-cpus=“<数字>” 限制容器使用的cpu核(0-3,0,1)
–cpuset-mems=“” 限制容器的使用内存节点,该限制仅仅在NUMA系统中生效

1、创建两个容器a1和a2,a1的cpu权重为512,a2的cpu权重为1024,,同时将Dockerhost上的cpu全部占满

[root@docker~] dockerrun-it--namea1--rm-c512stress--cpu4
[root@docker~] dockerrun-it--namea2--rm-c1024stress--cpu4
[root@docker~] top
top-17:49:54up1:03,3users,loadaverage:7.51,3.55,1.45
Tasks:184total,9running,175sleeping,0stopped,0zombie
%Cpu(s):100.0us,0.0sy,0.0ni,0.0id,0.0wa,0.0hi,0.0si,0.0st
PID   USER PR NI VIRT RES SHR S %CPU  %MEM  TIME+ COMMAND
12288 root 20 0  7312 88  0   R 16.9  0.0   0:23.97 stress
12286 root 20 0  7312 88  0   R 16.6  0.0   0:23.96 stress
12287 root 20 0  7312 88  0   R 16.6  0.0   0:23.96 stress
12289 root 20 0  7312 88  0   R 16.3  0.0   0:23.96 stress

2、参数-cpuset-cpus用于设置容器可以使用的CPU核数,示例如下,将容器中的工作进程运行在cpu1和cpu3上面

[root@docker ~] docker run -it --name a1 --rm --cpuset-cpus="1,3" stress --vm 2 --vm-bytes 100M
[root@docker ~] top
top - 18:28:33 up 2 min, 2 users, load average: 0.37, 0.13, 0.05
Tasks: 204 total, 3 running, 201 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 2.0 sy, 0.0 ni, 97.6 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu1 : 3.7 us, 96.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 1.4 sy, 0.0 ni, 98.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 4.3 us, 95.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

Block IO限制

Block IO限制常用参数如表:

–blkio-weight=0 块设备IO相对权重,取值在10值1000之间的整数(包含10和1000)
–blkio-weight-device=“设备名称:权重值” 指定的块设备的IO相对权重
–device-read-dps=“<设备路径>:<数字>[<单位>]” 限制对某个设备的读取速率,数字需要使用正整数,单位是kb,mb,or gb中的一个
–device-write-dps=“<设备路径>:<数字>[<单位>]” 限制对某个设备的写速率,数字需要使用整数,单位是kb,mb,偶然gb中的一个
–device-read-iops=“<设备路径>:<数字>” 限制对某个设备每秒IO的读取速率,数字需要使用正整数
–device-write-iops=“<设备路径>:<数字>” 限制某个设备每秒IO的写速率,数字需要使用正整数

1、blkioIO权重,默认情况下,所有的容器都是平级的读写磁盘,可以通过–blkio-weight参数设置容器读写磁盘的优先级

示例如下,使用下面的命令创建两个–blkio-weight值不同的容器

[root@docker~] dockerrun--namecy1-it--rm--blkio-weight100centos:7
[root@docker~] dockerrun--namecy2-it--rm--blkio-weight1000centos:7

2、device-write-bps,默认情况下,Docker对容器的写速度是没有限制的,我们可以使用–device-write-bps参数限 制容器对硬盘些速度的限制

示例如下,使用下面的命令创建容器,并执行命令验证写速度的限制。通过直接结果可以得知,容器向硬盘写入20M 的数据,以1.0 MB/s的速度写入

[root@docker~] docker run --name cy3 -it --rm --device-write-bps /dev/sda:1mb centos:7
[root@579336a2f1bf /] time dd if=/dev/zero of=test.out bs=1M count=20 oflag=direct
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied, 20.0125 s, 1.0 MB/s
real 0m20.014s
user 0m0.008s
sys  0m0.001s

总结

  1. Linux内核总共实现了6种Namespace,分别是:UTS、IPC、PID、Mount、User、Network
  2. 随着容器的创建启动,在/sys/fs/cgroup/目录中,Linux会创建该容器的cgroup目录,目录中包含了 对容器所使用资源的限制
  3. Docker容器资源限制,只是在容器对资源的使用上进行限制,但是对于容器而言,它总是认为自己资 源和Docker host是一样的
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐