资源管理之CPU管控
1、cpu管控能力简介
cpu作为数据库资源的重要成员,GaussDB(DWS)应用cgroup实现了CPU管控,cgroup全称control group,是linux内核提供的用于对进程/线程使用的资源进行隔离、管控以及记录的组件,主要包含cpu、IO、内存相关子系统。其技术原理详见GaussDB(DWS)的CPU资源隔离管控能力-云社区-华为云 (huaweicloud.com)。
目前GaussDB基于cpu.shares实现cpu的共享配额(业务繁忙cpu满负载情况下,控制组之间按照配额比例进行cpu时间片)和基于cpuset.cpus实现的专属限额(只能使用限额配置的cpu资源,不能抢占其他控制组空闲的cpu资源)能力,其中限额只限制自己,不限额别人。配额与限额可同时设置。
2、GaussDB的cgroup管控层级
GaussDB(DWS)的cpu管控需要考虑其他进程与GaussDB(DWS)之间的cpu管控,GaussDB(DWS)内核后台线程与用户线程之间的cpu管控,用户之间的cpu管控。为了应对不同层级的cpu隔离管控需求,GaussDB(DWS)设计了基于cgroup层级特点的cpu分层隔离管控,GaussDB(DWS)的cgroup层级模型如下图所示:
以上cgroup均适配了cpu子系统和cpuset子系统,每一个cgroup都包含两个值:cpu.shares和cpuset.cpus。GaussDB(DWS)借助cgroup提供了三个维度的cpu隔离管控能力:
- GaussDB(DWS)与其他进程之间的隔离管控
- 数据库常驻后台线程与作业线程的隔离管控
- 数据库用户之间的隔离管控
GaussDB与其他进程之间的隔离管控
数据库集群的每个节点在cgroup的cpu子系统和cpuset子系统内均包含一个专属目录:“GaussDB:gaussdba”,作为GaussDB(DWS)的主cgroup节点(目录),用于限制和记录GaussDB(DWS)内所有线程使用的cpu,GaussDB(DWS)进程内所有线程均直接或间接的受到该cgroup的限制。通过限制GaussDB(DWS)内核使用的cpu,可防止数据库系统对其他应用程序造成影响。
数据库常驻后台线程与作业线程的隔离管控
GaussDB(DWS)主cgroup节点之下包含两个cgroup:Backend控制组和Class控制组。Backend控制组用于GaussDB(DWS)常驻后台线程的cpu隔离管控,Class控制组用于作业线程的cpu隔离管控。大部分后台常驻线程cpu资源占用较少,但AutoVacuum线程cpu资源占用可能较多,因此在Backend控制组单独提供Vacuum控制组用于AutoVaccum线程的cpu资源限制,而除AutoVacuum之外的其他后台常驻线程均受到DefaultBackend控制组的cpu资源限制。
数据库用户之间的隔离管控
通常情况下数据库系统会同时运行多种类型的作业,不同类型作业之间可能出现cpu资源争抢。GaussDB(DWS)资源管理为用户提供了双层的cgroup层级结构用于cpu隔离管控,用户可按需创建和修改cgroup配置实现不同类型作业之间的cpu资源限制。用户双层cgroup包含以下控制组:
- UserClass控制组:用户创建的父控制组,主要实现cpu资源的初步划分,如:不同的父控制组可以属于不同的部门/分公司
- RemainWD控制组:包含UserClass控制组创建UserWD控制组后剩余的cpu资源
- Timeshare控制组:创建UserClass控制组时默认创建的优先级控制组,包含四个优先级的控制组:Rush:High:Medium:Low,资源配比为:8:4:2:1
- UserWD控制组:用户创建的子控制组,在父控制组基础上实现cpu资源的细粒度划分,如:不同的子控制组可以属于同一部门下的不同类型作业
3、gs_cgroup工具及相关命令操作
1. 设置GaussDB进程可以使用的cpu范围
gs_cgroup -u -T Gaussdb -f 0-178
2. 设置顶层Class控制组占Gaussdb总CPU核资源的70%
gs_cgroup -u -T Class -t 70 --fixed
3. 创建Class控制组和Workload控制组
gs_cgroup -c -S ClassG -N ngName
gs_cgroup -c -S ClassG -G wg1 -N ngName
说明:
- 非逻辑模式下,不需要指定-N ngname,也不需要创建为逻辑集群创建cgroup。
-
默认Class控制组的CPU配额设置为20%,各Class控制组p配置之和可达到100%。
-
默认Workload控制组CPU配额设置为20%。各Workload控制组配额之和应小于99%(由于在Class控制组下面有默认timeshare控制组,在设计之初,为此预留了1%的CPU配额资源,此时可把99%看成100%)。
4. 修改Class控制组和Workload控制组CPU配额权重
gs_cgroup -u -S ClassG -s 40 -N ngName
gs_cgroup -u -S ClassG -G wg1 -g 40 -N ngName
说明:修改Class控制组cpu配额比例时,使用"-s"参数,修改Workload控制组cpu配额比例时,使用"-g"参数。
5.修改Class控制组和Workload控制组CPU限额权重
gs_cgroup -u -S ClassG -s 50 --fixed -N ngName
gs_cgroup -u -S ClassG -G wg1 -g 50 --fixed -N ngName
说明:
- Class或Workload核数范围指定必须通过--fixed参数设置。
- 设置限额权重只限制自己,不限制别人,即如果GaussDB整个进程可以使用的cpu核数为0-7共8个核心,资源池poolg关联的cgroup为classG:wg1,假设可用的cpu核心为0-3,那么绑定poolg资源池用户下发的作业只能运行在0-3的核心上,此时如果其他资源池关联的cgroup未做cpu限额管控,则下发的作业可运行在0-7所有的核心上。
6. 删除Class控制组和Workload控制组
gs_cgroup -d -S ClassG -G wg1
gs_cgroup -d -S ClassG
说明:删除控制组前,需要先解除cgroup与资源池的绑定关联,防止存在依赖删除失败。
7. 删除逻辑集群cgroup配置文件信息并重建
gs_cgroup -d -N xxx
gs_cgroup -c -N xxx
8. 回退上一步操作
gs_cgroup --recover
说明:--recover只支持对Class控制组和Workload控制组的增删改查操作进行回退,且只支持回退一次操作
9. 创建组资源池与业务资源池
create resource pool poolg with (control_group='ClassG'); -- 组资源池(父资源池)绑定Class控制组
create resource pool poolg1 with (control_group='ClassG:wg1'); -- 业务资源池(子资源池)绑定Workload控制组
10. 创建组用户和业务用户
create user userg with resource pool 'poolg' password 'xxxx'; -- 组用户(父租户)绑定组资源池
create user userg1 with resource pool 'poolg1' password 'xxxx' user group 'userg'; -- 业务用户(子租户)绑定业务资源池
说明:组用户不作为执行用户的用户使用,只作为资源的持有者。
11. 查看角色与资源池的关系
select * from pg_user;
select * from pg_resource_pool;
12. 修改用户绑定到默认资源池default_pool
alter user userg1 with resource pool 'default_pool' user group default;
4、内核cgroup相关视图与函数
GaussDB针对cgroup提供了大量的视图和函数进行cpu配置同步、监控和管控。
函数/视图/guc参数 | 功能 | 用法 |
gs_get_control_group_info | 查看所有nodegroup的所有cgroup信息 | select * from gs_get_control_group_info; |
gs_all_control_group_info | 查看当前nodegroup的所有cgroup信息 | select * from gs_all_control_group_info; |
gs_control_group_info | 查看资源池对应的cgroup信息,不包含异常规则 | select gs_control_group_info('default_pool'); |
pg_stat_get_cgroup_info | 查看所有nodegroup的所有cgroup信息 | select pg_stat_get_cgroup_info(0); |
gs_respool_exception_info | 打印资源池的异常规则信息(821版本之后异常规则已无需绑定在cgroup控制组上) | select gs_respool_exception_info('default_pool'); |
pg_control_group_config | 查看cgroup配置文件信息,和gs_cgroup -p一样 | select pg_control_group_config(); |
gs_wlm_switch_cgroup | 调整作业所在控制组 | SELECT gs_wlm_switch_cgroup(threadid, 'class_a:workload_a2'); |
pgxc_cgroup_reload_conf | 在所有实例在线加载cgroup信息 | select * from pgxc_cgroup_reload_conf(); |
gs_cgroup_reload_conf | 在当前实例进行在线加载cgroup | select * from gs_cgroup_reload_conf() |
cgroup_name | guc参数,设置可更改当前session的cgroup | set cgroup_name="class_a:workload_a2"; |
下面对常用的gs_get_control_group_info显示信息进行解析:
5、cgroup管控功能验证
对cgroup管控功能进行介绍之前先对cgroup的配置文件以及gs_cgroup -p、gs_cgroup -P结果进行解析说明
1. cgroup配置文件
GaussDB(DWS)使用二进制文件保存cgroup配置,文件位于$GAUSSHOME/etc下面。示例:$GAUSSHOME/etc/gscgroup_[user_name].cfg。而在逻辑集群模式下,每个逻辑集群会单独保存一份cgroup配置信息,示例:$GAUSSHOME/etc/vc1.gscgroup_[user_name].cfg。
2. gs_cgroup -p信息解析
通过“gs_cgroup -p”命令可以查看配置文件信息,如果有逻辑集群可执行gs_cgroup -p -N xxx查看逻辑集群的cgroup配置信息。
3. gs_cgroup -P信息解析
VFS (Virtual File System) 虚拟文件系统是系统内核非常强大的一个功能,它把文件系统的具体实现细节隐藏起来,给用户态进程提供一个统一的文件系统API接口。cgroup的接口操作也是基于VFS实现的,可以通过mount命令查看cgroup挂载信息,每个目录对应cgroup的一个子系统。
VFS系统挂载信息,通过“gs_cgroup -P”命令可以查看挂载信息;
4.观察当前作业运行的cpu核心编号
gsql -d postgres -p xxx -ar -c "select lwtid from pg_stat_activity where state='active'; " -o /tmp/ids
for id in $(cat /tmp/ids|grep '2');do cat /proc/${id}/status | grep list;done
6、cgroup定时任务
背景说明
GaussDB依赖OS的cgroup做资源控制,os重启时cgroup会丢失,因此需要GaussDB产品提供cgroup监控机制,保证内核资源受控。
Cgroup监控由管控面来完成。
FIM集群
提供mpp-cgroupMonitor.sh脚本监控cgroup,周期调用,一分钟一次。检测到cgroup掉了就重新挂载cgroup。
检测原理是检查{cgroupPath}/cpu/Gaussdb:omm/Class,{cgroupPath}/cpuset/Gaussdb:omm/Class,{cgroupPath}/cpuacct/Gaussdb:omm/Class 三个目录是否存在,不存在就重挂。
脚本日志在cgroupCheck.log里面
DWS集群
提供mount_gs_cgroup.py脚本监控cgroup,周期调用,一分钟一次。检测到cgroup掉了就重新挂载cgroup。
* * * * * source /etc/profile;source ~/.bashrc; nohup /bin/python3 /rds/datastore/dws/xxxx/mount_gs_cgroup.py >> /dev/null 2>&1 &"
检测原理是检查如下目录是否存在,不存在就重挂。
/var/chroot/sys/fs/cgroup/cpu/Gaussdb:Ruby
/var/chroot/sys/fs/cgroup/cpuacct/Gaussdb:Ruby
/var/chroot/sys/fs/cgroup/cpuset/Gaussdb:Ruby
脚本日志在:
/home/root/log/mount_gs_cgroup_upgrade.log
重新挂载定时任务执行流程示例:
root用户:
/var/chroot/opt/dws/tools/libcgroup/bin/gs_cgroup -U Ruby -d -D /var/chroot/DWS/manager/app
/var/chroot/opt/dws/tools/libcgroup/bin/gs_cgroup -U Ruby --upgrade -c -H /var/chroot/DWS/manager/app -D /var/chroot/dev
/var/chroot/opt/dws/tools/libcgroup/bin/gs_cgroup --refresh -H /var/chroot/DWS/manager/app
集群用户:
/var/chroot/opt/dws/tools/libcgroup/bin/gs_cgroup -c -N v3_logical -H /var/chroot/DWS/manager/app
7、cgroup常见问题处理方式
案例1:cgroup信息异常残留,删除cgroup控制组报错
该场景可采用如下方式进行修复:
1、root用户删除残留的cgroup,当无残留时,此命令可能会报错。
$GAUSSHOME/bin/gs_cgroup -d -U user_name
2、root用户挂载对应集群用户的cgroup
$GAUSSHOME/bin/gs_cgroup -c -U user_name -H $GAUSSHOME
3、集群用户刷新cgroup配置文件
-- 普通集群
gs_cgroup --refresh;
-- 逻辑集群
gs_cgroup --refresh -N xxx;
4、连接数据库执行如下命令(配置文件与内核同步)
select pgxc_cgroup_reload_conf();
8、参考文献
- 点赞
- 收藏
- 关注作者
评论(0)