2. GitOps 工作流:Pull vs Push 模式、Git 作为单一事实来源、状态收敛机制

GitOps 的核心在于将 Git 仓库作为整个交付管线的“单一事实来源”(Single Source of Truth),并通过自动化机制确保运行环境的状态始终与仓库中声明的期望状态保持一致。本章深入剖析 GitOps 工作流的两种驱动模式、Git 仓库的权威角色以及状态收敛的底层原理。

2.1 两种驱动模式:Push 与 Pull

传统 CI/CD 流水线多采用 Push 模式:CI 服务器在构建完成后,主动将制品或配置“推送”到目标环境。GitOps 则倡导 Pull 模式:运行在目标环境中的 Operator(操作器)主动从 Git 仓库“拉取”期望状态并执行同步。下表对比了两种模式的核心差异:

对比维度 Push 模式(传统) Pull 模式(GitOps)
触发方向 CI/CD 服务器主动推送至环境 环境内 Operator 主动拉取 Git 仓库
安全模型 CI 系统需持有目标集群的凭证 集群无需对外暴露 API,凭证仅存于集群内
事实来源 CI/CD 数据库或制品仓库 Git 仓库(唯一权威)
状态收敛 依赖外部触发器(Webhook/定时任务) Operator 持续循环对比,自动修复漂移
典型工具 Jenkins、GitLab CI、GitHub Actions Argo CD、Flux CD、Jenkins X
关键结论:Pull 模式将部署权限从 CI 系统转移至目标环境内部,显著降低了因 CI 凭证泄露导致的横向移动风险,同时使环境具备自主修复能力。

下图展示了两种模式在架构层面的本质区别:

Push vs Pull 模式对比架构图 Push 模式(传统) CI/CD 服务器 目标环境 推送部署 ⚠ 凭证暴露风险 需外部触发器修复漂移 Pull 模式(GitOps) Git 仓库 Operator 主动拉取 ✅ 集群无需暴露凭证 持续循环自动收敛

2.2 Git 作为单一事实来源

在 GitOps 体系中,Git 仓库不再仅仅是代码托管平台,而是整个系统状态的权威数据库。所有与环境相关的声明性配置——包括部署清单、ConfigMap、Secret 引用、网络策略、存储卷声明等——都必须存储在 Git 仓库中。

Git 仓库作为单一事实来源需满足以下原则:

  • 声明性(Declarative):仓库中存储的是“期望状态”的描述,而非达到该状态的命令序列。
  • 不可变(Immutable):任何环境变更都必须通过 Git 提交(Commit)发起,禁止手动修改运行环境。
  • 可审计(Auditable):每一次变更都记录在 Git 历史中,包含提交者、时间戳、变更内容及关联的 MR/PR。
  • 可回滚(Rollback-ready):通过 git revert 或切换到历史提交即可将环境恢复至任意已知状态。
实践建议:建议为每个环境(dev/staging/prod)建立独立的目录或分支,并在仓库根目录放置 kustomization.yaml 或 helmfile.yaml 作为入口点,使环境间的差异一目了然。

典型的 GitOps 仓库结构示例如下:

gitops-infra/
├── base/                          # 公共基础配置
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   └── service.yaml
├── overlays/
│   ├── dev/                       # 开发环境覆盖
│   │   ├── kustomization.yaml
│   │   ├── configmap-patch.yaml
│   │   └── replica-count.yaml
│   ├── staging/                   # 预发布环境覆盖
│   │   ├── kustomization.yaml
│   │   └── ingress.yaml
│   └── prod/                      # 生产环境覆盖
│       ├── kustomization.yaml
│       ├── hpa.yaml
│       └── pdb.yaml
└── README.md

2.3 状态收敛机制

状态收敛(State Reconciliation)是 GitOps 工作流的核心闭环。Operator 通过持续的“对比-修正”循环,确保运行环境的实际状态与 Git 仓库中声明的期望状态保持一致。当两者出现偏差时,Operator 会自动执行修正操作,将环境拉回期望状态。

收敛循环通常包含以下四个步骤:

  1. 检测(Detect):Operator 定期(如每 3 分钟)或通过 Webhook 触发,对比 Git 仓库中的期望清单与集群中的实际资源。
  2. 差异分析(Diff):生成期望状态与实际状态之间的差异报告,识别出新增、修改、删除的资源。
  3. 修正(Reconcile):自动应用差异补丁,创建/更新/删除 Kubernetes 资源,使集群状态向期望状态对齐。
  4. 反馈(Feedback):将同步结果(成功/失败、资源状态、事件日志)写回 Git 仓库或通知外部系统。
注意:状态收敛并非盲目覆盖。Operator 应支持“自愈保护”策略——对于由 HPA(水平自动扩缩)或 Cluster Autoscaler 等控制器管理的资源(如 Pod 副本数),Operator 应忽略这些动态字段,避免与集群自治逻辑冲突。

下图展示了 GitOps 状态收敛的完整闭环:

GitOps 状态收敛闭环 GitOps 状态收敛闭环 Git 仓库 期望状态(声明性配置) Operator 对比 → 差异分析 → 修正 Kubernetes 集群 实际状态(运行中资源) 拉取期望状态 应用修正 状态反馈 漂移场景示例: 运维人员手动执行 kubectl scale 或误删 Pod → Operator 在下一次循环中检测到差异 → 自动将副本数恢复至 Git 仓库中声明的值 若差异由 HPA 等合法控制器产生,Operator 应通过 annotation 或 ignore-diff 配置跳过该字段

2.4 三种收敛策略对比

不同的 GitOps 工具在实现状态收敛时采用不同的策略,下表对比了三种主流方式:

策略 工作原理 代表工具 适用场景
定时轮询 Operator 每隔固定时间(如 3 分钟)拉取 Git 仓库并与集群对比 Flux CD(默认) 对实时性要求不高的环境,减少 API 调用频率
Webhook 触发 Git 仓库收到新提交后,通过 Webhook 通知 Operator 立即执行同步 Argo CD(可选) 需要快速响应变更的 CI/CD 流水线
事件驱动 监听 Git 仓库事件(Push/PR Merge),结合消息队列触发同步 Argo CD + Event Source 大规模多集群场景,需要精细化事件路由
生产建议:推荐采用“定时轮询 + Webhook 加速”的组合策略。轮询作为兜底机制确保状态最终一致,Webhook 用于缩短变更生效的延迟。同时,应在 Operator 中配置“同步窗口”(Sync Window),限制生产环境在特定时间段内执行自动同步,避免非预期变更影响业务高峰。