在cgroup中,与CPU相关的子系统包括cpusets、cpuacct和cpu。其中cpuset主要用来设置CPU的affinity,可以限制cgroup中的进程只运行在指定的CPU上,或者不运行在指定的CPU上,cpuset还可以设置内存的affinity。设置affinity一般只有在特殊情况下才需要,这里就不介绍了。cpuacct包含了当前cgroup使用的CPU的统计信息,信息量不大。有兴趣的可以去看它的文档,这里就不介绍了。本文只介绍cpu子系统,包括如何限制一个cgroup的CPU使用率限制,以及相对于其他cgroup的相对值。本文所有示例均在ubuntu-server-x86_6416.04下执行。通过在ubuntu下创建子cgroup,systemd已经帮我们挂载了cpu子系统。我们只需要在相应的目录下创建一个子目录即可。#从这里输出可以看出,cpuset挂载在/sys/fs/cgroup/cpuset上,#而cpu和cpuacct一起挂载在/sys/fs/cgroup/cpu上,在cpuacct下dev@ubuntu:~$mount|grepcgroupon/sys/fs/cgroup/cpusettypecgroup(rw,nosuid,nodev,noexec,relatime,cpuset)cgroupon/sys/fs/cgroup/cpu,cpuaccttypecgroup(rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)#Enter/sys/fs/cgroup/cpu,cpuacct并创建子cgroupdev@ubuntu:~$cd/sys/fs/cgroup/cpu,cpuacctdev@ubuntu:/sys/fs/cgroup/cpu,cpuacct$sudomkdirtestdev@ubuntu:/sys/fs/cgroup/cpu,cpuacct$cdtestdev@ubuntu:/sys/fs/cgroup/cpu,cpuacct/test$lscgroup.clone_childrencpuacct.statcpuacct.usage_percpucpu.cfs_quota_uscpu.stattaskscgroup.procscpuacct.usagecpu.cfs_period_uscpu.sharesnotify_on_release除了cgroup中常见的cgroup.clone_children、tasks、cgroup.procs、notify_on_release文件外,cpuacct开头的文件。与cpuacct子系统有关。这里我们只需要关注cpu开头的文件即可。cpu.cfs_period_us&cpu.cfs_quota_uscfs_period_us用于配置时间段长度,cfs_quota_us用于配置当前cgroup在设置的时间段长度内可以使用的CPU时间量。这两个文件共同作用来设置CPU使用率的上限。两个文件的单位都是微秒(us),cfs_period_us的取值范围是1毫秒(ms)到1秒(s),cfs_quota_us的值大于1ms,如果cfs_quota_us的值为-1(默认值),说明不受cpu时间限制。下面举几个例子:1.只能使用1个CPU(每250ms可以使用250ms的CPU时间)#echo250000>cpu.cfs_quota_us/*quota=250ms*/#echo250000>cpu.cfs_period_us/*period=250毫秒*/2。限制使用2个CPU(核)(每500ms可以使用1000ms的CPU时间,即使用两个核)#echo1000000>cpu.cfs_quota_us/*quota=1000ms*/#echo500000>cpu.cfs_period_us/*周期=500毫秒*/3。限制使用20%的CPU(每50ms可以使用10ms的CPU时间,即使用20%的CPU核)#echo10000>cpu.cfs_quota_us/*quota=10ms*/#echo50000>cpu.cfs_period_us/*period=50ms*/cpu.sharesshares用于设置CPU的相对值,它是针对所有CPU(核心)的。默认值为1024,如果系统中有两个cgroup,A和B,A的份额值为1024,B的份额值为512,则A得到1024/(1204+512)=66%的CPU资源,B将获得33%的CPU资源。Shares有两个特点:如果A不忙,没有使用66%的CPU时间,那么剩余的CPU时间将由系统分配给B,即如果有新的A,B的CPU使用率可以超过33%cgroup加入C,其份额值为1024,则A的配额变为1024/(1204+512+1024)=40%,B的配额变为20%。,shares基本不起作用,只有在CPU忙的时候才起作用,这是一个优势。由于shares是一个绝对值,所以需要和其他cgroups的值进行比较,才能得到自己的相对极限。在一台部署了很多容器的机器上,cgroups的数量会发生变化,所以这个限制也会发生变化。设置一个较高的值,但其他人可能设置了更高的值,因此该功能无法准确控制CPU使用率。cpu.stat包含以下三个统计结果nr_periods:表示经过了多少个cpu.cfs_period_us中配置的时间段。Itsquotaisusedupinthetimeperiod)throttled_time:cgroup中的进程被限制使用CPU的时间(纳秒)。示例这里以cfs_period_us&cfs_quota_us为例,演示如何控制CPU占用率。#继续使用上面创建的子cgroup:test#设置只有20%的时间可以使用1个cpudev@ubuntu:/sys/fs/cgroup/cpu,cpuacct/test$sudosh-c"echo50000>cpu.cfs_period_us"dev@ubuntu:/sys/fs/cgroup/cpu,cpuacct/test$sudosh-c"echo10000>cpu.cfs_quota_us"#将当前的bash添加到这个cgroupdev@ubuntu:/sys/fs/cgroup/cpu,cpuacct/test$echo$$5456dev@ubuntu:/sys/fs/cgroup/cpu,cpuacct/test$sudosh-c"echo5456>cgroup.procs"#在bash中开始无限循环消耗cpu,normal这种情况应该使用100%的cpu(也就是应该消耗一个core)dev@ubuntu:/sys/fs/cgroup/cpu,cpuacct/test$while:;做回声测试>/dev/null;done#-------------------------重新打开一个shell窗口--------------------#通过top命令可以看到5456的CPU使用率在20%左右,说明是受限了#但是此时系统的%us+%sy在10%左右,那是因为我测试的机器上的CPU是双核的,#所以系统整体的cpu使用率在10%左右dev@ubuntu:~$topTasks:139total,2running,137sleeping,0stopped,0zombie%Cpu(s):5.6us,6.2sy,0.0ni,88.2id,0.0wa,0.0hi,0.0si,0.0stKiB内存:总计499984,免费15472,已使用81488,403024buff/cacheKiB交换:总计0,免费0,0用过的。383332availMemPIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND5456dev2002264054723524R20.31.10:04.62bash#Nowyoucanseetherestrictedstatisticsdev@ubuntu:~$cat/sys/fs/cgroup/cpu,cpuacct/test/cpu.statnr_periods1436nr_throttled1304throttled_time51542291833结论使用cgroup限制CPU使用率比较纠结。使用cfs_period_us和cfs_quota_us。份额,而且没有办法配置百分比,极难控制。总之,使用cgroup的cpu子系统需要谨慎。参考CFSBandwidthControlcpu
