一 CPU CGROUP介绍
cpu cgroup是什么?为何要用?
之前我们提过Cgroup是用于限制进程对资源使用的一种机制,而Cpu Cgroup是Cgroup机制的一种,即cpu cgroup是cgroups的一个子系统,具体用来限制进程对cpu资源的使用的
k8s里pod的request与limit底层其实就是在配置cpu cgroup
二 储备知识cpu usage
既然cpu cgroup是限制进程对cpu的使用,那么在研究具体如何配置相关限制之前,我们必须搞清楚进程对cpu的使用都有哪些
因为cpu usage有一些对cpu的使用时不会计入进程对cpu占用的,
如下:CPU Usage
总结:进程对cpu的使用包括两部分
- linux cpu 的使用总共分为两类:一类是用户态,包含us与ni,另外一类是内核态也就是sy
- 至于wa、hi、si,这些I/O或者中断相关的cpu使用,cpu cgroup不会去做限制
三 CPU Cgroup的使用
每个Cgroups的子系统都是通过一个虚拟文件系统挂载点的方式,挂到一个缺省的目录下。在linux发行版里,cpu cgroup一般是挂载到/sys/fs/cgroup/cpu目录下
在该目录下,每个控制组(Control Group)都是一个子目录,各个控制组之间的关系是一个树状的层级关系(hiearchy)
例如,我们在子系统的最顶层目录开始创建两个控制组,其实就是创建两个目录group1与group2,然后再在group2下面创建两个控制组group3与group4,如此,我们便建立了一个树状的控制组层级,如下图所示
创建控制组后,会在目录下自动生成一系列文件
删除控制组
在云平台里,大部分程序都不是实时调度的进程,而是普通调度(SCHED_HORMAL)类型进程,对于普通调度用到的算法,在linux系统中目前是CFS(Completely Fair Scheduler,即完全公平调度器)。在CPU Cgroup中和CFS相关的参数,共有三个
- cpu.cfs_period_us:它是CFS算法的一个调度周期,以microseconds(微妙)为单位,1微妙等于千分之一毫秒,1毫秒等于千分之一秒,例如值为100 000microseconds,则代表100ms
- cpu.cfs_quota_us:它表示CFS算法中,在一个调度周期里,此控制组被允许的运行时间,比如该值为50000时,就是50ms
cpu.cfs_quota_us / cpu.cfs_period_us就是此控制组被允许使用cpu的最大配额,例如50ms / 100ms = 0.5 ,
代表该控制组被允许使用的cpu最大配置为0.5个cpu
- cpu.shares:该值用于控制在一个控制组目录树下,同一级控制组关于cpu的分配比例,例如上例中的group3与group4,如果group3下该值为1024,group4下该值为4096,则group3:group4比值为1:4,代表在一个5颗cpu的机器上,当group3与group4都需要5个cpu时,它们实际分配的cpu是:group3是1个,group4时候4个
k8s会为每个容器创建一个控制组,然后把容器进程pid写入控制组
yaml里的limit控制的就是cpu.cfs_quota_us/cpu.cfs_period_us的比值,得到是资源使用上限
我们为Kubernetes设置CPU requests实际上是设置了cpu.shares cgroup属性。就像内存requests对调度器的意义一样,CPU requests会让调度器选择至少拥有那么多可用CPU分片的节点。不同于内存requests,设置CPU requests也会给cgroup设置相应的属性,帮助内核实际给进程分配一样数量的CPU核心分片。Limits的处理也与内存不一样。超出内存limits会让你的容器进程成为oom-kill的选项,但是你的进程基本上不可能超出设置的cpu配额,并且永远不会因为试着使用更多CPU而被驱逐。系统在调度器那里加强了配额的使用,所以进程在到达limits后只会被限流。
先来开发一个能够占用cpu的程序,输入cpu个数,运行程序便占用n个cpu,此处我们用python编写,为了规避GIL对我们的影响,我们采用ctypes调用c语言库的方式,详见:https://egonlin.com/?p=7204
(1)编写一个libdead_loop.c
(2)编译为.so库,把so文件放到/opt目录下吧,这样方面后面查找
(3)编写py脚本test.py
补充:如果不会编写脚本也可以直接使用负载模拟工具