返回博客

使用 Cgroups 管理 Docker 资源

使用 Cgroups 管理 Docker 资源

上个月我在 ApacheCon 上发表了演讲,主题是关于 Cgroups。似乎很少有 Linux 用户(包括不久前的我自己)熟悉 Cgroups 及其强大功能。这很遗憾,因为 Cgroups 是非常强大的,它允许您以比 Linux 工具包中任何其他可用工具更细粒度的方式在服务器上分配资源。此外,它直接内置于内核中,并且大多数 Linux 发行版都开箱即用。

在这篇文章中,我将介绍如何将 Cgroups 与 Docker 结合使用,作为我在Docker Meetup(德克萨斯州奥斯汀)上发表的另一场演讲的后续。

本文确实需要对 Cgroups 有一些基本的了解。如果您对 Cgroups 完全陌生,我建议您浏览一下我的幻灯片(来自 ApacheCon)以及末尾的资源。不过不用担心,我们不会深入探讨。如果您只是粗略浏览一下幻灯片,应该就能掌握基本概念。

Docker 和 Cgroups

Docker 附带了两种不同的驱动程序:LXC 和 libcontainer。LXC 驱动程序是旧版驱动程序,而 libcontainer 是新的默认驱动程序。在大多数情况下,libcontainer 是首选驱动程序,因为那是创新发生的地方(例如 docker exec 无法与 LXC 驱动程序一起工作)。

然而,需要注意的是,存在两种不同的驱动程序,因为并非所有 Cgroup 功能都已移植到 libcontainer(或至少向 Docker 开放)。使用 LXC 驱动程序时,您只需直接传递 LXC 参数,而使用 libcontainer 时,有显式的 Cgroup 策略参数暴露给 Docker。启动 Docker 守护进程时,您需要显式设置驱动程序,因此无法同时运行这两个驱动程序。

以下是如何检查的示例:

[bash light=”true”] # 使用 LXC 驱动程序
$ docker run -d –name=’lxc_test’ \
–lxc-conf="lxc.cgroup.cpu.shares=50" \
busybox

# 使用 libcontainer 驱动程序
$ docker run -d –name=’libcontainer_test’ \
–cpu-shares=50 \
busybox
[/bash]

以下是一些 Cgroup 功能以及它们在两个驱动程序之间映射的概述:

功能 Libcontainer LXC
相对 CPU 份额 -c, –cpu-shares –lxc-conf=”lxc.cgroup.cpu.shares”
绑定到 CPU 核心 –cpuset-cpus –lxc-conf=”lxc.cgroup.cpuset.cpus”
限制内存 -m, –memory –lxc-conf=”lxc.cgroup.cpuset.mems”

LXC

如果您想在 Docker 中使用 LXC 驱动程序,首先需要启用它。具体方法因 Linux 发行版而异,但以下是关于如何在 Ubuntu 14.04 上启用 LXC 驱动程序.

如上所述,这样做会放弃许多功能。因此,除非您确实需要某个尚未在 Docker 中使用 libcontainer 公开的功能,否则您真的应该坚持使用默认驱动程序。

一些尚未在 libcontainer 中公开的有用 Cgroup 策略包括 I/O 限制(在演示文稿中有所提及),这对于某些应用程序非常方便。

如果您已决定使用 LXC 驱动程序,添加参数非常简单。您只需添加参数 --lxc-conf 并传入您想要设置的 Cgroup 策略。

Libcontainer

如上表所示,基本的 Cgroup 策略已在当前版本的 Docker(撰写本文时为 1.6)中公开。

使用这些策略非常简单。例如,如果您想将 Docker 容器锁定到第一个 CPU 核心,您可以将 --cpuset-cpus=0 追加到您的 docker run 命令中。

您还可以使用 --cgroup-parent 参数与 libcontainer 配合使用,并手动设置更细粒度的资源限制。然后,您可以使用该参数将其映射到该组。

演示:结合 Cgroups 使用 Docker

在下面的视频演示中,我们将使用两个 Docker 容器(‘low_prio’ 和 ‘high_prio’)。我们使用 ‘busybox’ 基础容器并运行 md5sum /dev/urandom 来模拟一个消耗大量 CPU 的进程。默认情况下,这将消耗所有可用的 CPU 资源。然而,我们将应用两个 Cgroup 策略来管理资源。首先,我们使用 ‘cpuset.cpus’ 将容器锁定到同一个 CPU 核心(核心 0)。

接下来,我们使用 ‘cpu.shares’ 来分配相对 CPU 份额。我们给 ‘low_prio’ 容器分配值 20,给 ‘high_prio’ 分配值 80。这意味着 20% 的 CPU 将分配给 ‘low_prio’ 容器,而 80% 的 CPU 将分配给 ‘high_prio’ 容器。但请注意,相对份额是一个任意比例(我们同样可以使用 2 和 8 作为值)。

在证明了资源管理确实有效之后,我们将在不使用任何 Cgroup 策略的情况下启动相同的一组容器,以观察它们的行为。

作为参考,以下是用于启动容器的命令。

[bash light=”true”] $ docker run -d \
–name=’low_prio’ \
–cpuset-cpus=0 \
–cpu-shares=20 \
busybox md5sum /dev/urandom
$ docker run -d \
–name=’high_prio’ \
–cpuset-cpus=0 \
–cpu-shares=80 \
busybox md5sum /dev/urandom
[/bash]

总结

如果您在同一台主机上管理多个 Docker 容器,那么使用 Cgroups 来管理容器之间的资源是非常有意义的。例如,您可能在一个容器中运行一些后台处理任务,而另一个容器则用于服务用户内容。在这种情况下,您可以使用新学到的知识,确保优先考虑面向用户的容器,而不是后台任务。

author

Viktor Petersson

作者 · CloudSigma

Preslav Dobrev 是 CloudSigma 的创意设计师,专注于通过传统和创新营销渠道打造一致的企业形象。他擅长将艺术愿景与战略营销相融合,创造具有影响力的品牌叙事。

评论

暂无评论。发表第一条评论吧。