第16章 GitOps实践¶
GitOps是一种以Git仓库作为单一事实来源(Single Source of Truth)的运维范式,通过声明式配置和自动化同步实现基础设施和应用的持续交付。
目录¶
- 1. GitOps核心概念
- 2. GitOps工作流
- 3. Argo CD实战
- 4. Flux CD实战
- 5. GitOps与Kubernetes集成
- 6. GitOps最佳实践
- 7. 面试题精选
- 8. 推荐资源
1. GitOps核心概念¶
1.1 什么是GitOps¶
GitOps由Weaveworks在2017年提出,核心思想:
- 声明式:用声明式配置描述系统期望状态
- 版本化:所有配置存储在Git中,变更历史可追溯
- 自动化:自动将Git中的配置同步到目标环境
- 自愈:当实际状态偏离期望状态时自动修复
1.2 传统CI/CD vs GitOps¶
Text Only
传统推送模式 (Push):
┌──────┐ push ┌──────┐ push ┌──────────┐
│ 开发者 │ ───────→ │ CI/CD │ ───────→ │ K8s集群 │
└──────┘ └──────┘ └──────────┘
CI工具需要集群访问权限(安全风险)
GitOps拉取模式 (Pull):
┌──────┐ commit ┌──────┐ watch ┌──────────┐
│ 开发者 │ ───────→ │ Git │ ←─────── │ GitOps │
└──────┘ │ Repo │ │ Operator │
└──────┘ sync │ (集群内) │
──────→ │ │
└──────────┘
GitOps agent在集群内部拉取配置(更安全)
1.3 GitOps四大原则¶
| 原则 | 说明 |
|---|---|
| 声明式描述 | 系统的期望状态以声明式的方式定义 |
| 版本控制 | 期望状态存储在Git中,Git作为唯一事实来源 |
| 自动应用 | 经过批准的变更自动应用到系统 |
| 持续调谐 | Agent持续监控并纠正实际状态与期望状态的偏差 |
1.4 Git作为单一事实来源¶
Text Only
GitOps 仓库结构:
├── apps/
│ ├── production/
│ │ ├── frontend/
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ └── ingress.yaml
│ │ └── backend/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── configmap.yaml
│ └── staging/
│ ├── frontend/
│ └── backend/
├── infrastructure/
│ ├── namespaces.yaml
│ ├── rbac.yaml
│ └── monitoring/
└── README.md
2. GitOps工作流¶
2.1 标准GitOps工作流¶
Text Only
开发者 代码仓库 CI流水线 配置仓库 GitOps Agent K8s集群
│ │ │ │ │ │
│──push代码──→│ │ │ │ │
│ │──触发CI────→│ │ │ │
│ │ │──构建镜像──→│ │ │
│ │ │──推送到仓库──→ │ │
│ │ │──更新配置──→│ │ │
│ │ │ │──检测变更──→│ │
│ │ │ │ │──同步配置──→│
│ │ │ │ │──健康检查──→│
2.2 分支策略¶
Text Only
环境与分支映射:
┌──────────────────────────────────────────┐
│ main分支 → production环境 │
│ staging分支 → staging环境 │
│ develop分支 → development环境 │
│ │
│ 推荐:每个环境对应独立目录而非独立分支 │
│ 使用Kustomize overlay管理环境差异 │
└──────────────────────────────────────────┘
2.3 镜像更新策略¶
YAML
# 方式一:CI流水线自动更新配置仓库中的镜像标签
# .github/workflows/ci.yaml
name: CI Pipeline
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build & Push Image
run: |
docker build -t myapp:${{ github.sha }} .
docker push myregistry/myapp:${{ github.sha }}
- name: Update K8s Manifest
run: |
cd gitops-repo
kustomize edit set image myapp=myregistry/myapp:${{ github.sha }}
git commit -am "chore: update myapp to ${{ github.sha }}"
git push
3. Argo CD实战¶
3.1 Argo CD概述¶
Argo CD是CNCF毕业项目,是最流行的Kubernetes GitOps工具。
核心特性: - 声明式GitOps持续交付 - 多集群管理 - SSO集成(OIDC, OAuth2, LDAP) - Web UI + CLI + API - 支持Helm/Kustomize/Jsonnet/Plain YAML - 自动同步与手动同步策略
3.2 安装Argo CD¶
Bash
# 创建命名空间并安装
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# 安装CLI
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd && sudo mv argocd /usr/local/bin/ # &&前一个成功才执行后一个;||前一个失败才执行
# 登录
argocd login <ARGOCD_SERVER> --username admin --password <PASSWORD>
3.3 Application定义¶
YAML
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/gitops-repo.git
targetRevision: main
path: apps/production/backend
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # 删除Git中移除的资源
selfHeal: true # 自动修复手动变更
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
3.4 ApplicationSet(多环境/多集群)¶
YAML
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-set
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: staging
url: https://staging-cluster.example.com
namespace: staging
- cluster: production
url: https://prod-cluster.example.com
namespace: production
template:
metadata:
name: 'my-app-{{cluster}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/gitops-repo.git
targetRevision: main
path: 'apps/{{cluster}}/backend'
destination:
server: '{{url}}'
namespace: '{{namespace}}'
3.5 同步策略¶
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 手动同步 | 需要手动触发同步 | 生产环境 |
| 自动同步 | Git变更后自动同步 | 开发/测试环境 |
| 自动修剪 | 删除Git中不存在的资源 | 与自动同步配合 |
| 自愈 | 修复手动对集群的变更 | 防止配置漂移 |
4. Flux CD实战¶
4.1 Flux概述¶
Flux是CNCF毕业项目,采用GitOps Toolkit模块化架构。
核心组件:
Text Only
┌────────────────────────────────────────────┐
│ Flux GitOps Toolkit │
├──────────────┬──────────┬─────────────────┤
│ Source │ Kustomize │ Helm │
│ Controller │ Controller│ Controller │
├──────────────┼──────────┼─────────────────┤
│ Notification │ Image │ Image │
│ Controller │ Reflector│ Automation │
└──────────────┴──────────┴─────────────────┘
4.2 Flux安装与配置¶
Bash
# 安装Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash # |管道:将前一命令的输出作为后一命令的输入
# 引导Flux到集群
flux bootstrap github \
--owner=myorg \
--repository=gitops-repo \
--branch=main \
--path=clusters/production \
--personal
# 检查状态
flux check
flux get all
4.3 Flux资源定义¶
YAML
# GitRepository源
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: my-app
namespace: flux-system
spec:
interval: 1m
url: https://github.com/myorg/gitops-repo
ref:
branch: main
---
# Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
path: ./apps/production
prune: true
sourceRef:
kind: GitRepository
name: my-app
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: backend
namespace: production
4.4 Flux镜像自动更新¶
YAML
# 镜像仓库扫描
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: my-app
namespace: flux-system
spec:
image: myregistry/my-app
interval: 5m
--- # YAML文档分隔符
# 镜像策略(使用最新semver标签)
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: my-app
namespace: flux-system
spec:
imageRepositoryRef:
name: my-app
policy:
semver:
range: '>=1.0.0'
---
# 自动更新配置
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: my-app
git:
commit:
author:
name: fluxcdbot
email: fluxcd@example.com
messageTemplate: 'chore: update image to {{.NewImage}}'
push:
branch: main
update:
path: ./apps/production
strategy: Setters
5. GitOps与Kubernetes集成¶
5.1 Kustomize环境管理¶
Text Only
kustomize/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── replicas-patch.yaml
│ └── production/
│ ├── kustomization.yaml
│ ├── replicas-patch.yaml
│ └── resources-patch.yaml
YAML
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: replicas-patch.yaml
- path: resources-patch.yaml
namespace: production
# overlays/production/replicas-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 5
5.2 Helm Chart GitOps¶
YAML
# Argo CD with Helm
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prometheus
spec:
source:
repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: 45.0.0
helm:
values: |
prometheus:
retention: 30d
grafana:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: monitoring
5.3 Secret管理¶
YAML
# 方案一:Sealed Secrets
apiVersion: bitnami.com/v1alpha1 # apiVersion指定K8s API版本
kind: SealedSecret # kind指定资源类型
metadata:
name: my-secret
spec: # spec定义资源的期望状态
encryptedData:
password: AgBy3i...encrypted...
# 方案二:SOPS + Age/PGP
# .sops.yaml
creation_rules:
- path_regex: .*\.enc\.yaml$
age: age1...publickey...
# 加密后可安全存入Git
sops --encrypt --age age1... secret.yaml > secret.enc.yaml
# 方案三:External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: my-secret
data:
- secretKey: password
remoteRef:
key: /myapp/production/db-password
6. GitOps最佳实践¶
6.1 仓库策略¶
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 单仓库(Monorepo) | 应用+配置在同一仓库 | 小团队、少量应用 |
| 双仓库 | 代码仓库 + 配置仓库分离 | 中大型团队(推荐) |
| 多仓库 | 每个团队/应用独立配置仓库 | 大型组织 |
6.2 变更管理¶
Text Only
推荐的GitOps变更流程:
1. 开发者创建PR修改配置
2. 自动化检查(lint、diff预览、策略检查)
3. 团队Review + 批准
4. 合并到主分支
5. GitOps Agent自动同步
6. 监控告警确认部署健康
6.3 回滚策略¶
Bash
# Argo CD回滚
argocd app rollback my-app
# Git回滚(推荐)
git revert HEAD
git push origin main
# GitOps agent会自动同步到回滚后的状态
7. 面试题精选¶
Q1: GitOps与传统CI/CD的核心区别?¶
| 维度 | 传统CI/CD | GitOps |
|---|---|---|
| 部署方式 | Push(CI推送到集群) | Pull(Agent从Git拉取) |
| 事实来源 | CI/CD工具配置 | Git仓库 |
| 安全模型 | CI需要集群凭证 | Agent在集群内运行 |
| 漂移检测 | 无 | 持续监控+自愈 |
| 审计追踪 | CI日志 | Git历史 |
| 回滚 | 重新执行旧版本Pipeline | git revert |
Q2: Argo CD和Flux如何选型?¶
| 维度 | Argo CD | Flux |
|---|---|---|
| UI | 内置强大Web UI | 无官方UI(可用Weave GitOps) |
| 架构 | 单体应用 | 模块化Toolkit |
| 多集群 | 原生支持 | 需Hub-Spoke模式 |
| 镜像自动更新 | 需Argo CD Image Updater | 原生支持 |
| 学习曲线 | 较低 | 中等 |
| CNCF状态 | 毕业项目 | 毕业项目 |
Q3: GitOps如何处理Secret?¶
- Sealed Secrets:加密后存入Git,集群内解密
- SOPS:使用KMS/PGP加密YAML文件
- External Secrets Operator:从外部Secret管理器(Vault/AWS SM)同步
- Vault Agent Injector:HashiCorp Vault直接注入
原则:永远不要将明文Secret存入Git。
Q4: 如何防止配置漂移?¶
- 启用GitOps Agent的自愈功能(selfHeal)
- 使用OPA/Kyverno策略禁止手动kubectl变更
- RBAC限制集群直接写权限
- 定期审计实际状态与Git状态的差异
Q5: GitOps的多环境管理策略?¶
- 推荐:目录分离 —— 同一仓库不同目录对应不同环境
- 可选:分支分离 —— 不同分支对应不同环境(PR合并=升级环境)
- 使用Kustomize overlay管理环境差异
- 通过ApplicationSet自动生成多环境Application
8. 推荐资源¶
- OpenGitOps —— GitOps标准定义
- Argo CD官方文档
- Flux官方文档
- GitOps Principles (CNCF)
- 《GitOps and Kubernetes》—— Billy Yuen等
下一步学习:结合05-CI-CD流水线设计完整的GitOps交付管道,并参考17-基础设施即代码实现基础设施的声明式管理。