ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

containerd Snapshotters 全解析:快照器插件全景、快照生命周期与实战配置

containerd Snapshotters 全解析:快照器插件全景、快照生命周期与实战配置 containerd Snapshotters 全解析快照器插件全景、快照生命周期与实战配置【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerdcontainerd 的 Snapshotter快照器负责管理容器文件系统的所有快照从镜像层解包、父子快照的层叠到最终生成容器 rootfs 的挂载点。本文以 docs/snapshotters/README.md 为骨架结合仓库中 Snapshotter 核心接口、各快照器插件源码与 devmapper、blockfile、erofs、remote-snapshotter 等配套文档系统讲解 containerd 2.x 中快照器的分类、核心接口语义、各插件的配置参数与选型方法。读完后你将能够判断当前实例可用的快照器、为 overlayfs/devmapper/blockfile/erofs 等插件编写正确的config.toml配置、理解快照从 Prepare 到 Commit 的完整生命周期以及理解 remote snapshotter 如何借助containerd.io/snapshot.ref标签实现免拉层的快速镜像准备。一、Snapshotter 是什么定义与核心接口官方文档给出的定义是Snapshotters manage the snapshots of the container filesystems——快照器管理容器文件系统的快照。它是 containerd 存储抽象层的核心插件类型io.containerd.snapshotter.v1镜像层在解包unpack时被逐层提交commit为快照容器启动时再基于最终快照准备prepare一个可写的 active 快照返回一组 mount 供运行时挂载为容器 rootfs。核心接口定义在 core/snapshots/snapshotter.go 的Snapshotter接口中理解它的关键是快照生命周期与命名约定三种快照类型KindKindView、KindActive、KindCommitted见 core/snapshots/snapshotter.go#L73-L78。View 是只读视图Active 是可写事务Committed 是已提交、可被作为父层的最终快照。命名空间约定key指 active 快照name指 committed 快照parent指父快照active 与 committed 快照共用同一个 key 空间因此同一个 key 不能同时被 active 和 committed 快照占用。典型生命周期Prepare(ctx, key, parent, opts...)创建一个以 parent 为基的 active 快照并返回 mountsparent 必须是一个 committed 快照默认表示空目录。挂载 mounts 后向其写入变更如解包镜像层、容器运行时写入数据。Commit(ctx, name, key)将 key 的变更捕获为名为 name 的 committed 快照并删除该 active 快照。容器运行结束时通常调用Remove(ctx, key)放弃变更若需要保留新镜像则调用Commit。View行为与Prepare相同但只读且不能对其调用CommitStat用于存在性检查与类型判定Usage返回该快照自身不含父快照占用的 inodes 与字节数Walk支持按name/parent/kind/labels.(label)过滤遍历。接口的文档注释里还完整示范了三段式用法导入一个层Prepare→ 挂载 → 解包层 tar →Commit、导入下一层以上一层的 digest 作为 parent 重复该过程、运行容器以镜像 rootfs 的 ChainID 作为 parent 调用Prepare将返回的 mounts 直接交给容器运行时。此外core/snapshots/snapshotter.go#L29-L67 定义了一批影响快照行为的保留标签是理解 remote snapshotter 与并行解包的关键标签/常量作用UnpackKeyPrefix/UnpackKeyFormatextract-%s %s解包用快照的 key 格式前缀containerd.io/snapshot.refunpacker 在 Prepare 时指定的目标 chainID快照器若已存在对应 committed 快照会返回ErrAlreadyExists使 unpacker 跳过拉取和应用该层remote snapshot 协议containerd.io/snapshot/diff-id正在解包层的未压缩 diffIDcontainerd.io/snapshot/uidmapping、/gidmappingUID/GID 重映射idmapped 场景containerd.io/snapshot/max-size提示快照器将 active 快照的文件系统限制到指定字节数基于块镜像或支持配额的快照器应遵守RebaseCaprebase能力标记允许 Commit 时通过WithParent指定父快照使 unpacker 可以并行准备并应用层再在 commit 时重组链注意注释中的一点约束只有前缀为containerd.io/snapshot/的标签会被继承到快照器的Prepare、View或Commit调用中配套实现是 core/snapshots/snapshotter.go#L409-L421 的FilterInheritedLabels。二、如何查看当前可用的 Snapshotter官方文档给出的检查方式见 docs/snapshotters/README.mdctr plugins ls # 或 nerdctl infoctr plugins ls会列出所有已加载的io.containerd.snapshotter.v1插件及其平台与状态ok。快照器以插件形式注册进 containerd 进程插件目录位于 plugins/snapshots当前仓库包含overlay、native、blockfile、devmapper、btrfs、erofs等核心实现以及windows、lcow两个面向 Windows 容器场景的实现后两者未在 README 的通用列表中展开属于平台特化插件。需要强调适用前提各快照器对内核、文件系统与工具链的要求不同可用取决于宿主环境例如 overlayfs 需要 OverlayFS 内核支持devmapper 需要dmsetup与 thin-poolerofs 需要 EROFS 内核模块与 erofs-utils。三、核心快照器插件逐一解析官方文档将核心插件分为三类通用型Generic、块设备型Block-based、文件系统特化型Filesystem-specific另有一类已废弃插件。以下按原分类继承并逐项扩充。3.1 overlayfs默认类比 Docker 的 overlay2overlayfs是 Linux 上的默认快照器基于 OverlayFS功能上相当于 Docker/Moby 的 overlay2 存储驱动——但 containerd 中的实现不叫 overlay2。从源码看插件注册在 plugins/snapshots/overlay/plugin/plugin.goregistry.Register将其注册为Type: plugins.SnapshotPlugin, ID: overlayfs。其配置结构体Config支持的config.toml字段为[plugins.io.containerd.snapshotter.v1.overlayfs] # 插件根目录留空则使用 containerd 的默认插件目录 root_path # 为快照附加 upperdir 标签记录变更集存放位置 upperdir_label false # true 时删除操作同步执行默认异步删除依赖 GC 回调延迟清理 sync_remove false # 允许在 idmap 挂载不可用时回退到递归 chown有性能开销 slow_chown false # overlay 挂载的额外选项不作用于 bind mount mount_options []这些字段的处理逻辑在插件初始化函数中可逐一对应UpperdirLabel映射到 overlay.go 的WithUpperdirLabel标签 key 为containerd.io/snapshot/overlay.upperdir见 plugins/snapshots/overlay/overlay.go#L38-L41!SyncRemove时启用AsynchronousRemoveMountOptions经WithMountOptions注入。此外还有两个从源码结构可确认的运行时行为若内核支持 idmapped mountsoverlayutils.SupportsIDMappedMounts()通过插件自动启用WithRemapIDs并声明remap-ids能力否则若未开启slow_chown则声明only-remap-ids表示只接受 idmap 挂载。不在用户命名空间运行时插件会声明rebasesnapshots.RebaseCap能力支撑并行解包源码注释指出该能力依赖mknod c 0 0转换白点文件故在 UserNS 中不可用。3.2 native文件复制型类比 vfsnative是原生文件复制驱动相当于 Docker/Moby 的 vfs每个快照都是一份完整目录层叠通过复制实现。实现位于 plugins/snapshots/native/native.go。它功能最简单、兼容性最广但空间与 I/O 开销最大适合作为调试或无 OverlayFS 环境的兜底选择。3.3 blockfile每个快照一个裸块文件blockfile 快照器为每个快照使用一个裸块文件块文件从父块文件或基础空块文件复制而来挂载需要虚拟机或支持 loopback 挂载。目标场景容器跑在 VM 内。VM 无法 bind-mount 宿主目录而 blockfile 快照器为快照创建块设备可直接挂给 VM 作为磁盘把 OCI 镜像内容传进 guest。文档同时列出替代方案virtiofs 驱动、9p 协议或 devmapper 快照器。配置来自 docs/snapshotters/blockfile.md[plugins.io.containerd.snapshotter.v1.blockfile] scratch_file /opt/containerd/blockfile root_path /somewhere/on/disk fs_type ext4 mount_options [] recreate_scratch true参数说明root_path块文件存放目录必须对 containerd 进程可写scratch_file作为所有块文件底板的空文件路径首次使用前应已存在fs_type块文件使用的文件系统类型当前支持ext4与xfsmount_options挂载块文件时的附加挂载选项recreate_scratch为true时缺失 scratch 文件会自动重建为false时缺失即报错。创建 scratch 文件的示例500MB、ext4# 创建一个 500M 的空文件 $ dd if/dev/zero of/opt/containerd/blockfile bs1M count500 # 格式化为 ext4 $ sudo mkfs.ext4 /opt/containerd/blockfile工作原理对三层镜像 A→B→C快照器依次为每层复制上一块的块文件第一层复制 scratch 文件、loopback 挂载、应用层、卸载最终块文件分别包含 A、AB、AC 的内容。由于使用稀疏文件块文件只占实际内容空间例如每层 25MB 时三层共 150MB而非 3×500MB。运行容器$ ctr image pull docker.io/library/busybox:latest $ ctr run -rm -t --snapshotter blockfile docker.io/library/busybox:latest hello sh通过 Go client 使用时与其他快照器完全一致containerd.WithSnapshotter(blockfile)即可。3.4 devmapperext4/xfs 的 device mapper 快照devmapper插件将快照存放在Device-mapper thin-pool 中的文件系统镜像里利用 device-mapper 的 thin provisioning 与快照特性。完整操作文档见 docs/snapshotters/devmapper.md核心内容如下。最小配置示例version 2 [plugins] ... [plugins.io.containerd.snapshotter.v1.devmapper] root_path /var/lib/containerd/devmapper pool_name containerd-pool base_image_size 8192MB ...支持的配置参数全部继承自原文档参数说明root_path元数据目录为空则使用 containerd 插件默认位置pool_nameDevice-mapper thin-pool 名称须与/dev/mapper/中的名称一致base_image_size从 basepool设备创建 thin 快照时的分配空间async_remove是否通过快照 GC 的 cleanup 回调异步删除设备默认falsediscard_blocks删除设备时是否 discard 块对 loopback 设备回收磁盘空间尤其有用默认falsefs_type快照设备挂载的文件系统有效值ext4和xfs默认ext4fs_options可选文件系统选项目前仅适用于 ext4默认其中root_path、pool_name、base_image_size为必填项。前置要求需安装dmsetup 1.02.110thin-pool 需在启动 containerd 前创建好。文档给出两种典型方式Loopback 设备开发/测试环境性能慢不推荐生产创建 data/meta 文件 →losetup --find --show分配 loop 设备 → 按SECTOR_SIZE/DATA_BLOCK_SIZE/LOW_WATER_MARK计算参数后dmsetup create pool --table 0 length thin-pool meta data block_size low_water_mark并建议配置discard_blocks truedirect-lvm thin-pool生产环境借助 container-storage-setup 工具在指定块设备上创建 VG 与 thin pool随后配置pool_name ${VG_NAME}-${POOL_NAME}。验证与运行$ dmsetup ls # 确认 thin-pool 存在 $ ctr images pull --snapshotter devmapper docker.io/library/hello-world:latest $ ctr run --snapshotter devmapper docker.io/library/hello-world:latest test3.5 btrfs / zfs需要专用文件系统承载插件根目录btrfs需要把插件根目录/var/lib/containerd/io.containerd.snapshotter.v1.btrfs整体挂载为 btrfs 文件系统。当前仓库仍在 plugins/snapshots/btrfs 下提供该实现。zfs需要把插件根目录/var/lib/containerd/io.containerd.snapshotter.v1.zfs挂载为 ZFS。从当前仓库的 plugins/snapshots 目录结构看zfs 实现已不在仓库内维护README 亦将其指向独立仓库containerd/zfs单独演进——这一点与仓库目录事实一致。这类文件系统特化快照器利用文件系统自身的 copy-on-write/快照能力快照创建近乎零成本但前提是宿主机已部署对应文件系统。3.6 erofsEROFS 只读层 OverlayFS 活动层erofs快照器要求为 active 快照启用 OverlayFS 内核模块。它是为每个 committed 快照保留 EROFS 格式 blob、为每个 active 快照准备 OverlayFS 挂载的原生快照器。完整文档见 docs/snapshotters/erofs.md要点必须搭配 EROFS differ才能将 OCI 层直接转成 EROFS blob否则退回 walking differ 时其行为类似 overlayfs 快照器先解包再 commit 时转成 EROFS blob更慢。关键配置[plugins.io.containerd.snapshotter.v1.erofs] enable_fsverity true # 为 EROFS 层启用 fsverity默认 false ovl_mount_options [] # overlayfs 的附加挂载选项 default_size 20GiB # 可选块模式配额限制可写层大小 dmverity_mode auto # dm-verityauto默认/ on / off [plugins.io.containerd.service.v1.diff-service] default [erofs, walking]数据完整性三件套set_immutableIMMUTABLE_FL 文件属性、enable_fsverityfs-verity 校验、enable_dmveritydiffer 侧dmverity_mode快照器侧块级校验支持并行解包、layer_content_caches预构建 EROFS blob 缓存、tar index 模式等详见原文档各节。3.7 已废弃aufsaufs快照器自 containerd 1.5 起废弃、在 containerd 2.0 中已移除对应仓库 RELEASES.md 的 deprecated features 记录。当前仓库 plugins/snapshots 目录下也不再存在 aufs 实现与文档描述一致。四、非核心快照器插件Remote Snapshotter 生态README 列出的非核心快照器均以独立仓库维护、以插件/外部服务方式接入 containerd统称remote snapshotter远程快照器生态插件说明fuse-overlayfsFUSE-OverlayFS 快照器用户态实现 overlay 语义nydusNydus 快照器面向按需拉取on-demand pulling的懒加载镜像overlaybdOverlayBD 快照器块设备形态的加速容器镜像stargzStargz 快照器基于 stargz 镜像格式的懒加载实现remote snapshotter 的工作机制值得深入完整说明见 docs/snapshotters/remote-snapshotter.md其核心协议与核心接口源码相互印证客户端Pull带WithPullUnpackWithPullSnapshotter(...)时containerd 会对每一层调用快照器的Prepare并携带containerd.io/snapshot.ref标签值为目标 committed 快照的 ChainID同时把用户通过snapshots.WithLabels或 image handler wrapper标签须以containerd.io/snapshot/前缀传入的快照器专属信息合并进 labels——对应 core/unpack/unpacker.go 中的 unpack 逻辑与 core/snapshots/snapshotter.go#L406-L421 的FilterInheritedLabels。若远程共享存储中已存在该 ChainID 的快照remote snapshotter必须返回ErrAlreadyExists客户端随后调用Stat(chainID)确认存在即跳过该层的拉取与解包从而实现不拉层也能准备快照的快速路径。Go 客户端用法示例继承自原文档import ( containerd github.com/containerd/containerd/v2/client github.com/containerd/containerd/v2/core/snapshots ) image, err : client.Pull(ctx, ref, containerd.WithPullUnpack, containerd.WithPullSnapshotter( my-remote-snapshotter, snapshots.WithLabels(map[string]string{ containerd.io/snapshot/reference: ref, }), ), )当标签需随快照动态变化时可用WithImageHandlerWrapper注入例如 CRI 包、nerdctl 使用的 handler wrapper它会把目标层 descriptor 上的 Annotations同样须带containerd.io/snapshot/前缀转交快照器。五、Mount Target快照器如何描述 rootfs 子挂载README 的最后一节讲了一个常被忽略的契约mounts 可以携带 target 字段来描述容器 rootfs 内的子挂载submount。若快照器希望在 overlayfs 挂载之上再 bind mount 一个子目录它可以返回如下 mounts 列表[ { type: overlay, source: overlay, options: [ workdir..., upperdir..., lowerdir... ] }, { type: bind, source: /path/on/host, target: /path/inside/container, options: [ ro, rbind ] } ]约束bind mount 的目标点/path/inside/container必须已经存在于 rootfs 中因此必须由前一个 mount 负责提供该目录——在上例中即由 overlay 的某个 lowerdir 中预置了该目录来使 bind mount 得以成立。这一约定解释了为什么 EROFS 等快照器能在 mount 列表里自由组织多层挂载而运行时挂载逻辑无需改动也印证了 core/snapshots/snapshotter.go 中Mounts方法返回 active 快照的挂载列表的设计。六、选择与配置快照器的实用建议综合以上文档与源码证据给出一份选型与配置速查场景推荐快照器关键依据通用 Linux 生产环境overlayfs默认插件功能最完整声明rebase能力可并行解包非 UserNS 时无 OverlayFS/调试兜底native纯文件复制兼容面最广容器运行在 VM 内、需要块设备blockfile或devmapperblockfile 产出裸块文件可挂给 VMdevmapper 基于 thin-pool追求解包性能与层数据保护erofs直转 EROFS blob、fsync 粒度持久化、并行解包、dm-verity 完整性宿主已部署 btrfs/ZFSbtrfs/zfs利用文件系统原生快照注意 zfs 实现已移出本仓库独立维护懒加载/按需拉取stargz、nydus、overlaybdremote snapshotter 生态走ErrAlreadyExists免拉层协议两点全局性的配置事实均有源码依据默认快照器可按命名空间覆盖defaults/defaults.go#L30-L31 定义了命名空间标签containerd.io/defaults/snapshotterDefaultSnapshotterNSLabel各平台默认值在 defaults/defaults_linux.go 等文件中定义任何[plugins.io.containerd.snapshotter.v1.id]配置修改后都需要重启 containerd 才生效——快照器在进程启动的插件初始化阶段完成注册如 plugins/snapshots/overlay/plugin/plugin.go 的InitFn运行期不会重读配置。最后用官方检查命令收尾验证ctr plugins ls中应能看到io.containerd.snapshotter.v1行内对应的插件 ID如overlayfs、blockfile、devmapper、erofs与ok状态再配合本文第三节的参数表即可完成一次快照器的落地配置。【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表