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)的传递路径:
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 从安全控制视角,展示镜像拉取链路中每一层可施加的策略与检查点:
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 启动失败。