Systemd服务无法按预期分配NUMA节点0的Huge Pages问题
Systemd 一次性服务无法为NUMA节点0分配Huge Pages的问题排查与解决
问题描述
编写的systemd一次性服务无法按预期为NUMA节点0分配Huge Pages。硬件服务需依赖NUMA节点0的大页资源,但服务文件中配置的分配命令执行后无效果;以root身份在命令行执行相同命令却能正常生效,日志显示命令已执行,但Huge Pages的数值未发生变化。
排查相关信息
1. /var/log/messages 日志片段
[2024-05-20 10:15:00] systemd[1]: Starting Allocate Huge Pages for NUMA node 0...
[2024-05-20 10:15:00] systemd[1]: Started Allocate Huge Pages for NUMA node 0.
[2024-05-20 10:15:00] hugepages-setup[1234]: Executing echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
[2024-05-20 10:15:00] hugepages-setup[1234]: Command executed successfully
2. Systemd 服务文件(/etc/systemd/system/hugepages-setup.service)
[Unit] Description=Allocate Huge Pages for NUMA node 0 Before=hardware-service.service [Service] Type=oneshot ExecStart=/bin/sh -c 'echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages' User=root Group=root [Install] WantedBy=multi-user.target
3. 命令行执行成功示例
# echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages # cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages 1024
原因分析
- 服务启动时机过早:系统早期启动阶段,NUMA节点对应的sysfs路径可能未完全初始化,导致写入操作无实际效果。
- 安全模块拦截:SELinux或AppArmor可能限制了systemd服务对sysfs节点的写入权限,虽然日志显示命令执行成功,但实际写入被拦截。
- 命令封装方式问题:使用
/bin/sh -c封装命令时,systemd的执行环境可能存在隐性差异,导致重定向操作未生效。
解决方案
1. 调整服务启动时机
修改服务文件,添加After=sysfs.target,确保在sysfs挂载完成后再执行分配命令:
[Unit] Description=Allocate Huge Pages for NUMA node 0 Before=hardware-service.service After=sysfs.target
更新配置后重启服务:
systemctl daemon-reload systemctl restart hugepages-setup.service
2. 排查安全模块限制
- SELinux 测试与修复:
临时关闭SELinux验证:
重启服务后若生效,生成并加载对应的SELinux规则:setenforce 0ausearch -m avc -ts recent | audit2allow -M hugepages-setup semodule -i hugepages-setup.pp - AppArmor 测试与修复:
临时禁用相关profile验证:aa-disable /etc/apparmor.d/systemd-hugepages
3. 优化命令执行方式
避免/bin/sh -c封装,直接使用systemd支持的重定向语法,或改用tee命令确保写入生效:
# 方式1:直接使用echo的绝对路径与重定向 ExecStart=/bin/echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages # 方式2:用tee命令确保写入 ExecStart=/usr/bin/tee /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages <<< "1024"
4. 添加预执行检查
在服务中添加预执行步骤,查看执行前的大页资源状态,便于排查:
[Service] Type=oneshot ExecStartPre=/bin/sh -c 'echo "Pre-check: Current hugepages on node0: $(cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages)"' ExecStart=/bin/echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages ExecStartPost=/bin/sh -c 'echo "Post-check: Current hugepages on node0: $(cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages)"'
内容的提问来源于stack exchange,提问作者Mark Lakata
相关产品推荐
相关产品推荐

