4. 容器镜像仓库与制品管理

在云原生应用交付链路中,镜像仓库不只是“存放镜像的地方”,它是构建产物进入生产环境前的最后一道可控关口。Amazon ECR(Elastic Container Registry)提供私有仓库、镜像扫描、跨区域复制、生命周期策略、镜像签名等能力,配合 ECR Public 可以形成从构建、存储、分发到验证的完整制品供应链。本节围绕“如何把镜像安全地管起来”展开,重点讲清仓库创建、扫描机制、复制策略、生命周期规则以及签名验证的实际做法。

私有仓库的创建与访问控制

ECR 私有仓库的最小创建单元是 repository,命名通常采用 应用名/组件名 的形式,例如 order-service/api。创建时建议开启 tag immutability(标签不可变),这样同一个 tag 不能被重复推送覆盖,避免“latest 被悄悄替换”导致生产环境拉取到非预期镜像。访问控制通过 IAM 策略和仓库策略两层实现:IAM 决定“谁可以调用 ECR API”,仓库策略决定“哪些账号或角色可以拉取/推送该仓库”。在跨账号场景中,通常由共享账号在仓库策略中授予业务账号 ecr:BatchGetImage、ecr:GetDownloadUrlForLayer 等拉取权限,而不是直接共享凭证。

推送镜像的标准流程如下,其中 aws ecr get-login-password 返回的临时令牌有效期约 12 小时,适合在 CI 流水线中动态获取:

aws ecr create-repository \
  --repository-name order-service/api \
  --image-tag-mutability IMMUTABLE \
  --image-scanning-configuration scanOnPush=true \
  --region cn-north-1

aws ecr get-login-password --region cn-north-1 | \
  docker login --username AWS --password-stdin \
  123456789012.dkr.ecr.cn-north-1.amazonaws.com

docker tag order-api:v1.4.2 \
  123456789012.dkr.ecr.cn-north-1.amazonaws.com/order-service/api:v1.4.2

docker push 123456789012.dkr.ecr.cn-north-1.amazonaws.com/order-service/api:v1.4.2

镜像扫描:基础扫描与增强扫描

ECR 提供两种扫描方式。基础扫描(Basic scanning)基于开源 Clair 规则库,支持 scanOnPush 在推送时自动触发,也可手动调用 start-image-scan;它覆盖操作系统包漏洞,但不检测编程语言依赖。增强扫描(Enhanced scanning,基于 Amazon Inspector)可以同时检测 OS 包和语言级依赖(如 Maven、npm、Python 包),并支持持续扫描——当新漏洞披露时自动重新评估已有镜像。对于生产级供应链,建议对关键仓库启用增强扫描,并把 scan frequency 设为 CONTINUOUS_SCAN。

扫描结果可通过 describe-image-scan-findings 查看,关键字段是 severity(CRITICAL/HIGH/MEDIUM/LOW)和 fixAvailable。实践中常见的门禁做法是:在 CI 中拉取扫描结果,若存在 CRITICAL 且 fixAvailable=true 的漏洞,则阻断部署并输出漏洞列表。需要注意,扫描是异步的,推送后立即查询可能返回 IN_PROGRESS,应轮询直到 COMPLETE 再判断。

跨区域复制与生命周期策略

跨区域复制用于把镜像自动同步到其他 Region,典型场景是多地部署时让各 Region 就近拉取,降低跨区流量和拉取延迟。复制在仓库级别配置,可指定目标 Region、目标仓库前缀,甚至跨账号复制。复制是异步的,源仓库推送成功后目标仓库通常在数十秒内出现同名镜像;若目标仓库不存在且未开启自动创建,复制会失败,因此建议在规则中允许自动创建目标仓库。

生命周期策略(Lifecycle Policy)解决“镜像越积越多”的问题。策略由规则组成,每条规则包含 selection(tagStatus、tagPrefixList、countType、countNumber)和 action(expire)。例如:保留最近 30 个带 v 前缀的发布镜像,超过 30 天且未被任何 tag 引用的 untagged 镜像自动过期。规则按优先级从低到高执行,rulePriority 越小越先匹配。一个常见误区是把 countType 设为 imageCountMoreThan 时忘记限制 tagStatus,导致把正在使用的发布镜像也清理掉,因此建议对发布 tag 和临时 tag 分别建规则。

Amazon ECR 容器制品供应链 构建 → 推送 → 扫描 → 复制 → 生命周期 → 签名验证 → 部署 CI 构建 docker build tag: v1.4.2 推送至 ECR order-service/api tag 不可变 ECR 私有仓库 cn-north-1 scanOnPush = true IAM + 仓库策略 镜像扫描 Basic / Enhanced OS 包 + 语言依赖 CRITICAL 阻断门禁 跨区域复制 异步同步镜像 目标 Region / 跨账号 允许自动创建仓库 目标 Region 仓库 cn-south-1 就近拉取 降低跨区流量 生命周期策略 保留最近 30 个 v* 发布镜像 untagged 超过 30 天自动过期 rulePriority 由小到大匹配 镜像签名与验证 cosign sign / verify 签名存于 ECR 关联 OCI 制品 部署前校验签名与摘要 部署到 EKS / ECS 按 digest 拉取 签名验证通过才准入 扫描无 CRITICAL ECR Public 公开基础镜像 / 工具镜像 匿名拉取,无需认证 仅用于非敏感制品 关键控制点:tag 不可变 · 推送即扫描 · 跨区复制 · 生命周期清理 · 签名验证 · 按 digest 部署

镜像签名与供应链验证

扫描解决“已知漏洞”,签名解决“来源可信与未被篡改”。ECR 本身不内置签名服务,但支持存储 OCI 关联制品,因此可以用 cosign 把签名作为独立制品推送到同一仓库。典型做法是:CI 构建完成后用私钥对镜像 digest 签名,部署侧在准入控制器(如 Kyverno、OPA Gatekeeper)中调用 cosign verify,只有签名有效且公钥匹配的镜像才允许创建 Pod。签名应绑定 digest 而非 tag,因为 tag 可变,digest 才是内容寻址的唯一标识。

cosign sign --key aws-kms://arn:aws:kms:cn-north-1:123456789012:key/abcd-... \
  123456789012.dkr.ecr.cn-north-1.amazonaws.com/order-service/api@sha256:9f2c...

cosign verify --key aws-kms://arn:aws:kms:cn-north-1:123456789012:key/abcd-... \
  123456789012.dkr.ecr.cn-north-1.amazonaws.com/order-service/api@sha256:9f2c...

ECR Public 则用于托管可公开分发的镜像,例如团队自研的基础镜像、CLI 工具镜像。它支持匿名拉取,适合作为公共依赖源,但绝不能把含内部配置、密钥或业务代码的镜像推到 Public。实践中常见的组合是:基础镜像发布到 ECR Public,业务镜像存放在私有 ECR,构建时从 Public 拉取基础层,最终制品只进私有仓库。

一个可落地的仓库治理参数示例

下表给出一组示例参数,用于说明如何把上述能力组合成可执行的治理规则。参数为教学示例,实际取值需结合团队发布节奏和合规要求调整。

治理项示例配置作用
tag 不可变IMMUTABLE防止发布 tag 被覆盖
推送扫描scanOnPush=true,增强扫描推送即检测 OS 与语言依赖漏洞
扫描门禁CRITICAL 且 fixAvailable 则阻断阻止高危镜像进入部署
跨区复制cn-north-1 → cn-south-1就近拉取,降低延迟与流量
生命周期保留 30 个 v*,untagged 30 天过期控制存储成本,保留发布版本
签名验证cosign + KMS 密钥,按 digest 校验确保镜像来源可信、未被篡改
建议把“扫描结果查询”和“签名验证”都放进 CI 的部署前阶段,而不是只依赖人工检查。扫描是异步的,轮询到 COMPLETE 后再判断;签名验证要针对 digest,不要针对 tag。
生命周期策略一旦误配,可能删除仍在使用的镜像。建议先对非生产仓库启用规则并观察一段时间,确认清理范围符合预期后再推广到生产仓库;对发布 tag 与临时 tag 分别设置规则,避免“一刀切”。

把以上能力串起来,ECR 就不只是镜像存储,而是可审计、可复制、可清理、可验证的制品供应链节点。构建产物从进入仓库那一刻起,就带着扫描结论、复制状态、生命周期归属和签名信息,部署侧只需按 digest 拉取并验证签名,即可在“能跑”之外回答“这个镜像是否可信、是否安全、是否该保留”。