1. 威胁模型:GitOps 不是“更安全”,而是“更可治理”
在开始堆砌工具前,先把黑箱打开。典型威胁包括: 仓库侧攻击(恶意 commit、供应链依赖被投毒、PR 规则被绕过); 交付侧攻击(manifest / Helm values 被篡改、镜像被替换); 集群侧攻击(kubectl 直连导致的 drift、越权写入、凭据泄露)。 GitOps 的优势在于:你能把“期望状态”固定在 Git,并且在应用前后插入校验与拒绝逻辑。 安全的目标就是:让非法变更无法到达数据面(data plane),并且让拒绝可解释、可审计。
| 威胁点 | 常见后果 | GitOps 可插入的控制 |
|---|---|---|
| Malicious commit | 不该部署的变更上生产 | commit signing + PR policy + required reviews |
| Image supply chain | 镜像替换、依赖投毒 | cosign verification + SBOM attestations + allowlist |
| Cluster tampering | drift、越权写入 | admission control + selfHeal / prune + audit logs |
2. 签名(Signing):把“可信”写进证据链
GitOps 的签名可以有多层。你不必一口气全部启用,但要形成“最小可用集合(minimum viable trust)”: 提交签名(commit/tag signing)用于证明 Git 历史的身份可信; 镜像签名(container signing)用于证明运行时制品的来源; 配置/打包签名(config bundles / chart provenance)用于证明交付产物未被篡改。 当这些证据进入 admission/policy,系统就能在 apply 前拒绝非法输入。
3. 验证(Verification):把 cosign 的结果变成可拒绝的信号
签名验证最好发生在两个层级:一是 CI(快速失败、早期反馈),二是 admission(真正阻断)。 以 cosign 为例,你会校验证书身份、仓库/镜像引用、以及是否存在不可变的透明度记录。 当验证失败,策略引擎应返回明确原因:缺签名、签名身份不匹配、证书已吊销、或证据不在 allowlist 内。
# Illustrative cosign verification commands (adjust for your policies)
cosign verify \
--key k8s://cosign-public-key/production \
registry.example.com/payments-api:v1.2.3
# Verify with identity constraints (example)
cosign verify \
--certificate-identity "builds@company.com" \
--certificate-issuer "https://token.actions.githubusercontent.com" \
registry.example.com/payments-api:v1.2.3
4. 策略控制(Policy):用 OPA / Gatekeeper 写“允许什么”
政策引擎的职责是把安全目标翻译成可判定的规则。建议你把策略按层级拆分: Repository & scope:限制 Application 指向哪些仓库、哪些命名空间; Workload rules:限制使用哪些镜像来源、是否必须存在签名/注释; Admission blocking:在无法验证时直接 deny。 OPA(Rego)让规则可读、可测;Gatekeeper 或其他 webhook 负责把规则执行嵌入集群。
# Illustrative Rego policy snippet (deny unsigned images)
package gitops.security
deny[msg] {
input.request.operation == "CREATE"
some c
c := input.review.object.spec.containers[_]
image := c.image
not has_valid_signature(image)
msg := sprintf("image %v is missing a valid signature", [image])
}
# Placeholder for your integration (cosign verifier / signature store)
has_valid_signature(image) {
# Implement lookup against your verification service or attestation store
true
}
5. 多团队协作:边界、升级与“可解释的审批”
真正让团队在速度与安全之间不打架的,是协作模型。你需要三件事: 边界(谁能指向哪些仓库/集群/命名空间); 升级链路(dev → staging → prod 的 promotion workflow); 审批与审计(审批由什么触发、审批的理由如何固化进证据)。 对 Argo CD 来说,AppProject 的范围限制就是边界;对 Flux 来说,依赖图 + 多层 Kustomization 也是边界。 无论选哪个系统,多团队的基本做法都是:每个团队拥有自己的仓库与环境覆盖面,平台团队提供“受控的平台 root”。
6. 运维要点:密钥轮转、吊销与事故响应
一旦进入签名验证与策略阻断,你就需要把“密钥生命周期”写进日常: 密钥轮转要考虑兼容窗口(dual trust), 吊销要能快速传播到验证服务或证据存储, 事故响应要能解释为何拒绝了某些变更、哪些证据缺失或失效。 最后别忘了:策略引擎与验证服务自身也要有审计与可观测性。
7. 本章清单
- 能描述至少三类 GitOps 威胁:仓库侧、交付侧、集群侧,并知道对应控制点。
- 理解多层签名:commit/tag、config bundles、container images,并知道它们如何进入验证链路。
- 能写出可落地的 verification 规则:CI 快速失败 + admission 最终阻断。
- 会用 OPA(Rego)表达 allow/deny 逻辑,并保证 deny 返回可解释 reason。
- 能为多团队设计边界与 promotion:仓库分层、namespace 隔离、必要的审批与审计证据固化。
- 知道密钥轮转与吊销的运维策略:dual trust、快速传播、事故可追溯。
- 预告下一章:进入 Spinnaker 入门,对比 GitOps 与经典 CD 平台的编排方式。