如何让K8s的imagePullPolicy=Never在主节点正常生效?
问题:本地镜像存在但Pod报ErrImageNeverPull无法启动
我按照博客指导创建简单容器镜像并部署到K8s集群,但Pod无法运行:
student@master:~$ k get pod -o wide -l app=hello-python --field-selector spec.nodeName=master NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES hello-python-58547cf485-7l8dg 0/1 ErrImageNeverPull 0 2m26s 192.168.219.126 master <none> <none> hello-python-598c594dc5-4c9zd 0/1 ErrImageNeverPull 0 2m26s 192.168.219.67 master <none> <none> student@master:~$ sudo podman images hello-python REPOSITORY TAG IMAGE ID CREATED SIZE localhost/hello-python latest 11cf1e5a86b1 50 minutes ago 941 MB student@master:~$ hostname master student@master:~$
我原以为问题出在worker节点,但为何在已缓存镜像的master节点也无法运行?查看Pod事件:
student@master:~$ k describe pod hello-python-58547cf485-7l8dg | grep -A 10 'Events:' Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 10m default-scheduler Successfully assigned default/hello-python-58547cf485-7l8dg to master Warning Failed 8m7s (x12 over 10m) kubelet Error: ErrImageNeverPull Warning ErrImageNeverPull 4m59s (x27 over 10m) kubelet Container image "localhost/hello-python:latest" is not present with pull policy of Never student@master:~$
核心问题:在master节点已通过podman images确认存在hello-python镜像的情况下,如何让设置了imagePullPolicy=Never的Pod在master节点正常运行?
补充说明:
- 集群是部署在GCE上的双VM K8s集群,由Linux Foundation的Kubernetes开发者课程LFD0259提供的脚本搭建。
- master节点允许运行工作负载,为课程默认配置,示例如下:
student@master:~$ k create deployment xyz --image=httpd deployment.apps/xyz created student@master:~$ k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES xyz-6c6bd4cd89-qn4zr 1/1 Running 0 5m37s 192.168.171.66 worker <none> <none> student@master:~$ student@master:~$ k scale deployment xyz --replicas=10 deployment.apps/xyz scaled student@master:~$ k get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES xyz-6c6bd4cd89-c2xv4 1/1 Running 0 73s 192.168.219.71 master <none> <none> xyz-6c6bd4cd89-g89k2 0/1 ContainerCreating 0 73s <none> master <none> <none> xyz-6c6bd4cd89-jfftl 0/1 ContainerCreating 0 73s <none> worker <none> <none> xyz-6c6bd4cd89-kbdnq 1/1 Running 0 73s 192.168.219.106 master <none> <none> xyz-6c6bd4cd89-nm6rt 0/1 ContainerCreating 0 73s <none> worker <none> <none> xyz-6c6bd4cd89-qn4zr 1/1 Running 0 7m22s 192.168.171.66 worker <none> <none> xyz-6c6bd4cd89-vts6x 1/1 Running 0 73s 192.168.171.84 worker <none> <none> xyz-6c6bd4cd89-wd2ls 1/1 Running 0 73s 192.168.171.127 worker <none> <none> xyz-6c6bd4cd89-wv4jn 0/1 ContainerCreating 0 73s <none> worker <none> <none> xyz-6c6bd4cd89-xvtlm 0/1 ContainerCreating 0 73s <none> master <none> <none> student@master:~$
解决方案
问题核心原因:kubelet依赖的容器运行时(通常是containerd)无法读取Podman存储的镜像。Podman与containerd默认使用不同的镜像存储路径和格式,因此你用Podman构建的镜像,kubelet无法识别。
可通过以下几种方法解决:
方法1:将Podman镜像导入到containerd中
- 把Podman镜像导出为tar包:
sudo podman save localhost/hello-python:latest -o hello-python.tar
- 将tar包导入到containerd存储:
sudo ctr images import hello-python.tar
- 验证镜像是否存在于containerd:
sudo ctr images list | grep hello-python
- 删除原有Pod,让Deployment重新创建实例:
k delete pod -l app=hello-python
方法2:直接用containerd构建镜像
如果后续需要修改镜像,直接使用containerd命令构建,避免跨存储的问题:
# 假设Dockerfile在当前目录 sudo ctr images build -t localhost/hello-python:latest .
方法3:修改imagePullPolicy为IfNotPresent(临时方案)
若仅需快速验证功能,可修改Deployment的镜像拉取策略:
k edit deployment hello-python
在编辑器中找到imagePullPolicy: Never,替换为imagePullPolicy: IfNotPresent,保存退出即可。
此方法仅绕过问题,未解决镜像存储不共享的根本矛盾,长期使用建议选择前两种方案。
内容的提问来源于stack exchange,提问作者mark
相关产品推荐
相关产品推荐

