如何使用cgroups将除白名单之外的所有进程限制为单个CPU?

如何使用cgroups将除白名单之外的所有进程限制为单个CPU?

有一个Red Hat 的 cgroup 指南这可能有点帮助(但没​​有回答这个问题)。

我知道如何在启动该进程的命令期间将特定进程限制到特定 CPU,方法是:

首先,将以下内容*放入/etc/cgconfig.conf

mount {
  cpuset =  /cgroup/cpuset;
  cpu =     /cgroup/cpu;
  cpuacct = /cgroup/cpuacct;
  memory =  /cgroup/memory;
  devices = /cgroup/devices;
  freezer = /cgroup/freezer;
  net_cls = /cgroup/net_cls;
  blkio =   /cgroup/blkio;
}

group cpu0only {
  cpuset {
    cpuset.cpus = 0;
    cpuset.mems = 0;
  }
}

然后启动一个进程并使用以下命令将其专门分配给该 cgroup:

cgexec -g cpuset:cpu0only myprocessname

我可以通过以下方式自动限制特定进程名称的所有实例(I思考这是正确的)将以下内容放入/etc/cgrules.conf

# user:process  controller  destination
*:myprocessname cpuset      cpu0only

我的问题是:我该怎么做撤销

换句话说,我该如何分配全部除一组特定的白名单进程之外的进程和他们的孩子到受限制的 cgroup?


根据我所研究但尚未测试的内容,我相信那一个部分的解决方案是:

添加“无限制”cgroup:

group anycpu {
  cpuset {
    cpuset.cpus = 0-31;
    cpuset.mems = 0;  # Not sure about this param but it seems to be required
  }
}

将我的进程明确分配给不受限制的组,并将其他所有内容分配给受限制的组:

# user:process  controller  destination
*:myprocessname cpuset      anycpu
*               cpuset      cpu0only

然而,对此的警告似乎是(通过阅读文档,而不是通过测试,因此持保留态度), 的子级myprocessname将被重新分配到受限制的cpu0onlycgroup。

一种可能的替代方法是创建一个用户来运行myprocessname并拥有所有该用户的进程不受限制,而其他一切都受到限制。然而,在我的实际用例中,该进程需要由 root 运行,并且还有其他进程也必须由 root 运行,其中应该受到限制。

我如何使用 cgroup 来实现这一点?


如果 cgroup 无法做到这一点(我现在怀疑是这样),我对部分解决方案的想法是否正确?它们会像我想象的那样起作用吗?

*免责声明:这可能不是一个最小的代码示例;我不明白全部所以我不知道哪些部分是不必要的。

答案1

更新:请注意,下面的答案适用于 RHEL 6。在 RHEL 7 中,大多数 cgroup 由 systemd 管理,并且 libcgroup 已弃用。


自从发布这个问题以来,我研究了上面链接的整个指南,以及大部分内容cgroups.txt文档和cpusets.txt。我现在对 cgroup 的了解比我预期的要多,所以我将在这里回答我自己的问题。

您可以采取多种方法。我们公司在红帽的联系人(技术架构师)建议不要对所有流程进行全面限制,而应采用更具声明性的方法——仅限制我们特别想要限制的流程。根据他对此主题的陈述,其原因是系统调用可能依赖于用户空间代码(例如 LVM 进程),如果限制这些代码可能会减慢系统速度,这与预期效果相反。因此,我最终限制了几个特定名称的进程,并保留了其他所有进程。

另外,我想提一下一些cgroup基本数据当我发布问题时我失踪了。


Cgroups 做不是取决于libcgroup是否安装。 然而,这是一组用于自动处理 cgroup 配置和 cgroup 进程分配的工具,并且非常有帮助。

我发现 libcgroup 工具也可能会产生误导,因为 libcgroup 包是建立在其基础上的自己的关于 cgroup 使用的一组抽象和假设,与 cgroup 的实际内核级实现略有不同。 (我可以举一些例子,但这需要一些工作;如果您感兴趣,请发表评论。)

因此,在使用libcgroup工具(如/etc/cgconfig.conf、、、、、等)之前我/etc/cgrules.confcgexeccgcreatecgclassify高度建议非常熟悉/cgroup虚拟文件系统本身,并手动创建 cgroup、cgroup 层次结构(包括附加多个子系统的层次结构,libcgroup 偷偷地、泄漏地抽象掉了这些层次结构)、通过运行将进程重新分配给不同的 cgroup ,以及在下面执行的echo $the_pid > /cgroup/some_cgroup_hierarchy/a_cgroup_within_that_hierarchy/tasks其他看似神奇的任务libcgroup引擎盖。


我缺少的另一个基本概念是,如果/cgroup虚拟文件系统完全安装在您的系统上(或者更准确地说,如果任何 cgroup 子系统又名“控制器”完全安装),那么每一个整个系统的进程是在一个cgroup。 不存在“有些进程在 cgroup 中,有些不在 cgroup 中”这样的情况。

有一种东西叫做cgroup 对于给定的层次结构,它拥有全部附加子系统的系统资源。例如,附加了 cpuset 和 blkio 子系统的 cgroup 层次结构将具有一个根 cgroup,该根 cgroup 拥有全部系统上的 cpu 和系统上的所有 blkio,并且可以与以下人员共享其中一些资源孩子cgroups。您无法限制 root cgroup,因为它拥有全部您的系统资源,因此限制它甚至没有意义。


我缺少关于 libcgroup 的其他一些简单数据:

如果您使用/etc/cgconfig.conf,您应该确保将chkconfig --list cgconfig显示设置cgconfig为在系统引导时运行。

如果更改/etc/cgconfig.conf,则需要运行service cgconfig restart以加载更改。 (在进行测试时,停止服务或运行的问题cgclear非常常见。对于调试,我建议,例如,lsof /cgroup/cpusetifcpuset是您正在使用的 cgroup 层次结构的名称。)

如果您想使用/etc/cgrules.conf,您需要确保“cgroup 规则引擎守护进程”( cgrulesengd) 正在运行:service cgred startchkconfig cgred on。 (并且您应该意识到与此服务有关的可能但不太可能的竞争条件,如红帽资源管理指南在页面底部的第 2.8.1 节中。)

如果您想手动闲逛并使用虚拟文件系统(我建议首次使用)设置您的 cgroup,您可以这样做,然后使用其各种选项创建一个cgconfig.conf文件来镜像您的设置。cgsnapshot


最后,当我写下以下内容时,我遗漏了关键信息:

然而,对此的警告似乎是……myprocessname 的子进程将被重新分配给受限的 cpu0only cgroup。

我是对的,但有一个我不知道的选择。

cgexec是启动进程/运行命令并将其分配给 cgroup 的命令。

cgclassify是将已经运行的进程分配给 cgroup 的命令。

这两者也会阻止cgred( cgrulesengd) 将指定进程重新分配给基于 的不同 cgroup /etc/cgrules.conf

cgexec和都cgclassify支持该--sticky标志,此外防止cgred重新分配孩子流程基于/etc/cgrules.conf.


所以,我写的问题的答案(尽管不是我最终实现的设置,因为上面提到的红帽技术架构师的建议)是:

按照我的问题中的描述制作cpu0only和cgroup 。 anycpu(确保cgconfig设置为在启动时运行。)

* cpuset cpu0only按照我的问题中的描述制定规则。 (并确保cgred设置为在启动时运行。)

启动我想要的任何进程无限制的和:cgexec -g cpuset:anycpu --sticky myprocessname

这些进程将不受限制,并且它们的所有子进程也将不受限制。 系统上的其他所有内容将仅限于 CPU 0(一旦重新启动,因为cgred不会将 cgrules 应用于已经运行的进程,除非它们更改其 EUID)。这并不完全可取,但这是我最初的要求,而且它通过 cgroup 完成。

相关内容