nydus-snapshotter 部署手册(Kubernetes 1.32 + containerd 2.x)

举报
大水牛bpi 发表于 2026/10/26 09:23:19 2026/10/26
【摘要】 nydus-snapshotter 部署手册(Kubernetes 1.32 + containerd 2.x)目标:在 worker 节点上启用 nydus 快照器,实现镜像按需加载(懒加载),同时保留 overlayfs 作为默认快照器(混合模式),普通镜像与 nydus 镜像可共存。 0. 前提与注意事项项目要求containerd2.x(config 版本 version = 3)...

nydus-snapshotter 部署手册(Kubernetes 1.32 + containerd 2.x)

目标:在 worker 节点上启用 nydus 快照器,实现镜像按需加载(懒加载),同时保留 overlayfs 作为默认快照器(混合模式),普通镜像与 nydus 镜像可共存。


0. 前提与注意事项

项目 要求
containerd 2.x(config 版本 version = 3)。若为 1.x 见 §5.4
节点范围 仅 worker 节点。master/control-plane 节点必须保持默认 overlayfs,kube-apiserver 等静态 Pod 依赖默认快照方式
内核 需支持 fuse(fusedev 模式);开启 user_allow_other

下载清单

组件 版本 地址
nydus-static(含 nydusd、nydus-image、nydusify) 2.4.0 https://github.com/dragonflyoss/nydus/releases/tag/v2.4.0
nydus-snapshotter v0.15.11 https://github.com/containerd/nydus-snapshotter/releases/tag/v0.15.11
nerdctl(可选,用于登录/调试) 2.2.1 https://github.com/containerd/nerdctl/releases/tag/v2.2.1

按系统选择安装包:

  • Ubuntu / Debian:nydus-static-2.4.0-linux-amd64.deb
  • CentOS / RHEL:nydus-static-2.4.0-linux-amd64.rpm

配置参考:https://github.com/dragonflyoss/nydus/blob/master/docs/containerd-env-setup.md


1. 安装 nydus 工具链

# Ubuntu / Debian
sudo apt install ./nydus-static-2.4.0-linux-amd64.deb

# CentOS / RHEL
sudo rpm -ivh nydus-static-2.4.0-linux-amd64.rpm

# 验证
nydusd --version
nydus-image --version
nydusify --version

2. 安装 nydus-snapshotter

tar -xf nydus-snapshotter-v0.15.11-linux-static.tar.gz
cp bin/containerd-nydus-grpc /usr/local/bin/
chmod +x /usr/local/bin/containerd-nydus-grpc

mkdir -p /etc/nydus

3. 配置 nydusd

sudo tee /etc/nydus/nydusd-config.fusedev.json > /dev/null << EOF
{
  "device": {
    "backend": {
      "type": "registry",
      "config": {
        "scheme": "",
        "skip_verify": true,
        "timeout": 5,
        "connect_timeout": 5,
        "retry_limit": 4,
        "auth": ""
      }
    },
    "cache": {
      "type": "blobcache",
      "config": {
        "work_dir": "cache"
      }
    }
  },
  "mode": "direct",
  "digest_validate": false,
  "iostats_files": false,
  "enable_xattr": true,
  "fs_prefetch": {
    "enable": true,
    "threads_count": 4
  }
}
EOF

关于 auth 字段

  • 公共仓库:留空即可。

  • 私有仓库:填 base64(username:password),快照器会自动读取该串去仓库延迟拉取。必须去掉换行符:

    echo -n 'username:password' | base64 -w 0
    

4. 配置 systemd 服务并启动

sudo tee /etc/systemd/system/nydus-snapshotter.service > /dev/null << EOF
[Unit]
Description=nydus snapshotter
After=network.target
Before=containerd.service

[Service]
Type=simple
Environment=HOME=/root
ExecStart=/usr/local/bin/containerd-nydus-grpc --nydusd-config /etc/nydus/nydusd-config.fusedev.json
Restart=always
RestartSec=1
KillMode=process
OOMScoreAdjust=-999
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now nydus-snapshotter
systemctl status nydus-snapshotter

之后每次修改 nydusd 配置,都要 systemctl daemon-reload && systemctl restart nydus-snapshotter。

确认 socket 已生成(containerd 靠它通信):

ls -l /run/containerd-nydus/containerd-nydus-grpc.sock

5. 配置 containerd

采用混合模式:全局默认仍是 overlayfs,nydus 镜像通过 RuntimeClass 显式指定,两种互不影响。

5.1 修改已有配置项

# 全局快照器保持 overlayfs(不要改成 nydus)
# 必须开启快照注解,否则 CRI 会剥离 nydus 镜像的 annotation
sed -i 's#disable_snapshot_annotations = true#disable_snapshot_annotations = false#g' /etc/containerd/config.toml

5.2 新增 proxy_plugins

放在 [plugins] 之前、与 [grpc] / [metrics] 平级的顶层位置:

[proxy_plugins]
  [proxy_plugins.nydus]
    type = "snapshot"
    address = "/run/containerd-nydus/containerd-nydus-grpc.sock"

5.3 新增 runc-nydus 运行时

在 [plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes] 下新增(与已有的 runc 平级):

        [plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc-nydus]
          runtime_type = "io.containerd.runc.v2"
          snapshotter = "nydus"
          [plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc-nydus.options]
            SystemdCgroup = true

5.4 containerd 1.x 的旧格式差异

若 containerd --version 为 1.x(config version = 2),键名不同,改写为:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc-nydus]
  runtime_type = "io.containerd.runc.v2"
  runtime_engine = ""
  runtime_root = ""
  privileged_without_host_devices = false
  snapshotter = "nydus"

proxy_plugins 部分两版格式一致,无需改动。

5.5 重启 containerd

systemctl restart containerd
systemctl status containerd

6. 转换镜像为 nydus 格式

# 安装 nerdctl(可选)
tar -xf nerdctl-2.2.1-linux-amd64.tar.gz
cp nerdctl /usr/sbin/

# 登录镜像仓库(nydusify 会读取 ~/.docker/config.json)
nerdctl login -u <用户名> -p <密码> swr.cn-north-4.myhuaweicloud.com

# 转换:源镜像 -> nydus 镜像
nydusify convert \
  --source swr.cn-north-4.myhuaweicloud.com/testapp/my-nginx:v3 \
  --target swr.cn-north-4.myhuaweicloud.com/testapp/nydus-nginx:v3

7. 创建 RuntimeClass

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: nydus
handler: runc-nydus   # 必须与 containerd 中配置的 runtime 名一致
kubectl apply -f runtimeclass.yaml
kubectl get runtimeclass

8. 部署验证

nydus 镜像的 Pod 需要同时指定 runtimeClassName 和注解 io.containerd.cri.runtime-handler:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nydus-demo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nydus-demo
  template:
    metadata:
      labels:
        app: nydus-demo
      annotations:
        io.containerd.cri.runtime-handler: runc-nydus
    spec:
      runtimeClassName: nydus
      containers:
        - name: container-1
          image: swr.cn-north-4.myhuaweicloud.com/testapp/nydus-nginx:v3
          resources: {}
      imagePullSecrets:
        - name: default-secret   # 私有仓库时需要

普通 OCI 镜像不需要任何特殊配置,走默认 overlayfs 正常拉取运行。

验证:

kubectl get pod -o wide
# 在节点上查看 nydus 挂载
mount | grep nydus
journalctl -u nydus-snapshotter -f

回显
overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/a12f3695a4c0b8ce8f37d60bff487f5451b0a34c02a4d4bfc83d973ad2d08910/rootfs type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/1/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/2/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/2/work,nouserxattr)
rafs on /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/8/mnt type fuse (ro,nosuid,nodev,noatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=1052672)
overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/f959bf461f6abfbd3f9769386823f0baac95f350828b45e72190c751c2d70128/rootfs type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/8/mnt,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/9/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/9/work,xino=off,nouserxattr)


9. 要点速查

问题 说明
master 节点能否启用 不能,必须保持默认快照器
disable_snapshot_annotations 必须为 false,否则 nydus 镜像注解被剥离,退化为普通拉取
混合模式 全局 snapshotter = 'overlayfs' + runc-nydus 运行时,按需切换
只改配置不换运行时会怎样 nydus 镜像不会被快照器识别,无法懒加载
改了配置没生效 containerd 和 nydus-snapshotter 都要重启,且顺序为 snapshotter 先于 containerd

10. 总结

挂载信息详解

overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/a12f3695a4c0b8ce8f37d60bff487f5451b0a34c02a4d4bfc83d973ad2d08910/rootfs type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/1/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/2/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/2/work,nouserxattr)
rafs on /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/8/mnt type fuse (ro,nosuid,nodev,noatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=1052672)
overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/f959bf461f6abfbd3f9769386823f0baac95f350828b45e72190c751c2d70128/rootfs type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/8/mnt,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/9/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/9/work,xino=off,nouserxattr)

第 2 行是决定性证据

rafs on /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/8/mnt type fuse (ro,nosuid,nodev,noatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=1052672)

rafs 是 nydus 自己的镜像格式,type fuse 说明 nydusd 已经把这个镜像层挂成了一个 FUSE 挂载点。这意味着数据没有完整落到本地,只有真正读到的块才会从仓库拉取。挂载参数也都对:ro 符合镜像层只读语义,allow_other 让容器进程能访问,max_read=1052672 是 nydusd 设的单次读取上限(约 1MB)。

第 3 行证明容器确实跑在它上面

lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/8/mnt
upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/9/fs

lowerdir 正好指向第 2 行那个 rafs 挂载点,upperdir 是独立的可写层。只读层懒加载 + 可写层本地,这就是 nydus 容器该有的形态。

注意这里多了个 xino=off。这是正常的——overlay 的 xino 特性要求下层文件系统支持稳定的 inode 编号,FUSE 挂载满足不了,内核自动关掉了。第 1 行的普通 overlay 挂的是真实目录,不需要关,所以参数里是 nouserxattr 而非 xino=off。这两个参数的差异本身就能区分哪个走了 rafs。

第 1 行是没走懒加载的那个

lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/1/fs

目录名是 fs 不是 mnt,说明这是个普通 OCI 镜像层,被完整解包在本地。nydus-snapshotter 对非 nydus 镜像会自动退化成普通 overlay 行为,属于设计内的兼容。

结合 snapshot 编号(1、2 是最早分配的,8、9 靠后),这个 a12f 容器大概率是 Pod 的 pause/sandbox 容器,pause 镜像本来就不是 nydus 格式。如果你希望所有业务容器都走 rafs,建议确认一下它到底是什么:

bash
crictl ps -a --name a12f # 或用完整 ID 前几位
crictl inspect a12f3695a4c0 | grep -i image
如果它确实是 pause,那就完全正常,不用管。

看 blob cache 是否在增长(证明确实在按需下载)
du -sh /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache
总结
回显完全正常,而且三行连起来恰好是 nydus 生效的完整证据链:rafs 挂载成功 → 容器 rootfs 以它为 lowerdir → nydusd 按需拉取。唯一需要留意的是 a12f 那个容器走的还是普通解包路径,确认它是 pause 就没有任何问题。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。