本文用于分析 containerd 如何升级到 2.0 版本。

containerd v2.0 在 2024.11.6 出了正式版本,也表明了该版本的主要目的。

containerd 2.x 的首个重要版本重点关注 containerd 核心功能集的持续稳定性,以及从 containerd 1.x 的轻松升级。该版本包括稳定上一个 1.x 版本中添加的新功能,以及删除 1.x 版本中废弃的功能。

通过 containerd-2.0.md 文档可以看到在这个新版本中存在大量的变更。下面重点关注一下平滑升级,以及我感兴趣的变化。

升级前检测

弃用警告已添加到自省服务的 ServerResponse 中 (/containerd.services.introspection.v1.Introspection/Server) 和 ctr 工具中,通过 ctr deprecation list 命令可查看。

为了帮助用户过渡到 containerd 2.0,社区已决定将此功能回移植到 containerd 1.6 和 1.7 发布分支,以提供用户识别迁移 containerd 版本的障碍的工具。

在 containerd 版本 >= 1.6.27 和 >= 1.7.12 上运行的工作负载的管理员,可以查询其 containerd 服务器,以接收已标记为弃用并在关键路径上的功能的警告。使用 ctr 客户端,用户可以运行 ctr deprecations list(并可选择传递 --format json 以获取机器可读的输出)。

例如 #9772 中标注的

# ctr deprecations list
ID                                               LAST OCCURRENCE                   MESSAGE    
io.containerd.deprecation/pull-schema-1-image    2024-02-06T11:28:37.765563957Z    Schema 1 images are deprecated since containerd v1.7 and removed in containerd v2.0. Since containerd v1.7.8, schema 1 images are identified by the "io.containerd.image/converted-docker-schema1" label.

同样,在该 issue 中也说明了 ctr deprecations list 获取的列表不是持久化的,而是在 containerd 本次启动后的启用告警。因此这个命令最好在特定低版本(>= 1.6.27 和 >= 1.7.12)上运行一段时间后再进行检测。 一些配置中的告警必然每次都会报,但像 cri v1alaph2 APIDocker Schema 1本次containerd启动后没有使用就不会被检测到 ,需要特别注意。

需重点关注变更

守护进程配置版本 3

此版本增加了对 containerd 守护进程配置 version = 3 的支持。守护进程配置在启动时会自动迁移到最新版本。这确保以前的配置在未来的守护进程上继续工作;但是,建议迁移到最新版本以避免迁移并优化守护进程启动时间。有关更多详细信息,请参见发布文档中的 “守护进程配置”

问题不大。自动升级

CRI 注册表属性已弃用

以下 [plugins."io.containerd.grpc.v1.cri".registry] 属性的支持已弃用,并将在未来的版本中移除。

  • CRIRegistryMirrors(mirrors)属性。用户应迁移至使用 config_path
  • CRIRegistryAuths(auths)属性。用户应迁移至使用 ImagePullSecrets
  • CRIRegistryConfigs(configs)属性。用户应迁移至使用 config_path

registry 配置是常用配置,需要特别关注。一般在配置 register mirror 和 私有镜像仓 都会大量用到本配置。实际移除将会在 containerd v2.1 (已经一推再推了) 。

CRI v1alpha2 API 已被移除

在 containerd v1.7 中已弃用,CRI v1alpha2 API 的支持已被移除。用户应迁移至使用 CRI v1。

这一条变更的重灾区是 kubernetes 用户。官方建议参考 “Kubernetes 支持” 矩阵,以验证其 Kubernetes 版本的支持情况。

从支持矩阵可以看到,v1alpha2 在 kubernetes 1.26 弃用,见Kubernetes v1.26: Electrifying | Kubernetesv1 在 1.23版本开始支持,见 cri-api/README.md

对 Kubernetes v1.31,kubelet 偏向于使用 CRI v1 版本。 如果容器运行时不支持 CRI 的 v1 版本,那么 kubelet 会尝试协商较老的、仍被支持的所有版本。 v1.31 版本的 kubelet 也可协商 CRI v1alpha2 版本,但该版本被视为已弃用。 如果 kubelet 无法协商出可支持的 CRI 版本,则 kubelet 放弃并且不会注册为节点。

所以不是 1.23 版本之前的 kubernetes,这一变更无须太过关心。(k8s都不升级,还会升级containerd???)

使用 ctr deprecations list 前下发个容器就能检测到。

Docker Schema 1 图像支持默认禁用

默认情况下,拉取 Docker Schema 1 (application/vnd.docker.distribution.manifest.v1+json 或 application/vnd.docker.distribution.manifest.v1+prettyjws) 图像被禁用。用户应通过使用最新的 Docker 或 nerdctl+Buildkit 工具重建/推送其容器镜像进行迁移。可以通过为 containerd(在 CRI 的情况下)和 ctr 设置环境变量 CONTAINERD_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1 重新启用以前的行为;但是,强烈建议用户迁移到 Docker Schema 2 或 OCI 镜像。未来的版本将完全移除对 Docker Schema 1 图像的支持。

老版本镜像就别用了。这个在上文说过,ctr deprecations list 不一定检测得到。建议删除所有镜像重新拉取后再检测 deprecations。

io_uring_* 系统调用默认被禁止

以下系统调用 (io_uring_enterio_uring_register, 和 io_uring_setup) 已从默认的 Seccomp 配置文件允许列表中移除。许多报告的 Linux 内核漏洞与 io_uring 有关,使用它无法推荐为默认允许列表的一部分。

找了一下 kubernetes 使用 Seccomp 的方法,如果还想使用,可以使用自定义列表:使用 seccomp 限制容器的系统调用 | Kubernetes

LimitNOFILE 配置已被移除

Remove `LimitNOFILE` from `containerd.service` by polarathene · Pull Request #8924 · containerd/containerd · GitHub

containerd 的资源限制(rlimits)由容器继承,因此守护进程的 LimitNOFILE 会影响容器内的 RLIMIT_NOFILE。建议使用默认的 systemd LimitNOFILE 配置。

功能

参考资料