Kubernetes containerd运行时如何使用本地自定义镜像
问题场景
使用containerd作为容器运行时的Kubernetes集群中,尝试使用本地docker build构建的app:latest镜像部署工作负载:
本地镜像信息如下:
REPOSITORY TAG IMAGE ID CREATED SIZE app latest 726b53fd88c1 About an hour ago 932MB
直接在Deployment中配置镜像名为app时,Pod状态为ErrImagePull,伴随镜像拉取退避事件,报错信息如下:
Failed to pull image "app": rpc error: code = Unknown desc = failed to
pull and unpack image "docker.io/library/app:latest": failed to
resolve reference "docker.io/library/app:latest": pull access denied,
repository does not exist or may require authorization: server
message: insufficient_scope: authorization failed
初步排查时执行ctr images ls未查询到对应镜像,将镜像导入containerd后可通过命令查询到镜像存在:
REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/library/app:latest application/vnd.docker.distribution.manifest.v2+json sha256:9e12e07a860f91b713adbb9d5752aef364328afc468d1ccc1af6a31ca464fd78 910.5 MiB linux/amd64 -
但在Deployment中填写上述完整REF路径后,仍然出现完全一致的镜像拉取报错。
问题根因
报错持续存在由两个核心配置错误导致:
- containerd通过命名空间做资源隔离,
ctr命令默认操作default命名空间下的资源,但Kubernetes的kubelet组件调用containerd时使用的是*k8s.io命名空间*。此前导入的镜像存放在default命名空间下,kubelet完全无法感知到该本地镜像。 - Kubernetes的镜像拉取策略默认规则:当镜像tag为
latest时,imagePullPolicy默认值为Always,会强制从远程镜像仓库拉取镜像,忽略本地存储的镜像文件,因此持续抛出远程仓库拉取权限错误。
正确操作步骤
按照以下流程操作即可正常使用本地自定义镜像部署工作负载:
- 从本地Docker环境导出镜像为tar压缩包
执行命令:docker save app:latest -o app.tar - 将镜像导入containerd的
k8s.io命名空间(必须指定命名空间参数,否则导入位置无效)
执行命令:
导入完成后执行验证命令,能查询到对应镜像即代表导入位置正确:ctr -n k8s.io images import app.tarctr -n k8s.io images ls | grep app - 修改工作负载的镜像拉取策略
在Deployment/Pod的容器配置段,将imagePullPolicy设置为IfNotPresent(本地存在镜像则不拉取)或Never(仅使用本地镜像,从不拉取),配置示例如下:containers: - name: app image: app:latest # 也可填写完整REF路径docker.io/library/app:latest,需和导入的镜像REF完全匹配 imagePullPolicy: IfNotPresent - 多节点集群场景下,需要在所有可能调度该Pod的节点上重复执行步骤1、2的镜像导入操作,否则目标节点无本地镜像时仍会触发拉取报错。
注意事项
- 所有使用
ctr操作Kubernetes相关镜像/容器的场景,都必须携带-n k8s.io参数指定命名空间,否则操作的资源对Kubernetes不可见。 - 配置中填写的
image字段值必须和导入到k8s.io命名空间的镜像REF完全一致,否则containerd无法匹配到本地镜像。 - 如果镜像使用自定义tag(非
latest),默认imagePullPolicy即为IfNotPresent,无需手动修改,但仍需确保镜像导入到正确的containerd命名空间。
内容的提问来源于stack exchange,提问作者Rodr
相关产品推荐
相关产品推荐

