Docker 19.03.9 还在用?containerd 2.1.6 已不认账
containerd 2.1.6 不再支持 Docker V1 镜像格式,导致 K8s 业务 Pod 拉取镜像失败。根因是 Jenkins 使用旧版 Docker 19.03.9 构建出 V1 格式镜像,而新版 containerd 已彻底移除对 V1 的支持。临时修复可通过 Docker 重新推送镜像自动转换为 V2 格式;长期方案是使用 buildx 或开启 BuildKit 构建 V2 标准镜像。
一、基本信息
-
涉及环境
-
K8s节点运行时:containerd 2.1.6(新版云原生运行时)
-
CI构建节点:Jenkins + Docker 19.03.9
-
镜像仓库:阿里云镜像仓库
-
-
故障影响:业务Pod无法启动,镜像拉取失败,服务部署中断,新版本业务无法上线
二、故障现象
1. 业务现象
K8s业务Pod状态持续为ErrImagePull,卡在镜像拉取阶段,无法正常创建启动,新版本业务无法上线。
2. 核心报错日志
K8s节点containerd报错:
rpc error: code = Unimplemented desc = failed to pull and unpack image "镜像地址:v1.0": not implemented: media type "application/vnd.docker.distribution.manifest.v1+prettyjws" is no longer supported since containerd v2.1
Docker构建拉取镜像前置警告(长期被忽略):
[DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release.
三、根因深度分析
1. 核心技术根因(版本兼容断层)
containerd 2.1及以上版本官方彻底移除Manifest V1(Schema1)镜像解析代码,无任何配置参数可开启兼容,属于强制性规范废弃,并非程序Bug。老旧V1格式镜像在新版运行时中会被直接拦截拒绝拉取。
2. 构建端根源(镜像格式不标准)
Jenkins构建节点使用Docker 19.03.9,默认关闭BuildKit,采用老式传统构建引擎,打包产出的镜像为废弃的Manifest V1格式(mediaType:application/vnd.docker.distribution.manifest.v1+prettyjws),不符合新版containerd运行时规范。
3. 问题长期潜伏原因
-
旧版Docker 19.03.9内置containerd v1.2.13,兼容V1旧镜像,仅弹出警告、不阻断使用,问题长期未暴露;
-
集群升级containerd至2.1.6后,强校验镜像格式,直接触发故障;
-
运维人员未关注Docker官方弃用警告,无镜像格式校验流程。
4. 排查附加问题
Jenkins非登录Shell,不加载系统环境变量,全局环境变量配置不生效。
四、故障完整排查流程
-
通过
kubectl describe pod查看Pod事件,定位核心报错:镜像媒体类型不被containerd 2.1支持; -
排查节点containerd版本,确认2.1.6已废弃V1镜像兼容逻辑,排除运行时配置问题;
-
尝试通过skopeo校验镜像格式,因命令未安装、网络超时等问题改用Docker原生工具;
-
开启Docker实验特性,执行
docker manifest inspect校验,确认镜像为废弃V1格式; -
排除降级containerd方案(稳定性风险高),确定最优方案:统一镜像构建格式,适配新版运行时;
-
Jenkins安装buildx插件,改造构建流程,重新打包推送合规镜像;
-
校验镜像格式更新为V2标准,节点清理缓存后拉取镜像验证,重建Pod恢复业务。
五、故障修复方案(临时+长期)
1. 临时应急修复(存量旧镜像快速兼容)
针对仓库已存在的V1格式旧镜像,无需重新编译代码,直接通过Docker重新推送自动转换为V2格式,快速恢复业务:
# 拉取旧格式镜像
docker pull 镜像地址:v1.0
# 重新推送自动生成V2标准Manifest,覆盖原标签
docker push 镜像地址:v1.0
2. 长期根治方案(流水线标准化改造)
最优方案:Jenkins集成buildx构建(永久杜绝V1镜像)
步骤1:Jenkins节点安装buildx插件(一次性操作)
mkdir -p ~/.docker/cli-plugins
wget https://github.com/docker/buildx/releases/download/v0.17.1/buildx-v0.17.1.linux-amd64 -O ~/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx
docker buildx version
步骤2:初始化构建器(一次性操作)
docker buildx create --use --name main-builder
docker buildx inspect --bootstrap
步骤3:流水线构建命令替换
# 废弃旧构建命令
# docker build -t xxx:tag . && docker push xxx:tag
# 新合规构建命令(默认产出V2标准镜像)
docker buildx build -t 镜像地址:v1.0 --push .
3. 备选轻量化方案(无插件改造)
流水线Shell头部临时开启BuildKit,无需安装插件、无需重启Jenkins:
export DOCKER_BUILDKIT=1
docker build -t xxx:tag .
docker push xxx:tag
六、镜像合规校验标准流程(上线前置校验)
1. 远端镜像格式校验(推荐)
docker buildx imagetools inspect 镜像地址:tag
✅ 合规标准:MediaType 为application/vnd.docker.distribution.manifest.v2+json /application/vnd.oci.image.manifest.v1+json
❌ 违规标准:MediaType 为 application/vnd.docker.distribution.manifest.v1+prettyjws
2. K8s节点最终实测校验(权威验证)
# 清理节点旧镜像缓存
crictl rmi 镜像地址:v1.0
# 内网拉取测试
crictl pull 镜像地址:v1.0
无媒体类型报错即为完全兼容。
七、业务恢复操作步骤
-
K8s节点清理本地旧镜像缓存,避免缓存复用问题;
-
通过内网VPC域名拉取全新V2格式镜像,验证拉取成功;
-
删除异常Pod,触发Deployment自动重建Pod;
-
查看Pod运行状态、日志,确认业务正常启动,故障恢复。
八、问题总结与预防机制
1. 问题总结
本次故障本质是CI构建标准滞后于集群运行时标准,老旧Docker构建工具产出废弃格式镜像,新版containerd强校验拦截,属于典型的环境版本不兼容问题。故障长期潜伏的核心原因是团队忽略Docker官方弃用警告、无镜像格式校验机制。
2. 长期预防规范
-
统一构建标准:所有业务镜像强制使用buildx/BuildKit构建,杜绝V1格式镜像产出;
-
新增上线校验卡点:CI流水线新增镜像格式校验步骤,不合规镜像禁止推送上线;
-
规范环境配置:禁止通过
/etc/profile配置Jenkins环境变量,流水线变量统一脚本内声明; -
统一仓库访问规则:K8s运行端用内网VPC域名,规避网络超时问题;
-
跟进开源版本迭代:持续关注容器运行时、Docker官方废弃特性,提前适配规范,避免版本断层故障。
九、最终验证结果
故障镜像已完成格式升级,当前合规信息:
Name: 镜像地址:v1.0
MediaType: application/vnd.docker.distribution.manifest.v2+json
Digest: sha256:f72115d6ce286f1ee591e41b7a5587dafc94e2d686ee2e2ca759c9d3e3c2939a
镜像完全兼容containerd 2.1.6及以上所有新版运行时,业务部署恢复正常。