大家好,我是小白。今天给大家讲解一下Linux下的资源控制cgroup。
提到cgroup,可能有的同学一时不太清楚做什么用的,但大家应该都用过公有云虚拟机或者容器,套餐1C2G,如何限制资源使用实现的呢,答案就是cgroup啦~
一、何为cgroup
Linux cgroups 的全称是 Linux Control Groups,它是 Linux 内核的特性,主要作用是限制、记录和隔离进程组(process groups)使用的物理资源(cpu、memory、IO 等)。
cgroups 从设计之初使命就很明确,为进程提供资源控制,它主要的功能包括:
Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
Prioritization: 优先级控制,比如:CPU利用和磁盘IO吞吐。
Accounting: 一些审计或一些统计,主要目的是为了计费。
Control: 挂起进程,恢复执行进程
目前 cgroups 已经成为很多技术的基础,比如 Openstack、LXC、Docker、Kubernetes、systemd等。
二、Cgroup概念
cgroup 全程control group,除了它本身的概念,还有Task(进程)、 Hierarchy(层级结构) 和 subsystem(子系统) 的概念
1. cgroups子系统
cgroups为每种可以控制的资源定义了一个子系统。典型的子系统介绍如下:
cpu 子系统,主要限制进程的 cpu 使用率。
cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
memory 子系统,可以限制进程的 memory 使用量。
blkio 子系统,可以限制进程的块设备 io。
devices 子系统,可以控制进程能够访问某些设备。
net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace。
这里面每一个子系统都需要与内核的其他模块配合来完成资源的控制,比如对 cpu 资源的限制是通过进程调度模块根据 cpu 子系统的配置来完成的;对内存资源的限制则是内存模块根据 memory 子系统的配置来完成的,而对网络数据包的控制则需要 Traffic Control 子系统来配合完成。本文不会讨论内核是如何使用每一个子系统来实现资源的限制,而是重点放在内核是如何把 cgroups 对资源进行限制的配置有效的组织起来的,和内核如何把cgroups 配置和进程进行关联的,以及内核是如何通过 cgroups 文件系统把cgroups的功能暴露给用户态的。
2. cgroups 层级结构(Hierarchy)
内核使用 cgroup 结构体来表示一个 control group 对某一个或者某几个 cgroups 子系统的资源限制。cgroup 结构体可以组织成一颗树的形式,每一棵cgroup 结构体组成的树称之为一个 cgroups 层级结构。cgroups层级结构可以 attach 一个或者几个 cgroups 子系统,当前层级结构可以对其 attach 的 cgroups 子系统进行资源的限制。每一个 cgroups 子系统只能被 attach 到一个 cpu 层级结构中。
3. cgroup概念间的关系
系统创建hierarchy 之后,所有的进程都会加入这个hierarchy的cgroup的根节点。在这个cgroup根节点是hierarchy默认创建的。
一个subsystem只能附加到一个hierarchy上面。
一个进程可以作为多个cgroup的成员,但是cgroup必须在不同的hierarchy中。
一个进程fork的子进程和父进程在同一个cgroup中也可以根据需要移到其他cgroup中。
三、容器如何使用cgroup的
1. Docker容器和cgroup
Docker 容器的内存限制放在了 /sys/fs/cgroup/memory/docker 目录下,比如:
2. Kubernetes Pod和cgroup
CRI-O 是被设计面向 Kubernetes 的,所以在一些目录名中就有浓浓的 k8s 风格。
CRI-O 容器的内存限制放在了 /sys/fs/cgroup/memory/kubepods.slice 目录下,这一层目录下,又根据 QoS 创建了三个子目录 kubepods-besteffort.slice、kubepods-burstable.slice、kubepods-guaranteed.sice 分别表示三种不同 QoS Class的内存限制。
#kubectl -n wcloud get pods
#docker inspect k8s_xxxx-scheduler_xxxx-scheduler-0_wcloud_e9ea0db4-cbbb-4902-99d2-21c9b9b3d20b_0 |grep CgroupParent
"CgroupParent": "/kubepods/besteffort/pode9ea0db4-cbbb-4902-99d2-21c9b9b3d20b",
Kubernete对资源的限制,靠的是cri-o,cri-o对资源的限制,靠的是Linux Cgroup 。
Linux Cgroup 限制资源,是限制进程,只需要在Cgroup配置目录的tasks文件中,添加进程ID,限制立即生效。
Linux Cgroup 不仅仅可以限制CPU,内存,还可以限制磁盘IO等。