PostgreSQL使用Linux cgroup2控制资源消耗

PostgreSQL使用Linux cgroup2控制资源消耗

多租户和共host是一个挑战性问题。运行多个PG实例可以帮助减少内部竞争点(可伸缩性问题)。然而,一个租户的load可能会影响其他tenets,即所谓的“Noisy Neighbor”效应。幸运的是Linux允许用户通过每个程序使用cgroups来控制资源消耗。Cgroup2替代了cgroup1,处理了版本1几乎所有的限制。

Linux的5.2.0及其之后版本的内核可以使用cgroup2。实际上,2022年及其之后的Linxu分支的及其很可能已经准备好了cgroup2。

检查Linux是cgroup1还是cgroup2,可以通过cgroup mount的个数进行检查:

$ grep -c cgroup /proc/mounts
1

如果count值是1,那么就是cgroup2。因为cgroup2有一个统一单层次结构。如果是cgroup1,那么会看到多个mounts值。

如果Linux内核比较新并且仍旧使用cgroup1,那么可以使用boot参数:“systemd.unified_cgroup_hierarchy=1”。Redhat/OEL系统中,可以执行下面命令添加这个参数:

sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"

通常情况下将这个作为引导选项添加到内核参数中:

$ cat /etc/default/grub
…
GRUB_CMDLINE_LINUX="xxxxxx systemd.unified_cgroup_hierarchy=1"
…

需要重启机器生效。重启后可以验证:

$ sudo mount -l | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate)

请确保是cgroup2。现在我们检查这个虚拟文件系统,以便很好地理解:

[jobinaugustine@localhost ~]$ ls -l /sys/fs/cgroup/
total 0
-r--r--r--. 1 root root 0 May 27 02:10 cgroup.controllers
-rw-r--r--. 1 root root 0 May 27 02:10 cgroup.max.depth
-rw-r--r--. 1 root root 0 May 27 02:10 cgroup.max.descendants
-rw-r--r--. 1 root root 0 May 27 02:10 cgroup.procs
-r--r--r--. 1 root root 0 May 27 02:10 cgroup.stat
-rw-r--r--. 1 root root 0 May 27 02:10 cgroup.subtree_control
-rw-r--r--. 1 root root 0 May 27 02:10 cgroup.threads
-rw-r--r--. 1 root root 0 May 27 02:10 cpu.pressure
-r--r--r--. 1 root root 0 May 27 02:10 cpuset.cpus.effective
-r--r--r--. 1 root root 0 May 27 02:10 cpuset.mems.effective
-r--r--r--. 1 root root 0 May 27 02:10 cpu.stat
drwxr-xr-x. 2 root root 0 May 27 02:10 init.scope
-rw-r--r--. 1 root root 0 May 27 02:10 io.pressure
-r--r--r--. 1 root root 0 May 27 02:10 io.stat
drwxr-xr-x. 2 root root 0 May 27 02:10 machine.slice
-r--r--r--. 1 root root 0 May 27 02:10 memory.numa_stat
-rw-r--r--. 1 root root 0 May 27 02:10 memory.pressure
-r--r--r--. 1 root root 0 May 27 02:10 memory.stat
-r--r--r--. 1 root root 0 May 27 02:10 misc.capacity
drwxr-xr-x. 107 root root 0 May 27 02:10 system.slice
drwxr-xr-x. 3 root root 0 May 27 02:16 user.slice

这个是root control group。所有的slices都在这个下面。可以看到“system.slice”和“user.slice”,他们都是作为一个目录,因为他们是下一层级。

可以检查下哪些是可用的cgroup controller:

[jobinaugustine@localhost ~]$ cat /sys/fs/cgroup/cgroup.controllers
cpuset cpu io memory hugetlb pids rdma misc

1、实践

创建一个slice

当有多个实例时,为每个PG实例都创建一个独立的slice是一个不错的主意。允许我们从高级别控制资源的整个消耗。

假设想要限制所有PG服务使用不超过机器CPU的25%:

1)创建一个slice

sudo systemctl edit --force postgres.slice

2)为了演示,添加下面配置

[Unit]
Description=PostgreSQL Slice
Before=slices.target
[Slice]
MemoryAccounting=true
MemoryLimit=2048M
CPUAccounting=true
CPUQuota=25%
TasksMax=4096

3)保存后重新加载

sudo systemctl daemon-reload

4)检查slice的状态

sudo systemctl status postgres.slice

更改PG服务

1)我们可以使用PG服务中创建的slice,编辑:

$ sudo systemctl edit --full postgresql-16

2)添加slice配置,例如Slice=postgres.slice:

...
[Service]
Type=notify
User=postgres
Group=postgres
Slice=postgres.slice
...

3)保存并退出编辑。需要重启PG服务。重启时,PG会在新的slice下运行:

$ systemd-cgls | grep post
├─postgres.slice
│ └─postgresql-16.service
│ ├─3760 /usr/pgsql-16/bin/postgres -D /var/lib/pgsql/16/data/
│ ├─3761 postgres: logger
│ ├─3762 postgres: checkpointer
│ ├─3763 postgres: background writer
│ ├─3765 postgres: walwriter
│ ├─3766 postgres: autovacuum launcher
│ └─3767 postgres: logical replication launcher
│   └─3770 grep --color=auto post

4)服务状态中也会看到同样的信息

0572a44d1b7498d5f27c74035e509425.png

验证

尝试在一个CPU机器上并行多个会话,运行一个benchmark执行一个厚重的负载。不管我尝试了什么,Linux都限制了PG不超过slice指定的限制:

fe55261206a17f3980b14690eb118293.png

如果我们将PG的所有进程的CPU利用率都加起来,我们会看到2.3*4+2*7+1.7 = 24.9

同样的负载下不进行任何cgroup限制,会带来100%的利用率(0% idle):

c1eb3401812da646a70ff004a4d32803.png

Cgroup slice限制了负载,这符合预期。我们可以在一个slice中弄多个服务,这是下一个层级。systemd-cgtop可以展示slice-wise和单独的service-wise利用率:

9204e0e35cfdb53013e3efa4fd203abe.png

系统级别的控制

Cgroup2非常有用,可选项更多。例如,你可能不想为PG服务创建单独的slice,特别当该机器上仅有一个PG实例时。默认情况下,PG和所有服务都作为“system.slice”的一部分。这种场景下,最简单的方式是在service级别指定cgroup限制,而不是slice级别:

sudo systemctl edit --full postgresql-16

添加:

...
[Service]
User=postgres
Group=postgres
CPUAccounting=true
CPUQuota=25%
...

重启后生效。

2、总结

Control group在docker和kubernetes中广泛使用。它们是限制机器上资源消耗的有效方法之一。Cgroup2使得使用更加便捷。使用场景:

1)更好的多租户环境

可以通过防止租户争夺同一套资源来防止“Noisy Neighbor”效应。

2)同一台机器上部署数据库服务和应用服务

绝大多数应用都是CPU密集型,数据库服务大多是内存/IO密集型。因此某些场景可以将他们部署在同台机器上。实际上我们看到许多情况下网络是潜在威胁,另一个优势是我们不必向网络公开数据库服务端口。

3)保护系统不受滥用、服务拒绝攻击

当系统重负载时,可能造成机器上运行的所有程序失去响应。这种情况往往会导致HA框架异常。对资源的良好控制可以防止这种情况发生。

3、原文

https://www.percona.com/blog/controlling-resource-consumption-on-a-postgresql-server-using-linux-cgroup2/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值