3. 镜像拉取策略详解:Always、IfNotPresent、Never 策略的适用场景与配置方法

在 Kubernetes Deployment 的灾备与生产运维中,镜像拉取策略(imagePullPolicy)直接决定了 Pod 在启动时如何获取容器镜像。错误的策略配置可能导致版本回滚失败、镜像拉取超时、离线环境部署异常等严重故障。本章将系统解析三种策略的核心差异、适用场景与 YAML 配置方法。

3.1 三种策略的核心对比

策略值 行为描述 kubelet 检查逻辑 默认触发条件
Always 每次启动 Pod 时,kubelet 都会向镜像仓库发起拉取请求 无论本地是否存在同名镜像,都执行 docker pull 或 crictl pull 镜像标签为 :latest 时的默认策略
IfNotPresent 仅当本地节点上不存在该镜像时,才从仓库拉取 先检查本地镜像缓存,命中则直接启动;未命中则拉取 镜像标签为具体版本号(如 :v1.2.3)时的默认策略
Never 从不主动拉取镜像,仅使用本地已存在的镜像 直接检查本地镜像缓存,若不存在则 Pod 启动失败(ErrImageNeverPull) 需显式设置,无默认触发场景
关键认知: 策略的选择本质是 「一致性」与「效率」 的权衡。Always 保证每次运行的都是仓库最新版本,但增加了启动延迟和仓库压力;IfNotPresent 在版本固定时效率最高;Never 适用于完全离线的灾备环境。

3.2 策略适用场景详解

3.2.1 Always:强制一致性场景

  • 开发/测试环境: 频繁推送 :latest 标签,需要每次 Pod 重建时立即获取最新代码。
  • 金丝雀发布与滚动更新: 配合 Deployment 的 strategy 字段,确保新 Pod 拉取的是仓库中最新的稳定版本。
  • 镜像仓库存在覆盖推送: 当同一标签(如 :v2.0)被多次覆盖推送时,Always 可避免使用过期的本地缓存。

3.2.2 IfNotPresent:效率优先场景

  • 生产环境固定版本部署: 使用语义化版本号(如 :v3.1.4),镜像内容不可变,本地缓存可大幅加速 Pod 启动。
  • 大规模集群滚动更新: 减少对镜像仓库的并发拉取请求,避免仓库限流或网络带宽瓶颈。
  • 离线或弱网络灾备节点: 节点已通过预加载或 P2P 分发拥有镜像,无需再次拉取。

3.2.3 Never:完全离线与安全隔离场景

  • 气隙环境(Air-Gapped): 集群节点无法访问外部仓库,所有镜像通过 USB 或内部 Registry 提前导入。
  • 安全合规审计: 禁止 Pod 运行时从外部网络拉取任何镜像,所有镜像必须经过安全扫描并固化在节点上。
  • 故障演练与灾备恢复: 模拟仓库不可用时,验证本地缓存镜像能否支撑业务启动。
灾备陷阱: 在灾备切换场景中,若使用 Always 策略且仓库处于故障状态,即使节点本地已有正确版本的镜像,Pod 也会因拉取超时而启动失败。灾备集群应优先使用 IfNotPresent 或 Never。

3.3 配置方法与 YAML 示例

镜像拉取策略在 Pod 规约的 containers 字段中通过 imagePullPolicy 指定。以下展示三种策略的完整配置片段:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-production
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: app
        # 场景一:Always —— 强制拉取最新镜像
        image: registry.example.com/app:latest
        imagePullPolicy: Always

        # 场景二:IfNotPresent —— 仅本地缺失时拉取
        # image: registry.example.com/app:v3.1.4
        # imagePullPolicy: IfNotPresent

        # 场景三:Never —— 仅使用本地镜像
        # image: registry.example.com/app:v3.1.4
        # imagePullPolicy: Never
配置要点:
  • 若 imagePullPolicy 字段未显式定义,Kubernetes 根据镜像标签自动推断:标签为 :latest 或未指定标签时默认为 Always;其他标签默认为 IfNotPresent。
  • Never 策略必须显式声明,不存在自动推断场景。
  • 当 imagePullSecrets 配置了私有仓库认证信息时,Always 策略每次拉取都会使用该凭证;IfNotPresent 仅在首次拉取时使用。

3.4 镜像拉取策略决策流程

下图展示了 kubelet 在启动容器时,根据 imagePullPolicy 执行的核心决策路径:

kubelet 镜像拉取策略决策流程 Pod 调度到节点 imagePullPolicy 值判断 Always 强制拉取镜像 IfNotPresent 检查本地镜像缓存 Never 仅使用本地镜像 拉取成功? 是 → 启动容器 本地存在? 是 → 直接启动 本地存在? 是 → 直接启动 拉取失败 / 镜像缺失 Pod 状态:ImagePullBackOff

3.5 灾备场景下的策略选择建议

灾备场景 推荐策略 理由
主集群故障,切换至灾备集群 IfNotPresent 灾备集群节点已通过预加载拥有镜像,避免依赖仓库可用性
仓库完全不可用(网络中断) Never 彻底禁止拉取动作,仅依赖节点本地镜像,防止启动超时
灾备演练:验证本地镜像版本 Never 确保演练过程中不会意外拉取到仓库中的错误版本
跨地域多集群镜像同步 IfNotPresent 配合 P2P 分发或预热工具,减少跨地域拉取延迟
金丝雀发布到灾备集群 Always 确保新版本镜像被正确拉取,避免使用旧缓存导致验证失败
最佳实践: 在 Deployment 的 template.spec 中,建议为生产容器显式设置 imagePullPolicy: IfNotPresent,并配合 image: myapp:v1.2.3 这种不可变标签。这既能保证版本一致性,又能利用本地缓存加速启动。仅在需要强制刷新镜像时(如紧急修复),临时修改为 Always。