一次构建、多次部署的前提是制品被可靠地存放、标识与追溯。制品管理不只是「找个地方存镜像」,而是覆盖仓库选型、制品晋升、SBOM 生成、签名溯源到供应链门禁的一整条链路。本文沿着「构建出什么 → 存在哪里 → 怎么晋升 → 如何证明来源 → 怎么放行」的顺序,讲清一套可落地的制品与供应链治理方案。
目录
1. 制品与制品仓库
1.1 什么是制品
制品(artifact)是构建流水线产出的、被部署到运行环境的不可变产物:容器镜像、JAR/WAR 包、npm/PyPI 包、二进制、Helm Chart 等。制品的核心属性是「一旦生成就不再修改」,任何修改都意味着产生一个新制品。
1.2 制品仓库的职责
制品仓库不只是存储,它承担四件事:存储与分发、版本与元数据管理、访问控制、以及与安全扫描的集成。
| 职责 | 说明 |
|---|---|
| 存储分发 | 就近拉取、断点续传、缓存代理 |
| 版本元数据 | 标签、摘要、构建信息、依赖关系 |
| 访问控制 | 仓库级与路径级权限、令牌管理 |
| 安全集成 | 漏洞扫描、签名校验、准入拦截 |
1.3 本地缓存与代理
制品仓库通常还承担上游代理:缓存 Maven Central、npm registry、Docker Hub 的拉取结果。这既加速构建,又能在上游不可用时提供可用性保障,也是供应链攻击的拦截点。
2. 镜像仓库与包仓库
2.1 镜像仓库
镜像仓库管理 OCI 制品。主流选择有 Harbor(自建、功能全)、JFrog Artifactory(商业、多类型统一)、以及云厂商的 ECR、GAR、ACR。镜像用标签(tag)与摘要(digest)双重标识。
镜像标识
tag : 可变的友好名,如 order-service:v1.2.3
digest : 内容寻址的哈希,如 sha256:9f2a...
规则 :部署用 digest,人读用 tag
陷阱 :tag 可被覆盖,digest 不会
2.2 包仓库
包仓库管理语言生态的依赖包与自研包:Nexus 与 Artifactory 支持 Maven、npm、PyPI、NuGet、Go module 等多种格式。私有包仓库是内网构建的前提,也是依赖治理的抓手。
2.3 关键差异
| 维度 | 镜像仓库 | 包仓库 |
|---|---|---|
| 制品形态 | OCI 层叠镜像 | 语言生态包 |
| 标识 | tag + digest | 坐标 + 校验和 |
| 典型工具 | Harbor、ECR | Nexus、Artifactory |
| 扫描重点 | OS 包与基础镜像 | 依赖漏洞与许可证 |
| 部署关联 | 直接部署单元 | 构建输入 |
3. 制品晋升模型
3.1 一次构建,多次晋升
核心原则是「同一个制品从开发一路晋升到生产,绝不重新构建」。重新构建会产生不同制品,破坏了「测试过的就是上线的」这一保证。
晋升链路
build → dev → staging → prod
同一个 digest 在环境中移动,不重新构建
每个环境有独立的准入策略与审批
3.2 用不可变标签
环境标签用不可变方式管理:order-service:dev 指向的 digest 确定后不再改变,晋升时通过重新打标签指向同一 digest 实现。这样「晋升」是元数据操作,不是内容复制。
3.3 环境晋级门禁
每跨一个环境都要过门禁:单元测试、集成测试、安全扫描、性能基线、人工审批。门禁在流水线里实现,不依赖人的自觉。
4. SBOM 软件物料清单
4.1 SBOM 是什么
SBOM(Software Bill of Materials)是制品的成分清单,列出它包含的所有组件及其版本、许可证、依赖关系。相当于食品的营养成分表,让「这个制品里有什么」可被机器查询。
4.2 生成格式与工具
主流格式有 SPDX 与 CycloneDX 两种,工具链上 Syft、Trivy、cdxgen 都能生成,且多数能直接集成进构建流水线。
# 用 Syft 为镜像生成 CycloneDX 格式的 SBOM
syft order-service:v1.2.3 -o cyclonedx-json > sbom.json
# 用 Trivy 扫描镜像漏洞并输出 SBOM
trivy image --format cyclonedx --output sbom.json order-service:v1.2.3
# SBOM 作为制品附件一起入库,与镜像同 digest 关联
cosign attach sbom --sbom sbom.json registry.example.com/order-service@sha256:9f2a...
4.3 SBOM 的消费场景
生成只是第一步,价值在消费:出漏洞时快速定位哪些制品受影响、审计时回答许可证合规、采购时评估上游依赖风险。
| 场景 | 输入 | 输出 |
|---|---|---|
| 漏洞响应 | CVE + 全量 SBOM | 受影响制品清单 |
| 许可证审计 | SBOM 依赖树 | 违规许可证报告 |
| 依赖治理 | 跨制品 SBOM | 组件使用分布 |
| 合规交付 | 制品 SBOM | 交付物成分证明 |
5. 来源溯源与签名
5.1 签名证明制品未被篡改
签名解决「这个制品是不是我以为的那个」。Sigstore 的 cosign 提供无密钥签名(keyless),用 OIDC 身份与透明日志(Rekor)记录签名,无需自建 PKI。
# 用 cosign 对镜像签名(keyless,绑定 CI 身份)
cosign sign registry.example.com/order-service@sha256:9f2a...
# 部署前验证签名与签发者
cosign verify \
--certificate-identity-regexp '.*@example.com' \
--certificate-oidc-issuer https://accounts.example.com \
registry.example.com/order-service@sha256:9f2a...
5.2 SLSA 来源溯源
SLSA(Supply-chain Levels for Software Artifacts)用分级描述构建过程的完整性:制品是否由受信任的构建服务产出、构建过程是否可复现、来源信息是否被签名。
| 等级 | 要求 | 抵御的风险 |
|---|---|---|
| SLSA 1 | 有构建过程文档 | 最低可追溯 |
| SLSA 2 | 由托管构建服务产出、有签名来源 | 篡改构建脚本 |
| SLSA 3 | 构建环境隔离、来源不可伪造 | 污染构建环境 |
| SLSA 4 | 双人评审、可复现构建 | 内部人员作恶 |
5.3 Provenance 证明
来源证明(provenance)记录「谁、用什么源码、在什么环境、用什么命令构建了这个制品」,用 in-toto 格式签名后附在制品旁。部署时校验证明,确认制品确实来自预期流水线。
6. 供应链安全门禁
6.1 门禁的位置
门禁至少设在三处:构建时(阻断引入高危依赖)、入库时(拒绝未签名或扫描不通过的制品)、部署时(准入控制器校验签名与证明)。
6.2 准入控制
在 Kubernetes 里用准入控制器强制「未签名不得部署」:镜像必须有有效签名、SBOM 可查、来源证明可信,否则拒绝创建 Pod。
# 准入策略示意:只允许来自可信仓库且已签名的镜像
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: require-signed-images
spec:
images:
- glob: "registry.example.com/**"
authorities:
- keyless:
identities:
- issuer: https://accounts.example.com
subject: ".*@example.com"
6.3 从告警到阻断
门禁上线应分两阶段:先以「只告警不阻断」模式运行,观察误报与遗漏;规则稳定后再切到阻断模式,避免一上线就把发布流程卡死。
7. 制品清理与生命周期
7.1 为什么必须清理
制品仓库会无限膨胀:每次构建都产生新镜像,几个月就是几 TB。不清理不仅占存储,还拖慢索引与拉取,并扩大漏洞暴露面。
7.2 保留策略
按「环境 + 时间 + 数量」组合制定保留规则:生产环境保留全部已发布版本,预发保留最近 N 个,开发环境只保留最近几天的构建。
保留策略示例
prod : 保留所有已晋升版本,永不自动删除
staging: 保留最近 20 个版本
dev : 保留最近 7 天
清理前 : 标记为待删除,观察期 7 天后再真正删除
例外 : 有生产引用的 digest 强制保留
7.3 安全删除
删除前必须确认「没有运行中的工作负载引用该 digest」。用引用扫描建立「制品到部署」的映射,避免误删正在被使用的镜像导致滚动重启拉不到镜像。
8. 可追溯性与审计
8.1 端到端链路
一条完整的可追溯链路是:源码 commit → 构建流水线运行 → 制品 digest → SBOM → 签名与证明 → 晋升记录 → 生产部署。任何一环缺失,追溯就断。
| 环节 | 记录内容 | 存放位置 |
|---|---|---|
| 源码 | commit sha、作者、评审 | 版本控制 |
| 构建 | 流水线 ID、参数、环境 | CI 系统 |
| 制品 | digest、标签、扫描结果 | 制品仓库 |
| 签名 | 签名者身份、时间、日志 | Rekor 透明日志 |
| 部署 | 环境、时间、操作者 | CD 系统 |
8.2 漏洞响应的价值
当爆发一个严重 CVE,如果 SBOM 与溯源链路齐全,可以在几分钟内回答「哪些生产制品受影响、分别部署在哪些环境」,而不是靠人工逐个排查。这正是供应链治理最直接的回报。
8.3 审计留痕
所有晋升、签名、放行操作都要留审计日志,记录操作者、时间与理由。审计不是为了事后追责,而是为了在出问题时能快速还原事实。
9. 案例与最佳实践
9.1 落地 Checklist
□ 一次构建多次晋升,同一 digest 贯穿所有环境
□ 部署引用 digest,tag 仅作人读标识
□ 每个环境独立准入策略与审批门禁
□ 构建时自动生成 SBOM,与镜像同 digest 关联入库
□ 用 cosign keyless 签名,签名绑定 CI 身份
□ 按 SLSA 分级推进,先做到来源可签、可验
□ 准入控制器强制「未签名不得部署」
□ 制定保留策略,删除前确认无引用
□ 打通 commit 到部署的端到端可追溯链路
9.2 常见坑与对策
| 坑 | 现象 | 对策 |
|---|---|---|
| 部署用可变 tag | 上线内容与预期不符 | 部署引用 digest |
| 各环境重新构建 | 测试过的不是上线的 | 一次构建多次晋升 |
| SBOM 只生成不消费 | 出漏洞时仍靠人工排查 | 接入漏洞响应流程 |
| 门禁一上来就阻断 | 误报卡死发布 | 先告警后阻断 |
| 无保留策略 | 仓库膨胀到数 TB | 按环境制定保留规则 |
| 误删在用镜像 | 滚动重启拉不到镜像 | 删除前做引用扫描 |
| 签名不绑身份 | 谁签的说不清 | keyless 绑定 CI 身份 |
小结
制品管理与供应链溯源的完整链路是:构建产出不可变制品 → 存入仓库并用 digest 标识 → 一次构建多次晋升 → 生成 SBOM 与签名证明 → 在准入处校验并放行 → 用保留策略控制膨胀 → 打通端到端可追溯。核心原则有三条:部署永远引用 digest 而非可变标签、制品只构建一次然后晋升、每一个放行决定都基于可验证的签名与证明。做到这三点,才能在漏洞爆发时快速定位、在审计时从容举证。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。