ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

3步跑通nerdctl的OverlayBD懒加载:镜像按需加载原理、snapshotter配置到镜像转换

3步跑通nerdctl的OverlayBD懒加载:镜像按需加载原理、snapshotter配置到镜像转换

3步跑通nerdctl的OverlayBD懒加载:镜像按需加载原理、snapshotter配置到镜像转换

【免费下载链接】nerdctlcontaiNERD CTL - Docker-compatible CLI for containerd, with support for Compose, Rootless, eStargz, OCIcrypt, IPFS, ...项目地址: https://gitcode.com/gh_mirrors/ne/nerdctl

nerdctl 是 containerd 的 Docker 兼容命令行工具,从 0.15.0 版本起,它配合 OverlayBD 技术可以只对容器镜像按需加载真正用到的数据块,而不必把整个镜像拉下来再逐层解压。这篇指南带你走完 containerd overlaybd snapshotter 配置、用 nerdctl 转换 overlaybd 镜像的完整流程,并列出实际部署中容易踩的坑。

从一次「拉不动」的大镜像说起

先把场景摆出来:一台离线环境或带宽受限的机器,nerdctl run一个几 GB 的镜像,pull 进度条走了十几分钟还没结束;就算拉完了,容器还要等所有层解压落盘才真正启动。传统 OCI 镜像的工作方式就是这样——先完整下载,再逐层解压,启动时间被两层串行流程叠满。

OverlayBD 懒加载(lazy pulling)改变的就是这个顺序:它让「镜像可用」和「数据全部下载」解耦。镜像先挂上一个虚拟块设备,容器立刻启动,文件被真正读取时才去远端取对应的数据块。官方文档把这个过程叫 Lazy-pulling,完整说明见 docs/overlaybd.md。

懒加载背后发生了什么

理解 OverlayBD,关键在两点。

它不是文件级懒加载,而是块级懒加载。传统 OCI 镜像是一层层 tar 压缩包,想跳过不读的文件很难;OverlayBD(学术论文出处为 USENIX ATC'20 的 DADI:Block-Level Image Service for Agile and Elastic Application Deployment)把每一层做成 ext4 文件系统的远程块设备,读取的最小单位是块。应用只打开了 100MB 的文件,就只产生 100MB 级别的远端请求,而不是把整层下回来。

它跑在 containerd 的 proxy plugin 机制里。overlaybd 不是 containerd 内置功能,而是一个独立的overlaybd-snapshotter进程,通过 Unix socket 对外提供 gRPC 服务;containerd 侧只需在配置里注册一个type = "snapshot"的 proxy plugin,把快照操作转发过去。nerdctl 本身不直接和它打交道,转换镜像和选择 snapshotter 的逻辑分别在 pkg/imgutil/converter/ 和 pkg/imgutil/snapshotter.go 里。

一句话总结:pull 阶段只拉元数据和索引,启动阶段挂块设备,运行阶段按需回源取块——这正是镜像按需加载原理的核心。

三步完成 overlaybd snapshotter 配置

第一步:安装 overlaybd-snapshotter 插件

安装 containerd 远程快照插件overlaybd(即overlaybd-snapshotter二进制)。它独立于 containerd 构建,构建方式可参考 accelerated-container-image 项目的 BUILDING 文档(仓库内 docs/overlaybd.md 里有对应入口)。注意:即使你只用nerdctl image convert转换镜像、不跑容器,这一步也必须完成。

第二步:修改 /etc/containerd/config.toml

在配置文件中加入 proxy plugin 注册项,三个关键字段是type = "snapshot"和address指向的 socket 路径:

[proxy_plugins] [proxy_plugins.overlaybd] type = "snapshot" address = "/run/overlaybd-snapshotter/overlaybd.sock"

再加一段可选项,把 overlaybd 登记为 linux 平台镜像 unpack 的默认 snapshotter,这样转换、导入镜像时 containerd 能自动选择,省去手动指定:

[[plugins."io.containerd.transfer.v1.local".unpack_config]] platform = "linux" snapshotter = "overlaybd"

第三步:启动两个服务,运行容器验证

overlaybd-snapshotter和containerd必须都在运行,缺一个 socket 就通不了。然后带上--snapshotter=overlaybd跑一个现成的 OverlayBD 镜像:

nerdctl run --net host -it --rm --snapshotter=overlaybd \ registry.hub.docker.com/overlaybd/redis:6.2.1_obd

如果容器几秒内就进入运行状态、而本地并没有完整的镜像数据落盘,说明懒加载链路已经通了。

一条命令把现有镜像转成 OverlayBD

跑通现成镜像之后,通常还需要转换自己的镜像。nerdctl 内置了转换命令:

nerdctl image convert --overlaybd --oci myregistry.example.com/app:v1 myregistry.example.com/app:v1-ovbd

源镜像可以是 OCI 或 Docker v2 格式,--oci负责把 Docker media type 规整成 OCI 格式。几个常用参数:

  • --overlaybd-vsize:虚拟块设备大小(GB),默认 64,按镜像实际体量调小可以省空间
  • --overlaybd-fs-type:块设备内的文件系统类型,默认ext4
  • --platform:多架构镜像可指定输出平台,--all-platforms则全量转换

转换的耗时取决于源镜像大小。转完得到的镜像 tag 是新的(如上例的:v1-ovbd),运行时同样要带--snapshotter=overlaybd,否则 containerd 会拿普通 overlayfs 去解一个 OverlayBD 层,直接报错。

避坑清单

  1. snapshotter 与镜像格式必须成对出现。OverlayBD 镜像只能用 overlaybd snapshotter 跑;反过来,普通 OCI 镜像也不必强行走 overlaybd。配好上面那段unpack_config后,多数操作可以自动选择,减少手动出错的概率。
  2. 转换前确认 overlaybd-snapshotter 二进制已安装。这是nerdctl image convert --overlaybd的硬性前置条件,官方文档专门强调了这一点,漏掉会直接失败。
  3. vsize不是越大越好。64GB 是默认值,块设备是稀疏存储,实际占多少空间取决于真实数据量,但给得离谱大只会在出问题时更难排查。
  4. 懒加载有首次访问成本。第一次读到某个数据块时要回源拉取,存在轻微延迟;冷启动后大量随机读的文件型负载,收益会被部分吃掉。启动大镜像、读文件少而集中的场景收益最明显。
  5. Rootless 环境先确认插件可用。overlaybd-snapshotter 需要挂载块设备,rootless 下的行为受内核和配置影响更大,部署前建议查一遍 docs/rootless.md 的说明。
  6. 同类方案不止一个。nerdctl 同时支持 SOCI、eStargz 等懒加载格式,配置套路与上文几乎一致,可对比 docs/soci.md、docs/stargz.md 再选:SOCI 对标准 OCI 镜像无需构建期转换,OverlayBD 则胜在块级 I/O 性能。

什么时候值得上 OverlayBD

  • 大镜像(数 GB 起)在带宽受限、离线或弱网环境部署:启动时间从「下载全程 + 解压全程」压缩到「只下载启动所需数据块」
  • CI/CD 频繁起容器:同一台机器上镜像数据块会缓存在本地,第二次启动几乎无网络开销
  • 需要把镜像启动 SLA 做硬约束的场景

镜像很小、或运行负载本身就是大吞吐随机读的场景,则不必引入这套额外组件。

从配置 proxy plugin、跑通第一个--snapshotter=overlaybd容器,到用image convert把存量镜像批量转过去,整条链路并不复杂;剩下的事情,就是挑几个真正的大镜像先试,用启动时间说话。

【免费下载链接】nerdctlcontaiNERD CTL - Docker-compatible CLI for containerd, with support for Compose, Rootless, eStargz, OCIcrypt, IPFS, ...项目地址: https://gitcode.com/gh_mirrors/ne/nerdctl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进