前言
GitOps 的"自动应用"原则不代表所有同步都要自动。ArgoCD 提供了精细的同步控制------自动同步、手动同步、同步钩子、同步窗口。本篇讲清楚如何根据场景选择和配置同步策略。
一、同步策略总览
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Automated + selfHeal | 全自动同步+修复漂移 | 测试环境 |
| Automated (no selfHeal) | 自动同步但不修复漂移 | 预发环境 |
| Manual | 手动触发同步 | 生产环境 |
| Sync Window | 限制同步时间窗口 | 生产环境 |
| Sync Hook | 同步前后执行自定义操作 | 数据库迁移等 |
二、自动同步
配置
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-dev
namespace: argocd
spec:
syncPolicy:
automated:
prune: true # 自动删除 Git 中已删除的资源
selfHeal: true # 自动修复漂移(手动改集群会被自动恢复)
allowEmpty: false # 禁止同步到空(防止误删所有资源)
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
prune 和 selfHeal 的区别
prune: Git 中删除了某个资源 → 集群中也删除该资源
Git: 删掉 Service YAML → 集群: 自动删除对应的 Service
selfHeal: 有人手动改了集群中的资源 → 自动恢复为 Git 中的值
有人: kubectl scale deployment myapp --replicas=1
Git: replicas=3
→ ArgoCD 检测到漂移 → 自动恢复 replicas=3
自动同步的行为
Git push (修改了 replicas 从 2 → 3)
↓
ArgoCD 检测到 Git 变化(3秒内,配了 Webhook)
↓
ArgoCD 开始同步
↓
kubectl set image / kubectl apply(集群内执行)
↓
等待 Pod 滚动更新完成
↓
状态变为 Synced + Healthy
踩坑提示 :
allowEmpty: false很重要。如果有人不小心把 Git 仓库清空了,ArgoCD 不会把集群中所有资源都删掉。这是防止"删库跑路"的最后一道防线。
三、手动同步
配置
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-prod
namespace: argocd
spec:
# 没有 syncPolicy.automated → 手动同步
syncPolicy:
syncOptions:
- CreateNamespace=true
# 需要 argocd app sync myapp-prod 手动触发
手动同步操作
bash
# CLI 触发同步
argocd app sync myapp-prod
# Web UI 触发同步
# → 应用页面 → Sync 按钮
# 同步时可以只同步部分资源
argocd app sync myapp-prod \
--resource deployment/myapp \
--resource service/myapp
# 干运行(只看会做什么,不实际执行)
argocd app sync myapp-prod --dry-run
# 只应用,不删除(不 prune)
argocd app sync myapp-prod --prune=false
手动同步 + 自动审批
yaml
# 用 ArgoCD Notifications + Slack 实现审批流程
spec:
syncPolicy:
syncOptions:
- CreateNamespace=true
# 不配置 automated → 需要手动同步
# 但可以用 Slack 按钮触发同步
yaml
# argocd-notifications-cm
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
trigger.on-sync-status-changed: |
- when: app.status.sync.status in ['OutOfSync']
send: [slack-sync-required]
service.slack: |
token: $slack-token
template.slack-sync-required: |
message: |
{{.app.metadata.name}} 需要同步
sync: |
# 在 Slack 消息中添加同步按钮
# 点击按钮触发 ArgoCD API 同步
四、同步钩子(Sync Hooks)
什么是同步钩子
同步流程:
PreSync Hook → Sync → PostSync Hook
↓ ↓ ↓
数据库迁移 部署应用 通知/清理
SyncFail Hook(同步失败时执行)
PreSync Hook:同步前执行
yaml
# 在部署清单中定义 PreSync Hook
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/hook: PreSync # 同步前执行
argocd.argoproj.io/hook-delete-policy: HookSucceeded # 成功后删除
spec:
template:
spec:
containers:
- name: migration
image: myapp-migration:v1.0
command: ["./migrate.sh", "up"]
restartPolicy: Never
backoffLimit: 2
PostSync Hook:同步后执行
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: post-deploy-notify
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
template:
spec:
containers:
- name: notify
image: curlimages/curl
command:
- curl
- -X
- POST
- $(NOTIFY_WEBHOOK)
- -H
- "Content-Type: application/json"
- -d
- '{"text":"Deployment completed: myapp-prod"}'
restartPolicy: Never
SyncFail Hook:同步失败时执行
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: sync-fail-handler
annotations:
argocd.argoproj.io/hook: SyncFail
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
template:
spec:
containers:
- name: alert
image: curlimages/curl
command:
- curl
- -X
- POST
- $(ALERT_WEBHOOK)
- -d
- '{"text":"Deployment FAILED: myapp-prod"}'
restartPolicy: Never
Hook 删除策略
| 策略 | 说明 |
|---|---|
| HookSucceeded | 成功后删除 Hook Job |
| HookFailed | 失败后删除 Hook Job |
| BeforeHookCreation | 下次创建前删除旧的 Hook Job |
| Never | 永不删除 |
培训要点:PreSync Hook 最常用于数据库迁移------在部署新代码前先跑迁移脚本。这样即使新代码依赖新的表结构,也能保证迁移先于部署执行。
五、同步窗口
限制同步时间
yaml
# AppProject 中定义同步窗口
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-alpha
namespace: argocd
spec:
syncWindows:
# 允许窗口:工作日 9:00-21:00
- kind: allow
schedule: '0 9 * * 1-5' # 周一到周五9点
duration: 12h # 持续12小时
applications:
- 'myapp-prod'
namespaces:
- 'myapp-prod'
clusters:
- 'prod-cluster'
manualSync: true # 允许紧急手动同步
# 拒绝窗口:冻结期(如双11)
- kind: deny
schedule: '0 0 10 11 *' # 11月10日0点开始
duration: 72h # 持续72小时
applications:
- 'myapp-prod'
manualSync: false # 禁止手动同步
同步窗口规则
规则:
1. deny 窗口优先于 allow 窗口
2. 没有匹配到任何窗口 → 默认允许
3. 匹配到 allow 窗口 → 允许自动和手动同步
4. 匹配到 deny 窗口 → 禁止自动同步
5. deny 窗口 + manualSync=false → 连手动同步也禁止
6. deny 窗口 + manualSync=true → 禁止自动但允许手动
六、同步选项详解
常用 Sync Options
yaml
spec:
syncPolicy:
syncOptions:
# 自动创建命名空间
- CreateNamespace=true
# 删除传播策略
- PrunePropagationPolicy=foreground # 前台删除(等待完成)
# - PrunePropagationPolicy=background # 后台删除
# 优先应用 Namespace 和 CRD
- ApplyOutOfSyncOnly=true
# 跳过验证
- SkipDryRunOnMissingResource=true
# 如果资源已存在则不创建(避免冲突)
# - FailOnSharedResource=true
# 保留部分资源的差异
# - RespectIgnoreDifferences=true
忽略资源差异
yaml
spec:
ignoreDifferences:
# 忽略 Deployment 的副本数差异
# 适用于 HPA 自动调整副本数的情况
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
# 忽略 Secret 的 data 巇异
# 适用于 External Secrets 自动管理的 Secret
- group: ''
kind: Secret
jsonPointers:
- /data
jqPathExpressions:
- .data
七、本篇要点回顾
- 自动同步:
automated.prune=true + selfHeal=true,适合测试环境 - 手动同步:不配 automated,适合生产环境,可用 Slack 按钮触发
- PreSync Hook:同步前执行数据库迁移等操作
- PostSync Hook:同步后发通知、跑冒烟测试
- SyncFail Hook:同步失败自动告警和回滚
- 同步窗口:限制部署时间,deny 优先于 allow
allowEmpty: false是防止误删所有资源的最后防线
下一篇预告:《与 Helm 集成:Helm Chart 的 GitOps 管理》------学习如何在 ArgoCD 中管理 Helm Chart 部署。