CentOS7 docker开启后设置SCHED_RR出现Operation not permitted的问题

在centos7使用了docker,而我们的部署程序中,有直接部署在宿主机上的,并且程序的需要,需要设置调度为SCHED_RR的CPU调度模式,结果在没有部署docker的设备中,可以正常运行为RR模式;而在运行了docker的设备上,则会被改变成了TS模式。因此怀疑是因为docker的引入后,导致程序设置为RR模式异常。

我们要看是否可以设置为RR模式,可以通过chrt命令来查看。

chrt -r 80 ps -e -o class,rtprio,pri,nice,cmd
RR      80 120   - ps -e -o class,rtprio,pri,nice,cmd

默认chrt是修改为RR模式,如果有修改成功,则会看到是RR 优先级为80.

而如果centos7启用了docker的话,则不能设置成功,会有如下的报错。

chrt -r 80 ps -e -o class,rtprio,pri,nice,cmd
chrt: failed to set pid 0's policy: Operation not permitted

这时候也就切换失败了。我们知道docker其实是基于cgroups以及namespase的技术的。关键就在于cgroups技术,centos7下,内核是开启RT_GROUP的,这点可以通过以下命令确定:

cat /boot/config-`uname -r` | grep -i rt_group
CONFIG_RT_GROUP_SCHED=y

也就是有开启了RT_GROUP的调度策略,而我测试了下,使用Ubuntu的话,则不会有这个问题,因为Ubuntu这个参数是关闭的。

再来看看cgroup,我们要查看系统的cgroup的一些配置,首先要知道其挂载的情况:

mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)

而CPU相关的,我们看/sys/fs/cgroup/cpu,cpuacct中的配置项,centos的没开启docker的配置项如下:

ls /sys/fs/cgroup/cpu,cpuacct/
cgroup.clone_children  cgroup.procs          cpuacct.stat   cpuacct.usage_percpu  cpu.cfs_quota_us  cpu.rt_runtime_us  cpu.stat           release_agent
cgroup.event_control   cgroup.sane_behavior  cpuacct.usage  cpu.cfs_period_us     cpu.rt_period_us  cpu.shares         notify_on_release  tasks

其中与RT_GROUP的CPU调度的配置文件有两个,一个是cpu.rt_runtime_us另一个是cpu.rt_period_us

cat /sys/fs/cgroup/cpu,cpuacct/cpu.rt_period_us 
1000000

cat /sys/fs/cgroup/cpu,cpuacct/cpu.rt_runtime_us 
950000

这两的单位是微秒,rt_period_us表示是实时进程调度的单位CPU时间 是1 秒;rt_runtime_us表示是实时进程在单位时间内(目前配置也就是1秒)实际占用的CPU时间, 0.95秒。

而当启动了docker之后,在cpu,cpuacct目录中会多出以下的一些文件夹。

ls /sys/fs/cgroup/cpu,cpuacct/
cgroup.clone_children  cgroup.sane_behavior  cpuacct.usage_percpu  cpu.rt_period_us   cpu.stat           release_agent  user.slice
cgroup.event_control   cpuacct.stat          cpu.cfs_period_us     cpu.rt_runtime_us  docker             system.slice
cgroup.procs           cpuacct.usage         cpu.cfs_quota_us      cpu.shares         notify_on_release  tasks

多了docker,user.slice,system.slice;也就是说,cgroup被细分了。而chrt我们是直接使用命令行的形式,因此是属于user.slice的。因此我们看看user.slice中cpu.rt_runtime_us以及cpu.rt_period_us的配置是如何的。

cat /sys/fs/cgroup/cpu,cpuacct/user.slice/cpu.rt_runtime_us 
0

cat /sys/fs/cgroup/cpu,cpuacct/user.slice/cpu.rt_period_us 
1000000

rt_period_us是一样的,但是rt_runtime_us为0,也就是禁用的CPU调度的相关策略,因此我们将rt_runtime_us 修改为默认的950000:

echo 950000 > /sys/fs/cgroup/cpu,cpuacct/user.slice/cpu.rt_runtime_us

然后再支持下chrt命令:

chrt -r 80 ps -e -o class,rtprio,pri,nice,cmd
RR      80 120   - ps -e -o class,rtprio,pri,nice,cmd

可以成功切换为RR,因此这个问题也就得到了解决!

 

参考资料:

Bug 1467919 – running docker containers prevents processes to use real-time scheduling when restarted [NEEDINFO]

【求助】sched_setscheduler(): Operation not permitted

Linux资源控制-CPU和内存

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Scroll to top