Argo CD 自动同步(Automated Sync)完全指南:从 syncPolicy.automated 配置到控制器实现原理
Argo CD 自动同步Automated Sync完全指南从 syncPolicy.automated 配置到控制器实现原理【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd本文围绕 Argo CD 的自动同步策略Automated Sync展开当检测到 Git 中的期望清单与集群实际状态存在差异时Argo CD 可以自动完成部署CI/CD 流水线无需再直接访问 Argo CD API Server只需向 Git 仓库提交变更即可。读完本文你将掌握spec.syncPolicy.automated下enabled、prune、allowEmpty、selfHeal以及retry含指数退避与refresh各字段的完整配置方式并能从argocd-application-controller的源码层面理解自动同步的触发条件、防抖机制与自我保护逻辑。一、什么是 Automated Sync以及为什么需要它Argo CD 能够在检测到 Git 仓库中的期望清单desired manifests与集群中的实际状态live state存在差异时自动同步应用。自动同步的核心价值在于解耦CI/CD 流水线不再需要持有 Argo CD API Server 的访问权限来执行部署而是把清单变更以 commit push 的方式提交到跟踪的 Git 仓库由 Argo CD 自行完成后续部署动作。这正是Git 即单一事实来源的 GitOps 工作流形态。配置自动同步有两种等价方式方式一使用 CLI 修改已有应用argocd app set APPNAME --sync-policy automated方式二在应用清单中声明syncPolicy.automatedspec: syncPolicy: automated: {}1.1enabled字段显式开启或关闭自动同步Application CRD 支持通过spec.syncPolicy.automated.enabled字段显式控制自动同步的开与关当enabled为true时自动同步生效当enabled为false时即使prune、selfHeal、allowEmpty均已设置控制器也会跳过自动同步当enabled为null即未设置时按自动同步已开启处理。spec: syncPolicy: automated: enabled: true这一行为可以直接在 API 类型定义中得到印证。在 pkg/apis/application/v1alpha1/types.go 中判断逻辑为// IsAutomatedSyncEnabled checks if the automated sync is enabled or disabled func (p *SyncPolicy) IsAutomatedSyncEnabled() bool { if p.Automated ! nil (p.Automated.Enabled nil || *p.Automated.Enabled) { return true } return false }即Automated非空且Enabled为 nil 或 true 时视为开启——nil按开启处理与文档中的 NOTE 说明完全一致。对应的SyncPolicyAutomated结构体定义在 pkg/apis/application/v1alpha1/types.gotype SyncPolicyAutomated struct { // Prune specifies whether to delete resources from the cluster that are not found in the sources anymore as part of automated sync (default: false) Prune *bool json:prune,omitempty ... // SelfHeal specifies whether to revert resources back to their desired state upon modification in the cluster (default: false) SelfHeal *bool json:selfHeal,omitempty ... // AllowEmpty allows apps have zero live resources (default: false) AllowEmpty *bool json:allowEmpty,omitempty ... // Enable allows apps to explicitly control automated sync Enabled *bool json:enabled,omitempty ... }注意这几个字段全部是*bool指针类型配合GetPrune()、GetSelfHeal()、GetAllowEmpty()等辅助方法同文件 #L1628-L1649在 nil 时回退为false。这种三态true / false / 未设置设计正是enabled字段能够区分未设置与显式关闭的基础。二、ApplicationSet 管理的应用临时切换自动同步的特殊性对于独立应用standalone application切换自动同步就是修改应用自身的spec.syncPolicy.automated字段但对于 ApplicationSet 托管的应用直接修改生成的 Application 的spec.syncPolicy.automated是没有效果的——ApplicationSet 控制器会基于 ApplicationSet 规格持续再生成应用手工改动会被覆盖或不被采纳。针对这类应用的临时开关操作应遵循 ApplicationSet 文档 《Controlling Resource Modification》 中描述的方式例如通过 ApplicationSet 的spec.syncPolicy.applicationsSync或修改控制资源本身来执行。三、自动清理Automatic Pruning默认情况下出于安全考虑即使检测到某资源已不再出现在 Git 清单中自动同步也不会删除该资源。此时总是可以执行一次带 prune 选项的手动同步来清理残留资源。若要让清理动作自动发生可以使用 CLIargocd app set APPNAME --auto-prune或在自动同步策略中设置prune: truespec: syncPolicy: automated: prune: true对应地CLI 参数--auto-prune在 cmd/util/app.go 中注册Set automatic pruning for automated sync policy与--self-heal、--allow-empty一起在setApp命令中写入spec.syncPolicy.automated的相应字段参见 cmd/util/app.go 中flags.Changed(auto-prune)等分支。从控制器侧看prune的取值直接影响自动同步是否被触发。在 controller/appcontroller.go 的autoSync函数中if !app.Spec.SyncPolicy.Automated.GetPrune() { requirePruneOnly : true for _, r : range resources { if r.Status ! appv1.SyncStatusCodeSynced !r.RequiresPruning { requirePruneOnly false break } } if requirePruneOnly { logCtx.Infof(Skipping auto-sync: need to prune extra resources only but automated prune is disabled) return nil, 0 } }含义是如果本次差异全部表现为仅需要 prune 多余资源而prune又未开启控制器会直接跳过自动同步并记录日志——这与prune 默认关闭是安全机制的文档表述一一对应。四、Allow-Empty 保护防止自动同步清空整个应用v1.8 引入默认情况下prune开启的自动同步内置了一项保护机制当目标资源集合为空没有任何资源需要保留时拒绝执行以防自动化脚本或人为错误把应用清空。若确实需要允许应用处于零资源状态可使用 CLIargocd app set APPNAME --allow-empty或在策略中同时设置prune与allowEmptyspec: syncPolicy: automated: prune: true allowEmpty: true控制器侧的对应实现在 controller/appcontroller.go当GetPrune()为 true 且GetAllowEmpty()为 false 时如果所有资源都标记为RequiresPruning即同步后应用将变为空控制器会放弃本次同步并写入一条SyncError条件if app.Spec.SyncPolicy.Automated.GetPrune() !app.Spec.SyncPolicy.Automated.GetAllowEmpty() { bAllNeedPrune : true for _, r : range resources { if !r.RequiresPruning { bAllNeedPrune false } } if bAllNeedPrune { message : fmt.Sprintf(Skipping sync attempt to %s: auto-sync will wipe out all resources, desiredRevisions) ... return appv1.ApplicationCondition{Type: appv1.ApplicationConditionSyncError, Message: message}, 0 } }这条 auto-sync will wipe out all resources 错误信息正是该安全机制在应用status.conditions中的直接体现排查应用停在 SyncError 却没有任何资源动作时可重点查看。五、自动自我修复Automatic Self-Healing默认情况下对集群的现场修改drift不会触发自动同步。若要让集群实际状态偏离 Git 定义这一情况也触发自动回正可使用 CLIargocd app set APPNAME --self-heal或声明式配置spec: syncPolicy: automated: selfHeal: true注意关闭 self-heal 并不能保证多源multi-source应用中现场修改的持久性。即便某个资源的来源未发生变化另一来源的变更仍可能触发自动同步autosync从而把现场修改抹掉。此类场景建议直接关闭 autosync即enabled: false。5.1 self-heal 的重试节奏超时与指数退避文档指出当selfHeal为 true 时同步会在 self-heal 超时默认 5 秒后再次尝试该超时由argocd-application-controller部署的--self-heal-timeout-seconds参数控制。该参数定义在 cmd/argocd-application-controller/commands/argocd_application_controller.gocommand.Flags().IntVar(selfHealTimeoutSeconds, self-heal-timeout-seconds, env.ParseNumFromEnv(ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_TIMEOUT_SECONDS, 0, 0, math.MaxInt32), Specifies timeout between application self heal attempts)同一命令行还配套注册了一组指数退避参数同文件 #L268-L271--self-heal-backoff-timeout-seconds默认 2 秒、--self-heal-backoff-factor默认 3、--self-heal-backoff-cap-seconds默认 300 秒以及已弃用的--self-heal-backoff-cooldown-seconds。控制器中self-heal 的重试计时由selfHealRemainingBackoff方法实现见 controller/appcontroller.go并在autoSync主流程中被调用if remainingTime : ctrl.selfHealRemainingBackoff(app, int(op.Sync.SelfHealAttemptsCount)); remainingTime 0 { logCtx.Infof(Skipping auto-sync: already attempted sync to %s with timeout %v (retrying in %v), ...) ctrl.requestAppRefresh(app.QualifiedName(), CompareWithLatest.Pointer(), remainingTime) return nil, 0 }也就是说self-heal 触发不是立即再次同步而是在退避窗口到期后请求一次带延迟的刷新再评估是否需要发起新同步每次 self-heal 尝试通过op.Sync.SelfHealAttemptsCount计数累积controller/appcontroller.go。六、带次数限制的自动重试Retry with a LimitArgo CD 支持使用指数退避策略自动重试失败的同步操作通过在syncPolicy.retry中配置spec: syncPolicy: retry: limit: 5 # number of retries (-1 for unlimited retries) backoff: duration: 5s # base duration between retries factor: 2 # exponential backoff factor maxDuration: 3m # maximum duration between retries各字段含义limit重试次数上限设为-1表示无限重试backoff.duration首次重试前的基础等待时长backoff.factor每次失败后乘以上一次的倍数backoff.maxDuration无论重试多少次两次重试之间的最大等待时长。类型定义见 pkg/apis/application/v1alpha1/types.go 的RetryStrategyLimit int64、Backoff *Backoff、Refresh bool。一个值得注意的实现细节在 controller/appcontroller.go 中控制器构造自动同步操作时若用户未配置retry会自动应用一个Retry: appv1.RetryStrategy{Limit: 5}的默认值若用户在spec.syncPolicy.retry中有声明则整体覆盖该默认值。因此未配置的自动同步默认重试 5 次是源码层面可以确认的事实。七、重试期间随新修订版刷新Automatic Retry Refresh on New Revisions该功能允许应用在当前同步处于重试中时随新 revision 出现而刷新即重试使用最新修订而非最初触发重试时的修订。启用方式argocd app set APPNAME --sync-retry-refresh或声明式配置spec: syncPolicy: retry: refresh: trueCLI 参数--sync-retry-refresh的注册见 cmd/util/app.go语义为 Indicates if the latest revision should be used on retry instead of the initial one与RetryStrategy.Refresh字段的注释Refresh indicates if the latest revision should be used on retry instead of the initial one (default: false)见 pkg/apis/application/v1alpha1/types.go相互对应。八、Automated Sync 的语义细节行为边界自动同步并非只要 OutOfSync 就无条件执行文档与源码共同界定了以下行为边界仅 OutOfSync 才触发处于 Synced 或错误状态的应用不会发起自动同步。源码印证见 controller/appcontroller.goif syncStatus.Status ! appv1.SyncStatusCodeOutOfSync时直接跳过。同一 commit-SHA1 参数组合只尝试一次若最近一次成功同步已经针对相同的 commit SHA 和参数执行过则不会再次尝试除非设置了selfHeal: true。该判断由alreadyAttemptedSync函数完成controller/appcontroller.go并带有一段关键注释这是为了防止同步/apply 之后清单仍然 OutOfSync例如 prune 关闭时导致的无限循环同步。失败的同步不会立即重来若针对同一 commit-SHA 和参数的上一次同步尝试失败自动同步不会再次尝试源码见 controller/appcontroller.go会返回 Failed last sync attempt... 的SyncError条件并停止恢复需要人工干预或等待 revision 变化。selfHeal 开启后的例外路径当已尝试过且上次成功但应用因现场漂移变为 OutOfSync 时会走 self-heal 分支——仅对Status ! Synced的资源构建同步操作controller/appcontroller.go并受第 5.1 节所述退避窗口约束。自动同步开启期间禁止回滚对启用了自动同步的应用不能执行 rollback 操作自动同步会持续把应用拉回目标修订与回滚语义冲突。同步间隔由argocd-cm决定自动同步的检查间隔由 docs/faq.md 中说明的argocd-cmConfigMap 的timeout.reconciliation值决定默认120s并叠加最大60s的抖动jitter实际检查周期最长约 3 分钟。其他跳过条件源码补充app.Operation ! nil有其他操作正在进行或应用处于删除中DeletionTimestamp 非零时autoSync也会直接跳过controller/appcontroller.go。九、配置速查表配置项CLIargocd app setYAML 字段默认值作用自动同步--sync-policy automatedspec.syncPolicy.automated: {}关闭Automated为 nil检测到 Git 与集群差异时自动同步显式开关—automated.enabled: true/falsenil 按 true 处理显式关闭后prune/selfHeal/allowEmpty 均不生效自动清理--auto-pruneautomated.prune: truefalse删除 Git 中已不存在的资源允许空应用--allow-emptyautomated.allowEmpty: truefalseprune 开启时防止同步会清空全部资源的保护自动自我修复--self-healautomated.selfHeal: truefalse集群现场漂移时自动回正重试节奏受--self-heal-timeout-seconds默认 5 秒及退避参数控制重试策略—retry.limit/retry.backoff.*未配置时控制器默认limit: 5失败同步按指数退避重试-1为无限重试刷新--sync-retry-refreshretry.refresh: truefalse重试时使用最新 revision 而非最初触发重试的 revision十、延伸阅读自动同步间隔的 FAQ 说明docs/faq.mdHow often does Argo CD check for changes... 一节ApplicationSet 应用的资源修改控制docs/operator-manual/applicationset/Controlling-Resource-Modification.md自动同步核心实现controller/appcontroller.goautoSync函数API 类型定义pkg/apis/application/v1alpha1/types.goCLI 参数注册cmd/util/app.go、控制器参数cmd/argocd-application-controller/commands/argocd_application_controller.goCLI 行为测试用例cmd/util/app_test.go覆盖--auto-prune/--self-heal/--allow-empty/--sync-retry-refresh的置位与复位【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →