Linux使用cgroups约束程序可使用的资源

cgroups(控制组)

cgroups 是 Linux 内核提供的一种资源管理机制,可以用于限制进程组(包括单个进程或一组相关进程)的资源使用。通过创建和配置相应的 cgroup,可以限制程序可使用的内存量。
在Linux环境中,cgroup(控制组)是一种用来限制、记录和隔离进程组所使用的物理资源(如CPU、内存、磁盘I/O等)的机制。


cgrouops目录

https://blog.csdn.net/yuelai_217/article/details/131332809


/sys/fs/cgroup/cpu目录下的文件解释

这些是与 CPU 控制组 (cgroup) CPU 资源使用和配置相关的文件和目录。
这些文件和目录提供了对 CPU 控制组的配置和监控。可以使用这些文件来设置 CPU 资源分享、限制 CPU 使用时间、查看 CPU 使用统计信息等。根据实际需求和系统配置,操作这些文件来管理和控制 CPU 资源的分配和使用。
下面是对其中一些文件和目录的解释:

文件名 解释
cpuacct.usage : 显示 CPU 控制组中所有进程的累计 CPU 使用时间。
cpu.shares : 用于设置 CPU 资源分享权重,值越高表示分配的 CPU 资源越多。
cgroup.clone_children : 控制是否在创建新的控制组时自动克隆父控制组的配置。
cpuacct.usage_percpu : 显示每个 CPU 核心的 CPU 使用时间。
cpu.stat : 提供有关 CPU 使用情况的统计信息,如用户态时间、内核态时间等。
cgroup.event_control : 用于控制和监控 cgroup 的事件。
cgroup.procs : 显示属于该 cgroup 的所有进程的进程 ID。
cgroup.sane_behavior : 控制组的行为设置,用于启用或禁用特定行为。
cpuacct.stat : 提供有关 CPU 使用的统计信息,例如用户态时间、内核态时间等。
cpu.cfs_period_us : 配置 CPU 使用时间片的周期,单位为微秒。
cpu.cfs_quota_us : 配置 CPU 使用时间片的配额,单位为微秒。
notify_on_release : 控制在释放 cgroup 时是否发送通知。
release_agent : 设置释放 cgroup 时要运行的命令或脚本。
system.slice : 默认的系统级控制组。
tasks : 包含属于该 cgroup 的所有进程的进程 ID。

/sys/fs/cgroup/memory目录下的文件解释

/sys/fs/cgroup/memory是与内存控制组 (cgroup) 相关的文件和目录。它们提供了有关内存资源使用和配置的信息。下面是对其中一些文件和目录的解释:

cgroup.clone_children 控制是否在创建新的控制组时自动克隆父控制组的配置。
cgroup.event_control 用于控制和监控 cgroup 的事件。
cgroup.procs 显示属于该 cgroup 的所有进程的进程 ID。
cgroup.sane_behavior 控制组的行为设置,用于启用或禁用特定行为。
memory.failcnt 发生内存资源超限的次数。
memory.force_empty 强制清空内存控制组中的所有缓存。
memory.kmem.failcnt 发生内核内存资源超限的次数。
memory.kmem.limit_in_bytes 配置内核内存使用的限制,以字节为单位。
memory.kmem.max_usage_in_bytes 内核内存使用的最大值,以字节为单位。
memory.kmem.slabinfo 提供有关内核内存使用的详细信息。
memory.kmem.tcp.failcnt 发生针对 TCP 使用的内核内存超限的次数
memory.kmem.tcp.limit_in_bytes 配置针对 TCP 使用的内核内存的限制,以字节为单位。
memory.kmem.tcp.max_usage_in_bytes 针对 TCP 使用的内核内存的最大值,以字节为单位。
memory.kmem.tcp.usage_in_bytes 针对 TCP 使用的内核内存的当前使用量,以字节为单位。
memory.kmem.usage_in_bytes 内核内存的当前使用量,以字节为单位。
memory.limit_in_bytes 配置内存使用的限制,包括文件缓存和应用程序内存,以字节为单位。
memory.max_usage_in_bytes 内存使用的最大值,包括文件缓存和应用程序内存,以字节为单位。
memory.move_charge_at_immigrate 控制在迁移进程时是否转移内存使用量。
memory.numa_stat 提供有关 NUMA(非一致性存储访问)的内存统计信息。
memory.oom_control 控制内存超限时的 OOM (Out of Memory) 行为。
memory.pressure_level 提供有关内存压力级别的信息。
memory.soft_limit_in_bytes 配置软限制内存使用的限制,以字节为单位。
memory.stat 提供有关内存使用的统计信息,如分配的页面数、缓存页面数等。
memory.swappiness 控制内存页交换的倾向性。
memory.usage_in_bytes 当前内存使用量,包括文件缓存和应用程序内存,以字节为单位。
memory.use_hierarchy 控制是否使用层次结构来跟踪内存使用。
notify_on_release 控制在释放 cgroup 时是否发送通知。
release_agent 设置释放 cgroup 时要运行的命令或脚本。
system.slice 默认的系统级控制组。
tasks 包含属于该 cgroup 的所有进程的进程 ID。

cgconfig服务

cgconfig 是一个用于管理控制组 (cgroup) 的服务。它负责加载和应用控制组的配置文件,并创建、管理和监控相应的控制组层次结构。
当启用 cgconfig 服务时,它会在系统启动时自动加载并读取指定位置的配置文件(例如 /etc/cgconfig.conf 或 /etc/cgconfig.d/ 目录下的配置文件)。这些配置文件定义了控制组的层次结构、资源限制和权限设置等规则。

# 开机启动cgconfig服务
systemctl enable --now cgconfig

配置文件–持久化配置cgroups

  1. 配置文件的持久性:
    1. 配置文件是一种持久性配置,它定义了控制组的配置规则,可以在系统启动时自动加载。一旦配置文件被定义和保存,控制组的配置将保持不变,除非显式地修改配置文件或删除控制组。
    2. 相比之下,手动使用 cgroup 命令指定参数是一次性的,仅在执行命令时生效,不会持久保存。
  2. 可读性和易管理性:
    1. 配置文件提供了一种结构化和易于管理的方式来定义控制组的配置。通过配置文件,可以将相关的控制组配置集中在一个文件中,便于查阅、修改和维护。
    2. 而手动使用 cgroup 命令指定参数则需要在每次执行命令时提供详细的参数,不如配置文件直观和便捷。
  3. 批量配置和一致性:
    1. 配置文件允许批量定义多个控制组及其相关的资源限制,可以一次性配置整个系统中的多个控制组。这样可以确保一致的资源管理策略应用于相关的进程组。
    2. 相比之下,手动使用 cgroup 命令指定参数需要逐个指定控制组和其对应的参数,可能更加繁琐和容易出错。

示例配置1如下:

vim /etc/cgconfig.d/PostgreSQL.conf

## 定义需要创建的cgroup子系统及其挂载点,这里创建cpu与cpuacct(统计)两个cgroup子系统
mount {
    
    
	cpu = /mnt/cgroups/cpu;
	cpuacct = /mnt/cgroups/cpu;
}

## 定义db_cage(数据库服务器进程)组
group db_cage {
    
    
    # 用户和组 "postgres" 可以管理这些 cgroup
    perm {
    
    
        task {
    
    
            # 指定 UID 为 postgres
            uid = postgres;  
            # 指定 GID 为 postgres
            gid = postgres;  
            # 设置文件权限为 774
            fperm = 774;     
        }
        admin {
    
    
            # 指定 UID 为 postgres
            uid = postgres;  
            # 指定 GID 为 postgres
            gid = postgres;  
            # 设置目录权限为 775
            dperm = 775;    
            # 设置文件权限为 774 
            fperm = 774;     
        }
    }
 
    # 限制内存为 1GB 并禁用交换分区
    memory {
    
    
        # 限制内存使用为 1GB
        memory.limit_in_bytes = 1G;   
        # 限制总内存(包括交换分区)使用为 1GB
        memory.memsw.limit_in_bytes = 1G;  
    }
    
    # 限制设备 8:0 的读取和写入 I/O 速度为每秒 10MB
    blkio {
    
    
        # 限制读取速度为 10MB/s
        blkio.throttle.read_bps_device = "8:0 10485760";  
        # 限制写入速度为 10MB/s
        blkio.throttle.write_bps_device = "8:0 10485760";  
    }
    
    # 将 CPU 时间限制为每秒钟的 0.25 秒
    cpu {
    
    
        # 设置 CPU 周期为 1 秒
        cpu.cfs_period_us = 1000000;  
        # 设置 CPU 配额为 0.25 秒
        cpu.cfs_quota_us = 250000;    
    }
    
    # 只允许使用 CPU 0-3 和内存节点 0
    cpuset {
    
    
        # 指定可使用的 CPU 为 0-3
        cpuset.cpus = 0-3; 
        # 指定可使用的内存节点为 0 
        cpuset.mems = 0;   
    }
}

示例配置2如下:

https://developer.aliyun.com/article/43544

## 定义需要创建的cgroup子系统及其挂载点,这里创建cpu与cpuacct(统计)两个cgroup子系统
mount {
    
    
	cpu = /mnt/cgroups/cpu     ;
	cpuacct = /mnt/cgroups/cpu ;
	}

## 定义daemons/www(web服务器进程)组
group daemons/www {
    
    
	## 定义这个组的权限
	perm {
    
    
		task {
    
    
			uid = root       ;
			gid = webmaster  ;
			}
		admin {
    
    
		uid = root          ;
		gid = root          ;
			}
		}
		## 定义cpu子系统的属性及CPU资源分享权重值,即属于此组的任务的权重为1000
		cpu {
    
    
			cpu.shares = 1000  ;
			}

					}

## 定义daemons/ftp(ftp进程)组
group daemons/ftp {
    
    
	perm {
    
    
		task {
    
    
			uid = root       ;
			gid = ftpmaster  ;
			}
		admin {
    
    
		uid = root        ;
		gid = root        ;
			}
		}

		## 定义cpu子系统的属性及CPU资源分享权重值,即属于此组的任务的权重为1000为500
		cpu {
    
    
			cpu.shares = 500 ;
			}
					}

上面配置文件定义相当于执行了如下shell命令

# 创建一个名为 /mnt/cgroups/cpu 的目录,用于挂载 CPU 控制组。
mkdir /mnt/cgroups/cpu

# 将 CPU 控制组挂载到 /mnt/cgroups/cpu 目录,使其可用。
mount -t cgroup -o cpu,cpuacct cpu /mnt/cgroups/cpu

# 在 /mnt/cgroups/cpu 目录下创建一个名为 daemons 的子目录,用于组织 CPU 控制组。
mkdir /mnt/cgroups/cpu/daemons

# 在 /mnt/cgroups/cpu/daemons 目录下创建一个名为 www 的子目录,用于表示名为 www 的进程组。
mkdir /mnt/cgroups/cpu/daemons/www

# 将 /mnt/cgroups/cpu/daemons/www 目录下的所有文件的所有者和所属组设置为 root。
chown root:root /mnt/cgroups/cpu/daemons/www/*

# 将 /mnt/cgroups/cpu/daemons/www/tasks 文件的所有者设置为 root,所属组设置为 webmaster。
chown root:webmaster /mnt/cgroups/cpu/daemons/www/tasks

# 将 /mnt/cgroups/cpu/daemons/www/cpu.shares 文件中的内容设置为 1000,这是用来设置 CPU 资源分享权重的值。
echo 1000 >/mnt/cgroups/cpu/daemons/www/cpu.shares

# 在 /mnt/cgroups/cpu/daemons 目录下创建一个名为 ftp 的子目录,用于表示名为 ftp 的进程组。
mkdir /mnt/cgroups/cpu/daemons/ftp

# 将 /mnt/cgroups/cpu/daemons/ftp 目录下的所有文件的所有者和所属组设置为 root。
chown root:root /mnt/cgroups/cpu/daemons/ftp/*

# 将 /mnt/cgroups/cpu/daemons/ftp/tasks 文件的所有者设置为 root,所属组设置为 ftpmaster。
chown root:ftpmaster /mnt/cgroups/cpu/daemons/ftp/tasks

# 将 /mnt/cgroups/cpu/daemons/ftp/cpu.shares 文件中的内容设置为 500,这是用来设置 CPU 资源分享权重的值。
echo 500 >/mnt/cgroups/cpu/daemons/ftp/cpu.shares

cgroup常用命令

常用的cgroup工具命令:

  • cgcreate - 创建cgroup
  • cgdelete - 删除cgroup
  • cgexec - 在cgroup中执行命令
  • cgclassify - 将进程移动到cgroup
  • cgget - 获取cgroup参数
  • cgset - 设置cgroup参数

请注意,这些方法仅限制程序在用户空间中使用的内存,而不包括内核占用的内存。另外,这些方法都需要适当的权限来设置和管理资源限制。确保您具有足够的权限,并了解如何正确应用这些限制。
首先,需要确保系统已安装并配置了 cgroups。然后,可以使用工具如 cgcreatecgsetcgexec 来创建和管理 cgroups

以下是一些示例


1.创建cgroup

# 创建 cgroup
cgcreate -g <subsystem>:/<cgroup_name>
# 等同于在cgroup目录下手动创建目录
mkdir /sys/fs/cgroup/<subsystem>/<cgroup_name>

创建约束内存的cgroup进程组

# 创建一个限制内存的cgroup:
cgcreate -g memory:/app1
# 等同于在memory目录下创建app1目录
mkdir -p /sys/fs/cgroup/memory/app1

创建约束CPU的cgroup进程组

# 创建一个限制CPU的cgroup:
cgcreate -g cpu:/app1
# 等同于在cpu目录下创建app1目录
mkdir -p /sys/fs/cgroup/cpu/app1

2.将进程移动到cgroup

使用app1这个cgroup进程组限制名为 my_app 的程序及其子进程。

# 将进程加入cgroup
cgclassify -g <subsystem><cgroup进程组> <pid>

# 将一个进程添加到cgroup:
cgclassify -g cpu:demo pid编号
# 等同于将PID写入到该文件中
echo $$ > /sys/fs/cgroup/cpu/demo/tasks

# 将my_app程序运行在app1这个cgroup 中:
cgexec -g memory:app1 my_app

3.设置cgroup参数进行资源限制


限制memorpy

限制一个进程组的内存使用量为 1GB:

# 设置内存限制为 1GB:
cgset -r memory.limit_in_bytes=1G app1

限制CPU

# 设置cgroup的cpu限制:
## 1000表示该程序只能使用1%的CPU
cgset -r cpu.cfs_quota_us=1000 app1

# 等同于将1000写入该文件
echo 1000 > /sys/fs/cgroup/cpu/app1/cpu.cfs_quota_us

4.获取cgroup参数

# 查看cgroup的cpu使用情况:
## -r cpu.stat 指定要查询的资源参数为 cpu.stat,即 CPU 统计信息。
cgget -r cpu.stat app1

# 查看cgroup的cpu使用情况:
cat /sys/fs/cgroup/cpu/app1/cpu.stat

# 查看 cgroup 的使用情况
## -g <cgroup_path> 指定要执行命令的控制组路径
## -l 显示执行命令时的资源限制信息
cgexec -g <cgroup_path> -l

5.删除cgroup进程组

# 删除app1这个cgroup
cgdelete -g memory:/app1

# 等同于删除cgroup的指定目录--不可执行
rmdir /sys/fs/cgroup/<subsystem>/<cgroup_name>

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/omaidb/article/details/132432845