docker资源隔离和资源限制原理分析
一、概述
docker通过namespace实现了资源的隔离,通过cgroup实现了资源限制,通过写时复制实现了高效的文件操作。本文主要介绍namespace、cgroup以及docker run命令资源分配的相关参数
二、 namespace资源隔离
下面列出8个namespace和用来构建docker的特性
- MNT:文件系统访问和结构(挂载点)
- chroot():控制文件系统跟目录的位置
- Cgroup:资源保护
- PID:进程标示符和进程能力(进程编号)
- NET:网络访问和结构(网络设备、网络栈、端口)
- UTS: 主机和域名
- USR: 用户名和标识符(用户和用户组)
- IPC: 通过共享内存进行通信(信号量、消息队列和共享内存)
实际上,Linux内核实现namespace的一个主要目的,是实现轻量级虚拟化(容器)服务。同一个naespace下的进程可以感知彼此的变化,而对外界的进程一无所知。这样就可以让容器中的进程产生错觉,仿佛自己置身一个独立的系统环境中,以达到独立和隔离的目的
三、cgroup资源限制
cgroups通过给资源设置权重、计算使用量、操控任务(进程和线程)启停等来实现资源控制。
cgroups官方定义–cgroups是Linux内核提供的一种机制,这种机制可以根据需求把一系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。
简单的说cgroups可以限制、记录任务组所使用的物理资源(包括CPU、Memory、IO、Network等)为容器实现虚拟化提供了基本保证,是构建docker等一些列虚拟化管理工具的基石。
- cgroups的4个特点:
- cgroups的API以一个伪文件系统的方式实现,用户态的程序可以通过文件操作实现cgroups的组织管理
- cgroups的组织管理操作单元可以细粒度到线程级别,另外用户可以创建和销毁cgroup,从而实现资源再分配和管理
- 所以资源管理的功能都以子系统的方式实现,接口统一
- 子任务创建之初与其父任务处于同一个cgroups的控制组
本质上来说,cgroups是内核附加在程序上的一系列钩子,通过程序运行时对资源的调度触发相应的钩子以达到资源追踪的目的
- cgroups 四个功能
- 资源限制
- 对任务使用的资源总额进行限制
- 优先级分配
- 通过分配的cpu时间片数量及磁盘IO带宽大小,实现优先级控制
- 资源统计
- 统计资源使用量,如CPU使用时长、内存用量等
- 任务控制
- cgroups可以对任务执行挂起、恢复等操作。
- 资源限制
/sys/fs/cgroup/cpu/
下文件的作用- tasks
- cgroup.proc
- notify_on_release
- release_agent
四、docker client使用的参数
- docker中查看路径
/sys/fs/cgroup/cpuacct/cpu.cfs_quota_us
-
--cpu-share
- –cpu-share是相对权重值,在资源时决定分配给容器的资源比例
- 如:容器A、B,docker run --cpu-share 参数分别为1024和2048,在主机CPU资源竞争时,docker会根据1:2的比例把cpu的时间片分配给容器A、B
--cpu-share
对应着k8s中的spec.container[].resources.requests.cpu
参数,该参数会转化成core数,再乘以1024,再将这个结果作为--cpu-share
的参数传递给docker run
。spec.container[].resources.requests.cpu
对于k8s而言是绝对值,,作为k8s调度和管理的依据。但是--cpu-share
docker而言是相对值,主要用于资源分配比例。两种用途作用范围不同,不够成冲突。
-
--cpu-quota
(–cpu-quota和–cpu-period配合使用)- –cpu-period 默认为100000,表示docker重新计量和分配cpu时间片的时间间隔为100ms
- 如
---quota
参数值为10000,--cpu-period
为100000,意味着docker在100ms内最多给盖容器分配10ms*core的计算资源用量,10/100=0.1core。 --cpu-quota
对应着k8s中的spec.container[].resources.limits.cpu
spec.container[].resources.limits.cpu
1 -> 转换为--cpu-quota
100000
-
--memory
docker run --memory...
直接使用即可。--memory
对应着k8s的spec.container[].resources.limits.memory
spec.container[].resources.requests.memory
参数只提供给k8s调度器作为调度和管理的依据,不传递给dockerspec.container[].resources.limits.memory
参数转化为byte整数,作为–memory参数传递给docker run- 容器在运行过程中使用的内存超出limits配置的限制值时,那么它可能会被杀掉。
- CPU在容器技术中属于可压缩资源,一般不会引发没有上述的由于使用超额内存而被杀死的情况
-