香港物理服务器上如何使用Linux cgroup v2实现CPU+内存双维度的业务隔离限流?

香港物理服务器上如何使用Linux cgroup v2实现CPU+内存双维度的业务隔离限流?

我在运维一台部署于香港的数据中心的物理服务器时,多个内部业务共用同一宿主机资源,经常因某个进程瞬时占满CPU或吃掉内存,导致其他关键服务抖动甚至OOM。我决定使用Linux原生的资源控制机制——cgroup v2,从CPU与内存两个维度,对业务服务进行隔离与限流,确保整体系统稳定性。

下面是我在香港裸金属服务器上,基于Ubuntu 22.04内核5.15+的实操路径。

一、前置准备:确认系统支持cgroup v2

首先我需要确认服务器内核版本支持cgroup v2,并且启用了统一层级控制。

uname -r
# 输出应为5.10及以上,例如:5.15.0-91-generic

mount | grep cgroup2
# 输出应包含 cgroup2 on /sys/fs/cgroup

如果系统未启用cgroup v2统一层级,我通过以下方式调整GRUB启动参数:

sudo vim /etc/default/grub

# 修改或追加如下行:
GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1"

# 更新GRUB并重启:
sudo update-grub
sudo reboot

二、创建统一的业务资源控制目录

在cgroup v2下,所有控制器都挂载在/sys/fs/cgroup统一树状目录中。我为两个业务进程分别创建资源子组:

cd /sys/fs/cgroup

# 创建两个cgroup子组
mkdir -p service-a
mkdir -p service-b

为了系统能应用资源限制,我需要为控制器开启委托(部分发行版如Arch会自动配置,Ubuntu需手动):

# 确保我们有权限配置子组
chown -R root:$(whoami) /sys/fs/cgroup/service-*
chmod 755 /sys/fs/cgroup/service-*

三、配置CPU限流参数

cgroup v2使用cpu.max文件控制CPU限流。格式为:

cpu.max = <quota> <period>

单位是微秒(µs),例如每100ms允许使用20ms的CPU,表示20%限额。

# 限制A业务最多使用1核的50%
echo "50000 100000" > /sys/fs/cgroup/service-a/cpu.max

# B业务限制为单核20%
echo "20000 100000" > /sys/fs/cgroup/service-b/cpu.max

如果某服务可以抢占所有CPU资源,我也可以设置为无限制:

echo "max 100000" > /sys/fs/cgroup/service-b/cpu.max

四、配置内存限制与OOM保护

  • cgroup v2的内存控制主要涉及两个文件:
  • memory.max: 最大可用内存(强限制)
  • memory.high: 超过后将进入soft reclaim状态,系统会优先回收

例如我希望A服务最多用1GB,B服务用512MB:

echo $((1024*1024*1024)) > /sys/fs/cgroup/service-a/memory.max
echo $((512*1024*1024)) > /sys/fs/cgroup/service-b/memory.max

可以加上memory.oom.group=1实现组级别OOM kill:

echo 1 > /sys/fs/cgroup/service-a/memory.oom.group
echo 1 > /sys/fs/cgroup/service-b/memory.oom.group

五、将业务进程挂载到指定cgroup

一旦子组配置完成,需要把服务的PID加入对应的cgroup.procs文件。

假设A服务的主进程PID为12345,B服务为23456:

echo 12345 > /sys/fs/cgroup/service-a/cgroup.procs
echo 23456 > /sys/fs/cgroup/service-b/cgroup.procs

也可以在启动服务时手动绑定:

# 预绑定并启动
echo $$ > /sys/fs/cgroup/service-a/cgroup.procs
exec ./run-service-a

或通过systemd方式(见后续章节)自动管理绑定。

六、进阶:结合systemd自动化cgroup绑定

为了实现更自动化的管理,我将资源限制写入systemd服务文件。例如为service-a创建/etc/systemd/system/service-a.service:

[Unit]
Description=A业务服务
After=network.target

[Service]
ExecStart=/opt/bin/service-a
CPUQuota=50%
MemoryMax=1G
MemoryHigh=768M
Slice=service-a.slice

[Install]
WantedBy=multi-user.target

创建对应slice文件以确保隔离:

# /etc/systemd/system/service-a.slice
[Slice]
CPUAccounting=true
MemoryAccounting=true

加载后启用服务即可:

systemctl daemon-reexec
systemctl daemon-reload
systemctl enable --now service-a

七、实时监控资源使用

cgroup v2支持直接读取当前资源使用情况:

# 查看内存使用
cat /sys/fs/cgroup/service-a/memory.current

# 查看CPU使用累计时间(纳秒)
cat /sys/fs/cgroup/service-a/cpu.stat

配合ps, top, systemd-cgls、systemd-cgtop等工具能实现实时可视化监控。

八、总结与实践效果

完成配置后,我对这台香港物理机上的业务进行了系统级的资源隔离。A服务在高负载时被硬性限在50% CPU与1GB内存以内,避免了过去某个模块因逻辑异常吃满资源拖垮全局的情况。

与传统nice, ulimit, taskset等方法相比,cgroup v2具备:

  • 多维度(CPU/内存/IO等)精细化控制
  • 统一层级、继承清晰、系统稳定
  • 与systemd无缝集成,支持大规模部署

在生产环境中,特别是容器未引入或部分组件依赖系统服务时,cgroup v2提供了比容器更轻量、颗粒度更细的控制能力,是我在香港物理服务器中强烈推荐的隔离手段。

未经允许不得转载:A5数据 » 香港物理服务器上如何使用Linux cgroup v2实现CPU+内存双维度的业务隔离限流?

相关文章

contact