【docker笔记-001】如何设置docker使得容器能在多个numa之间均匀使用内存

【未经授权,请勿转载,感谢支持】

都知道 numactl 有个 --interleave 的参数,可以将运行的应用绑定在指定的numa节点上,而且使用的内存可以均匀的在多个numa节点上。

例如运行一个脚本 我们可以这样:

bash 复制代码
// 假设本地有两个numa节点,分别为 0,1
// 如果不知道有多少个numa,可以用 lscpu 查询本地信息
numactl --interleave=0,1 bash ./test.sh

上述命令即可实现运行 test.sh 脚本时,在 0,1 两个numa上都均匀使用内存。

那么问题来了,如果我们是 docker 容器场景,怎样在不修改 docker 镜像的前提下,通过设置docker的配置,使得运行起来的所有容器,都自动可以绑定到多个numa 上,且均匀使用这些numa节点的内存呢?

有的兄弟,有的!下面,直接讲干货!

大致原理如下:

通过截获底层创建容器时 create 命令,在命令前面加上 numactl --interleave 即可。

步骤如下:

  1. 编写如下脚本
bash 复制代码
#!/bin/bash

# 定义 NUMA 策略
# 这里设置绑定节点 0,1 并交错分配内存
NUMA_ARGS="--interleave=0,1"

# 真正的 OCI 运行时路径 (通常是 runc,可以通过 which runc 确认)
# 如果你的系统使用的是 crun,请改为 /usr/bin/crun
REAL_RUNTIME="/usr/sbin/runc"

if [ ! -x "$REAL_RUNTIME" ]; then
    # 尝试备用路径
    REAL_RUNTIME="/usr/bin/runc"
fi

if [ ! -x "$REAL_RUNTIME" ]; then
    echo "Error: Cannot find runc. Please install runc or update the script." >&2
    exit 1
fi

# 解析参数
# Docker/containerd 会传递一系列参数,我们需要找到 "create" 或 "run" 命令,
# 并在其执行前插入 numactl。
# 但更简单的方法是:如果最后一个参数是 bundle 目录,或者命令是 create,
# 我们直接用 numactl 包裹 runc 的执行。

# 检查是否包含 "create" 子命令 (containerd 通常调用 create)
if [[ "$@" == *"create"* ]]; then
    # 构造新命令:numactl [numa_args] runc [original_args]
    exec numactl $NUMA_ARGS "$REAL_RUNTIME" "$@"
else
    # 如果是其他命令 (如 delete, kill, spec 等),直接透传给 runc,不加 numactl
    exec "$REAL_RUNTIME" "$@"
fi

将上面脚本内容存入到一个脚本文件中,例如我这里存放到如下路径中:

/usr/local/bin/docker-numa-runtime

然后将这个脚本添加可执行权限:

bash 复制代码
chmod +x /usr/local/bin/docker-numa-runtime
  1. 修改docker的daemon.json文件

vim /etc/docker/daemon.json

如果没有这个文件,可以先创建。添加如下 runtime 信息:

bash 复制代码
{
        "runtimes": {
                // numa-balanced 这个名字,建议不要修改
                "numa-balanced": {
                        "path": "/usr/local/bin/docker-numa-runtime", // 如果脚本的位置是自定义的路径,这里记得改一下路径,且确保脚本有可执行权限,最好是 root 权限。
                        "runtimeArgs": []  // 这里之所以参数留空,是因为脚本中已经处理参数了
                }
        },
        "default-runtime": "numa-balanced"  // 这里设置了默认运行时,表示所有的容器都按照上述情况执行;也可以不设置这个,只需要添加 docker run 参数即可,例如 "docker run --runtime numa-balanced ..."
}
  1. 重启docker
bash 复制代码
sudo systemctl daemon-reload
sudo systemctl restart docker

ok,至此docker设置已完成!下面来验证成果!

先手动运行一个容器:

说明一下,容器中运行了一个redis,其中规格为16g,且运行了压测命令,让容器尽量使用完分配的内存。如果我设置在numa 0,1 上均匀使用的话,理论上 每个numa肯定会占用超过8G内存。

那么用如下命令,看一下实时的内存使用情况:

watch -n 1 "numastat -m"

bash 复制代码
                          Node 0          Node 1           Total
                 --------------- --------------- ---------------
MemTotal              1547117.36      1572864.00      3119981.36
MemFree               1508840.50      1562577.61      3071418.11
MemUsed                 38276.86        10286.39        48563.25
SwapCached                  0.00            0.00            0.00

可以看到,numa 0,1 上都使用了内存超过8GB,验证成功!

另外说明一下,我在 k3s 集群中用工具自动化部署容器,生成的容器也是会均匀使用多个numa节点内存资源的。

相关推荐
1104.北光c°2 小时前
Leetcode3.无重复字符的最长子串 HashSet+HashMap 【hot100算法个人笔记】【java写法】
java·开发语言·笔记·程序人生·算法·leetcode·滑动窗口
❀͜͡傀儡师2 小时前
docker部署开源的SQL审核平台Yearning
sql·docker·开源
鹭天2 小时前
目标检测学习笔记
笔记·学习·目标检测
-许平安-2 小时前
MCP项目笔记五(PluginAPI)
c++·笔记·rpc·json·mcp·pluginapi
今儿敲了吗2 小时前
Linux学习笔记第二章——虚拟机基础操作
linux·笔记·学习
老虎06272 小时前
LeetCode热题100 刷题笔记(第一天)哈希 「两数之和」
笔记·算法·leetcode
CODE_RabbitV2 小时前
【保姆级实操版 - STM32 系列笔记】STM32F103标准库开发:Keil5新建工程完整教程
笔记·stm32·嵌入式硬件
NULL指向我3 小时前
STM32 F103C8T6学习笔记20:cubemx 配置 ADC采样 电位器
笔记·stm32·学习
小疙瘩3 小时前
VirtualBox 下 CentOS-10 下 Docker 安装 Redis
java·docker·容器