【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节点内存资源的。

相关推荐
苍煜5 小时前
Docker容器网络详解+端口映射原理(系列第二篇:实战核心)
网络·docker·容器
问心无愧05137 小时前
ctf show web入门37
笔记
羊群智妍8 小时前
2026生成式AI搜索优化:GEO监测工具全解析
笔记
koo3649 小时前
周报5.10
笔记
gwjcloud9 小时前
Kubernetes从入门到精通(高级篇)04
云原生·容器·kubernetes
kdxiaojie10 小时前
U-Boot分析【学习笔记】(3)
linux·笔记·学习
智者知已应修善业11 小时前
【51单片机模拟生日蜡烛】2023-10-10
c++·经验分享·笔记·算法·51单片机
智者知已应修善业11 小时前
【51单片机如何让LED灯从一亮到八,再从八亮到一】2023-10-13
c++·经验分享·笔记·算法·51单片机
张文君11 小时前
上古世纪服务端编译安装AAEmu docker编译安装
运维·docker·容器
qeen8711 小时前
【数据结构】二叉树相关经典函数C语言实现
c语言·数据结构·c++·笔记·学习·算法·二叉树