GitOps 仓库分离最佳实践
成熟的 GitOps 实践要求将应用代码仓库和配置仓库(Config Repo)分离。将两者混在一起会导致 CI/CD 耦合、权限难以控制、历史记录混乱等问题。
双仓库 GitOps 架构 ┌──────────────────────────────────────────────────────────────────────────┐ │ 应用代码仓库 (my-org/my-app) │ │ src/ tests/ Dockerfile .github/workflows/ │ │ 应用源代码 单元测试 构建镜像 CI Pipeline │ └──────────────────────────────────┬───────────────────────────────────────┘ │ CI: 构建镜像,推送 GHCR │ CI: 更新配置仓库的 image tag ┌──────────────────────────────────▼───────────────────────────────────────┐ │ 配置仓库 (my-org/my-app-config) │ │ apps/ │ │ └── my-app/ │ │ ├── base/ (通用 K8s 资源) │ │ └── overlays/ (环境差异化配置) │ │ ├── dev/ → image:v1.6 (dev 环境最新) │ │ ├── staging/ → image:v1.5 (staging 稳定版) │ │ └── prod/ → image:v1.4 (prod 慢更新) │ └──────────────────────────────────┬───────────────────────────────────────┘ │ ArgoCD Poll(每3分钟) ┌──────────────────────────────────▼───────────────────────────────────────┐ │ K8s 集群(ArgoCD 自动同步) │ └──────────────────────────────────────────────────────────────────────────┘
应用代码仓库职责
- 存放应用源代码
- CI Pipeline(构建/测试/扫描)
- Dockerfile
- 单元测试/集成测试
- 不包含 K8s YAML
配置仓库职责
- 所有环境的 K8s YAML
- Kustomize overlays / Helm values
- ArgoCD Application CRD
- 更严格的访问控制(prod 需审批)
- 不包含应用源代码
GitHub Actions CI 完整流程
以下是一个生产级的 GitHub Actions CI 工作流,完成从代码提交到更新配置仓库的全流程:
# .github/workflows/ci.yaml(应用代码仓库)
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Tests
run: make test
build-push:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' # 只有 main 分支才构建推送
permissions:
contents: read
packages: write
outputs:
image_tag: ${{ steps.meta.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=,format=short
type=raw,value=latest
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
update-config:
needs: build-push
runs-on: ubuntu-latest
steps:
- name: Checkout config repo
uses: actions/checkout@v4
with:
repository: my-org/my-app-config
token: ${{ secrets.CONFIG_REPO_PAT }} # PAT 需要配置仓库写权限
- name: Install kustomize
uses: imranismail/setup-kustomize@v2
- name: Update image tag in dev overlay
run: |
cd apps/my-app/overlays/dev
kustomize edit set image \
ghcr.io/my-org/my-app=ghcr.io/my-org/my-app:${{ needs.build-push.outputs.image_tag }}
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "chore: update my-app to ${{ needs.build-push.outputs.image_tag }}"
git push
Argo Rollouts:渐进式交付
Argo Rollouts 是 Argo 生态的渐进式交付控制器,提供比原生 Kubernetes Deployment 更强大的发布策略,与 ArgoCD 深度集成。
# Argo Rollouts 金丝雀发布示例
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 5 # 5% 流量切到新版本
- pause:
duration: 5m # 等待 5 分钟观察
- analysis: # 自动指标分析
templates:
- templateName: error-rate
- setWeight: 25
- pause:
duration: 10m
- setWeight: 50
- pause:
duration: 10m
- setWeight: 100 # 全量切换
selector:
matchLabels:
app: my-app
template:
spec:
containers:
- name: my-app
image: ghcr.io/my-org/my-app:v2.0.0
Argo Workflows vs ArgoCD
| 对比维度 | Argo Workflows | ArgoCD |
|---|---|---|
| 核心职责 | 流水线执行引擎(CI、批处理) | 持续交付(CD)、GitOps |
| 触发方式 | 主动触发(事件/定时) | 监听 Git 变更(Pull 模式) |
| 执行模型 | DAG 工作流,步骤间有数据流 | 声明式同步,无步骤概念 |
| 状态管理 | 有执行历史和 Artifact | 管理 K8s 资源持续状态 |
| 适用场景 | 构建镜像、运行测试、ML 训练 | 部署应用、管理配置 |
| 组合使用 | Argo Workflows(CI)→ 更新配置仓库 → ArgoCD(CD)→ 集群 | |
企业级落地经验
从小规模开始,逐步推广
不要一次性将所有应用迁移到 ArgoCD。选择 1-2 个非核心服务作为试点,跑通 GitOps 流程后再逐步推广。让团队有足够时间适应"不再直接 kubectl"的工作方式。
配置仓库需要更严格的审批流程
生产环境的配置仓库需要强制 Code Review(至少 2 人审批),并通过 Branch Protection 防止直接 push main。建议为 dev/staging/prod 三个环境设置不同的 PR 审批要求。
ArgoCD 本身也要 GitOps 管理
ArgoCD 的 Application、AppProject、RBAC 配置等,都应该存储在 Git 中,通过"App of Apps"或 ApplicationSet 管理。避免直接在 UI 上创建资源,否则 ArgoCD 本身就不符合 GitOps 原则。
合理设置同步间隔和 Webhook
默认的 3 分钟轮询对大多数场景够用。对延迟敏感的场景,配置 Git Webhook,ArgoCD 收到 push 事件后立即触发同步,延迟降到秒级。注意 Webhook 需要 ArgoCD API Server 对外可达。
selfHeal 和 prune 需要充分测试
在生产环境开启 selfHeal 前,必须在 staging 环境充分验证。selfHeal 会覆盖运维人员在紧急情况下的手动操作,需要确保 Git 配置始终是正确的"参考状态"。prune 开启前要确认所有应用资源都在 Git 中有记录。
建立清晰的镜像 tag 策略
生产环境禁止使用 latest tag,必须使用 Semver(v1.2.3)或 Commit SHA(sha-abc123f)。这确保每次部署的版本完全确定可重现,是 GitOps 可审计性的基础。
完整架构总结
企业级 GitOps 完整架构 ┌────────────────────────────────────────────────────────────────────────┐ │ 开发人员推送代码 │ └──────────────────────────────────┬─────────────────────────────────────┘ ↓ ┌──────────────────────────────────▼─────────────────────────────────────┐ │ GitHub Actions CI │ │ ① 运行单元测试 → ② 构建 Docker 镜像 → ③ 推送到 GHCR → ④ 更新配置仓库 │ └──────────────────────────────────┬─────────────────────────────────────┘ ↓ PR 自动合并 or 人工审批 ┌──────────────────────────────────▼─────────────────────────────────────┐ │ 配置仓库 (my-app-config) │ │ Kustomize overlays | Helm values | Application CRDs │ └──────────────────────────────────┬─────────────────────────────────────┘ ↓ ArgoCD Poll / Webhook ┌──────────────────────────────────▼─────────────────────────────────────┐ │ ArgoCD (Hub 集群) │ │ Application CRD | AppProject RBAC | Notifications | Prometheus │ └──────┬──────────────────────┬──────────────────────┬────────────────────┘ ↓ auto-sync ↓ auto-sync ↓ auto-sync ┌──────▼──────────┐ ┌───────▼─────────┐ ┌──────▼──────────────┐ │ Dev 集群 │ │ Staging 集群 │ │ Prod 集群 │ │ Argo Rollouts │ │ Argo Rollouts │ │ Argo Rollouts Canary │ └─────────────────┘ └─────────────────┘ └─────────────────────┘
恭喜完成整个 ArgoCD 与 GitOps 实战教程!核心要点:GitOps 以 Git 为事实来源,通过声明式配置和持续协调实现可审计的自动化交付。ArgoCD 是 GitOps 的最佳实践工具,配合 Helm/Kustomize 的多环境管理、ApplicationSet 的批量操作、RBAC 的安全控制,以及 Argo Rollouts 的渐进式发布,构成了一套完整的企业级 GitOps 技术栈。将 CI(构建)与 CD(部署)在仓库层面解耦,是 GitOps 落地的关键架构决策。