4. Git 仓库结构设计:应用仓库与配置仓库分离
在 GitOps 实践中,仓库结构是同步复核的基石。错误的仓库设计会导致权限混乱、回滚困难、Secrets 泄露。本章聚焦于应用仓库与配置仓库分离、环境分支策略、目录组织规范以及Secrets 管理四个核心维度,帮助你构建可审计、可复现的 GitOps 仓库体系。
4.1 应用仓库 vs 配置仓库:职责分离
将应用源代码与部署配置存放在同一个仓库中,是传统 CI/CD 的常见做法,但在 GitOps 中会引发以下问题:
- 权限粒度粗:开发者对部署配置的修改无法与代码变更隔离。
- 同步噪声高:每次代码提交都会触发配置仓库的 ArgoCD 同步,即使配置未变。
- 回滚耦合:回滚应用代码时可能连带回滚了不应变更的部署配置。
推荐采用双仓库模型:
| 维度 | 应用仓库 (App Repo) | 配置仓库 (Config Repo) |
|---|---|---|
| 内容 | 源代码、Dockerfile、CI 流水线 | K8s Manifest、Helm Chart、Kustomize 覆盖、Secrets 加密文件 |
| 触发方式 | PR → CI 构建镜像 | PR → 人工复核 → 自动同步到集群 |
| 访问权限 | 开发团队读写 | 平台/SRE 团队审批,开发只读 |
| 变更频率 | 高(每日多次) | 低(每次部署前复核) |
| 回滚影响 | 仅影响代码版本 | 仅影响集群状态 |
最佳实践:配置仓库应设置为
protected 分支,要求至少 1 人复核才能合并。应用仓库的 CI 流水线在构建成功后,自动更新配置仓库中的镜像 Tag 并创建 PR,而非直接提交。
4.2 环境分支策略:main / staging / prod
环境分支策略决定了变更如何在不同环境间流转。推荐使用主线 + 环境分支模型:
- main:始终与生产环境(prod)保持一致的真理源。所有环境分支从 main 创建,最终合并回 main。
- staging:预发布环境,用于集成测试和验收。从 main 定期同步,或通过 PR 从 feature 分支合并。
- prod:生产环境分支,仅从 main 或 staging 经过严格审批后合并。通常设置为只读,禁止直接推送。
策略要点:不要使用
main 直接部署到生产。将 main 视为“已批准的生产状态”,而 prod 分支是“实际生效的生产配置”。两者之间的差异应始终为空,否则说明同步复核流程存在漏洞。
以下 SVG 展示了环境分支与同步复核的流转关系:
4.3 目录组织规范
配置仓库的目录结构直接影响可发现性和自动化能力。推荐以下规范:
config-repo/
├── apps/ # 应用级配置
│ ├── frontend/
│ │ ├── base/ # 环境无关的基础配置
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ └── kustomization.yaml
│ │ ├── overlays/
│ │ │ ├── staging/
│ │ │ │ ├── deployment-patch.yaml
│ │ │ │ ├── configmap.yaml
│ │ │ │ └── kustomization.yaml
│ │ │ └── prod/
│ │ │ ├── deployment-patch.yaml
│ │ │ ├── hpa.yaml
│ │ │ └── kustomization.yaml
│ │ └── secrets/ # 加密后的 Secrets
│ │ ├── staging.enc.yaml
│ │ └── prod.enc.yaml
│ └── backend/
│ └── ... # 同上结构
├── infrastructure/ # 基础设施层配置
│ ├── namespaces/
│ ├── ingress-controller/
│ └── monitoring/
├── clusters/ # 集群级配置
│ ├── staging-cluster/
│ │ └── apps.yaml # ArgoCD Application 定义
│ └── prod-cluster/
│ └── apps.yaml
└── .sops.yaml # SOPS 加密配置(全局)
避坑指南:不要在
base/ 目录中放置环境特定的配置。所有环境差异必须通过 overlays/ 中的 patch 或 Helm values 文件覆盖。否则,当 staging 和 prod 的 base 配置不一致时,同步复核将无法判断哪个是“标准配置”。
4.4 Secrets 管理:加密即代码
GitOps 要求所有配置都存储在 Git 中,但 Secrets 明文存储是安全红线。推荐使用SOPS + Age/GPG 或 Sealed Secrets 方案。
| 方案 | 加密方式 | 解密时机 | 适用场景 |
|---|---|---|---|
| SOPS + Age | 文件级非对称加密 | ArgoCD 同步前由插件解密 | 小团队,密钥管理简单 |
| SOPS + KMS | 云厂商 KMS 加密 | ArgoCD 同步前由插件解密 | 企业级,审计合规要求高 |
| Sealed Secrets | 集群内非对称加密 | SealedSecret 控制器在集群内解密 | 需要集群自管理密钥,避免外部依赖 |
| External Secrets | 引用外部 Secret Store | 运行时从 Vault/AWS Secrets Manager 拉取 | 已有集中式 Secrets 管理平台 |
推荐组合:使用 SOPS + Age 加密 Secrets 文件,并配合
.sops.yaml 定义哪些文件需要加密。在 ArgoCD 中配置 age-key 作为集群 Secret,实现同步前的自动解密。这样既保证了 Git 中存储的是密文,又无需额外部署控制器。
以下 SVG 展示了 Secrets 从加密到部署的完整流程:
4.5 同步复核中的仓库结构检查清单
在每次同步复核时,复核人应逐项检查以下内容:
- 分支合规性:变更是否来自正确的环境分支?禁止从 feature 分支直接合并到 prod。
- 目录完整性:新增应用是否遵循
apps/<app-name>/base/+overlays/结构? - Secrets 加密状态:所有
secrets/目录下的文件是否已通过 SOPS 加密?明文文件应被.gitignore排除。 - 镜像 Tag 可追溯:配置中引用的镜像 Tag 是否与 CI 构建产物一致?建议使用 Git commit SHA 作为 Tag。
- 环境差异最小化:staging 与 prod 的 overlay 差异是否仅限于资源规格、副本数等必要参数?不应存在逻辑差异。
自动化辅助:在 CI 中集成
conftest 或 kubeconform,对 PR 中的 Manifest 进行 Schema 校验和安全策略检查。复核人只需关注业务逻辑和变更意图,语法问题由自动化门禁拦截。