十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

containerd Shim Capabilities 机制详解:通过 Bootstrap 扩展声明运行时能力

containerd Shim Capabilities 机制详解:通过 Bootstrap 扩展声明运行时能力 containerd Shim Capabilities 机制详解通过 Bootstrap 扩展声明运行时能力【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd导读Shim Capabilities 是 containerd 运行时 v2 架构中一套能力协商机制shim 在启动时通过BootstrapResult附加类型化扩展typed extension主动告诉 containerd 自己能够独立完成哪些挂载类型mount type与挂载变换transform从而让 mount manager 不再重复代劳。本文以 docs/shim-capabilities.md 为主体结合 bootstrap.proto、mount.proto 与 core/runtime/v2/task_mounts.go 等源码讲解该扩展的协议格式、注册表语义、链式变换的后缀规则以及旧注解的迁移路径帮助 shim 开发者与容器运行时集成方正确声明自身能力。一、能力声明的载体BootstrapResult 扩展在 containerd 2.3 引入的引导协议bootstrap protocol中shim 的start子命令从 stdin 读取BootstrapParams向 stdout 写出BootstrapResult。BootstrapResult除了携带监听地址address与通信协议protocol可取ttrpc或grpc之外还预留了一个可选字段message BootstrapResult { ... // Optional: Typed detail describing what this shim instance is able to // do, so that containerd can adjust its own behavior. repeated Extension extensions 6; }每个Extension内部就是一个google.protobuf.Anyshim 可以将任意类型化的结构化数据打包进去。containerd 侧的解析逻辑如下见 core/runtime/v2/task_mounts.gofunc mountCapabilitiesExtension(bootstrap *bootapi.BootstrapResult) (*apitypes.MountCapabilities, error) { var caps apitypes.MountCapabilities found, err : bootstrap.FindExtension(caps) if err ! nil { return nil, err } if !found { return nil, nil } return caps, nil }向后兼容的关键设计containerd 会忽略无法识别的扩展类型。这意味着 shim 可以无条件地附加扩展当它运行在一个不认识该扩展的旧版 containerd 上时旧守护进程只是继续保持原有行为不会因此出错。这一点在bootstrap.proto的注释中亦有明确约定containerd MUST ignore an extension whose type it does not recognize相关测试可见 core/runtime/v2/shim_test.go 中的TestBootstrapParamsUnknownExtension。扩展的查找与注册BootstrapResult携带的extensions字段是注册表式registry-style的设计shim 通过AddExtension附加containerd 通过FindExtension按类型 URL 查找整个过程对协议本身零侵入。引入一种新的能力类型不需要修改核心协议只需要双方约定一个新的类型 URL。二、MountCapabilities 扩展详解当前文档注册表中的第一种、也是截至本文写作时文档记录的能力扩展是containerd.types.MountCapabilities。它描述的是shim 自己执行了某些挂载类型或变换mount manager 不得再代为执行。典型场景是 VM 类运行时——它可以把磁盘镜像文件直接传给 guest而不是让宿主机先建立 loop 设备从而获得更优的性能。2.1 Proto 定义与字段语义定义见 api/types/mount.protomessage MountCapabilities { // Types are the mount types the sender performs itself, such as erofs or // loop. These are base mount types, with any transform prefixes removed. repeated string types 1; // Transforms are the mount transforms the sender applies itself, such as // format, mkfs or mkdir. // // A transform is named on its own, without the /mount-type suffix that // appears in a mount type, so format covers the mount types format/bind // and format/mkdir/overlay alike. repeated string transforms 2; }两个字段的命名规则非常关键字段取值示例语义typeserofs、loop基础挂载类型必须去掉变换前缀。即只写overlay不写format/mkdir/overlaytransformsformat、mkfs、mkdir变换名本身不带/mount-type后缀。声明format即同时覆盖format/bind和format/mkdir/overlay等一切以format/开头的挂载链由于两个字段都是开放字符串open ended strings未来新增挂载类型或变换同样不需要修改协议。2.2 空扩展的含义附加一个两个字段都为空的MountCapabilities扩展表示shim 除了普通系统挂载之外不处理任何额外内容——mount manager 将照常完成全部工作。这在源码中表现为mountClaimOpts遍历caps.Types与caps.Transforms为空时不会产生任何激活选项见 core/runtime/v2/task_mounts.go。2.3 containerd 侧的翻译containerd 会把扩展内容翻译为 mount manager 的激活选项activation optionsopts : make([]mount.ActivateOpt, 0, len(caps.Types)len(caps.Transforms)) for _, t : range caps.Types { opts append(opts, mount.WithAllowMountType(t)) } for _, t : range caps.Transforms { opts append(opts, mount.WithAllowTransform(t)) }即types→mount.WithAllowMountTypetransforms→mount.WithAllowTransform。这两个选项定义在 core/mount/manager.goWithAllowMountType(mountType)即使存在该类型的自定义 handler这些挂载也不应被执行——除非为了支撑后续挂载而必须执行WithAllowTransform(transform)该变换由调用者自己执行mount manager 不执行——除非后续挂载依赖它。翻译的正确性由 core/runtime/v2/task_mounts_test.go 中的TestTaskMountControllerActivate覆盖例如声明Types: [erofs, loop]、Transforms: [format, mkfs]后断言AllowMountTypes [erofs, loop]、AllowTransforms [format, mkfs]。三、链式变换的后缀规则只能认领链的后缀这是 MountCapabilities 语义中最容易踩坑、也最需要理解的部分。3.1 变换从外向内执行在 docs/mounts.md 描述的挂载管理模型中变换通过前缀链式书写transformer1/transformer2/mount-type例如format/mkdir/overlay。变换的执行顺序是从外向内outside-in外层变换的输出是内层变换的输入。因此一个被认领claimed的变换只有作为其所在链的后缀时才会被尊重。以format/mkdir/overlay为例认领mkdirmount manager 会先执行format然后把mkdir/overlay交还给 shim 自行完成只认领format什么都不发生因为mkdir的输入依赖format已经运行完毕mkdir无法在format未运行的情况下执行一个想自己执行format的 shim必须把链中format之后的所有变换一并认领即同时认领format与mkdir。这套行为在 mount manager 的规划逻辑中有精确的测试用例core/mount/manager/plan_test.go测试用例激活选项行为什么都不认领无manager 执行整条链applyCount 2认领最内层mkdirWithAllowTransform(mkdir)manager 执行到format为止mkdir/overlay留给调用者applyCount 1只认领最外层formatWithAllowTransform(format)不被尊重manager 仍执行整条链applyCount 2两个变换都认领WithAllowTransform(format)WithAllowTransform(mkdir)manager 一个都不执行applyCount 0认领完整字面类型WithAllowMountType(format/mkdir/overlay)等价于认领链中所有变换applyCount 0TestPlanActivationClaimedGapInMiddle还覆盖了三变换链format/mkfs/mkdir/overlay中认领format与mkdir、而中间的mkfs未被认领的情形由于mkfs未认领它强制 manager 执行到它为止applyCount 2只有它之后的mkdir才真正留给调用者。这一中间有空缺gap则空缺之前都归 manager的语义与文档描述完全一致。3.2format变换的特殊性format变换负责用 Go 模板解析挂载参数例如{{ mount 0 }}会引用 mount manager 内部挂载点参见 docs/mounts.md 中source/target/mount/overlay四个模板值。这些模板引用的挂载点是mount manager 内部私有的状态shim 无法凭空构造因此shim 只能在覆盖链剩余部分的完整后缀中认领format绝不能单独认领format。单独认领format在语义上不可能成立——format的输出是内层变换的输入如果format由 shim 完成那么后续变换的输入对 manager 而言是不存在的挂载点链条无法继续。四、迁移路径废弃的 runtime-allow-mounts 注解MountCapabilities扩展是在containerd 2.4中加入的它取代了已废弃的运行时信息注解containerd.io/runtime-allow-mounts。为了平滑迁移扩展优先只要 shim 在 bootstrap 结果中附加了MountCapabilities扩展就以扩展为准完全不 consult 旧注解测试extension present takes precedence, legacy is not consulted明确验证了这一点注解兜底未附加扩展的 shimcontainerd 仍会去查询其RuntimeInfo注解作为迁移路径已知例外io.containerd.runc.v2与io.containerd.runhcs.v1这两个运行时确定从未设置过该注解因此会直接跳过查询见 core/runtime/v2/task_mounts_deprecated.go 的deprecatedNoAnnotationRuntimes映射测试well known default runtimes are never queried for the annotation亦有覆盖。旧注解的值是一个逗号分隔列表其中transform/*形式的条目表示变换其余表示挂载类型解析逻辑见deprecatedParseAllowedMountsfunc deprecatedParseAllowedMounts(v string) *apitypes.MountCapabilities { caps : apitypes.MountCapabilities{} for entry : range strings.SplitSeq(v, ,) { if entry { continue } if transform, ok : strings.CutSuffix(entry, /*); ok { caps.Transforms append(caps.Transforms, transform) continue } caps.Types append(caps.Types, entry) } return caps }例如注解值block,format/*会被解析为Types: [block]、Transforms: [format]。此外旧路径对成功查询结果做了进程级缓存sync.Mapruntime 名 → capabilities失败查询不缓存以便下次重试当旧注解被命中时containerd 会记录一条 warn 日志提示 shim 应改用MountCapabilities扩展。安全失败方向无论扩展解析失败例如类型 URL 匹配但二进制内容损坏、旧注解查询失败还是完全没有声明mountClaimOpts都遵循**什么都不认领的安全方向**即 mount manager 承担全部挂载工作而不是冒险把挂载留给可能没有实现它的 shim。测试用例a malformed extension claims nothing rather than failing与a failed legacy lookup claims nothing rather than failing均验证了这一点。五、工作流程与整体关系将上述机制放入完整链路中看containerd 启动 shimcontainerd-shim-xxx start通过 stdin 传递BootstrapParamsshim 完成初始化后向 stdout 写出BootstrapResult其中extensions字段附带上containerd.types.MountCapabilitiescontainerd 读取结果通过FindExtension提取扩展若存在则由mountClaimOpts翻译为WithAllowMountType/WithAllowTransform激活选项taskMountController.Activate在激活任务 rootfs 时带上这些选项调用 mount manager见 core/runtime/v2/task_mounts.go并把ActivationInfo.System仍需 shim 自行完成的挂载返回给 shimshim 在 rootfs 中就位后启动容器。关键点在于shim 必须先于其挂载被激活而启动这样它的能力声明才能被纳入激活决策docs/mounts.md 的 Support with containerd shims 一节明确说明The shim is started before its mounts are activated, so that what it advertises can be taken into account.。此外若挂载 manager 插件未配置manager nilActivate会原样返回 rootfs能力协商自然退化为无操作。六、给 shim 开发者的实操建议综合文档与源码为 shim 附加能力扩展时请遵循以下要点协议层面在写出的BootstrapResult中调用AddExtension(apitypes.MountCapabilities{...})扩展机制由pkg/shim自动处理新协议失败时会回退到旧机制无需 shim 自行判断。命名规则types只写基础挂载类型如erofs、loop、blocktransforms只写变换名如format、mkfs、mkdir不要写format/mkdir/overlay这样的完整链式类型除非你想表达整条链都归我——此时认领完整字面类型与认领全部变换等价。后缀规则认领变换时务必从链的最内层最后一个变换开始认领想自己执行format就必须同时认领其后所有变换。只认领链中间的变换不会生效。format特殊对待由于format依赖 manager 内部挂载点的模板解析它只能在覆盖整条链剩余部分的后缀中被认领绝不能单独认领。迁移新 shim 一律使用MountCapabilities扩展仍在使用containerd.io/runtime-allow-mounts注解的 shim 应尽快迁移注解按transform/*区分变换迁移完成前 containerd 2.4 会继续兼容查询但io.containerd.runc.v2与io.containerd.runhcs.v1除外。参考资料docs/shim-capabilities.md本文主体能力扩展注册表与语义的权威定义docs/runtime-v2.md引导协议bootstrap protocol与 shim 编写总览docs/mounts.mdmount manager、挂载类型与变换、以及与运行时的关系api/runtime/bootstrap/v1/bootstrap.protoBootstrapParams/BootstrapResult/Extension定义api/types/mount.protoMountCapabilities消息定义core/runtime/v2/task_mounts.go扩展解析与激活选项翻译的实现core/runtime/v2/task_mounts_deprecated.go废弃注解的迁移查询与解析core/runtime/v2/task_mounts_test.go 与 core/mount/manager/plan_test.go能力翻译与后缀规则的测试验证core/mount/manager.goWithAllowMountType/WithAllowTransform激活选项定义【免费下载链接】containerdAn open and reliable container runtime项目地址: https://gitcode.com/GitHub_Trending/co/containerd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表