导读:本期聚焦于高建功创作的《Kubernetes 中 Docker 镜像拉取策略有哪些?如何正确选择?》,敬请观看详情。镜像拉取失败的原因经常被误判为网络抖动,实际上 imagePullPolicy 与镜像标签的组合才是关键变量。Kubernetes 为 Pod 的容器镜像提供了 Always、IfNotPresent、Never 三种拉取策略,默认取值与镜像标签是否 latest 直接相关。很多集群里出现节点本地已有镜像却仍然拉取、或者标签变化但 Pod 未更新的问题,往往就来自策略配置不当。本文从策略语义、默认规则、生产环境标签规范、私有仓库凭证以及 containerd 等运行时差异几个角度展开,帮助读者理解如何在不同场景下选择 imagePullPolicy,并通过具体 YAML 示例与排查命令避开常见误区。文中提到的 Docker 镜像同样遵循 OCI 标准,配置方式与容器运行时无关。

在 Kubernetes 中,容器镜像的拉取行为并不由节点上是否已经存在镜像单独决定,而是由 Pod 规范中的 imagePullPolicy 字段显式控制。该字段定义了 kubelet 在创建容器时如何从镜像仓库获取镜像,取值可以是 Always、IfNotPresent 或 Never。理解这三种策略的默认逻辑,对保证应用发布的一致性和避免启动失败至关重要。

Kubernetes 中 Docker 镜像拉取策略有哪些?如何正确选择?

imagePullPolicy 直接作用于每一个容器的镜像拉取阶段。即使两个容器使用相同镜像,只要策略不同,Kubernetes 调度到同一节点后也可能触发不同的仓库请求。接下来从取值语义、默认规则以及生产环境常见问题几个方面详细展开。

imagePullPolicy 的三种取值与默认规则

imagePullPolicy 支持三种取值。Always 表示每次创建 Pod 时都向镜像仓库发起拉取请求,即使节点本地已经存在相同的镜像名称和标签,也会检查远端仓库;IfNotPresent 表示仅当节点本地不存在指定镜像时才从仓库拉取,如果本地已有缓存则直接使用;Never 表示完全禁止自动拉取,节点上必须事先存在对应镜像,否则容器会启动失败。

当 Pod 或 Deployment 中没有显式设置 imagePullPolicy 时,Kubernetes 会根据镜像标签自动推断。如果镜像标签是 latest,或者镜像名称中完全没有指定标签,例如只写了 nginx,那么默认策略会变为 Always。如果指定了明确的非 latest 标签,例如 nginx:1.25.3,则默认策略为 IfNotPresent。这一规则容易被忽略,很多团队在测试环境写 nginx 时没有显式声明策略,结果每次创建 Pod 都会向 Docker Hub 发起请求,遇到限流后出现拉取失败。

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
spec:
  containers:
  - name: app
    image: nginx:1.25.3
    imagePullPolicy: IfNotPresent
  - name: sidecar
    image: busybox:latest
    imagePullPolicy: Always

从上面示例可以看出,同一个 Pod 的不同容器可以拥有不同的拉取策略。第一个容器使用具体版本标签并显式指定 IfNotPresent,节点已有 nginx:1.25.3 时就不会访问仓库;第二个容器使用 latest 标签并指定 Always,即使节点已经有 busybox:latest,kubelet 仍然会尝试从仓库拉取最新内容。这种组合在应用主容器与辅助容器之间很常见,但需要明确各自行为,避免误判。

latest 标签的隐患与镜像标签规范

latest 标签在 Kubernetes 中非常容易引发问题。它并不是一个不可变标签,镜像仓库允许 latest 指向任意一次构建结果。如果部署时没有指定其他标签,同一份 YAML 在不同时间执行可能拉取到完全不同的镜像,导致滚动更新过程不可控。更麻烦的是,不同节点上的 latest 镜像缓存可能不一致,因为每个节点是否拥有旧缓存取决于历史调度情况,最终会出现同一个 Deployment 中部分 Pod 运行新版本、部分 Pod 运行旧版本的割裂状态。

生产环境强烈建议使用不可变标签,例如语义化版本号或 Git Commit SHA。持续集成完成构建后,将镜像推送到仓库时打上唯一标签,并在 Kubernetes 资源配置中引用该标签。这样可以保证每次部署内容确定,同时配合 IfNotPresent 提高启动速度,因为节点只需要在首次拉取时访问仓库。下面是一个推荐写法。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: registry.ipipp.com/web:v1.4.2
        imagePullPolicy: IfNotPresent

如果团队出于调试目的必须使用 latest 标签,建议显式设置 imagePullPolicy 为 Always,以确保每次创建 Pod 都能获取最新镜像。但这种做法会增加仓库访问频率,还可能受到 Docker Hub 等公共仓库的速率限制。更好的替代方案是在每次构建时生成唯一标签,这样既不用依赖 latest 的变动语义,也能保持镜像来源清晰可追溯。

私有镜像仓库与 imagePullSecrets

拉取私有镜像仓库中的镜像时,Kubernetes 需要携带认证信息。认证信息存储在 Secret 对象中,类型为 kubernetes.io/dockerconfigjson。可以通过 kubectl create secret docker-register 命令从命令行参数直接生成,也可以从本机 Docker 配置文件导入。创建完成后,在 Pod 或 Deployment 中通过 imagePullSecrets 字段引用。

kubectl create secret docker-registry regcred \
  --docker-server=registry.ipipp.com \
  --docker-username=admin \
  --docker-password=secret \
  --docker-email=admin@ipipp.com \
  -n production

上述命令会在 production 命名空间下创建名为 regcred 的 Secret,其中包含访问 registry.ipipp.com 所需的账号密码。需要注意的是,Secret 是命名空间级资源,同一个 Secret 不能跨命名空间使用,如果多个命名空间都需要访问同一私有仓库,必须在每个命名空间分别创建。也可以在 Pod 规范中引用不同的 Secret,以应对多个私有仓库并存的情况。

apiVersion: v1
kind: Pod
metadata:
  name: private-pod
  namespace: production
spec:
  imagePullSecrets:
  - name: regcred
  containers:
  - name: app
    image: registry.ipipp.com/team/app:v2.0.1
    imagePullPolicy: IfNotPresent

除了在每个 Pod 中重复声明 imagePullSecrets,还可以把凭证绑定到 ServiceAccount。通过给 default 或其他 ServiceAccount 打补丁,可以让使用该 ServiceAccount 的 Pod 自动附加镜像拉取凭证,减少配置重复。命令示例如下。

kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "regcred"}]}' -n production

这样做之后,该命名空间下未显式指定 ServiceAccount 的 Pod 也会自动挂载 regcred。需要提醒的是,为 default ServiceAccount 自动附加凭证会作用于所有新建 Pod,如果某些 Pod 不需要私有仓库权限,也可能因此无意中携带访问凭证,安全上需要谨慎评估。更精细的做法是创建专用 ServiceAccount,并只给需要访问私有仓库的工作负载使用。

容器运行时差异与拉取失败排查

Kubernetes 从 1.24 版本开始移除了 dockershim,节点上的容器运行时通常使用 containerd 或 CRI-O。Docker 镜像本身遵循 OCI 标准,所以 containerd 可以直接拉取 Docker 构建的镜像,但节点上 Docker 命令看到的本地镜像与 containerd 的镜像存储并不共享。如果运维人员习惯用 docker images 检查节点镜像,却看到 Kubernetes 仍然报镜像拉取失败,很可能就是运行时不同导致误解。此时应改用 crictl images 查看实际供 Kubernetes 使用的镜像存储。

当 Pod 状态长时间处于 ImagePullBackOff 或 ErrImagePull 时,首先通过 kubectl describe pod 查看 Events 中的具体错误信息。常见原因包括镜像标签不存在、仓库域名无法解析、认证失败或节点磁盘空间不足。可以进一步在节点上执行 crictl pull 来验证运行时是否能单独拉取该镜像,从而判断问题出在 Kubernetes 层面还是运行时或网络层面。

kubectl describe pod private-pod -n production | tail -20
crictl images | grep web
crictl pull registry.ipipp.com/team/app:v2.0.1

如果 crictl pull 也失败,需要检查节点到仓库的网络连通性,以及 containerd 配置文件中的镜像仓库 TLS 配置。containerd 的认证和镜像仓库配置位于 /etc/containerd/config.toml,与早期 Docker daemon 的配置位置不同。私有仓库使用自签名证书时,需要在 containerd 中正确配置证书路径,否则即使 Secret 正确也无法建立安全连接。对于集群管理员来说,理解运行时差异可以大幅缩短镜像拉取故障的定位时间。

总结而言,imagePullPolicy 看似只有三个取值,但它与镜像标签、私有仓库凭证、运行时存储以及网络环境紧密相关。选择 IfNotPresent 能提升启动效率,但需要保证标签不可变;选择 Always 能避免缓存不一致,却会带来额外流量和限流风险。将策略与镜像标签规范、Secret 管理以及运行时特点结合起来,才能在 Kubernetes 中稳定高效地拉取 Docker 镜像。

Kubernetes镜像拉取策略Docker修改时间:2026-08-23 16:34:07

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。