国外域名注册商网站,好的企业官网建设公司,如何查询企业联系方式,h5表单制作背景 在使用 docker 运行容器时#xff0c;默认的情况下#xff0c;docker没有对容器进行硬件资源的限制#xff0c;当一台主机上运行几百个容器#xff0c;这些容器虽然互相隔离#xff0c;但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制默认的情况下docker没有对容器进行硬件资源的限制当一台主机上运行几百个容器这些容器虽然互相隔离但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制那么容器之间会互相影响小的来说会导致容器资源使用不公平大的来说可能会导致主机和集群资源耗尽服务完全不可用。 docker 作为容器的管理者自然提供了控制容器资源的功能。正如使用内核的 namespace 来做容器之间的隔离docker 也是通过内核的 cgroups 来做容器的资源限制包括CPU、内存、磁盘三大方面基本覆盖了常见的资源配额和使用量控制。 Docker内存控制OOME在linxu系统上如果内核探测到当前宿主机已经没有可用内存使用那么会抛出一个OOME(Out Of Memory Exception:内存异常 )并且会开启killing去杀掉一些进程。 一旦发生OOME任何进程都有可能被杀死包括docker daemon在内为此docker特地调整了docker daemon的OOM_Odj优先级以免他被杀掉但容器的优先级并未被调整。经过系统内部复制的计算后每个系统进程都会有一个OOM_Score得分OOM_Odj越高得分越高在docker run的时候可以调整OOM_Odj得分最高的优先被kill掉当然也可以指定一些特定的重要的容器禁止被OMM杀掉在启动容器时使用 –oom-kill-disabletrue指定。 参考Docker监控容器资源的占用情况 cgroup简介 cgroup是Control Groups的缩写是Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如 cpu、memory、磁盘IO等等) 的机制被LXC、docker等很多项目用于实现进程资源控制。cgroup将任意进程进行分组化管理的 Linux 内核功能。cgroup本身是提供将进程进行分组化管理的功能和接口的基础结构I/O 或内存的分配控制等具体的资源管理功能是通过这个功能来实现的。这些具体的资源管理功能称为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上的线程。目前docker只是用了其中一部分子系统实现对资源配额和使用的控制。 可以使用stress工具来测试CPU和内存。使用下面的Dockerfile来创建一个基于Ubuntu的stress工具镜像。 FROM ubuntu:14.04RUN apt-get update apt-get install stress 资源监控的关键目录cat读出 已使用内存 /sys/fs/cgroup/memory/docker/应用ID/memory.usage_in_bytes 分配的总内存 /sys/fs/cgroup/memory/docker/应用ID/memory.limit_in_bytes 已使用的cpu单位纳秒 /sys/fs/cgroup/cpuacct/docker/应用ID/cpuacct.usage 系统当前cpu $ cat /proc/stat | grep cpu 周期/时间片/jiffies
#得到的数字相加/HZcat /boot/config-uname -r | grep ^CONFIG_HZ ubuntu 14.04为250就是系统时间秒 #再乘以10*9就是系统时间纳秒 例子 [~]$ cat /proc/stat
cpu 432661 13295 86656 422145968 171474 233 5346 cpu0 123075 2462 23494 105543694 16586 0 4615 cpu1 111917 4124 23858 105503820 69697 123 371 cpu2 103164 3554 21530 105521167 64032 106 334 cpu3 94504 3153 17772 105577285 21158 4 24 intr 1065711094 1057275779 92 0 6 6 0 4 0 3527 0 0 0 70 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ctxt 19067887 btime 1139187531 processes 270014 procs_running 1 procs_blocked 0 输出解释 CPU 以及CPU0、CPU1、CPU2、CPU3每行的每个参数意思以第一行为例为 参数 解释 user (432661) 从系统启动开始累计到当前时刻用户态的CPU时间单位jiffies 不包含 nice值为负进程。 nice (13295) 从系统启动开始累计到当前时刻nice值为负的进程所占用的CPU时间单位jiffies system (86656) 从系统启动开始累计到当前时刻核心时间单位jiffies idle (422145968) 从系统启动开始累计到当前时刻除硬盘IO等待时间以外其它等待时间单位jiffies iowait (171474) 从系统启动开始累计到当前时刻硬盘IO等待时间单位jiffies irq (233) 从系统启动开始累计到当前时刻硬中断时间单位jiffies softirq (5346) 从系统启动开始累计到当前时刻软中断时间单位jiffies cpu使用率 已使用2-已使用1/系统当前2-系统当前1*100% 内存限制 Docker 提供的内存限制功能有以下几点 容器能使用的内存和交换分区大小。容器的核心内存大小。容器虚拟内存的交换行为。容器内存的软性限制。是否杀死占用过多内存的容器。容器被杀死的优先级一般情况下达到内存限制的容器过段时间后就会被系统杀死。 内存限制相关的参数 执行docker run命令时能使用的和内存限制相关的所有选项如下。 选项描述-m,--memory内存限制格式是数字加单位单位可以为 b,k,m,g。最小为 4M--memory-swap内存交换分区大小总限制。格式同上。必须必-m设置的大--memory-reservation内存的软性限制。格式同上--oom-kill-disable是否阻止 OOM killer 杀死容器默认没设置--oom-score-adj容器被 OOM killer 杀死的优先级范围是[-1000, 1000]默认为 0--memory-swappiness用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数--kernel-memory核心内存限制。格式同上最小为 4M用户内存限制 用户内存限制就是对容器能使用的内存和交换分区的大小作出限制。使用时要遵循两条直观的规则-m--memory选项的参数最小为 4 M。--memory-swap不是交换分区而是内存加交换分区的总大小所以--memory-swap必须比-m,--memory大。在这两条规则下一般有四种设置方式。 你可能在进行内存限制的实验时发现docker run命令报错WARNING: Your kernel does not support swap limit capabilities, memory limited without swap. 这是因为宿主机内核的相关功能没有打开。按照下面的设置就行。 step 1编辑/etc/default/grub文件将GRUB_CMDLINE_LINUX一行改为GRUB_CMDLINE_LINUXcgroup_enablememory swapaccount1 step 2更新 GRUB即执行$ sudo update-grub step 3: 重启系统。 1. 不设置 如果不设置-m,--memory和--memory-swap容器默认可以用完宿舍机的所有内存和 swap 分区。不过注意如果容器占用宿主机的所有内存和 swap 分区超过一段时间后会被宿主机系统杀死如果没有设置--00m-kill-disabletrue的话。 2. 设置-m,--memory不设置--memory-swap 给-m或--memory设置一个不小于 4M 的值假设为 a不设置--memory-swap或将--memory-swap设置为 0。这种情况下容器能使用的内存大小为 a能使用的交换分区大小也为 a。因为 Docker 默认容器交换分区的大小和内存相同。 如果在容器中运行一个一直不停申请内存的程序你会观察到该程序最终能占用的内存大小为 2a。 比如$ docker run -m 1G ubuntu:16.04该容器能使用的内存大小为 1G能使用的 swap 分区大小也为 1G。容器内的进程能申请到的总内存大小为 2G。 3. 设置-m,--memorya--memory-swapb且b a 给-m设置一个参数 a给--memory-swap设置一个参数 b。a 时容器能使用的内存大小b是容器能使用的 内存大小 swap 分区大小。所以 b 必须大于 a。b -a 即为容器能使用的 swap 分区大小。 比如$ docker run -m 1G --memory-swap 3G ubuntu:16.04该容器能使用的内存大小为 1G能使用的 swap 分区大小为 2G。容器内的进程能申请到的总内存大小为 3G。 4. 设置-m,--memorya--memory-swap-1 给-m参数设置一个正常值而给--memory-swap设置成 -1。这种情况表示限制容器能使用的内存大小为 a而不限制容器能使用的 swap 分区大小。 这时候容器内进程能申请到的内存大小为 a 宿主机的 swap 大小。 Memory reservation 这种 memory reservation 机制不知道怎么翻译比较形象。Memory reservation 是一种软性限制用于节制容器内存使用。给--memory-reservation设置一个比-m小的值后虽然容器最多可以使用-m使用的内存大小但在宿主机内存资源紧张时在系统的下次内存回收时系统会回收容器的部分内存页强迫容器的内存占用回到--memory-reservation设置的值大小。 没有设置时默认情况下--memory-reservation的值和-m的限定的值相同。将它设置为 0 会设置的比-m的参数大 等同于没有设置。 Memory reservation 是一种软性机制它不保证任何时刻容器使用的内存不会超过--memory-reservation限定的值它只是确保容器不会长时间占用超过--memory-reservation限制的内存大小。 例如 $ docker run -it -m 500M --memory-reservation 200M ubuntu:16.04 /bin/bash 如果容器使用了大于 200M 但小于 500M 内存时下次系统的内存回收会尝试将容器的内存锁紧到 200M 以下。 例如 $ docker run -it --memory-reservation 1G ubuntu:16.04 /bin/bash 容器可以使用尽可能多的内存。--memory-reservation确保容器不会长时间占用太多内存。 OOM killer 默认情况下在出现 out-of-memory(OOM) 错误时系统会杀死容器内的进程来获取更多空闲内存。这个杀死进程来节省内存的进程我们姑且叫它 OOM killer。我们可以通过设置--oom-kill-disable选项来禁止 OOM killer 杀死容器内进程。但请确保只有在使用了-m/--memory选项时才使用--oom-kill-disable禁用 OOM killer。如果没有设置-m选项却禁用了 OOM-killer可能会造成出现 out-of-memory 错误时系统通过杀死宿主机进程或获取更改内存。 下面的例子限制了容器的内存为 100M 并禁止了 OOM killer $ docker run -it -m 100M --oom-kill-disable ubuntu:16.04 /bin/bash 是正确的使用方法。 而下面这个容器没设置内存限制却禁用了 OOM killer 是非常危险的 $ docker run -it --oom-kill-disable ubuntu:16.04 /bin/bash 容器没用内存限制可能或导致系统无内存可用并尝试时杀死系统进程来获取更多可用内存。 一般一个容器只有一个进程这个唯一进程被杀死容器也就被杀死了。我们可以通过--oom-score-adj选项来设置在系统内存不够时容器被杀死的优先级。负值更教不可能被杀死而正值更有可能被杀死。 核心内存 核心内存和用户内存不同的地方在于核心内存不能被交换出。不能交换出去的特性使得容器可以通过消耗太多内存来堵塞一些系统服务。核心内存包括 stack pages栈页面slab pagessocket memory pressuretcp memory pressure可以通过设置核心内存限制来约束这些内存。例如每个进程都要消耗一些栈页面通过限制核心内存可以在核心内存使用过多时阻止新进程被创建。 核心内存和用户内存并不是独立的必须在用户内存限制的上下文中限制核心内存。 假设用户内存的限制值为 U核心内存的限制值为 K。有三种可能地限制核心内存的方式 U ! 0不限制核心内存。这是默认的标准设置方式K U核心内存时用户内存的子集。这种设置在部署时每个 cgroup 的内存总量被过度使用。过度使用核心内存限制是绝不推荐的因为系统还是会用完不能回收的内存。在这种情况下你可以设置 K这样 groups 的总数就不会超过总内存了。然后根据系统服务的质量自有地设置 U。K U因为核心内存的变化也会导致用户计数器的变化容器核心内存和用户内存都会触发回收行为。这种配置可以让管理员以一种统一的视图看待内存。对想跟踪核心内存使用情况的用户也是有用的。例如 $ docker run -it -m 500M --kernel-memory 50M ubuntu:16.04 /bin/bash 容器中的进程最多能使用 500M 内存在这 500M 中最多只有 50M 核心内存。 $ docker run -it --kernel-memory 50M ubuntu:16.04 /bin/bash 没用设置用户内存限制所以容器中的进程可以使用尽可能多的内存但是最多能使用 50M 核心内存。 Swappiness 默认情况下容器的内核可以交换出一定比例的匿名页。--memory-swappiness就是用来设置这个比例的。--memory-swappiness可以设置为从 0 到 100。0 表示关闭匿名页面交换。100 表示所有的匿名页都可以交换。默认情况下如果不适用--memory-swappiness则该值从父进程继承而来。 例如 $ docker run -it --memory-swappiness0 ubuntu:16.04 /bin/bash 将--memory-swappiness设置为 0 可以保持容器的工作集避免交换代理的性能损失。 $ docker run -tid —name mem1 —memory 128m ubuntu:16.04 /bin/bash$ cat /sys/fs/cgroup/memory/docker/容器的完整ID/memory.limit_in_bytes$ cat /sys/fs/cgroup/memory/docker/容器的完整ID/memory.memsw.limit_in_bytes CPU 限制 概述 Docker 的资源限制和隔离完全基于 Linux cgroups。对 CPU 资源的限制方式也和 cgroups 相同。Docker 提供的 CPU 资源限制选项可以在多核系统上限制容器能利用哪些 vCPU。而对容器最多能使用的 CPU 时间有两种限制方式一是有多个 CPU 密集型的容器竞争 CPU 时设置各个容器能使用的 CPU 时间相对比例。二是以绝对的方式设置容器在每个调度周期内最多能使用的 CPU 时间。 CPU 限制相关参数 docker run命令和 CPU 限制相关的所有选项如下 选项描述--cpuset-cpus允许使用的 CPU 集值可以为 0-3,0,1-c,--cpu-shares0CPU 共享权值相对权重cpu-period0限制 CPU CFS 的周期范围从 100ms~1s即[1000, 1000000]--cpu-quota0限制 CPU CFS 配额必须不小于1ms即 1000--cpuset-mems允许在上执行的内存节点MEMs只对 NUMA 系统有效其中--cpuset-cpus用于设置容器可以使用的 vCPU 核。-c,--cpu-shares用于设置多个容器竞争 CPU 时各个容器相对能分配到的 CPU 时间比例。--cpu-period和--cpu-quata用于绝对设置容器能使用 CPU 时间。 --cpuset-mems暂用不上这里不谈。 CPU 集 我们可以设置容器可以在哪些 CPU 核上运行。 例如 $ docker run -it --cpuset-cpus1,3 ubuntu:14.04 /bin/bash 表示容器中的进程可以在 cpu 1 和 cpu 3 上执行。 $ docker run -it --cpuset-cpus0-2 ubuntu:14.04 /bin/bash$ cat /sys/fs/cgroup/cpuset/docker/容器的完整长ID/cpuset.cpus 表示容器中的进程可以在 cpu 0、cpu 1 及 cpu 3 上执行。 在 NUMA 系统上我们可以设置容器可以使用的内存节点。 例如 $ docker run -it --cpuset-mems1,3 ubuntu:14.04 /bin/bash 表示容器中的进程只能使用内存节点 1 和 3 上的内存。 $ docker run -it --cpuset-mems0-2 ubuntu:14.04 /bin/bash 表示容器中的进程只能使用内存节点 0、1、2 上的内存。 CPU 资源的相对限制 默认情况下所有的容器得到同等比例的 CPU 周期。在有多个容器竞争 CPU 时我们可以设置每个容器能使用的 CPU 时间比例。这个比例叫作共享权值通过-c或--cpu-shares设置。Docker 默认每个容器的权值为 1024。不设置或将其设置为 0都将使用这个默认值。系统会根据每个容器的共享权值和所有容器共享权值和比例来给容器分配 CPU 时间。 假设有三个正在运行的容器这三个容器中的任务都是 CPU 密集型的。第一个容器的 cpu 共享权值是 1024其它两个容器的 cpu 共享权值是 512。第一个容器将得到 50% 的 CPU 时间而其它两个容器就只能各得到 25% 的 CPU 时间了。如果再添加第四个 cpu 共享值为 1024 的容器每个容器得到的 CPU 时间将重新计算。第一个容器的CPU 时间变为 33%其它容器分得的 CPU 时间分别为 16.5%、16.5%、33%。 必须注意的是这个比例只有在 CPU 密集型的任务执行时才有用。在四核的系统上假设有四个单进程的容器它们都能各自使用一个核的 100% CPU 时间不管它们的 cpu 共享权值是多少。 在多核系统上CPU 时间权值是在所有 CPU 核上计算的。即使某个容器的 CPU 时间限制少于 100%它也能使用各个 CPU 核的 100% 时间。 例如假设有一个不止三核的系统。用-c512的选项启动容器{C0}并且该容器只有一个进程用-c1024的启动选项为启动容器C2并且该容器有两个进程。CPU 权值的分布可能是这样的 PID container CPU CPU share
100 {C0} 0 100% of CPU0 101 {C1} 1 100% of CPU1 102 {C1} 2 100% of CPU2$ docker run -it --cpu-shares100 ubuntu:14.04 /bin/bash$ cat /sys/fs/cgroup/cpu/docker/容器的完整长ID/cpu.shares 表示容器中的进程CPU份额值为100。 CPU 资源的绝对限制 Linux 通过 CFSCompletely Fair Scheduler完全公平调度器来调度各个进程对 CPU 的使用。CFS 默认的调度周期是 100ms。 关于 CFS 的更多信息参考CFS documentation on bandwidth limiting。 我们可以设置每个容器进程的调度周期以及在这个周期内各个容器最多能使用多少 CPU 时间。使用--cpu-period即可设置调度周期使用--cpu-quota即可设置在每个周期内容器能使用的 CPU 时间。两者一般配合使用。 例如 $ docker run -it --cpu-period50000 --cpu-quota25000 ubuntu:16.04 /bin/bash 将 CFS 调度的周期设为 50000将容器在每个周期内的 CPU 配额设置为 25000表示该容器每 50ms 可以得到 50% 的 CPU 运行时间。 $ docker run -it --cpu-period10000 --cpu-quota20000 ubuntu:16.04 /bin/bash$ cat /sys/fs/cgroup/cpu/docker/容器的完整长ID/cpu.cfs_period_us$ cat /sys/fs/cgroup/cpu/docker/容器的完整长ID/cpu.cfs_quota_us 将容器的 CPU 配额设置为 CFS 周期的两倍CPU 使用时间怎么会比周期大呢其实很好解释给容器分配两个 vCPU 就可以了。该配置表示容器可以在每个周期内使用两个 vCPU 的 100% 时间。 CFS 周期的有效范围是 1ms~1s对应的--cpu-period的数值范围是 1000~1000000。而容器的 CPU 配额必须不小于 1ms即--cpu-quota的值必须 1000。可以看出这两个选项的单位都是 us。 正确的理解“绝对” 注意前面我们用--cpu-quota设置容器在一个调度周期内能使用的 CPU 时间时实际上设置的是一个上限。并不是说容器一定会使用这么长的 CPU 时间。比如我们先启动一个容器将其绑定到 cpu 1 上执行。给其--cpu-quota和--cpu-period都设置为 50000。 $ docker run --rm --name test01 --cpu-cpus 1 --cpu-quota50000 --cpu-period50000 deadloop:busybox-1.25.1-glibc 调度周期为 50000容器在每个周期内最多能使用 50000 cpu 时间。 再用docker stats test01可以观察到该容器对 CPU 的使用率在100%左右。然后我们再以同样的参数启动另一个容器。 $ docker run --rm --name test02 --cpu-cpus 1 --cpu-quota50000 --cpu-period50000 deadloop:busybox-1.25.1-glibc 再用docker stats test01 test02可以观察到这两个容器每个容器对 cpu 的使用率在 50% 左右。说明容器并没有在每个周期内使用 50000 的 cpu 时间。 使用docker stop test02命令结束第二个容器再加一个参数-c 2048启动它 $ docker run --rm --name test02 --cpu-cpus 1 --cpu-quota50000 --cpu-period50000 -c 2048 deadloop:busybox-1.25.1-glibc 再用docker stats test01命令可以观察到第一个容器的 CPU 使用率在 33% 左右第二个容器的 CPU 使用率在 66% 左右。因为第二个容器的共享值是 2048第一个容器的默认共享值是 1024所以第二个容器在每个周期内能使用的 CPU 时间是第一个容器的两倍。 磁盘IO配额控制 相对于CPU和内存的配额控制docker对磁盘IO的控制相对不成熟大多数都必须在有宿主机设备的情况下使用。主要包括以下参数 –device-read-bps限制此设备上的读速度bytes per second单位可以是kb、mb或者gb。–device-read-iops通过每秒读IO次数来限制指定设备的读速度。–device-write-bps 限制此设备上的写速度bytes per second单位可以是kb、mb或者gb。–device-write-iops通过每秒写IO次数来限制指定设备的写速度。–blkio-weight容器默认磁盘IO的加权值有效值范围为10-100。–blkio-weight-device 针对特定设备的IO加权控制。其格式为DEVICE_NAME:WEIGHT存储配额控制的相关参数可以参考Red Hat文档中blkio这一章了解它们的详细作用。 磁盘IO配额控制示例 blkio-weight 要使–blkio-weight生效需要保证IO的调度算法为CFQ。可以使用下面的方式查看 rootubuntu:~# cat /sys/block/sda/queue/schedulernoop [deadline] cfq 使用下面的命令创建两个–blkio-weight值不同的容器 docker run -ti –rm –blkio-weight 100 ubuntu:stressdocker run -ti –rm –blkio-weight 1000 ubuntu:stress 在容器中同时执行下面的dd命令进行测试 time dd if/dev/zero oftest.out bs1M count1024 oflagdirect 最终输出如下图所示 在我的测试环境上没有达到理想的测试效果通过docker官方的blkio-weight doesn’t take effect in docker Docker version 1.8.1 #16173可以发现这个问题在一些环境上存在但docker官方也没有给出解决办法。 device-write-bps 使用下面的命令创建容器并执行命令验证写速度的限制。 docker run -tid –name disk1 –device-write-bps /dev/sda:1mb ubuntu:stress 通过dd来验证写速度输出如下图示 可以看到容器的写磁盘速度被成功地限制到了1MB/s。device-read-bps等其他磁盘IO限制参数可以使用类似的方式进行验证。 容器空间大小限制 在docker使用devicemapper作为存储驱动时默认每个容器和镜像的最大大小为10G。如果需要调整可以在daemon启动参数中使用dm.basesize来指定但需要注意的是修改这个值不仅仅需要重启docker daemon服务还会导致宿主机上的所有本地镜像和容器都被清理掉。 使用aufs或者overlay等其他存储驱动时没有这个限制。转载于:https://www.cnblogs.com/Zfc-Cjk/p/10851837.html