docker(六)--docker系统资源限制

 

 默认情况下容器是没有资源限制的,所以它可以几乎消耗完docker主机上所分配的所有资源
 docker提供了限制一个容器可使用的内存、cpu、block io的方法。
 当一个容器内的进程消耗完它的内存后,可能会因为OOM被kill掉,而CPU是可压缩性资源,kernel可以压缩它不受影响

内存OOME

linux主机上kernel探测到主机内存不足使用,就会发出一个异常,并且开始杀死一些进程一旦发生OOME,任何进程都有可能被杀死,包括docker daemon在内,为此,Docker特地的调整了docker daemon的OOM优先级,以免它被杀掉,但容器的优先级并未被调整

工作逻辑:在宿主机上,运行了很多的容器,系统级也有很多的进程,包括docker daemon自身的进程,如果内核要执行一些系统管理级的操作,发现内存没有了,启动评估,一般认为哪个耗内存更多,就会kill掉那个进程,比较快释放内存,但是这个进程不一定应该被杀,如A可以消耗内存10G,B可消耗内存1G,A只消耗10分之一,B已经消耗完了,不一定要Kill A。

  内核会对进程排优先级,自从到下逆序,一个个的杀掉,直接内存足够使用为止。

  每个进程可以分配OOM obj, 每个进程计算好后可以有一个OOM score,得分越高就应该被杀掉的,得分是对它的申请和占用的空间使用一系列复杂的计算来做的,如果计算出后,某个进程是最高的,但是不应该被杀掉,如docker daemon这个进程可以调整优先级处理。每个进程有一个oom adj,也就是权重,优先级越低,得分就变得越少,可以把docker daemon的优先级调低,得分就少,就不会被杀。如果一个容器在生产提供重要的服务,它却被杀掉,就很严重,应该开启就要调整它的优先级。而且也可以定义容器的策略,一旦被kill掉,可以restart。

 

控制容器的内存资源

# docker run --help

-m, --memory bytes Memory limit
--memory-reservation bytes Memory soft limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)

ram物理内存,swap交换内存

  • -m (-memory) 限制ram内存空间,接收k,b,m,g作为单位
  • --memory-swap * 限制交换内存空间使用,使用它的前提必须先设定-m,没有设置物理内存,就不能设置交换分区
  • --memory-swappiness 使用memory的倾向性(0-100),0表示能不用交换内存就不用
  • --memory-reservation 预留的内存空间
  • --oom-kill-disable 禁止OOM被KILL掉,如容器很消耗内存,但是又很重要不能被kill

 

 

CPU

跟内存不同,默认情况下,每个容器是不限制使用宿主机上CPU资源,可以自行限制,不过大多数用户使用默认的CFS调度,CPU的核心数量是小于进程数的,一个系统上可能运行很多进程,需要运行进程数量大于核心数量时,那个应该优先运行?所以需要调度器来操作,因此内核中进程管理最重要的一个组件是进程调度器,调度进程运行在本地CPU核心上的,那个进程应该被优先运行,非实时的优先级是100-139,实时是0-99,使用nice值来调整[-20,19]非实时的,使用CFS(完全公平调度器),是分配每个进程使用的CPU的,进程还分为两类批处理的和交互式的,交互式的优先级比较高,用户点击mouse就要执行,不然就感觉很慢,但是交互界面使用的CPU的时间都比较短的,但是批处理进程比较消耗CPU,但是通常不需要立刻做出响应,优先级比较低。
  CPU密集型表示对资源占用很大,I/O密集型的是对于I/O资源占用比较大的,对于CPU资源应该尽可能调低它的优先级,因为给它它就会尽可能的使用,内核有算法对这些进程做计算和惩罚,动态调低调高。

选项:

-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)


--cpu-shares CPU资源共享,按比例切分系统上所有可用的CPU资源, 如当前系统上一共运行了两个容器,权重比是1024:512的值,假设两个容器不需要尽可能多的使用CPU,CPU资源假设有100份,两个容器的比例是2:1, 如果第二个容器启动几乎都不需要CPU资源,这时第一个容器可以占用所有的CPU资源,就是需要就按比例分,不需要就给需要用的。CPU是可压缩资源,随时按比例运行。
--cpus=<value>  一个容器可以使用几核心,可以使用小数,如1.5核(限制数量)
--cpuset-cpus   进程只能运行在指定那个核上(限制范围)

 

CPU密集型 vs IO密集型

CPU密集型又称计算密集型,特点是要进行大量的计算,主要消耗CPU资源,一些大量循环的代码(例如:图片处理、视频编码、人工智能等),全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。对于计算密集型任务,最好用C语言编写。

IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

 

docker压测工具
# docker pull lorel/docker-stress-ng
# docker run --name stress -it --rm lorel/docker-stress-ng:latest

测试内存

# docker run --name stress -it --rm -m 256m lorel/docker-stress-ng:latest stress --vm 2
#-m指定可使用的内存大小,--vm启动的子进程,每个进程默认是256MB,所以两个进程需要512M,会超出

# docker top stress #显示容器占了多少资源
可以看到内存最多跑到256M,不会达到512M

测试cpu

# lscpu

# docker run --name stress -it --rm --cpus 1 lorel/docker-stress-ng:latest stress --cpu 4
#限制使用1颗核心,启动4个进程来操作
# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5a006d928b2c stress 99.97% 7.938MiB / 3.686GiB 0.21% 508B / 0B 0B / 0B 5
如果不限制,它会使用完,因为是两核,差不多200%
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
abb5cf0e98f9 stress 199.06% 7.934MiB / 3.686GiB 0.21% 578B / 0B 0B / 0B 5

指定使用哪个核cpu
# docker run --name stress -it --rm --cpuset-cpus 1 lorel/docker-stress-ng:latest stress --cpu 4

尽可能使用
# docker run --name stress -it --rm --cpu-shares 1024 lorel/docker-stress-ng:latest stress --cpu 4

 

posted @ 2020-02-27 11:09  卡布爱学习  阅读(1201)  评论(0编辑  收藏  举报