3、镜像拉取流程详解:kubelet → containerd → registry 的完整链路、镜像凭证的传递机制

在多集群与混合云环境中,镜像拉取是工作负载调度的核心前置动作。理解从 kubelet 发起请求,经过 containerd 运行时,最终到达远端 registry 的完整链路,以及镜像凭证(Image Pull Secret)在其中的传递与生效机制,是配置 Cilium 网络策略、保障跨集群拉取权限的基础。

3.1 镜像拉取的三段式架构

整个拉取流程可抽象为三个角色、两个接口:

角色 组件 职责 网络出口
调度者 kubelet 解析 PodSpec,获取镜像名与凭证引用,调用 CRI 接口 本地 Unix Socket
执行者 containerd (CRI) 接收拉取指令,管理镜像层缓存,发起 HTTPS 请求 节点 eth0 / 隧道接口
存储者 Registry (Harbor / ECR / GCR / Docker Hub) 鉴权、限流、返回镜像层 Blob 公网 / 专线 / VPC 端点
关键认知: kubelet 本身不直接与 registry 建立 TCP 连接。所有镜像层数据的传输均由 containerd 进程完成。因此,Cilium 网络策略的生效点应聚焦于 containerd 的出站流量,而非 kubelet。

3.2 完整拉取时序与凭证传递

以下 SVG 展示了从 Pod 创建到镜像层下载的完整时序,并标注了凭证(Image Pull Secret)的传递路径:

镜像拉取时序与凭证传递链路 kubelet containerd Registry 镜像缓存 ① PullImage(ImageSpec, AuthConfig) ② 检查本地缓存 (containerd 元数据) ③ 缓存未命中,发起 HTTPS GET ④ 鉴权 (Bearer / Basic Auth) ⑤ 返回 Manifest + Blob 列表 ⑥ 逐层下载 Blob (并发) ⑦ 写入本地缓存 + 解压 ⑧ 返回 SandboxImage 就绪 凭证传递关键路径 kubelet 从 PodSpec.ImagePullSecrets 读取 Secret → 通过 CRI AuthConfig 传给 containerd containerd 将 AuthConfig 组装为 HTTP Authorization Header → 发送至 Registry

3.3 凭证传递的三种模式

根据集群配置与 registry 类型,凭证传递存在三种典型模式:

模式 凭证来源 传递方式 适用场景
Pod 级别 PodSpec.imagePullSecrets kubelet 通过 CRI AuthConfig 传入 containerd 多租户隔离、不同应用使用不同 registry 账号
节点级别 /var/lib/kubelet/config.json 或 containerd 配置 containerd 启动时读取,无需 kubelet 传递 所有 Pod 共享同一 registry 凭证(如私有 Harbor)
云厂商 IAM 节点实例角色 / ServiceAccount containerd 调用云厂商 SDK 获取临时 EKS/GKE/AKS 使用 ECR/GCR/ACR
最佳实践: 在多集群场景下,推荐使用节点级别 + IAM 角色的组合。这可以避免在数百个命名空间中重复管理 ImagePullSecret,同时降低 Cilium 网络策略的复杂度——你只需要放通 containerd 到 registry 的出站,而不需要为每个 Secret 单独配置策略。

3.4 containerd 出站流量的网络特征

从 Cilium 网络策略配置的角度,containerd 的出站流量具有以下关键特征:

  • 目标端口: 443 (HTTPS) 或 5000 (HTTP,私有 registry)
  • 目标 IP: registry 域名解析后的 A 记录 / CNAME
  • 协议: TCP,TLS 1.2/1.3
  • 源端点: 节点 IP(非 Pod IP),因为 containerd 运行在宿主机命名空间
  • DNS 依赖: 必须先解析 registry 域名,否则 containerd 无法建立连接
常见陷阱: 许多工程师在配置 Cilium 网络策略时,错误地将源端点设置为 Pod CIDR 或特定 Pod 标签。实际上,containerd 的镜像拉取流量不经过 Pod 网络命名空间,它直接从宿主机 eth0 发出。因此,策略必须使用 fromEntities: host 或基于节点标签的 EndpointSelector 来匹配 containerd 的出站流量。

3.5 凭证传递失败时的典型错误码

理解以下错误码有助于快速定位凭证或网络问题:

错误码 含义 常见原因 排查方向
401 Unauthorized 凭证无效或缺失 ImagePullSecret 过期、Secret 名称错误、IAM 角色未绑定 检查 Secret 内容与 registry 账号是否匹配
403 Forbidden 凭证有效但无权限 registry 项目权限未授权、镜像不存在、跨账号拉取未配置 检查 registry 项目成员与镜像可见性
429 Too Many Requests 限流 Docker Hub 匿名拉取限制、Harbor 配额耗尽 配置镜像缓存或使用认证账号
502 Bad Gateway 网络链路中断 Cilium 策略阻断、NAT 网关故障、TLS 拦截 检查 Cilium 策略日志与 Hubble 流量

3.6 链路中各层的安全控制点

以下 SVG 从安全控制视角,展示镜像拉取链路中每一层可施加的策略与检查点:

镜像拉取链路安全控制点 kubelet 准入控制 / 凭证校验 containerd 镜像签名验证 / 缓存策略 节点网络 Cilium 网络策略 / eBPF Registry 鉴权 / 限流 / 审计 控制点 1:准入 Webhook 校验 ImagePullSecret 是否存在、是否过期、是否与 registry 匹配 控制点 2:镜像策略引擎 验证镜像签名 (Cosign/Notary)、检查镜像来源白名单 控制点 3:Cilium 网络策略 限制 containerd 仅可访问特定 registry IP/域名,阻断恶意出站 控制点 4:Registry 访问控制 基于 IP 白名单、OIDC 令牌、机器人账号的细粒度权限

3.7 多集群场景下的凭证传递挑战

当镜像拉取跨越集群边界时,凭证传递面临以下额外挑战:

  • 凭证同步延迟: 在 Cluster A 中创建的 ImagePullSecret 不会自动同步到 Cluster B,需要外部工具(如 External Secrets Operator)进行跨集群同步。
  • Registry 域名解析差异: 不同集群可能使用不同的 DNS 解析策略(CoreDNS / NodeLocal DNSCache),导致 containerd 解析到不同的 registry IP。
  • 网络策略碎片化: 每个集群的 Cilium 策略需要独立配置 containerd 到 registry 的出站规则,且需保持策略一致性。
  • IAM 角色跨集群信任: 使用云厂商 IAM 时,需要建立跨集群的 OIDC 信任关系,否则 containerd 无法获取有效的临时凭证。
核心结论: 镜像拉取凭证的传递本质上是身份与网络的双重信任链。kubelet 负责身份传递,containerd 负责网络执行,Cilium 负责网络边界控制。在多集群环境中,这三层必须协同工作,任何一层的断裂都会导致 Pod 启动失败。