使用cgroup管理资源限制
1、管理资源限制
1.1 使用ulimit限制系统资源
限制系统资源早期使用的方法是ulimit命令,设置的限制是系统范围的,并在登录和会话启动时由PAM模块进行验证并执行,ulimit命令是一个bash内置命令,用于限制shell及其子进程可用的资源,这个方法对于限制失控的资源使用是足够的,但对于处理资源争用是不够的。
1.2 配置持久化ulimit规则
使用ulimit交互式限制单个用户shell。pam_limits这个PAM模块在登录时设置POSIX资源限制。在默认的/etc/pam.d/system-auth文件中,有一个运行pam限制的会话调用。
此PAM模块在用户登录期间解析并应用/etc/security/limits.conf和/etc/security/limits.d/*.conf中的limit设置。
# 配置资源限制规则
[root@test01 ~]# cat /etc/security/limits.conf
# /etc/security/limits.conf
#
#This file sets the resource limits for the users logged in via PAM.
#It does not affect resource limits of the system services.
#
#Also note that configuration files in /etc/security/limits.d directory,
#which are read in alphabetical order, override the settings in this
#file in case the domain is the same or more specific.
#That means for example that setting a limit for wildcard domain here
#can be overriden with a wildcard setting in a config file in the
#subdirectory, but a user specific setting here can be overriden only
#with a user specific setting in the subdirectory.
#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>
#
#Where:
#<domain> can be:
# - a user name
# - a group name, with @group syntax
# - the wildcard *, for default entry
# - the wildcard %, can be also used with %group syntax,
# for maxlogin limit
#
#<type> can have the two values:
# - "soft" for enforcing the soft limits
# - "hard" for enforcing hard limits
#
#<item> can be one of the following:
# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open file descriptors
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit (KB)
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to values: [-20, 19]
# - rtprio - max realtime priority
#
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
# End of file
# 查看子配置文件目录,修改limit规则在该目录添加.conf结尾的配置文件即可
[root@test01 ~]# ls /etc/security/limits.d/
[root@test01 ~]#
例如:为了将manager组中的用户限制在最多三次同时登录,/etc/security/limits.d/managers.conf将包括以下设置:
[root@test01 ~]# echo "@managers hard maxlogins 3" > /etc/security/limits.d/managers.conf
[root@test01 ~]# cat /etc/security/limits.d/managers.conf
@managers hard maxlogins 3
1.3 软硬限制
前面的示例显示了硬限制的配置。您还可以配置软限制,该限制不应超过硬限制。这些软限制也得到了执行,用户不能超过它们。软限制和硬限制的区别在于,非根用户可以配置软限制,但只有具有根权限的用户才能修改硬限制。
用户类型 | 硬限制 | 软限制 |
普通用户 | 无法配置 或 具有权限的普通用户 | 可以配置 |
root用户 | 可以配置 | 可以配置 |
1.4 设置limits服务
POSIX限制也设置在systemd服务上,使用单元文件的[Service]块中的Limit*=XXX
# 例如,为了限制示例,服务在被杀死之前的CPU时间最多为30秒,将创建以下文件来定义限制
[root@test01 /etc/systemd/system/example.service.d]# cat 10-cpulimits.conf
[Service]
LimitCPU=30
[root@test01 /etc/systemd/system/example.service.d]# systemctl daemon-reload
# 使用重新加载systemd
2、 control groups介绍
control groups(cgroup)是用于精细控制资源的Linux内核机制。对于组,资源被放置在代表资源类型的控制器中;
类型 | 资源 |
cpu | cpu time |
Memory | memory usage |
blkio | disk I/O |
控制器可以细分,以树结构表示,与树枝和树叶相关的不同权重或限制,树枝和树叶是群。每个cgroup都有零个或多个与之相关的进程。默认情况下,资源在组中平均共享,但可以在子组上设置不同的限制和权重,只要它们不超过父组限制。除非明确覆盖,否则新组继承了在其父组上设置的限制。
2.1 cgroup和systemd
使用systemd守护进程管理cgroup是处理复杂资源配置的简单方法。默认情况下,systemd将cpu、cpuacct、blkio和memory的cgroups细分为三个等分的切片
systemd | Slices |
system | System service and daemons |
machine | Virtual machines and container |
user | User session |
以前版本的红帽企业Linux使用libcgroup-tools包中已弃用的cgconfig和cgred服务。缺省资源控制器现在使用systemd。为了避免冲突,只使用libcgroup工具来管理systemd目前不支持的控制器。
2.2 三个默认systemd切片
默认情况下会创建三个父切片。管理员可以创建额外的*.slice单元,具有它们自己的限制,并将服务分配给这些切片。
要将切片创建为另一个切片的子切片,请将它们命名为包含父名称、破折号和子名称的切片。
<parent>-<child>.slice
<parent>.slice
slice | 说明 |
system.slice | 默认情况下,systemd启动的所有服务都将放在这个片的新子组中。 |
user.slice | 在这个片中为每个登录到系统的用户创建一个新的子片,该用户的每个会话都将被放入该切片的新子切片中。 |
machine.slice | 由libirt管理的虚拟机会自动分配此切片的新子切片,在启动第一台虚拟机之前不会创建机器。Linux容器也放置在machine.slice 切片中。 |
2.3 检查cgroups
cgrouop检查工具 | 说明 |
systemd-cgtop | 交互式显示显示不同组的顶级概览,按名称、任务数量、CPU使用量、内存使用量或I/O活动排序 |
systemd-cgls | 输出所有slices、cgroup以及它们包含的进程的完整列表 |
除非CPU、内存或I/O计费为slice或cgroup打开,否则只报告cgroup中的任务数量,为某个服务启用计费功能可能会为同一片中的其他服务启用该功能。
# 使用systemd-cgtop交互式查看
[root@test01 ~]# systemd-cgls
Control group /:
-.slice
├─user.slice
│ └─user-0.slice
Control Group Tasks %CPU Memory Input/s Output/s
/ 200 - 1.6G - -
/init.scope 1 - 57.9M - -
/machine.slice - - 24.0K - -
/system.slice 84 - 1.2G - -
/system.slice/ModemManager.service 3 - 8.9M - -
/system.slice/NetworkManager.service 3 - 9.5M - -
/system.slice/atd.service 1 - 500.0K - -
/system.slice/auditd.service 4 - 11.4M - -
/system.slice/avahi-daemon.service 2 - 2.0M - -
/system.slice/boot.mount - - 56.0K - -
...
# systemd-cgls输出所有slices、cgroup以及它们包含的进程的完整列表
[root@test01 ~]# systemd-cgls
Control group /:
-.slice
├─user.slice
│ └─user-0.slice
│ ├─session-79.scope
│ │ ├─30501 sshd: root [priv]
│ │ ├─30506 sshd: root@pts/0
│ │ ├─30507 -bash
│ │ ├─30877 systemd-cgls
│ │ └─30878 less
│ └─[email protected]
│ ├─gvfs-daemon.service
│ │ ├─7403 /usr/libexec/gvfsd
│ │ └─7408 /usr/libexec/gvfsd-fuse /run/user/0/gvfs -f -o big_writes
│ ├─init.
│ │ ├─7177 /usr/lib/systemd/systemd --user
│ │ └─7180 (sd-pam)
│ └─dbus.service
│ └─7401 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
├─init.scope
│ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
└─system.slice
├─rngd.service
│ └─951 /sbin/rngd -f --fill-watermark=0
├─irqbalance.service
...
2.4 在运行时应用资源限制
使用systemctl set-property命令在运行时设置指定的单元属性。所支持的属性列表位于systemd .resource-control,更改立即应用并持久存储。
# 对程序使用内存做出限制(本次我拿SSHD服务为例)
[root@test01 ~]# systemctl set-property sshd.service MemoryAccounting=yes
[root@test01 ~]# systemctl set-property sshd.service MemoryLimit=2048M
# 进入/sys/fs/cgroup/memory/system.slice/程序名下查看
[root@test01 ~]# cat /sys/fs/cgroup/memory/system.slice/sshd.service/memory.limit_in_bytes
2147483648
# 使用命令查看限制
[root@test01 ~]# systemctl show -p MemoryAccounting sshd.service
MemoryAccounting=yes
[root@test01 ~]# systemctl show -p MemoryLimit sshd.service
MemoryLimit=2147483648
3、自定义cgroup
3.1 管理systemd cgroup设置
从RHEL7开始,通过将组层次结构系统与systemd单位树绑定,资源管理设置已从进程级移动到应用程序级别,systemctl提供systemd命令和服务单元文件,以简化和标准化系统资源管理控制。
- 开启cpu、内存或block I/O 服务切片
- 在单个服务或切片上设置资源限制
- 运行自定义服务切片
3.2 开启审计
在资源控制器中启用会计允许通过使用systemd-cgtop命令或查看组虚拟文件系统来观察资源使用的准确量。
# 设置CPU审计
CPUAccounting=true
# 设置内存审计
MemoryAccounting=true
# 设置块设备审计
BlockIOAccounting=true
将这些设置添加到单元的一个简单方法是使用drop-in文件。drop-in文件可以通过在/etc/systemd/system/下创建一个目录来配置,该目录以要配置的附加.d的单元命名。
# 例如,sshd的下拉目录。服务将是/etc/systemd/system/sshd.service.d/,添加一个20-accounting.conf审计功能配置文件
[root@test01 ~]# mkdir /etc/systemd/system/sshd.service.d/
# 开启内存审计
[root@test01 ~]# cat > /etc/systemd/system/sshd.service.d/20-accounting.conf <<END
[Service]
MemoryAccounting=true
END
[root@test01 ~]# cat /etc/systemd/system/sshd.service.d/20-accounting.conf
[Service]
MemoryAccounting=true
# 重新加载systemd
[root@test01 ~]# systemctl daemon-reload
# 重启服务
[root@test01 ~]# systemctl restart sshd
[root@test01 ~]# systemctl cat sshd | grep 20-accounting.conf -A 2
# /etc/systemd/system/sshd.service.d/20-accounting.conf
[Service]
MemoryAccounting=true
3.3 实施限制
用于控制资源使用的机制称为强制限制,创建限制的方式与启用记帐的方式相同,即将相关的systemd指令放置在单元插入文件中。
limits | 说明 |
CPUShares | 为CPU设置单独的权重(CPU是共享的) |
CPUQuota | 为CPU指定使用时间的配额,百分比说明在最大负载下可以使用多少时间CPU |
MemoryLimit | 用于设置本单元中进程或任务使用的内核内存的硬限制,可以指定限制的单位(K,M,G,T) |
BlockIO* | 块I/O可以使用相对权重、每个设备的相对权重或通过指定每个设备的最大读写带宽来限制 |
[Unit]
Description=Example Custom Slice
[Slice]
CPUShares=2048
MemoryAccounting=true
4、cgroup v2介绍
RHEL8包含cgroups v2作为技术预览。Linux社区开始使用cgroups v2来改进cgroups v1所完成的工作,并为资源管理引入更直接的层次结构。
4.1 cgroup层次结构
层次结构是每个控制组实现中的关键设计点。这是建议从libcgroups切换到systemd的主要原因。
在新的cgroups v2中,层次结构是简化资源管理的主要特性,并消除了由于跨多个cgroup控制器的资源条目重复造成的混乱。
cgroups v1中的层次结构具有与资源控制器相关联的cgroups。Cgroups v1挂载资源控制器,Cgroups是在控制器层次结构中创建的。在上图中,web cgroup在内存和blkio资源控制器中有一个重复的层次结构条目。同样的情况也发生在具有重复条目的dbase cgroup上,但是位于内存和pid资源控制器中。
cgroups v2中的层次结构具有与cgroups相关联的控制器。Cgroups v2创建了Cgroups,然后通过cgroup将所需的控制器合并到Cgroups中。subtree_control文件。在上图中,web和dbase cgroup只存在一次,它们在cgroup中列出了相关的资源控制器。subtree_control文件。
4.2 cgroup v2注意事项
- cgroup v2为所有资源控制器提供了一个单一的control group层次结构
- 不能同时挂载cgroup v1和cgroup v2
- 启用cgroup v2需要添加systemd.unified_cgroup_hierarchy=1
- cgroup v2目前只包含CPU、IO、内存、RDMA、PID
- cgrpu v1仍然是RHEL8的默认版本
- v1版本的blkio被v2的io取代
- CPUShares、MemoryLimit、BlockIOWeight被替换成CPUWeight、MemoryMax、IOWeight