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
当有多个实例时,为每个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
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)服务状态中也会看到同样的信息
尝试在一个CPU机器上并行多个会话,运行一个benchmark执行一个厚重的负载。不管我尝试了什么,Linux都限制了PG不超过slice指定的限制:
如果我们将PG的所有进程的CPU利用率都加起来,我们会看到2.3*4+2*7+1.7 = 24.9
同样的负载下不进行任何cgroup限制,会带来100%的利用率(0% idle):
Cgroup slice限制了负载,这符合预期。我们可以在一个slice中弄多个服务,这是下一个层级。systemd-cgtop可以展示slice-wise和单独的service-wise利用率:
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%
...
重启后生效。
Control group在docker和kubernetes中广泛使用。它们是限制机器上资源消耗的有效方法之一。Cgroup2使得使用更加便捷。使用场景:
1)更好的多租户环境
可以通过防止租户争夺同一套资源来防止“Noisy Neighbor”效应。
2)同一台机器上部署数据库服务和应用服务
绝大多数应用都是CPU密集型,数据库服务大多是内存/IO密集型。因此某些场景可以将他们部署在同台机器上。实际上我们看到许多情况下网络是潜在威胁,另一个优势是我们不必向网络公开数据库服务端口。
3)保护系统不受滥用、服务拒绝攻击
当系统重负载时,可能造成机器上运行的所有程序失去响应。这种情况往往会导致HA框架异常。对资源的良好控制可以防止这种情况发生。
https://www.percona.com/blog/controlling-resource-consumption-on-a-postgresql-server-using-linux-cgroup2/
本文分享自 yanzongshuaiDBA 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!