容器资源的限制
默认情况下,容器没有资源限制,可以使用主机内核调度程序允许的尽可能多的给定资源。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 的使用
cgroup
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命令查看其挂载目录:
[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 ~]#
以上目录都是可以限制的对象,
[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 可以被限制的对象
测试
[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目录下这两个参数默认值是多少:
[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等。