从 containerd 1.x 迁移:有什么变化以及如何检查
containerd 1.x 已过支持期,Kubernetes 也已放弃它 —— 迁移到 2.x 究竟会破坏什么,以及如何在升级之前找出来。
containerd 2.0 于 2024 年底发布,当时项目自己的建议是不要急于升级:1.x 分支还会在相当长的时间内继续受到支持。这个窗口现已关闭。containerd 1.7 的延长支持将于 2026 年 9 月结束,而且 Kubernetes 1.35 是最后一个支持 containerd 1.x 的 Kubernetes 版本 —— 之后的版本都要求 2.x。如果集群仍在使用 containerd 1.x,这就不再是一个可选的升级了。本指南介绍实际发生了哪些变化,以及如何在迁移之前检查你的受影响程度。
containerd 将自己的 API 与守护进程分开版本化
自 2.0 起,守护进程版本和 gRPC API 版本不再是同一个数字:containerd 跳到了 2.0,但 API 本身没有破坏性变更,仍停留在 1.x 系列(升到 1.8)。Go 客户端库也移到了自己的包路径下。实际上,这意味着大多数直接使用 API 或 Go 客户端的集成只需更新导入路径,而不需要重写 —— containerd 维护者提到,至少有一个下游工具的迁移正是如此,只是对导入路径做了一次查找替换。
2.0 中究竟移除了什么
- Docker schema 1 镜像支持,默认禁用。Schema 1 在 2014 年被 schema 2 取代,又在 2017 年被 OCI 镜像格式取代;如果某个镜像已有好几年历史且没有重新构建过,它就是 schema 1 的候选。containerd 在拉取时会转换 schema 1 镜像,而不是原样存储,所以对于仍然需要的镜像,实际的修复办法是拉取一次再推回你的镜像仓库,由此完成转换。
- CRI v1alpha2 API 支持。 Kubernetes 自己早在 1.23 版本就迁移到了稳定的 CRI v1 API;任何现代的 kubelet 使用的都已是 v1。真正有风险的是第三方工具、监控代理、安全扫描器,以及其他直接与 CRI 套接字通信的任何东西,它们可能没有更新过。凡是绑定挂载 containerd 套接字或以特权方式运行的,值得优先检查。
- 两个最旧的 shim 实现(
io.containerd.runtime.v1.linux和io.containerd.runc.v1),只留下io.containerd.runc.v2。这早已是多年来的默认值,所以大多数集群看不到行为变化,只是移除了没有人在使用的代码路径。 aufssnapshotter,它依赖一个非上游的内核文件系统。替代品是长期默认的overlayfs,如果你原本没有特意配置使用 aufs,就无需任何操作。- 基于 io_uring 的系统调用,因与之相关的内核 CVE 而默认拒绝。受影响的工作负载应回退到较旧的系统调用路径以获得同样的功能,而不是直接失败,不过 containerd 无法像对此处其他变更那样提前检测到这一点。
另外,旧的 dlopen 式 Go 插件机制和旧版 CRI 镜像仓库 mirror/配置选项在 2.0 中被弃用,并在后续的 2.x 版本中被移除,理由类似:实际使用率低,且有明确的替代方案(后者为 hosts.toml 风格的镜像仓库配置)。
找出你实际受到什么影响
containerd 包含一个弃用服务,当节点上有任何东西第一次真正使用某个即将被移除的特性时,它会记录一条带时间戳的警告。它只在实际使用时触发,而不是推测性的,所以一份干净的报告就意味着一次干净的升级:
ctr deprecations list
ctr deprecations list --format json # for feeding into other tooling
这是 1.x 的特性(已向 1.6 和 1.7 补丁版本回移植),而不是 2.0 的特性,这正是它有用之处:在升级任何东西之前,先在你当前的集群、即你即将离开的运行时上检查它。containerd 会在守护进程重启时清除这个状态,所以如果你最近重启过 containerd 或重建过节点,请先运行一段时间的工作负载,让真实的使用模式重新显现出来。
实用的升级顺序
- 先升级到最新的 1.7.x 补丁版本,这样弃用服务才准确,并且你不会把升级与无关的 bug 修复混为一谈。
- 让生产流量运行足够长的时间以显现真实的使用模式,然后在整个集群范围内检查
ctr deprecations list。 - 修复出现的所有问题:转换或替换 schema 1 镜像,更新仍在调用 CRI v1alpha2 的工具,检查配置中已弃用的镜像仓库语法(大部分会自动迁移;旧语法在过渡期间在 2.x 守护进程下仍能工作)。
- 重新运行并确认弃用列表为空。
- 先将测试集群或一部分节点升级到 2.x,然后再大范围推广。
如果你使用托管 Kubernetes 服务商,请检查它自己是否会呈现这些弃用警告 —— 有些服务商会将它们传播到节点状况或自己的控制台中,并把它们纳入自动化升级的把关,这样就不需要逐个 SSH 登录每个节点。
遇到这里没有涵盖的情况时去哪里查
containerd 项目在 containerd.io 和项目的 GitHub 仓库中发布了一份完整的表格,列出了 2.0 的每一项变更及其替代方案,并附有详细的发布说明。对于本指南没有涵盖的任何内容,那里是权威来源,CNCF Slack 的 #containerd 频道也可以提供直接帮助。