docker核心原理-Cgroup-硬件切割
Cgroup
可以限制被NameSpace隔离起来的资源,还可以为资源设置权重,计算用量等
cgroup全称是 control groups
control groups:控制组,被整合在了linux内核当中,把进程(tasks)放到组里面,对组设置权限,对进程进行控制。可以理解为用户和组的概念,用户会继承它所在组的权限。
cgroups是linux内核中的机制,这种机制可以根据特定的行为把一系列的任务,子任务整合或者分离,按照资源划分的等级的不同,从而实现资源统一控制的框架,cgroup可以控制、限制、隔离进程所需要的物理资源,包括cpu、内存、IO,为容器虚拟化提供了最基本的保证,是构建docker一系列虚拟化的管理工具
- cgroup的内核通过hook钩子来实现管理进程资源,提供了一个统一的接口,从单个进程的资源控制到操作系统层面的虚拟卡的过渡
Cgroup的功能
1.资源控制: Cgroup通过进程组队资源总额进行限制,例如对内存的总额进行限制等
2.优先级分配: 使用硬件的权重值,当两个程序都需要进程读取cpu,谁优先级高谁占用的资源就多
3.资源统计: 可以统计硬件资源的用量 统计cpu内存等硬件使用的时间
4.进程控制: 可以对进程组实现挂起和恢复操作
术语
- task
进程 表示系统中的某一个进程—PID
- cgroup
控制单位 资源控制,以cgroup来实现,其中cgroup中都是task,但是可以有多个cgroup,可以限制不同的内容,组名不能相同
- subsystem
子系统 资源调度控制器
- hierachy
层级树 一堆cgroup构成,包含多个cgroup的叫层级树 可以有多个 hierachy
- 他们之间的关系
一个cgroup中可以有多个task,subsystem相当于控制cgroup限制的类型,hierarchy里面可以有多个cgroup,一个系统可以有多个hierarchy
层级树的四个规则
- 同一个层级树(hierarchy)可以附加一个或多个子系统(subsystem)
可以看到一个层级树中,有一个cpu_mem_cg的cgroup组下还有两个组cg1和cg2,也就是说在cpu_mem_cg组中添加了cpu和mem两个子系统(subsystem)来同时控制cg1和cg2组中的task进程使用的硬件资源
- 一个子系统(subsystem)可以附加到多个层级树(hierarchy)中,但是只可以附加到没有任何子系统的层级树中
>可以看到cpu子系统先附加到了层级树A上了,这时就不能附加到层级树B上了,因为B上有一个mem子系统了,如果B和A都没有任何子系统的话,那么cpu子系统就可以附加到A和B上了
- 一个进程(task)不能属于同一个层级树(hierarchy)的不同cgroup
![](/images/docker/gz3.png)
>就是一个系统进程(task)只能当前这个层级树中的一个cgroup出现,当前层级树中的其他cgroup是不能出现第二个相同的task的,但是一个进程(task)是可以在多个层级树(hiearchy)中出现的
刚fork出的子进程在初始化状态时是和父进程处于一个cgroup的
进程(task)创建自己的子进程的时候,新创建出来的(task)默认是和它的父进程在一个cgroup中的,但是该子进程是可以被移除到该层级树(hierarchy)中不同的cgroup中的
Subsystem 子系统
为cgroup组分配调度硬件资源
Subsystem控制选项
cpuset 为cgroup中的task分配独立cpu和内存。 cpu 调度程序控制task对cpu的使用。 cpuacct 自动生成cpu资源使用情况报告。 memory 对内存用量的使用限制。同时可以生成使用报告。 devices 开启/关闭cgroup中task对设备的访问。 freezer 挂起/恢复cgroup中task。 net_cls,net_prio 没有被直接使用。通常等级识别符号 (classid)标记网络数据,从而控制流量。 blkio 为块设备设定输入或输出的限制。 perf_event 统一的性能测试。 hugetlb 没有被启用。 pids 单独对某个pid进行限制 net_cls 标记网络 net_prio 网络跟踪 pids 暂时没有使用,限制单一的PID运行 systemd 系统资源(进程) cgroup查看的位置就是 /sys/fs/cgroup 里面的内容都是子系统,而运行的容器在每个子系统里都有需要控制的选项, 例如 容器A在cpu里的docker组里面存在,也在memery里的docker组里, 那么容器A的task(进程号)会放在这两个子系统的tasks里,进行控制
docker使用cgroup对硬件进行限制
- 对cpu的限制 (仅对于cpu的使用权重)
-c 限制使用量(和权重差不多) --cpu 容器使用的cpu线程数或者核心数 --cpu-shares 限制cpu的权重
# 创建两个容器 并给容器设置权重
[root@localhost ~]# docker run -itd --name aa --cpu-shares 512 centos
f52dc219a31191b931bc21b3e2451a193d243247233310bb0181e64274e266be
[root@localhost ~]# docker run -itd --name bb --cpu-shares 1023 centos
744815c308a302c7addfbfe69b526a70029c4de59c6dd18e4564b06c915f2a0a
# 查看cgroup
[root@localhost ~]# cd /sys/fs/cgroup/cpu/docker/
# 进入到aa容器的文件
[root@localhost docker]# cd f52dc219a31191b931bc21b3e2451a193d243247233310bb0181
[root@localhost f52dc219a31191b931bc21b3e2451a193d243247233310bb0181e64274e266be]# cat cpu.shares
512 # 这是容器aa的权重
# 进入到bb容器的文件
[root@localhost docker]# cd 744815c308a302c7addfbfe69b526a70029c4de59c6dd18e4564
[root@localhost 744815c308a302c7addfbfe69b526a70029c4de59c6dd18e4564b06c915f2a0a]# cat cpu.shares
1023 # 这里是 容器bb的权重
# bb比aa的权重高
# --cpu-shares 和 -c 的效果是一样的
[root@localhost ~]# docker run -itd --name cc -c 2048 centos
b4ab2030db36b6bf25be38937d3aaee08eb7bfa9a3bb72e9c33d4459152b1a85
[root@localhost ~]# cd /sys/fs/cgroup/cpu/docker/b4ab2030db36b6bf25be38937d3aaee08eb7bfa9a3bb72e9c33d4459152b1a85/
[root@localhost b4ab2030db36b6bf25be38937d3aaee08eb7bfa9a3bb72e9c33d4459152b1a85]# cat cpu.shares
2048
对memory的限制
-m \--memory 限制内存的使用额度 -- memory-swap 限制内存+swap的大小 #对内存进行限制 [root@localhost ~]# docker run -itd --name dd -m 200M --memory-swap 300M centos 0ebd1f0babee7b64e114df78a19a4e556d31bc8277f0d01d1b4fed71b2cafa59 [root@localhost ~]# # 使用过程中,不使用memory-swap,memory-swap会默认为memory的1倍 # 如果写上的话 上面的 300M 就相当于 内存加swap的大小了 # 所以 swap的大小是100M # swap 分区通常被称为交换分区,这是一块特殊的硬盘空间,即当实际内存不够用的时候,操作系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前运行的程序腾出足够的内存空间。
对blockIO的限制
bps 每秒读写的数据量
iops 每秒输入输出的数据量
--device-read-bps | 限制此设备上的读取速度 |
---|---|
--device-write-bps | 限制此设备上的写入的速度 |
--device-read-iops | 通过每秒读取的IO次数来限制此设备的读取速度 |
--device-write-iops | 通过每秒写入IO次数来限制此设备的写入速度 |
-blkio-weight | 容器默认从磁盘IO的加权值(也就是权重)有效范围为 10-100 |
-blkio-weight-device | 针对特定设备的IO加权控制 格式为 DEVICE_NAME:WEIGHT |
# 限制硬盘的写入性能为 30M
[root@localhost ~]# docker run -it --device-write-bps /dev/sda:30MB centos
# 进入到容器内 通过 time记录时间,用dd命令测试写入速度
[root@d15bdae342a3 /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB) copied, 27.2592 s, 30.8 MB/s
real 0m27.369s
user 0m0.000s
sys 0m0.600s
[root@d15bdae342a3 /]#
# Time:追踪一条命令的执行时间
# dd:测试磁盘的读写性能
# bs=1M每次读1M
# If(input file):输入文件 zero是特殊目录(zero无限大的空间内容 night of(out of file)输出到的文件
# Bs=1M:一个block块的大小是1M
# Count=800:一共做800次
# Oflag=direct这个输出不走内存,直接读写硬盘
cgroup的目录层级
- cgroup分为三层
- 第一层
/sys/fs/cgroup/cpu/ 可以限制host主机所有程序的硬件资源
- 第二层
/sys/fs/cgroup/cpu/docker/ 可以限制docker中所有容器程序的硬件资源
- 第三层
/sys/fs/cgroup/cpu/docker/容器id 可以限制docker单个容器的硬件资源
本博客所有文章是以学习为目的,如果有不对的地方可以一起交流沟通共同学习 邮箱:1248287831@qq.com!