玩转 Cgroup 系列之二:使用 CPUShares 管理 Cgroup

874 阅读3分钟

在本系列的第一篇中,我们看到了 Linux 系统管理员视角下的 Cgroup,并了解了它如何帮助资源管理和性能调优。

在第二篇中,作者将继续介绍 CPUShares 以及它如何帮助管理 Cgroup,那么我们现在开始(点击参考原文)。

Linux I/O 调度

首先,我想用红帽企业版 Linux(RHEL)来简单介绍一下 Linux 的 I/O 调度程序。我简单看了一下实验室里的几台 Ubuntu 机器,发现它们的 I/O 调度程序有一些相似之处,所以我下面的一些观点可能也适用于其他发行版本。红帽系列产品(Fedora、CentOS 和 RHEL)大多数都默认使用 cfqdeadline 作为调度程序。

  • CFQ(完全公平队列算法):强调 I/O 实时进程,并使用历史数据来决定应用程序是否会在近期发出更多的 I/O 请求。
  • Deadline(最后期限算法):尝试为 I/O 请求提供有保障的延迟,特别适合于读取操作比写入操作更频繁的情况。在 deadline 调度程序中,读和写分别有一个队列,机器根据请求在队列中等待的时间来决定处理顺序。同时,内核会尽力在请求的最大等待时间耗尽之前处理它们。默认情况下,读操作优先于写操作处理。

在默认情况下,RHEL 对 SATA 驱动器使用 cfq 调度程序,对其他驱动器使用 deadline 调度程序,以便更好地调优系统。

当然,这些调度程序也是可以更改的,我们可以根据工作负载选择最适合的调度程序。另外,还可以针对每个块设备选择调度程序。也就是说,在单个系统上可以有多个调度程序,具体取决于磁盘的配置方式。

CPUShares 及其用途

CPUShares 为 Cgroup 中的任务分配了相对的 CPU 时间。只要系统挂载了 Cpu Cgroup 控制器,您就可以使用 cpu.shares 文件来定义分配给 Cgroup 的 CPU 份额。

CPU 时间可以通过 Cgroup 的 CPUShares 值除以系统上定义的总 CPUShares 值来确定。这个 CPU 时间的计算有些复杂,下面我们来看一些实例以便更好地理解。

cgroup 2-1.png

上图展示了 RHEL 7 OpenShift 容器平台控制平面上的一些常见元素。这个系统上的每个进程都从根目录的 / Cgroup 开始。

在 RHEL 中,从根目录的 / Cgroup 开始,共有 1024 个份额和 100% 的 CPU 资源。剩下的资源被平均分配给 /system.slice/user.slice/kubepod.slice 这些组,每个组默认的权重都是 1024,如下图所示:

cgroup 2-2.png

在这种情况下,计算的逻辑很简单:如果所有 Cgroup 同时要求资源,每个 slice 只能拥有 33% 的 CPUShares。数学计算就是:

cgroup 2-3.png

代入数字:

cgroup 2-4.png

然而,如果我们想要嵌套组或更改同一级别组的权重,会发生什么呢?下面就是一个嵌套组的示例:

cgroup 2-5.png

可以看到我为不同的用户创建了一个 Cgroup,然后计算就不一样了。你可能会这么计算:

cgroup 2-6.png

那就错了。其实该用户占到的份额是 user.slice 分配到的 33% 的 23%。也就是说,在资源争用的情况下,user1 大约可以占总 CPU 时间的 7.6%。

因此,CPUShares 的计算其实没那么简单。不过,好消息是,绝大多数控制器比这里展示的要更加直观简单,所以大可不必担心。

总结

CPUShares 可能会让 Cgroup 变得非常复杂,这也是我认为有必要在这里介绍它的一个原因。而如果掌握了 CPUShares 的内在逻辑,且可以正确地使用它的话,能够极大地帮助您有效、准确地管理系统。

在之后的系列文章中,我还将继续讨论 Cgroup 的管理,以及 systemd 的使用问题。敬请期待哦。