InLinux虚拟化– Chroot监狱文章中, 我们讨论了内核名称空间和进程监视。要理解本文, 你可能不需要阅读之前的文章, 但是我强烈建议你在进入资源限制之前先阅读一下。它应该有助于极大地了解正在发生的事情。
什么是cgroup?
cgroups(控制组的缩写)是一种Linux内核功能, 可限制, 说明和隔离进程集合的资源使用情况(CPU, 内存, 磁盘I / O, 网络等)。
此功能最初由Google的2位工程师开发, 名称为" process container", 但后来在Linux内核主线中合并为" cgroups"。
为什么需要它?
cgroup的设计目标之一是为许多不同的用例提供统一的界面, 从控制单个进程(例如, 使用漂亮的程序)到整个操作系统级虚拟化。简单来说, cgroups提供:
- 资源限制:可以将组设置为不超过配置的内存限制, 该限制还包括文件系统缓存。
- 优先次序–某些组可能会在CPU利用率或磁盘I / O吞吐量中获得更大份额。
- 会计–衡量组的资源使用情况, 例如可用于计费目的。
- 控制 -冻结进程组, 检查点并重新启动。
如何直接或间接使用它们?
控制组可以通过多种方式使用:
- 通过手动访问cgroup虚拟文件系统。
- 通过使用cgcreate, cgexec和cgclassify(来自libcgroup)之类的工具动态创建和管理组。
- 通过"规则引擎守护程序", 该守护程序可以按照配置中的指定自动将某些用户, 组或命令的进程移至cgroup。
- 通过其他使用cgroup的软件间接实现, 例如Docker, Linux容器(LXC)虚拟化, libvirt, systemd, Open Grid Scheduler / Grid Engine和Google的lmctfy。
你可能会感到惊讶, 但是这个无声的守护进程构成了你在线体验的重要部分, 因为很多网站都使用容器/虚拟化来托管多个服务器或网站, 包括NetFlix, heruko和reddit。
安装cgroup:一些Linux版本预装有cgroups。要检查它们是否已经安装/安装, 请检查以下输出:
$ mount | grep "^cgroup"
如果看到文件挂载在/ sys / fs / cgroup /上, 则可以直接跳至下一个主题以跳过安装部分。
第二个命令安装了cgroup-tools, 它使控制和监视控制组更加容易。在本教程中, 我们将使用相同的命令。我们将使用iotop实用程序来监视磁盘I / O速率。
$ sudo apt-get install cgroup-bin cgroup-lite libcgroup1 cgroup-lite
$ sudo apt-get install cgroup-tools
$ sudo apt-get install iotop
如果你安装了cgroup, 但无法在/ sys / fs / cgroup上看到它们, 请使用以下命令,
$ mount -t tmpfs cgroup_root /sys/fs/cgroup
$ mkdir /sys/fs/cgroup/blkio
$ mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
范例1:我们将创建一个磁盘控制的组, 以便我们可以使用有限数量的可用磁盘读/写来运行任何进程。即我们要限制一个或一组进程完成的读写操作。
第1步:要创建cgroup, 只需在/ sys / fs / cgroup中创建一个目录, 或者如果你具有cgroup-tools设置, 则可以在子系统的适当目录中使用它们。内核会自动使用设置文件节点填充cgroup的目录。不过, 建议使用cgroup-tools API,
# Switch to root for the rest of the commands
$ sudo su
$ cgcreate -g blkio:myapp OR mkdir /sys/fs/cgroup/blkio/myapp
此命令将在" blkio"系统下创建一个子组" myapp"。块I / O(blkio)子系统控制和监视cgroup中任务对块设备上I / O的访问。将值写入这些文件可提供对各种资源的受控访问。你可以通过运行命令lscgroup来检查是否创建了组, 该命令列出了所有控制组。
$ lscgroup | grep blkio:/myapp
blkio:/myapp
重要:这些文件不是磁盘上的普通文件。这些是伪文件, 内核直接使用它们读取和修改配置。不要在文本编辑器中打开它们并尝试保存它们。始终使用" echo"命令对其进行写入。
在讨论简单的东西之前, 让我们看一下新创建的组的目录结构。这是本教程需要的一些重要文件, 以了解cgroup的工作方式。 (最重要的部分在图像中突出显示)
第2步:我们创建2个终端, 并将它们一个放在另一个下面。成为两个终端中的root用户。在顶级终端中, 我们运行iotop实用程序以监视磁盘I / O,
$ sudo su
$ iotop -o
在下面的终端上, 我们使用" dd"命令创建一个512 MB的临时文件
$ sudo su
$ dd if=/dev/zero of=~/test_if bs=1M count=512
在dd命令中, " if"表示输入文件, " of"是输出文件, " bs"是块大小, " count"是写入块的次数。命令完成后, 〜/ temp_if创建的大小为512 MB。你可以在顶部终端窗口中看到实时I / O速率。
第三步:现在, 对于下一个实验, 我们需要确保已将所有文件系统缓冲区刷新到磁盘, 并删除了所有缓存, 以免它们干扰我们的结果。
$ free -m
$ sync
$ echo 3 > /proc/sys/vm/drop_caches
$ free -m
现在, 你应该看到可用RAM的增加和缓存大小的减少。
第三步:现在设置节流限制, 我们使用以下命令。假设我们要为一个进程设置5 MB的读/写限制。从内核文档中, 你会发现blkio.throttle.read_bps_device和blkio.throttle.write_bps_device接受以下格式的条目:
<主要>:<次要> <每秒速率>
其中重大的和次要是特定设备的值, 我们要对其进行限速。rates_per_second是该组流程可以达到的最大速率。
获取主要和次要数字很容易。我正在使用的机器只有一个磁盘/ dev / sda, 因此在运行命令ls -l / dev / sda *时, 我可以得到主要的, 次要的编号。
高亮显示的值是我的/ dev / sda磁盘的主要和次要数字。
现在, 我们写入以下值以将读取速率限制为5 Mb / sec
$ echo "8:0 5242880" > /sys/fs/cgroup/blkio/myapp/blkio.throttle.read_bps_device
$ cat /sys/fs/cgroup/blkip/myapp/blkio.throttle.read_bps_device
在运行受控过程之前, 我们必须对读取速度有所了解, 而不会进行任何限制。通过在底部终端中运行此命令, 读取我们先前创建的文件。
$ dd if=~/test_if of=/dev/null
步骤5:你可以在顶端查看实时读取率。文件创建完成后, 你还可以看到dd命令显示的平均速率。如前所述, 将数据刷新到磁盘并删除所有缓存, 以避免结果含糊不清。
为了在节流下运行此命令, 我们使用cgexec
$ cgexec -g blkio:/myapp dd if=~/test_if of=/dev/null
我们在-g参数中提供:名称, 在本例中为" blkio:myapp"。最高端的速率应与此类似。
有趣的是, 我们可以采用任何没有内置速率限制的应用程序, 可以根据需要对其进行限制。
上图是在读取2个文件的过程中绘制的, 这些文件的进程属于同一cgroup, 读取的油门限制为50 Mb / sec。正如你最初看到的那样, 读取速率跃升至最大值, 但是一旦第二次读取开始, 它便达到了平衡, 总速度达到了预期的50MB / s。一旦" file-abc"的读取结束, 速率就会跳升以再次达到最大值。
你可以通过在节气门文件。内核将自动更新配置。
范例2:我们遵循类似的步骤来创建受内存限制的应用程序。由于大多数解释都是相同的, 因此我将省略其解释, 而直接跳转到命令。
第1步 :我创建了一个简单的C程序, 该程序在每次迭代中分配1MB的内存, 并总共运行50次迭代, 总共分配50 MB的内存。
// a simple c-program that allocates 1MB in each
// iteration and run for a total of 50 iterations, // allocating a total of 50 MB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int i;
char *p;
for (i = 0; i < 50; ++i)
{
// Allocate 1 MB each time.
if ((p = malloc(1<<20)) == NULL)
{
printf("Malloc failed at %d MB\n", i);
return 0;
}
memset(p, 0, (1<<20));
printf("Allocated %d to %d MB\n", i, i+1);
}
printf("Done!\n");
return 0;
}
$ sudo su # Switch to root for the rest of the comands
$ cgcreate -g memory:myapp_mem OR mkdir /sys/fs/cgroup/memory/myapp_mem
$ cd /sys/fs/cgroup/memory/myapp_mem
$ lscgroup # To check if the group was created successfully.
现在, 可以从内核文档中获取限制内存配置的格式。(参考链接)
$ echo "5242880" > memory.limit_in_bytes
在运行代码之前, 我们需要禁用交换。如果程序无法从RAM获取内存(由于我们的限制), 它将尝试在交换时分配内存, 这在我们的情况下是不希望的。
$ sudo swapoff -a # Disable swap
交换状态必须与以上所示类似。
$ gcc mem_limit.c -o mem_limit
首先, 运行没有任何内存限制的代码,
$ ./mem_limit
现在, 比较从受控cgroup中运行时的输出,
$ cgexec -g memory:myapp_mem /root/mem_limit
你可以从中检查各种资源计费信息, 例如当前内存使用情况, 已使用的最大内存, 内存限制等,
$ cat memory.usage_in_bytes
$ cat memory.max_usage_in_bytes
$ cat memory.limit_in_bytes
你可以探索更多参数, 例如memory.failcnt, memory.kmem。*和memory.kmem.tcp。*。
你阅读文档越多, 你的理解就会越好。
我们可以扩展此方法并创建受限制的应用程序。该方法是很久以前创建的, 但是最近它已被广泛用于许多应用程序中。虚拟机, 容器等使用它来实施资源限制。
了解cgroup的目的是了解如何在容器中实际进行资源限制。下一个要探讨的主题是容器。我们将在下一篇文章中详细讨论。
参考文献:
- https://www.kernel.org/doc/Documentation/cgroup-v1/
- https://www.kernel.org/doc/Documentation/cgroup-v1/blkio-controller.txt
- https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/ch-Subsystems_and_Tunable_Parameters.html
- https://lwn.net/Articles/604609/
- https://help.ubuntu.com/lts/serverguide/cgroups.html
- https://www.youtube.com/watch?v=sK5i-N34im8码头工人团队的精彩演讲。该视频将充当本文和下一篇文章之间的桥梁。我将在下一篇文章的开头再次提及。在了解名称空间和cgroup时非常方便。
关于作者:
Pinkesh Badjatiya
来自海得拉巴IIIT的冰雹。他是一个极富建议心的极客。可见他的项目工作
这里。
如果你还希望在此处展示你的博客, 请参阅
日志
用于在lsbin上撰写访客博客。