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

层级树的四个规则

  1. 同一个层级树(hierarchy)可以附加一个或多个子系统(subsystem)

可以看到一个层级树中,有一个cpu_mem_cg的cgroup组下还有两个组cg1和cg2,也就是说在cpu_mem_cg组中添加了cpu和mem两个子系统(subsystem)来同时控制cg1和cg2组中的task进程使用的硬件资源

  1. 一个子系统(subsystem)可以附加到多个层级树(hierarchy)中,但是只可以附加到没有任何子系统的层级树中


>可以看到cpu子系统先附加到了层级树A上了,这时就不能附加到层级树B上了,因为B上有一个mem子系统了,如果B和A都没有任何子系统的话,那么cpu子系统就可以附加到A和B上了

  1. 一个进程(task)不能属于同一个层级树(hierarchy)的不同cgroup
![](/images/docker/gz3.png)
>就是一个系统进程(task)只能当前这个层级树中的一个cgroup出现,当前层级树中的其他cgroup是不能出现第二个相同的task的,但是一个进程(task)是可以在多个层级树(hiearchy)中出现的
  1. 刚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!