docker资源限制和应用总结

Docker(linux container)所依赖的底层技术php

1 Namespacenode

用来作容器的隔离,有了namespace,在docker container里头看来,就是一个完整的linux的世界。在host看来,container里的进程,就是一个普通的host进程namespace提供这种pid的映射和隔离效果,host承载着container,就比如一个世外桃源。linux

namespace包括:pid namespacenet namespaceipc namespacemnt namespaceuts 程序员

2 Cgroupsdocker

在前面了解了Docker背后使用的资源隔离技术namespace,经过系统调用构建一个相对隔离的shell环境,也能够称之为一个简单的容器下面咱们则要开始讲解另外一个强大的内核工具——cgroups他不只能够限制被namespace隔离起来的资源,还能够为资源设置权重、计算使用量、操控进程启停等等。因此cgroupsControl groups实现了对资源的配额和度量shell

cgroups是什么centos

cgroupsControl Groups)最初叫Process Container,由Google工程师(Paul MenageRohit Seth)于2006年提出,后来由于Container有多重含义容易引发误解,就在2007年改名为Control Groups,并被整合进Linux内核。顾名思义就是把进程放到一个组里面统一加以控制缓存

 

groups的做用服务器

通俗的来讲,cgroups能够限制、记录、隔离进程组所使用的物理资源(包括:CPUmemoryIO等),为容器实现虚拟化提供了基本保证,是构建Docker等一系列虚拟化管理工具的基石Cgroups提供了如下四大功能。网络

1资源限制(Resource Limitationcgroups能够对进程组使用的资源总额进行限制。如设定应用运行时使用内存的上限,一旦超过这个配额就发出OOMOut of Memory)。

2优先级分配(Prioritization:经过分配的CPU时间片数量及硬盘IO带宽大小,实际上就至关于控制了进程运行的优先级。

3资源统计(Accounting cgroups能够统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能很是适用于计费。

4进程控制(Controlcgroups能够对进程组执行挂起、恢复等操做。

 

下面就介绍cgroup如何作到内存,cpuio速率的隔离

本文用脚本运行示例进程,来验证Cgroups关于cpu、内存、io这三部分的隔离效果。

1测试机器环境

spacer.gif

2)执行mount命令查看cgroup的挂载点

 

wKiom1kvbYXzet6eAAEtu7G4DxI510.png 

 

从上图能够看到cgroup挂载在/sys/fs/cgroup目录

groups能够限制blkiocpucpuacctcpusetdevicesfreezermemorynet_clsns等系统的资源,如下是主要子系统的说明:

blkio 这个子系统设置限制每一个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。

cpu 这个子系统使用调度程序为cgroup任务提供cpu的访问。

cpuacct 产生cgroup任务的cpu资源报告。

cpuset 若是是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。

devices 容许或拒绝cgroup任务对设备的访问。

freezer 暂停和恢复cgroup任务。

memory 设置每一个cgroup的内存限制以及产生内存资源报告。

net_cls 标记每一个网络包以供cgroup方便使用,它经过使用等级识别符(classid)标记网络数据包,从而容许 Linux 流量控制程序(TCTraffic Controller)识别从具体cgroup中生成的数据包。

ns:命名空间子系统

 

3cgroups管理进程cpu资源

咱们先看一个限制cpu资源的例子:

跑一个耗cpu的脚本

wKioL1kvbYXSxl-aAABxIaCUkE4916.png 


wKioL1kvbfnyh-1JAADKTzRrMDE614.png

wKiom1kvbfrgNUegAAELpFk1Wuw420.png


wKioL1kvbfug47hdAAC-jqZlJ3o751.png



4将容器切换到后台运行或从新打开一个终端

宿主机上top能够看到这个脚本基本占了90%cpu资源

wKiom1kvbYbQ35z9AACVw7QnJWU212.png 

 

5下面用cgroups控制这个进程的cpu资源

对于centos7来讲,经过systemd-cgls来查看系统cgroups tree

#systemd-cgls

 

wKiom1kvbfiyKsEzAABqYlTMgmo228.png 

wKioL1kvbkrBSrxuAAA5p_fFzpM936.png 

 

注:41738就是咱们所运行的容器pid

wKioL1kvbfnyh-1JAADKTzRrMDE614.png 

cpu.cfs_quota_us设为50000,相对于cpu.cfs_period_us的100000是50%

 

进入容器,再次执行脚本,打开宿主机的另外一个终端执行top命令

而后top的实时统计数据以下,cpu占用率将近50%,看来cgroups关于cpu的控制起了效果

wKioL1kvbfqBS7rLAAELpFk1Wuw669.png 

 

CPU资源控制

CPU资源的控制也有两种策略,

一种是彻底公平调度(CFSCompletely Fair Scheduler策略,提供了限额和按比例分配两种方式进行资源控制;

另外一种是实时调度(Real-Time Scheduler)策略,针对实时进程按周期分配固定的运行时间。配置时间都以微秒(s)为单位,文件名中用us表示。

CFS调度策略下的配置

按权重比例设定CPU的分配

docker提供了–cpu-shares参数,在建立容器时指定容器所使用的CPU份额值例如

使用命令docker run -tid –-cpu-shares 100 镜像,建立容器,则最终生成的cgroupcpu份额配置能够下面的文件中找到:

# cat /sys/fs/cgroup/cpu/system.slice/docker-<容器的完整长

ID>/cpu.shares

wKioL1kvbfug47hdAAC-jqZlJ3o751.png

cpu-shares的值不能保证能够得到1vcpu或者多少GHzCPU资源,仅仅只是一个加权值。

该加权值是一个整数(必须大于等于2)表示相对权重,最后除以权重总和算出相对比例,按比例分配CPU时间。

默认状况下,每一个docker容器的cpu份额都是1024单独一个容器的份额是没有意义的,只有在同时运行多个容器时,容器的cpu加权的效果才能体现出来。例如,两个容器ABcpu份额分别为1000500,在cpu进行时间片分配的时候,容器A比容器B多一倍的机会得到CPU的时间片容器A的进程一直是空闲的,那么容器B是能够获取比容器A更多的CPU时间片的。极端状况下,好比说主机上只运行了一个容器,即便它的cpu份额只有50,它也能够独占整个主机的cpu资源。

cgroups只在容器分配的资源紧缺时,也就是说在须要对容器使用的资源进行限制时,才会生效。所以,没法单纯根据某个容器的cpu份额来肯定有多少cpu资源分配给它,资源分配结果取决于同时运行的其余容器的cpu分配和容器中进程运行状况。

cpu-shares演示案例:

先删除docker主机上运行的容器

wKiom1kvbfuTS8etAAAwqVH157k851.png 

 

Docker经过--cpu-shares 指定CPU份额

运行一个容器指定cpu份额为1024

先将镜像导入到本地

wKioL1kvb-KiDWC1AACA371w1-A690.png


wKioL1kvcHjAjYywAAAsZISo1NU328.png注:

--cpu-shares 指定CPU份额,默认就是1024

--cpuset-cpus能够绑定CPU。例如,指定容器在--cpuset-cpus 0,1 或--cpuset-cpus  0-3

--cpu是stress命令的选项表示产生n个进程每一个进程都反复不停的计算随机数的平方根

stress命令是linux下的一个压力测试工具。

docker宿主机上打开一个terminal执行top

wKiom1kvb-OSu6CMAAB5TkftNfU470.png 

 

而后再启动一个容器,--cpu-shares512

wKioL1kvb-SiCdd2AAAp_VZz3xA433.png 

 

查看top的现实结果

wKiom1kvb-ThgyzaAADDPHdt92I949.png 

 

能够看到container1的CPU占比为1024/(1024+512)=2/3,container2的CPU占比为512/(1024+512)=1/3

container1cpu.shares改成512

#echo “512” >/sys/fs/cgroup/cpu/system.slice/docker-<容器的完整长ID>/cpu.shares

wKioL1kvcNGQvsnsAACdKJMNW0U617.png


能够看到两个容器的CPU占比趋于平均

 

设定CPU使用周期使用时间上限

cgroups 里,能够用 cpu.cfs_period_us cpu.cfs_quota_us 来限制该组中的全部进程在单位时间里可使用的 cpu 时间。cpu.cfs_period_us 就是时间周期,默认为 100000,即百毫秒。cpu.cfs_quota_us 就是在这期间内可以使用的 cpu 时间,默认 -1,即无限制。

 

cpu.cfs_period_us:设定时间周期单位为微秒(μs,必须与cfs_quota_us配合使用。

cpu.cfs_quota_us :设定周期内最多可以使用的时间单位为微秒(μs。这里的配置指task对单个cpu的使用上限。

  1=1000毫秒

  1毫秒=1000微妙

举个例子,若是容器进程须要每1秒使用单个CPU0.2秒时间,能够将cpu-period设置为1000000(即1秒),cpu-quota设置为2000000.2秒)。

固然,在多核状况下,cfs_quota_uscfs_period_us的两倍,就表示在两个核上彻底使用CPU例如若是容许容器进程须要彻底占用两个CPU,则能够将cpu-period设置为100000(即0.1秒),cpu-quota设置为2000000.2秒)。

使用示例:

使用命令docker run建立容器

wKiom1kvcNKzvrUCAAAbzgOzbZo534.png 

在宿主机上执行top

wKiom1kvcNLTO7htAABrFrjuDQ0368.png 

从上图能够看到基本占了100%cpu资源

则最终生成的cgroupcpu周期配置能够下面的目录中找到:

/sys/fs/cgroup/cpu/system.slice/docker-<容器的完整长ID>/

wKiom1kvc×××p5_9AABEXOCA_5Q835.png 

修改容器的cpu.cfs_period_us cpu.cfs_quota_us

wKiom1kvcNPjaDHQAABEqe9-fFg975.png 

执行top查看cpu资源

wKioL1kvcbjTXYxEAABnnfw2vT4627.png

从上图能够看到基本占了50%cpu资源

RT调度策略下的配置 实时调度策略与公平调度策略中的按周期分配时间的方法相似,也是在周期内分配一个固定的运行时间。

cpu.rt_period_us :设定周期时间。

cpu.rt_runtime_us:设定周期中的运行时间

wKiom1kvcbnTzQwJAABE_t8z5EQ598.png 

 

cpuset - CPU绑定

对多核CPU的服务器,docker还能够控制容器运行限定使用哪些cpu内核和内存节点,即便–cpuset-cpus–cpuset-mems参数。对具备NUMA拓扑(具备多CPU、多内存节点)的服务器尤为有用,能够对须要高性能

计算的容器进行性能最优的配置。若是服务器只有一个内存节点,则–cpuset-mems的配置基本上不会有明显效果

注:

如今的机器上都是有多个CPU和多个内存块的。之前咱们都是将内存块当作是一大块内存,全部CPU到这个共享内存的访问消息是同样的。可是随着处理器的增长,共享内存可能会致使内存访问冲突愈来愈厉害,且若是内存访问达到瓶颈的时候,性能就不能随之增长。NUMANon-Uniform Memory Access)就是这样的环境下引入的一个模型。好比一台机器是有2个处理器,有4个内存块。咱们将1个处理器和两个内存块合起来,称为一个NUMA node,这样这个机器就会有两个NUMA node。在物理分布上,NUMA node的处理器和内存块的物理距离更小,所以访问也更快。好比这台机器会分左右两个处理器(cpu1, cpu2),在每一个处理器两边放两个内存块(memory1.1, memory1.2, memory2.1,memory2.2),这样NUMA node1cpu1访问memory1.1memory1.2就比访问memory2.1memory2.2更快。因此使用NUMA的模式若是能尽可能保证本node内的CPU只访问本node内的内存块,那这样的效率就是最高的。

 

使用示例:

wKioL1kvcbmgH43kAABYdhfjKu4487.png 

表示建立的容器只能用012这三个内核。最终生成的cgroupcpu内核配置以下:

wKiom1kvcbmzSZkKAAAk_-y3rp4346.png 

cpuset.cpus:在这个文件中填写cgroup可以使用的CPU编号,如0-2,16表明 012164CPU

cpuset.mems:与CPU相似,表示cgroup可以使用的memory node,格式同上

经过docker exec <容器ID> taskset -c -p 1(容器内部第一个进程编号通常为1),能够看到容器中进程与CPU内核的绑定关系,能够认为达到了绑定CPU内核的目的。

总结:

CPU配额控制参数的混合使用

当上面这些参数中时,cpu-shares控制只发生在容器竞争同一个内核的时间片时,若是经过cpuset-cpus指定容器A使用内核0,容器B只是用内核1,在主机上只有这两个容器使用对应内核的状况,它们各自占用所有的内核资源,cpu-shares没有明显效果。

cpu-periodcpu-quota这两个参数通常联合使用,在单核状况或者经过cpuset-cpus强制容器使用一个cpu内核的状况下,即便cpu-quota超过cpu-period,也不会使容器使用更多的CPU资源。

cpuset-cpuscpuset-mems只在多核、多内存节点上的服务器上有效,而且必须与实际的物理配置匹配,不然也没法达到资源控制的目的。

在系统具备多个CPU内核的状况下,须要经过cpuset-cpus为容器CPU内核才能比较方便地进行测试。

 

内存配额控制

CPU控制同样,docker也提供了若干参数来控制容器的内存使用配额,能够控制容器的swap大小、可用内存大小等各类内存方面的控制。主要有如下参数:

Docker提供参数-m, --memory=""限制容器的内存使用量果不设置-m,则默认容器内存是不设限的,容器可使用主机上的全部空闲内存

内存配额控制使用示例

设置容器的内存上限,参考命令以下所示

#docker  run  -dit  --memory128m  镜像

默认状况下,除了–memory指定的内存大小之外,docker还为容器分配了一样大小的swap分区,也就是说,上面的命令建立出的容器实际上最多可使用256MB内存,而不是128MB内存。若是须要自定义swap分区大小,则能够经过联合使用–memory–swap参数来实现控制

wKiom1kvcbqTVXq3AABAG0N-d68763.png 

能够发现,使用256MB进行压力测试时,因为超过了内存上限(128MB内存+128MB swap),进程被OOM(out of memory)杀死

使用250MB进行压力测试时,进程能够正常运行

wKioL1kvckjwnIk0AABe_Qxsuok303.png


经过docker stats能够查看到容器的内存已经满负载了。

#docker  stats  test2

wKiom1kvckjgmiveAAAlE8TCdjU016.png 

 

 

对上面的命令建立的容器,能够查看到在cgroups的配置文件中,查看到容器的内存大小为128MB (128×1024×1024=134217728B),内存和swap加起来大小为256MB (256×1024×1024=268435456B)

#cat /sys/fs/cgroup/memory/system.slice/docker-<容器的完整ID>/memory.limit_in_bytes
134217728

#cat /sys/fs/cgroup/memory/system.slice/docker-<容器的完整ID>/memory.memsw.limit_in_bytes
268435456

 

wKioL1kvckrw5NEGAACxMSOb_n4245.png 

 

 

磁盘IO配额控制

主要包括如下参数:

--device-read-bps:限制此设备上的读速度(bytes per second),单位能够是kbmb或者gb--device-read-iops:经过每秒读IO次数来限制指定设备的读速度。

--device-write-bps :限制此设备上的写速度(bytes per second),单位能够是kbmb或者gb

--device-write-iops:经过每秒写IO次数来限制指定设备的写速度。

--blkio-weight:容器默认磁盘IO的加权值,有效值范围为10-1000

--blkio-weight-device:针对特定设备的IO加权控制。其格式为DEVICE_NAME:WEIGHT

 

磁盘IO配额控制示例

blkio-weight

使用下面的命令建立两个–blkio-weight值不一样的容器:

在容器中同时执行下面的dd命令,进行测试

wKiom1kvckuA4kyxAABVp7fLPqY764.png 

wKioL1kvckzSW0XKAABXYb3JBdc828.png 

注:oflag=direct规避掉文件系统的cache,把写请求直接封装成io指令发到硬盘而按正常规律,数据先写入缓存,在由缓存封装给硬盘

 

3 Chroot

如何在container里头,看到的文件系统,就是一个完整的linux系统,有/etc/lib 等,经过chroot实现

 

4 Veth

container里,执行ifconfig能够看到eth0的网卡,如何通讯呢?实际上是在host上虚拟了一张网卡出来(veth73f7),跟container里的网卡作了桥接,全部从container出来的流量都要过host的虚拟网卡,进container的流量也是如此。

 

5 Union FS

对于这种叠加的文件系统,有一个很好的实现是AUFS,这个能够作到以文件为粒度的copy-on-write,为海量的container的瞬间启动。

 

6 Iptables, netfilter

主要用来作ip数据包的过滤,好比能够作container之间没法通讯,container能够没法访问host的网络,可是能够经过host的网卡访问外网等这样的网络策略

 

 

2、学习Docker也有一段时间了,了解了Docker的基本实现原理,也知道了Docker的使用方法,这里对Docker的一些典型应用场景作一个总结

 

1配置简化
  这是Docker的主要使用场景。将应用的全部配置工做写入Dockerfile中,建立好镜像,之后就能够无限次使用这个镜像进行应用部署了。这大大简化了应用的部署,不须要为每次部署都进行繁琐的配置工做,实现了一次打包,屡次部署。这大大加快了应用的开发效率,使得程序员能够快速搭建起开发测试环境,不用关注繁琐的配置工做,而是将全部精力都尽量用到开发工做中去。

 

2代码流水线管理
  代码从开发环境到测试环境再到生产环境,须要通过不少次中间环节,Docker给应用提供了一个从开发到上线均一致的环境,开发测试人员均只需关注应用的代码,使得代码的流水线变得很是简单,这样应用才能持续集成和发布。

 

3快速部署

 

在虚拟机以前,引入新的硬件资源须要消耗几天的时间。Docker的虚拟化技术将这个时间降到了几分钟,Docker只是建立一个容器进程而无需启动操做系统,这个过程只须要秒级的时间。

 

4应用隔离
  资源隔离对于提供共享hosting服务的公司是个强需求。若是使用VM,虽然隔离性很是完全,但部署密度相对较低,会形成成本增长。

Docker容器充分利用linux内核的namespace提供资源隔离功能。结合cgroups,能够方便的设置每一个容器的资源配额。既能知足资源隔离的需求,又能方便的为不一样级别的用户设置不一样级别的配额限制。

 

5服务器资源整合
  正如经过VM来整合多个应用,Docker隔离应用的能力使得Docker一样能够整合服务器资源。因为没有额外的操做系统的内存占用,以及能在多个实例之间共享没有使用的内存,Docker能够比VM提供更好的服务器整合解决方案。

一般数据中心的资源利用率只有30%,经过使用Docker并进行有效的资源分配能够提升资源的利用率。

 

6多版本混合部署
  随着产品的不断更新换代,一台服务器上部署多个应用或者同一个应用的多个版本在企业内部很是常见。但一台服务器上部署同一个软件的多个版本,文件路径、端口等资源每每会发生冲突,形成多个版本没法共存的问题。

若是用docker,这个问题将很是简单。因为每一个容器都有本身独立的文件系统,因此根本不存在文件路径冲突的问题; 对于端口冲突问题,只须要在启动容器时指定不一样的端口映射便可解决问题。

 

7版本升级回滚
  一次升级,每每不只仅是应用软件自己的升级,经过还会包含依赖项的升级。但新旧软件的依赖项极可能是不一样的,甚至是有冲突的,因此在传统的环境下作回滚通常比较困难。

若是使用docker,咱们只须要每次应用软件升级时制做一个新的docker镜像,升级时先停掉旧的容器,而后把新的容器启动。须要回滚时,把新的容器停掉,旧的启动便可完成回滚,整个过程各在秒级完成,很是方便。

 

8内部开发环境
  在容器技术出现以前,公司每每是经过为每一个开发人员提供一台或者多台虚拟机来充当开发测试环境。开发测试环境通常负载较低,大量的系统资源都被浪费在虚拟机自己的进程上了。

Docker容器没有任何CPU和内存上的额外开销,很适合用来提供公司内部的开发测试环境。并且因为Docker镜像能够很方便的在公司内部共享,这对开发环境的规范性也有极大的帮助。

 

9PaaS
  使用Docker搭建大规模集群,提供PaaS。这一应用是最有前景的一个了,目前已有不少创业公司在使用DockerPaaS了,例如云雀云平台。用户只需提交代码,全部运维工做均由服务公司来作。并且对用户来讲,整个应用部署上线是一键式的,很是方便。

 

10云桌面
  在每个容器内部运行一个图形化桌面,用户经过RDP或者VNC协议链接到容器。该方案所提供的虚拟桌面相比于传统的基于硬件虚拟化的桌面方案更轻量级,运行速率大大提高。不过该方案仍处于实验阶段,不知是否

相关文章
相关标签/搜索