linux cgroup、kubernetes limit
1.cgroups 简介
- cgroups,其名称源自控制组群(control groups)的缩写,是内核的一个特性,用于限制、记录和隔离一组进程的资源使用(CPU、内存、磁盘 I/O、网络等)
- 资源限制:可以配置cgroup,从而限制进程可以对特定资源(例如内存或 CPU)的使用量
- 优先级 :当资源发生冲突时,您可以控制一个进程相比另一个cgroup 中的进程可以使用的资源量(CPU、磁盘或网络)
- 记录:在 cgroup 级别监控和报告资源限制
- 控制:您可以使用单个命令更改cgroup 中所有进程的状态(冻结、停止或重新启动)
Cgroups功能的实现依赖于四个核心概念:子系统、控制组、层级树、任务
2.limit限制
k8s当设置了limit,真正设置限制的是cgroup,但是最终设置在哪一个组件上?下面一个图就可以清晰看出来。这也是k8s在24版本后放弃docker的原因,因为k8s可以直接调用到containerd,无序中间在多走一步docker
最终设置在了containerd-shim的执行中。同时cgroup也是设置在了这里。
3.cgroup文件
cgroup是树形结构的。当最下层的目录中没有限制(例如shares为空,则继承上级父目录的限制)
cgroup文件在 /sys/fs/cgroup下面,可以看到能限制的所有资源。
如果想要看到某种资源的限制情况,例如cpu,可以进入到cpu查看。可以看到这里cpu的限制是1024,也就是当前task文件里的所有进程,都是cpu限制上限1024。
当k8s创建一个pod时,会根据QOS分级,创建对应的文件夹,其中Guaranteed的pod会单独创建。
进入到burstable等级的文件夹中,会发现pod信息都在这里,k8s设置的limit值,就是在该目录下对文件的修改。
我本地启动了一个Guaranteed类型的pod
这个时候,cgroup下也出现了这个目录,进入这个目录查看cpu.shares和memory.limit_in_bytes。发现和describe pod中设置的limit信息是一致的。
这里有个小实验,就是把cpu.shares改小或者改大。这时候这个pod的限制回随着改动变化。但是describe pod的时候显示的依然是最初得值(存在了etcd),所以要在cgroup目录下直接修改值。
4.subsystem(子系统)
这里就是设置资源限制的使用量。直接贴文档了。
4.1、cpu子系统:于限制进程的 CPU 利用率
参数 | 说明 |
---|---|
cpu.shares | -cpu比重分配。通过一个整数的数值来调节cgroup所占用的cpu时间。例如,有2个cgroup(假设为CPU1,CPU2),其中一个(CPU1)cpu.shares设定为100另外一个(CPU2)设为200,那么CPU2所使用的cpu时间将是CPU1所使用时间的2倍。cpu.shares 的值必须为2或者高于2- |
cpu.cfs_period_us | 规定CPU的时间周期(单位是微秒)。最大值是1秒,最小值是1000微秒。如果在一个单CPU的系统内,要保证一个cgroup 内的任务在1秒的CPU周期内占用0.2秒的CPU时间,可以通过设置cpu.cfs_quota_us 为200000和cpu.cfs_period_us 为 1000000 |
cpu.cfs_quota_us | 在单位时间内(即cpu.cfs_period_us设定值)可用的CPU最大时间(单位是微秒)。cpu.cfs_quota_us值可以大于cpu.cfs_period_us值,例如在一个双CPU的系统内,想要一个cgroup内的进程充分的利用2个CPU,可以设定cpu.cfs_quota_us为 200000 及cpu.cfs_period_us为 100000 |
当设定cpu.cfs_quota_us为-1时,表明不受限制,同时这也是默认值
4.2 cpuacct子系统:统计各个 Cgroup 的 CPU 使用情况
参数 | 说明 |
---|---|
cpuacct.stat | cgroup中所有任务的用户和内核分别使用CPU的时长 |
cpuacct.usage | cgroup中所有任务的CPU使用时长(纳秒) |
cpuacct.usage_percpu | cgroup中所有任务使用的每个cpu的时间(纳秒) |
4.3 cpuset子系统:为一组进程分配指定的CPU和内存节点
参数 | 说明 |
---|---|
cpuset.cpus | 允许cgroup中的进程使用的CPU列表。如0-2,16代表 0,1,2,16这4个CPU |
cpuset.mems | 允许cgroup中的进程使用的内存节点列表。如0-2,16代表 0,1,2,16这4个可用节点 |
cpuset.memory_migrate | 当cpuset.mems变化时内存页上的数据是否迁移(默认值0,不迁移;1,迁移) |
cpuset.cpu_exclusive | cgroup是否独占cpuset.cpus 中分配的cpu 。(默认值0,共享;1,独占),如果设置为1,其他cgroup内的cpuset.cpus值不能包含有该cpuset.cpus内的值 |
cpuset.mem_exclusive | 是否独占memory,(默认值0,共享;1,独占) |
cpuset.mem_hardwall | cgroup中任务的内存是否隔离,(默认值0,不隔离;1,隔离,每个用户的任务将拥有独立的空间) |
cpuset.sched_load_balance | cgroup的cpu压力是否会被平均到cpuset中的多个cpu上。(默认值1,启用负载均衡;0,禁用。) |
4.4 memory子系统:限制cgroup所能使用的内存上限
参数 | 说明 |
---|---|
memory.limit_in_bytes | 设定最大的内存使用量,可以加单位(k/K,m/M,g/G)不加单位默认为bytes |
memory.soft_limit_in_bytes | 和 memory.limit_in_bytes 的差异是,这个限制并不会阻止进程使用超过限额的内存,只是在系统内存不足时,会优先回收超过限额的进程占用的内存,使之向限定值靠拢。该值应小于memory.limit_in_bytes设定值 |
memory.stat | 统计内存使用情况。各项单位为字节 |
memory.memsw.limit_in_bytes | 设定最大的内存+swap的使用量 |
memory.oom_control | 当进程出现Out of Memory时,是否进行kill操作。默认值0,kill;设置为1时,进程将进入睡眠状态,等待内存充足时被唤醒 |
memory.force_empty | 当设置为0时,清空该group的所有内存页;该选项只有在当前group没有tasks才可以使用 |
4.5 blkio子系统:限制cgroup对IO的使用
参数 | 说明 |
---|---|
blkio.weight | 设置权值,范围在[100, 1000],属于比重分配,不是绝对带宽。因此只有当不同 Cgroup 争用同一个 阻塞设备时才起作用 |
blkio.weight_device | 对具体设备设置权值。它会覆盖上面的选项值 |
blkio.throttle.read_bps_device | 对具体的设备,设置每秒读磁盘的带宽上限 |
blkio.throttle.write_bps_device | 对具体的设备,设置每秒写磁盘的带宽上限 |
blkio.throttle.read_iops_device | 对具体的设备,设置每秒读磁盘的IOPS带宽上限 |
blkio.throttle.write_iops_device | 对具体的设备,设置每秒写磁盘的IOPS带宽上限 |
4.6 devices子系统:限定cgroup内的进程可以访问的设备
devices.allow:允许访问的设备。文件包括4个字段:type(设备类型), major(主设备号), minor(次设备号), and access(访问方式)
type
- a — 适用所有设备,包括字符设备和块设备
- b — 块设备
- c — 字符设备
major, minor
-
9:*
-
*:*
-
8:1
access
- r — 读
- w — 写
- m — 创建不存在的设备
参数 | 说明 |
---|---|
devices.deny | 禁止访问的设备,格式同devices.allow |
devices.list | 显示目前允许被访问的设备列表 |
4.7 freezer子系统:暂停或恢复任务
freezer.state:当前cgroup中进程的状态
FROZEN:挂起进程
FREEZING:进程正在挂起中
THAWED:激活进程
1.挂起进程时,会连同子进程一同挂起。
2.不能将进程移动到处于FROZEN状态的cgroup中。
3.只有FROZEN和THAWED可以被写进freezer.state中, FREEZING则不能