3. Git 作为单一事实来源:仓库结构设计与分支策略

在 GitOps 模型中,Git 仓库不仅是代码存储库,更是整个系统的单一事实来源(Single Source of Truth)。所有环境(开发、预发布、生产)的期望状态都必须以声明式清单的形式存储在 Git 中。本章将深入探讨如何设计仓库结构、选择分支策略,并通过代码审查确保合规性。

3.1 仓库结构设计:单仓库 vs. 多仓库

GitOps 仓库结构通常分为两种模式:单仓库(Monorepo)和多仓库(Multi-Repo)。选择哪种模式取决于团队规模、微服务数量以及环境复杂度。

维度 单仓库(Monorepo) 多仓库(Multi-Repo)
管理复杂度 较低,所有配置集中管理 较高,需跨仓库协调
原子性变更 支持跨服务原子提交 需跨仓库 PR 联动
权限控制 粒度较粗,需通过目录级权限 粒度精细,按仓库隔离
CI/CD 触发 需智能路径过滤,避免全量触发 按仓库独立触发,简单直接
推荐场景 中小团队、微服务数量 < 20 大型组织、严格安全隔离
实践建议:对于大多数团队,推荐从单仓库起步,按目录划分环境和服务。当团队规模超过 50 人或微服务超过 30 个时,再考虑迁移到多仓库模式。

3.2 分支策略:GitFlow vs. Trunk-Based

分支策略决定了变更如何流入 Git 仓库,并最终同步到 Kubernetes 集群。GitOps 场景下,两种主流策略各有优劣。

3.2.1 GitFlow 模式

GitFlow 通过 main、develop、feature、release、hotfix 分支管理发布节奏。在 GitOps 中,main 分支通常映射生产环境,develop 映射预发布环境。

  • 优点:发布流程严谨,适合固定周期发布;热修复可快速绕过常规流程。
  • 缺点:分支生命周期长,合并冲突频繁;环境映射复杂,需维护多个长期分支。
  • GitOps 适配:每个环境分支(如 env/prod、env/staging)独立维护,通过 Cherry-pick 同步变更。

3.2.2 Trunk-Based 模式

Trunk-Based 强调所有开发者向 main(或 trunk)分支频繁提交,通过短生命周期特性分支或直接提交实现快速迭代。

  • 优点:合并冲突少,CI/CD 反馈快;天然支持环境即代码,通过目录或标签区分环境。
  • 缺点:对测试覆盖率和代码审查要求极高;不适合需要严格审批的合规场景。
  • GitOps 适配:使用 main 分支作为唯一事实来源,通过 kustomize 或 helmfile 的 overlay 目录区分环境。
关键对比:GitFlow 适合合规严格、发布周期固定的场景(如金融、医疗);Trunk-Based 适合追求交付速度、自动化测试完善的云原生团队。
GitFlow vs Trunk-Based 环境分支映射 GitFlow vs Trunk-Based 环境分支映射 GitFlow 模式 main (生产) develop (预发布) feature/* hotfix/* → 生产集群 → 预发布集群 → 开发集群 → 生产热修复 Trunk-Based 模式 main (唯一主干) 短特性分支 overlay/prod overlay/staging → 生产集群 → 开发集群 → 生产集群 → 预发布集群

3.3 环境分支映射与目录结构

无论选择哪种分支策略,环境映射都需要清晰的目录结构。以下是一个典型的单仓库 GitOps 目录设计,支持多环境、多服务。

gitops-repo/
├── base/                          # 基础配置(Kustomize base)
│   ├── kustomization.yaml
│   ├── namespace.yaml
│   └── common-labels.yaml
├── overlays/                      # 环境覆盖层
│   ├── dev/                       # 开发环境
│   │   ├── kustomization.yaml
│   │   ├── deployment-patch.yaml
│   │   └── configmap.yaml
│   ├── staging/                   # 预发布环境
│   │   ├── kustomization.yaml
│   │   ├── ingress.yaml
│   │   └── secrets.yaml
│   └── prod/                      # 生产环境
│       ├── kustomization.yaml
│       ├── hpa.yaml
│       └── pdb.yaml
├── apps/                          # 应用定义(Application CR)
│   ├── frontend.yaml
│   ├── backend.yaml
│   └── database.yaml
├── clusters/                      # 集群注册信息
│   ├── dev-cluster.yaml
│   ├── staging-cluster.yaml
│   └── prod-cluster.yaml
└── .github/                       # CI/CD 工作流
    ├── workflows/
    │   ├── pr-check.yaml
    │   └── sync-to-cluster.yaml
    └── CODEOWNERS                 # 代码审查规则
注意:避免将敏感信息(如数据库密码、)直接写入 Git 仓库。应使用 Sealed Secrets、External Secrets Operator 或 Vault 集成,仅存储加密后的密文或引用。

3.4 代码审查与合规

Git 作为单一事实来源,所有变更必须经过代码审查(Code Review)和合规检查才能合并。以下是 GitOps 场景下的审查流水线设计。

3.4.1 审查流水线步骤

  1. 提交 PR:开发者从特性分支向目标环境分支(如 main 或 env/prod)发起 Pull Request。
  2. 自动化检查:CI 触发以下检查:
    • YAML 语法校验:使用 yamllint 或 kubeval 检查清单格式。
    • Kubernetes 资源验证:使用 kubeconform 或 dry-run 确保资源定义正确。
    • 策略合规扫描:使用 OPA/Gatekeeper 或 Kyverno 检查是否违反安全策略(如禁止特权容器)。
    • 镜像签名验证:确保引用的容器镜像已通过 Cosign 签名。
  3. 人工审查:至少一名 Code Owner 或资深工程师审查变更逻辑。
  4. 合并与同步:PR 合并后,ArgoCD 或 Flux 自动检测到 Git 变更,并同步到目标集群。

3.4.2 合规策略示例(OPA)

以下是一个简单的 OPA 策略,禁止在生产环境中使用 latest 镜像标签:

package kubernetes.admission

deny[msg] {
  input.request.kind.kind == "Deployment"
  input.request.object.spec.template.spec.containers[_].image == "*:latest"
  msg := "禁止在生产环境使用 latest 镜像标签"
}
最佳实践:将合规策略作为代码存储在 Git 仓库的 policies/ 目录中,与基础设施配置一同版本化管理。这样,策略变更也需经过同样的审查流程。
GitOps 代码审查与合规流水线 GitOps 代码审查与合规流水线 ① 提交 PR ② 自动化检查 YAML / K8s / OPA ③ 人工审查 ④ 合并 ⑤ 同步 检查失败,返回修改 合规策略(OPA/Kyverno)在步骤②自动执行,确保所有变更符合安全与运维规范 人工审查步骤③至少需要 1 名 Code Owner 批准

3.5 小结

Git 作为单一事实来源的核心在于:仓库结构决定管理边界,分支策略决定发布节奏,环境映射决定部署目标,代码审查决定变更质量。选择适合团队的分支策略(GitFlow 或 Trunk-Based),配合清晰的目录结构和自动化合规检查,才能充分发挥 GitOps 的声明式发布优势。