Linux虚拟化:如何使用cgroup进行资源限制?

2021年3月18日16:23:42 发表评论 1,056 次浏览

InLinux虚拟化– Chroot监狱文章中, 我们讨论了内核名称空间和进程监视。要理解本文, 你可能不需要阅读之前的文章, 但是我强烈建议你在进入资源限制之前先阅读一下。它应该有助于极大地了解正在发生的事情。

什么是cgroup

cgroups(控制组的缩写)是一种Linux内核功能, 可限制, 说明和隔离进程集合的资源使用情况(CPU, 内存, 磁盘I / O, 网络等)。

此功能最初由Google的2位工程师开发, 名称为" process container", 但后来在Linux内核主线中合并为" cgroups"。

为什么需要它?

cgroup的设计目标之一是为许多不同的用例提供统一的界面, 从控制单个进程(例如, 使用漂亮的程序)到整个操作系统级虚拟化。简单来说, cgroups提供:

  • 资源限制:可以将组设置为不超过配置的内存限制, 该限制还包括文件系统缓存。
  • 优先次序–某些组可能会在CPU利用率或磁盘I / O吞吐量中获得更大份额。
  • 会计–衡量组的资源使用情况, 例如可用于计费目的。
  • 控制 -冻结进程组, 检查点并重新启动。

如何直接或间接使用它们?

控制组可以通过多种方式使用:

  1. 通过手动访问cgroup虚拟文件系统。
  2. 通过使用cgcreate, cgexec和cgclassify(来自libcgroup)之类的工具动态创建和管理组。
  3. 通过"规则引擎守护程序", 该守护程序可以按照配置中的指定自动将某些用户, 组或命令的进程移至cgroup。
  4. 通过其他使用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的工作方式。 (最重要的部分在图像中突出显示)

linux虚拟化

第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 *时, 我可以得到主要的, 次要的编号。

linuxvirtualzation2

高亮显示的值是我的/ 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"。最高端的速率应与此类似。

linuxvirtualzation3

有趣的是, 我们可以采用任何没有内置速率限制的应用程序, 可以根据需要对其进行限制。

linuxvirtualzation4

上图是在读取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
linuxvirtualzation5

交换状态必须与以上所示类似。

$ 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上撰写访客博客。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: