上个月我在 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 来管理容器之间的资源是非常有意义的。例如,您可能在一个容器中运行一些后台处理任务,而另一个容器则用于服务用户内容。在这种情况下,您可以使用新学到的知识,确保优先考虑面向用户的容器,而不是后台任务。
评论
暂无评论。发表第一条评论吧。