默认状况下,容器没有资源限制,可使用主机内核调度程序容许的尽量多的给定资源。Docker提供了控制容器可使用多少内存或CPU的方法,设置docker run命令的运行时配置标志。本节提供有关什么时候应设置此类限制以及设置这些限制的可能含义的详细信息。 其中许多功能都要求您的内核支持Linux功能。要检查支持,可使用该 docker info命令。若是内核中禁用了某项功能,您可能会在输出结尾处看到警告,以下所示: WARNING: No swap limit support
重要的是不要让正在运行的容器占用过多的主机内存。在Linux主机上,若是内核检测到没有足够的内存来执行重要的系统功能,它会抛出一个OOME或者 Out Of Memory Exception,并开始查杀进程以释放内存。任何进程都会被杀死,包括Docker和其余重要的应用程序。若是错误的进程被杀死,这能够有效地下降整个系统。 Docker尝试经过调整Docker守护程序上的OOM优先级来减轻这些风险,以便它比系统上的其余进程更不可能被杀死。容器上的OOM优先级未调整。这使得单个容器被杀死的可能性比Docker守护程序或其余系统进程被杀死的可能性更大。您不该试图经过--oom-score-adj在守护程序或容器上手动设置为极端负数或经过设置容器来绕过这些安全措施--oom-kill-disable。
* docker 经过cgroup 工具来限制容器的资源使用,对于资源最重要的就是cpu 和memory 的使用node
groups(缩写为控制组)是Linux内核功能,用于限制,计算和隔离进程集合的资源使用状况(CPU,内存,磁盘I / O,网络等)。 Google的工程师(主要是Paul Menage和Rohit Seth)于2006年以“流程容器”的名义开始了这项功能的工做。[1] 在2007年底,命名法改成“控制组”,以免由Linux内核上下文中“ 容器 ” 一词的多重含义引发的混淆,而且控制组功能在内核版本2.6中合并到Linux内核主线中.24,于2008年1月发布。[2]从那时起,开发人员增长了许多新功能和控制器,例如2014年对kernfs的支持,[3] 防火墙,[4]统一的层次结构。[5]
Cgroups提供: 资源限制 组能够设置为不超过配置的内存限制,其中还包括文件系统缓存[8] [9] 优先级 某些组可能得到更大的CPU利用率[10]或磁盘I / O吞吐量[11] 计费 测量组的资源使用状况,例如,可用于计费目的[12] 控制 冻结进程组,检查点和从新启动[12]
这些具体的资源管理功能称为cgroup子系统,有如下几大子系统实现: blkio:设置限制每一个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。 cpu:使用调度程序为cgroup任务提供cpu的访问。 cpuacct:产生cgroup任务的cpu资源报告。 cpuset:若是是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。 devices:容许或拒绝cgroup任务对设备的访问。 freezer:暂停和恢复cgroup任务。 memory:设置每一个cgroup的内存限制以及产生内存资源报告。 net_cls:标记每一个网络包以供cgroup方便使用。 ns:命名空间子系统。 perf_event:增长了对每group的监测跟踪的能力,便可以监测属于某个特定的group的全部线程以及运行在特定CPU上的线程。
在linux系统中一皆文件,固然对CGroup的接口操做也是经过文件来实现的,咱们能够经过mount命令查看其挂载目录:linux
[root@localhost ~]# mount -t cgroup cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event) cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids) cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer) cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory) [root@localhost ~]#
以上目录都是能够限制的对象,docker
[root@localhost ~]# ls /sys/fs/cgroup/memory/docker/ 2bf7818020607cd2cded3006c8bf6e76a4424175ddca76ca9bb372913b43bf24 memory.max_usage_in_bytes aa843c370defc11c303473302caad3367600ad87127bbcd65989ef7cbe4eabad memory.memsw.failcnt cgroup.clone_children memory.memsw.limit_in_bytes cgroup.event_control memory.memsw.max_usage_in_bytes cgroup.procs memory.memsw.usage_in_bytes memory.failcnt memory.move_charge_at_immigrate memory.force_empty memory.numa_stat memory.kmem.failcnt memory.oom_control memory.kmem.limit_in_bytes memory.pressure_level memory.kmem.max_usage_in_bytes memory.soft_limit_in_bytes memory.kmem.slabinfo memory.stat memory.kmem.tcp.failcnt memory.swappiness memory.kmem.tcp.limit_in_bytes memory.usage_in_bytes memory.kmem.tcp.max_usage_in_bytes memory.use_hierarchy memory.kmem.tcp.usage_in_bytes notify_on_release memory.kmem.usage_in_bytes tasks memory.limit_in_bytes [root@localhost ~]#
#标红的为容器ID 能够被限制的对象
测试ubuntu
[root@localhost ~]# cd /sys/fs/cgroup/cpu [root@localhost cpu]# ls cgroup.clone_children cpuacct.stat cpu.cfs_quota_us cpu.stat system.slice cgroup.event_control cpuacct.usage cpu.rt_period_us docker tasks cgroup.procs cpuacct.usage_percpu cpu.rt_runtime_us notify_on_release user.slice cgroup.sane_behavior cpu.cfs_period_us cpu.shares release_agent [root@localhost cpu]# mkdir limit_cpu_demo 在 /sys/fs/cgroup/cpu 目录下建立文件默认会在文件下生成限制的配置文件 [root@localhost cpu]# ls cgroup.clone_children cpuacct.stat cpu.cfs_quota_us cpu.stat release_agent cgroup.event_control cpuacct.usage cpu.rt_period_us docker system.slice cgroup.procs cpuacct.usage_percpu cpu.rt_runtime_us limit_cpu_demo tasks cgroup.sane_behavior cpu.cfs_period_us cpu.shares notify_on_release user.slice [root@localhost cpu]# cd limit_cpu_demo/ [root@localhost limit_cpu_demo]# ls cgroup.clone_children cpuacct.stat cpu.cfs_period_us cpu.rt_runtime_us notify_on_release cgroup.event_control cpuacct.usage cpu.cfs_quota_us cpu.shares tasks cgroup.procs cpuacct.usage_percpu cpu.rt_period_us cpu.stat [root@localhost limit_cpu_demo]# [root@localhost limit_cpu_demo]# while :; do :; done & #执行一个循环 [1] 17392 #top top - 22:47:15 up 1:21, 1 user, load average: 0.67, 0.21, 0.11 Tasks: 101 total, 2 running, 99 sleeping, 0 stopped, 0 zombie %Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 81028 free, 1496044 used, 286152 buff/cache KiB Swap: 4194300 total, 4185844 free, 8456 used. 157824 avail Mem
如上可见,此时该进程使用的CPU1已是100%,即%Cpu :100.0 us,咱们先来查看咱们刚才建立的cpu_limit_demo目录下这两个参数默认值是多少: centos
[root@localhost limit_cpu_demo]# cat cpu.cfs_quota_us
-1
[root@localhost limit_cpu_demo]# cat cpu.cfs_period_us
100000
cpu.cfs_quota_us值为-1表明没有任何限制,cpu.cfs_period_us 则是默认的 100 ms,即100000us,下面将向cpu_limit_demo控制组的cpu.cfs_quota_us文件写入50ms即50000us,这表示在100ms周期内,cpu最多使用%50,同时将该进程的pid号为17406写入对应的tasks文件,表示对那个进程限制: 缓存
[root@localhost limit_cpu_demo]# echo 50000 > cpu.cfs_quota_us [root@localhost limit_cpu_demo]# echo 17406 > tasks
能够看到cpu 使用率为50% 左右,说明限制生效了。一样的道理,在/sys/fs/cgroup下的子系统均可以限制不通的资源使用如Block IO、Memory等。安全
Docker能够强制执行硬内存限制,容许容器使用不超过给定数量的用户或系统内存或软限制,这容许容器使用尽量多的内存,除非知足某些条件,例如内核检测到主机上的低内存或争用。当单独使用或设置了多个选项时,其中一些选项会产生不一样的效果。
大部分的选项取正整数,跟着一个后缀b,k, m,g,,表示字节,千字节,兆字节或千兆字节。
选项 | 描述 |
---|---|
-m OR --memory= |
容器可使用的最大内存量。若是设置此选项,则容许的最小值为4m (4兆字节)。 |
--memory-swap * |
容许此容器交换到磁盘的内存量。查看--memory-swap 详情。 |
--memory-swappiness |
默认状况下,主机内核能够交换容器使用的必定百分比的匿名页面。您能够设置--memory-swappiness 0到100之间的值,以调整此百分比。查看--memory-swappiness 详情。 |
--memory-reservation |
容许您指定小于软盘限制--memory 时软盘限制,当Docker检测到主机上的争用或内存不足时。若是使用--memory-reservation ,则必须将其设置为低于--memory 优先级。由于它是软限制,因此不能保证容器不超过限制。 |
--kernel-memory |
容器可使用的最大内核内存量。容许的最小值是4m 。因为内核内存没法换出,所以内核内存不足的容器可能会阻塞主机资源,这会对主机和其余容器产生反作用。查看--kernel-memory 详情。 |
--oom-kill-disable |
默认状况下,若是发生内存不足(OOM)错误,内核会终止容器中的进程。若要更改此行为,请使用该--oom-kill-disable 选项。仅在已设置-m/--memory 选项的容器上禁用OOM杀手。若是-m 未设置标志,则主机可能会耗尽内存,内核可能须要终止主机系统的进程才能释放内存。 |
有关cgroup和内存的更多信息,请参阅内存资源控制器的文档。bash
--memory-swap
--memory-swap是一个修饰符标志,只有在--memory设置时才有意义。使用swap容许容器在容器耗尽可用的全部RAM时向磁盘写入多余的内存需求。常常将内存交换到磁盘的应用程序会下降性能。
默认--memory 和 --memory-swap 的值相同,而且 swap 的值为(--memory-swap - [--memory]) 的值。
假如 --m 为 300m ,--memory-swap 为 1G ,那么 可用memory 为300m ,swap 为 (1g-300M = 700M ),在实际配置中建议配合使用
若是只设置-m 那么默认 swap 和memory 相同,也不会进行计算,好比 -m 200M 那么 swap 默认200M 加起来 400M
官方说明copy网络
--memory-swap是一个修饰符标志,只有在--memory设置时才有意义。使用swap容许容器在容器耗尽可用的全部RAM时向磁盘写入多余的内存需求。常常将内存交换到磁盘的应用程序会下降性能。 它的设置会产生复杂的影响: 若是--memory-swap设置为正整数,那么这两个--memory和 --memory-swap必须设置。--memory-swap表示可使用的内存和交换总量,并--memory控制非交换内存使用的数量。所以,若是--memory="300m"和--memory-swap="1g",容器可使用300米的内存和700米(1g - 300m)交换。 若是--memory-swap设置为0,则忽略该设置,并将该值视为未设置。 若是--memory-swap设置为与值相同的值--memory,而且--memory设置为正整数,则容器无权访问swap。请参见 阻止容器使用交换。 若是--memory-swap未设置而且--memory已--memory设置,则若是主机容器配置了交换内存,则容器可使用两倍于设置的交换。例如,若是--memory="300m"和--memory-swap未设置,容器可使用300米的内存和600米的交换。 若是--memory-swap明确设置为-1,则容许容器使用无限制交换,最多可达主机系统上可用的数量。 在容器内部,工具如free报告主机的可用交换,而不是容器内可用的内容。不要依赖输出free或相似工具来肯定是否存在交换。 防止容器使用交换 若是--memory和--memory-swap设置为相同的值,则能够防止容器使用任何交换。这是由于--memory-swap可使用的组合内存和交换量,而--memory只是可使用的物理内存量。
[root@localhost ~]# docker run -it --name c2 -m 100M --memory-swap 200M centos:latest
--memory-swappiness
值为0将关闭匿名页面交换。 值100将全部匿名页面设置为可交换。 默认状况下,若是未设置--memory-swappiness,则值将从父进程继承。
[root@localhost ~]# docker run -it --name c2 --memory-swappiness=0 centos:latest [root@e9fac4e4aa4d /]#
默认状况下,若是发生内存不足(OOM)错误,内核会终止容器中的进程。若要更改此行为,请使用该--oom-kill-disable选项。仅在已设置-m/--memory选项的容器上禁用OOM杀手。若是-m未设置标志,则主机可能会耗尽内存,内核可能须要终止主机系统的进程才能释放内存。
[root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable centos:latest [root@2d440f001a3f /]# [root@localhost ~]# cat /sys/fs/cgroup/memory/docker/e9fac4e4aa4d1c5deb73881f612f3aa2f0bbbc42c020ce8e184f6e9601dc5d6b/memory.oom_control oom_kill_disable 0 #功能默认关闭,会kill 掉超过限制的容器 under_oom 0 [root@localhost ~]# cat /sys/fs/cgroup/memory/docker/2d440f001a3f04d69acb66c459d9a565fffc329d5e3ee9822c9480ccf58b476b/memory.oom_control oom_kill_disable 1 #功能开启,防止kill 掉容器 under_oom 0 [root@localhost ~]#
默认状况下,每一个容器对主机CPU周期的访问权限是不受限制的。您能够设置各类约束来限制给定容器访问主机的CPU周期。大多数用户使用和配置 默认CFS调度程序。在Docker 1.13及更高版本中,您还能够配置 实时调度程序。 配置默认CFS调度程序 CFS是用于正常Linux进程的Linux内核CPU调度程序。多个运行时标志容许您配置对容器具备的CPU资源的访问量。使用这些设置时,Docker会修改主机上容器的cgroup的设置。
选项 | 描述 |
---|---|
--cpus=<value> |
指定容器可使用的可用CPU资源量。例如,若是主机有两个CPU而且您已设置--cpus="1.5" ,则容器最多保证一个半CPU。这至关于设置--cpu-period="100000" 和--cpu-quota="150000" 。可在Docker 1.13及更高版本中使用。 |
--cpu-period=<value> |
指定与之一块儿使用的CPU CFS调度程序周期 --cpu-quota 。默认为100微秒。大多数用户不会更改默认设置。若是您使用Docker 1.13或更高版本,请--cpus 改用。 |
--cpu-quota=<value> |
在容器上施加CPU CFS配额。--cpu-period 限制前容器限制为每秒的微秒数。这样做为有效上限。若是您使用Docker 1.13或更高版本,请--cpus 改用。 |
--cpuset-cpus |
限制容器可使用的特定CPU或核心。若是您有多个CPU,则容器可使用的以逗号分隔的列表或连字符分隔的CPU范围。第一个CPU编号为0.有效值多是0-3 (使用第一个,第二个,第三个和第四个CPU)或1,3 (使用第二个和第四个CPU)。 |
--cpu-shares |
将此标志设置为大于或小于默认值1024的值,以增长或减小容器的重量,并使其能够访问主机的CPU周期的更大或更小比例。仅在CPU周期受限时才会强制执行此操做。当有足够的CPU周期时,全部容器都会根据须要使用尽量多的CPU。这样,这是一个软限制。--cpu-shares 不会阻止容器以群集模式进行调度。它为可用的CPU周期优先考虑容器CPU资源。它不保证或保留任何特定的CPU访问权限。 |
测试app
若是您有1个CPU,则如下每一个命令都会保证容器每秒最多占CPU的50%。
Docker 1.13及更高版本:
docker run -it --cpus=".5" ubuntu /bin/bash
[root@829f06a8eba2 /]# while :; do :; done & [1] 14 [root@829f06a8eba2 /]# top top - 07:49:43 up 6:24, 0 users, load average: 0.36, 0.11, 0.12 Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 95.0 us, 5.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 128896 free, 1400608 used, 333720 buff/cache KiB Swap: 4194300 total, 4167420 free, 26880 used. 248504 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14 root 20 0 11820 576 200 R 94.7 0.0 0:21.47 bash 1 root 20 0 11820 1888 1512 S 0.0 0.1 0:00.08 bash 15 root 20 0 56192 2004 1468 R 0.0 0.1 0:00.06 top [root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" centos:latest [root@12959b971167 /]# [root@12959b971167 /]# while :; do :; done & [1] 14 [root@12959b971167 /]# top top - 07:51:43 up 6:26, 0 users, load average: 0.42, 0.24, 0.17 Tasks: 3 total, 2 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 51.2 us, 0.3 sy, 0.0 ni, 48.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 127564 free, 1402052 used, 333608 buff/cache KiB Swap: 4194300 total, 4167420 free, 26880 used. 247084 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14 root 20 0 11820 604 208 R 50.2 0.0 0:07.50 bash 15 root 20 0 56192 2004 1468 R 0.3 0.1 0:00.01 top 1 root 20 0 11820 1928 1540 S 0.0 0.1 0:00.08 bash
限制容器可使用的特定CPU或核心。若是您有多个CPU,则容器可使用的以逗号分隔的列表或连字符分隔的CPU范围。第一个CPU编号为0.有效值多是0-3(使用第一个,第二个,第三个和第四个CPU)或1,3(使用第二个和第四个CPU)。
[root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" --cpuset-cpus=0 centos:latest
[root@ad48f90b38fa /]#
使用启动容器时,能够传递多个标志来控制容器的CPU优先级docker run
。有关ulimit
适当值的信息,请参阅操做系统的文档或命令。
nice 值
Nice值是类UNIX操做系统中表示静态优先级的数值。每一个进程都有本身的静态优先级,优先级高的进程得以优先运行。 Nice值的范围是-20~+19,拥有Nice值越大的进程的实际优先级越小(即Nice值为+19的进程优先级最小,为-20的进程优先级最大),默认的Nice值是0。因为Nice值是静态优先级,因此一经设定,就不会再被内核修改,直到被从新设定。Nice值只起干预CPU时间分配的做用,实际中的细节,由动态优先级决定。 “Nice值”这个名称来自英文单词nice,意思为友好。Nice值越高,这个进程越“友好”,就会让给其余进程越多的时间。
选项 | 描述 |
---|---|
--cap-add=sys_nice |
授予容器CAP_SYS_NICE 容量,容许容器提高过程nice 值,设置实时调度策略,设置CPU关联性和其余操做。 |
--cpu-rt-runtime=<value> |
容器能够在Docker守护程序的实时调度程序周期内以实时优先级运行的最大微秒数。你还须要--cap-add=sys_nice 旗帜。 |
--ulimit rtprio=<value> |
容器容许的最大实时优先级。你还须要--cap-add=sys_nice值 。 |
[root@localhost ~]# docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" --cpuset-cpus=0 centos:latest #没有给nice 值
[root@ae4bdc3fb9f9 /]#
[root@localhost ~]# ps -ef |grep docker root 19782 1 0 03:08 ? 00:00:17 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root 20085 19782 0 03:09 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8081 -container-ip 172.17.0.2 -container-port 8081 root 20098 6505 0 03:09 ? 00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/2bf7818020607cd2cded3006c8bf6e76a4424175ddca76ca9bb372913b43bf24 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc root 24464 19426 0 04:06 pts/3 00:00:00 docker run -it --name c2 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=.5 --cpuset-cpus=0 centos:latest root 24490 6505 0 04:06 ? 00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/ae4bdc3fb9f941fa7824916ef62ec0d2eacf76d5b53120a52392a9d37a9a2c53 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc root 24564 21769 0 04:06 pts/0 00:00:00 grep --color=auto docker [root@localhost ~]# top -p 24490 top - 04:07:08 up 6:41, 3 users, load average: 0.02, 0.10, 0.17 Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 1863224 total, 140776 free, 1402892 used, 319556 buff/cache KiB Swap: 4194300 total, 4167164 free, 27136 used. 246256 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 24490 root 20 0 10656 3352 2492 S 0.0 0.2 0:00.01 containerd-shim
root@localhost ~]# docker run -it --name c3 -m 200m --memory-swappiness=0 --oom-kill-disable --cpus=".5" --cpuset-cpus=0 --cap-add=sys_nice centos:latest [root@cb39dcbc9606 /]#