Argo CD ApplicationSet Progressive Syncs 实战指南:基于 RollingSync 的渐进式应用发布与回滚删除
2026/9/13 6:35:05 网站建设 项目流程

Argo CD ApplicationSet Progressive Syncs 实战指南:基于 RollingSync 的渐进式应用发布与回滚删除

【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd

导读

Progressive Syncs(渐进式同步)是 Argo CD ApplicationSet 提供的Beta 功能(自 v3.3.0 起),它允许你控制 ApplicationSet 控制器创建、更新乃至删除其托管 Application 的顺序。通过为生成的 Application 打上标签并按matchExpressions分组,你可以实现"先灰度环境、再验证环境、最后生产环境分批发布"的滚动式发布流程,并让每一步都等待前一批应用进入Healthy状态后再继续。读完本文,你将掌握 Progressive Syncs 的启用方式、RollingSync创建策略与Reverse删除策略的完整配置,并能结合源码理解其底层状态机(Waiting → Pending → Progressing → Healthy)与最终器(finalizer)保障机制。

功能状态:Beta。该功能整体稳定,但可能仍存在未覆盖的边缘场景。相关实现位于 applicationset/progressivesync/progressive_sync.go。

使用场景与设计边界

Progressive Syncs 的设计目标被刻意保持为轻量且灵活

  • 该功能只与托管 Application 的健康状态(Health)交互,不会与 Argo Rollouts、原生 ReplicaSet 控制器等"回滚控制器"直接集成。
  • 控制器会监听托管 Application 变为Healthy才进入下一阶段
  • 由于应用在 Pod 滚动期间会进入Progressing状态,因此 Deployment、DaemonSet、StatefulSet 以及 Argo Rollouts 都天然受支持;实际上,任何健康检查能够报告Progressing状态的资源都受支持(见 gitops-engine/pkg/health 的健康状态定义)。
  • Argo CD Resource Hooks(资源钩子)同样受支持,例如 sync-waves(同步波次)。官方建议:在无法使用 Argo Rollout 但又需要高级功能的场景(例如 DaemonSet 变更后的冒烟测试)下,优先采用这一方案。

启用 Progressive Syncs

作为实验性功能,Progressive Syncs 必须显式开启,三种方式任选其一:

  1. 命令行参数:在 ApplicationSet 控制器启动参数中传入--enable-progressive-syncs
  2. 环境变量:设置ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS=true
  3. ConfigMap:在 Argo CD 的argocd-cmd-params-cmConfigMap 中设置applicationsetcontroller.enable.progressive.syncs: "true"

从源码看,命令行标志通过环境变量兜底解析,默认均为false,见 cmd/argocd-applicationset-controller/commands/applicationset_controller.go:

command.Flags().BoolVar(&enableProgressiveSyncs, "enable-progressive-syncs", env.ParseBoolFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS", false), "Enable use of the experimental progressive syncs feature.")

启用后,控制器在协调循环(reconcile)中才会进入渐进式同步分支。注意两点行为差异(见 applicationset/controllers/applicationset_controller.go):

  • 若功能开启,但某个 ApplicationSet 的策略从RollingSync切回了默认策略,控制器会清理残留的ApplicationStatus条目;
  • 若功能关闭,控制器同样会清空所有ApplicationStatus,避免脏数据残留。

策略总览:创建与删除是两个独立字段

ApplicationSet 的策略(spec.strategy)同时控制应用的创建/更新删除,二者由两个独立字段配置:

字段控制对象可选值
type应用的创建与更新顺序AllAtOnce(默认)、RollingSync
deletionOrder应用的删除顺序AllAtOnce(默认)、Reverse

创建策略(Creation Strategies)

AllAtOnce(默认)

这是 ApplicationSet 的原始默认行为:ApplicationSet 一旦更新,其管理的所有 Application 将同时被更新,行为与未启用 Progressive Syncs 时完全一致。

spec: strategy: type: AllAtOnce # 显式声明,但该值本就是默认值

RollingSync

该更新策略允许你按生成 Application 资源上的标签进行分组:当 ApplicationSet 变化时,变更将按组依次应用到各 Application。

其核心语义如下:

  • 分组通过 Application 的labelsmatchExpressions完成选择;
  • 一个 Application 必须满足某步内的所有matchExpressions才会被选中(多个表达式之间是AND关系);
  • InNotIn操作符:只要匹配到至少一个values值即为真(OR关系);
  • NotInIn同时命中时,NotIn优先级更高
  • 每个分组内的所有 Application必须全部变为Healthy,控制器才会继续更新下一组;
  • 同组内并发更新的 Application 数量不超过maxUpdate参数(默认 100%,即不设上限);
  • RollingSync会捕获 ApplicationSet 资源之外的变更,因为它依赖监听托管 Application 的OutOfSync状态;
  • RollingSync会强制所有生成的 Application 关闭自动同步(autosync),凡是在 Application 规范里配置了自动同步策略的,都会在 applicationset-controller 日志中打印警告;
  • Sync 操作的触发方式与在 UI/CLI 中手动触发完全一致(即直接设置 Application 资源的operation状态字段),因此RollingSync 会像用户在 Argo UI 点击"Sync"按钮一样遵守同步窗口(sync windows)
  • 触发同步时,沿用 Application 自身配置的 syncPolicy,例如保留其重试(retry)设置;
  • 未被任何步骤选中的 Application 会被排除在滚动同步之外,需要手动通过 CLI 或 UI 同步。

配置示例——两个发布步骤:

spec: strategy: type: RollingSync rollingSync: steps: - matchExpressions: - key: envLabel operator: In values: - env-dev - matchExpressions: - key: envLabel operator: In values: - env-prod maxUpdate: 10%

该示例的执行过程:

  1. 第一步:所有带标签envLabel=env-dev的 Application 被选中先同步。由于未定义maxUpdate,采用默认值 100%,所有匹配的 Application 将同时同步;控制器等待每个被选中的应用都达到Healthy状态,才进入下一步;
  2. 第二步:所有带标签envLabel=env-prod的 Application 被选中同步,但这里maxUpdate: 10%意味着每次只同步匹配应用中的 10%。每一批应用达到Healthy后,再同步下一批,直到全部匹配应用完成同步。

若存在未匹配任何表达式的应用,它们不会被 RollingSync 策略同步,必须如前文所述手动同步。

maxUpdate 的取值规则(源码佐证)

在 applicationset/progressivesync/progressive_sync.go 的UpdateApplicationSetApplicationStatusProgress中:

  • maxUpdate同时支持整数百分比字符串两种写法(底层为intstr.IntOrString,经GetScaledValueFromIntOrPercent换算);
  • 百分比值向下取整,但对于大于 0% 的值,至少保证有 1 个 Application 被选中maxUpdateVal < 1时强制置为 1);
  • maxUpdate: 0表示该步骤不会更新任何匹配的 Application
  • maxUpdate值非法,控制器会记录一条InvalidMaxUpdates校验问题,并忽略该步骤的 maxUpdate 逻辑(即退化为不限数量)。
分组选择逻辑(源码佐证)

buildAppDependencyList(见 progressive_sync.go)负责把当前 Application 按步骤分桶:

  • 对每个步骤的每个matchExpression,先查 Application 是否含对应 label key:In操作符下缺 key 即不入选;NotIn下缺 key 则视为匹配;
  • 一个 Application 被多个步骤选中时,会打印警告并记录为DuplicateAppSelections校验问题;
  • 没有任何 Application 匹配的步骤会被记录为EmptySteps(空步骤);
  • 未被任何表达式选中的 Application 在步骤映射中默认落在step -1(见getAppStep),即被排除在滚动同步之外。
校验与状态条件(源码佐证)

ValidationIssues(见 applicationset/progressivesync/validation_issues.go)会收集四类问题:非法matchExpression操作符(仅支持In/NotIn)、重复选中、空步骤、非法maxUpdate。当存在问题时,控制器会在 ApplicationSet 上设置ApplicationSetConditionInvalidRolloutConfig条件,并优先报告其中优先级最高的一项。

同时,控制器会根据各步骤是否全部Healthy来维护ApplicationSetConditionRolloutProgressing条件(getProgressingCondition,见 progressive_sync.go):进行中时消息为ApplicationSet is performing rollout of step N,完成时为ApplicationSet Rollout has completed

底层状态机:Waiting → Pending → Progressing → Healthy

UpdateApplicationSetApplicationStatusUpdateApplicationSetApplicationStatusProgress的实现(progressive_sync.go)可以看到,每个 Application 在渐进式同步中经历以下状态:

  1. Waiting(等待):检测到目标修订(TargetRevisions)或期望 spec 与当前不一致(非 Git 变更,例如生成器参数变化)时进入;控制器会比较 revision 与 spec(通过SpecsEquivalentBuildIgnoreDiffConfig,支持ignoreApplicationDifferences配置);
  2. Pending(待定):当前步骤满足"所有前序步骤均 Healthy"且未超过maxUpdate配额后,由UpdateApplicationSetApplicationStatusProgress推进;
  3. Progressing(进行中):观测到 Application 触发了同步操作(OperationState)后进入;若 Application 存在错误条件(如InvalidSpecErrorUnknownError),也会直接推进到 Progressing 以暴露问题;
  4. Healthy(健康):Application 的 Health 为Healthy且 Sync 状态为Synced时达成,此时才算该波次完成。

此外,PerformProgressiveSyncs在开始前会通过ensureApplicationsReconciled(progressive_sync.go)确保所有 Application 已在最近一次变更之后完成协调(reconcile),必要时会给应用添加 refresh annotation 强制刷新;refresh-grace-period-seconds(默认 30 秒,环境变量ARGOCD_APPLICATIONSET_CONTROLLER_REFRESH_GRACE_PERIOD_SECONDS)用于控制强制刷新前的宽限期。

同步触发方式(源码佐证)

SyncDesiredApplicationssyncApplication(progressive_sync.go)展示了滚动同步如何触发同步:

  • 只为处于Pending状态的 Application 触发同步,并锁定到该步骤解除阻塞时记录的 TargetRevisions,避免发布中途新提交"劫持"已在进行中的步骤;
  • 通过构造OperationInitiatedByapplicationset-controllerAutomated: true)写入 Application 的operation字段,与 UI/CLI 手动触发路径一致;
  • 默认设置重试上限Retry.Limit = 5,与 Argo CD 应用控制器的自动同步行为保持一致;若 Application 的 syncPolicy 配置了自定义retry,则以其为准;
  • 同步时携带 Application 的syncOptionsprune设置;
  • 同时强制关闭生成应用的自动同步disableAutomatedSync),这正是文档所述"RollingSync 会强制所有生成的 Application 关闭 autosync"的底层实现。

删除策略(Deletion Strategies)

deletionOrder字段控制应用从 ApplicationSet 移除时的删除顺序

AllAtOnce 删除(默认)

所有需要删除的 Application同时被删除。该模式与AllAtOnceRollingSync两种创建策略均可搭配使用。

spec: strategy: type: RollingSync # 或 AllAtOnce deletionOrder: AllAtOnce # 显式声明,但该值本就是默认值

Reverse 删除(逆序删除)

RollingSync策略搭配deletionOrder: Reverse时,应用将rollingSync.steps中定义步骤的逆序被删除:越晚部署的应用越先删除。这在需要按特定顺序拆除依赖服务时尤其有用——例如先删前端服务,再删后端依赖。

Reverse 删除的硬性要求:

  • 必须与type: RollingSync搭配使用;
  • 必须定义rollingSync.steps
  • 应用严格按照步骤序列的逆序删除。

重要保障机制:

  • ApplicationSet 的 finalizer 在所有 Application 成功删除前不会被移除,这确保了清理的完整性,防止 ApplicationSet 在托管应用之前被删除;
  • deletionOrder设置为Reverse且渐进式同步启用时,ApplicationSet 控制器会确保存在 finalizer:如果 ApplicationSet 缺少必需的 finalizer,控制器会在生成应用之前自动为它添加(见 applicationset/controllers/applicationset_controller.go)。
spec: strategy: type: RollingSync deletionOrder: Reverse rollingSync: steps: - matchExpressions: - key: envLabel operator: In values: - env-dev # 步骤 1:最先创建,最后删除 - matchExpressions: - key: envLabel operator: In values: - env-prod # 步骤 2:第二个创建,最先删除

删除时执行顺序:

  1. env-prod的应用(步骤 2)先删除
  2. env-dev的应用(步骤 1)后删除

该顺序适合"拆除依赖服务"的场景,例如先删除前端服务、再删除其后端依赖。

Reverse 删除的底层实现(源码佐证)

PerformReverseDeletion(见 progressive_sync.go)实现了逆序删除:

  • 先通过buildAppDependencyList得到每个应用所属步骤,再按stepLength - appStep - 1计算逆序优先级并排序,逐级触发Client.Delete
  • 每个步骤删除后控制器会以 10 秒为间隔重新入队(requeue),持续轮询直到对象消失;
  • 对"已经标记删除但迟迟未消失"的应用,若超过2 分钟staleCacheThreshold)仍未消失,控制器会绕过 informer 缓存直接向 API Server 求证(通过APIReader),区分"删除缓慢"与"DELETED 事件丢失导致的幽灵缓存项"两种情形,必要时通过带 UID 前置条件的 Delete 触发缓存驱逐,避免幽灵条目阻塞 finalizer 的释放(相关回归测试见 applicationset/progressivesync/phantom_livecheck_test.go);
  • 整个流程结束(全部删除完成)后才返回,控制器才会释放 ApplicationSet 的 finalizer。

完整示例:分环境渐进式发布 guestbook

下面的完整示例演示了如何为显式配置了环境标签的 Application 编排一次渐进式发布。当一次变更被推送后,将按顺序发生如下动作:

  • 所有env-dev的 Application同时更新
  • 滚动过程会等待所有env-qa的 Application 通过argocdCLI 或 UI 中的 Sync 按钮被手动同步
  • 所有env-prod的 Application 将每次更新 10%,直到全部更新完毕。
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: guestbook spec: generators: - list: elements: - cluster: engineering-dev url: https://1.2.3.4 env: env-dev - cluster: engineering-qa url: https://2.4.6.8 env: env-qa - cluster: engineering-prod url: https://9.8.7.6/ env: env-prod strategy: type: RollingSync deletionOrder: Reverse # 应用将按步骤逆序删除 rollingSync: steps: - matchExpressions: - key: envLabel operator: In values: - env-dev #maxUpdate: 100% # 若不定义,默认一次更新所有匹配应用(默认 100%) - matchExpressions: - key: envLabel operator: In values: - env-qa maxUpdate: 0 # 若为 0,则不会更新任何匹配的应用 - matchExpressions: - key: envLabel operator: In values: - env-prod maxUpdate: 10% # maxUpdate 支持整数和百分比字符串(向下取整,但 >0% 时至少为 1 个应用) goTemplate: true goTemplateOptions: ['missingkey=error'] template: metadata: name: '{{.cluster}}-guestbook' labels: envLabel: '{{.env}}' spec: project: my-project source: repoURL: https://github.com/infra-team/cluster-deployments.git targetRevision: HEAD path: guestbook/{{.cluster}} destination: server: '{{.url}}' namespace: guestbook

要点解读:

  • goTemplate: true开启 Go 模板渲染生成器参数,envLabel标签来自生成器的env字段,是步骤选择(matchExpressions)的匹配依据;
  • maxUpdate: 0env-qa步骤"只等待、不自动同步",配合手动同步使用;
  • deletionOrder: Reverse保证删除时按env-prod → env-qa → env-dev的顺序逆序进行;
  • 模板中的projectsourcedestination是 Application 的标准字段,会被渐进式同步流程原样继承。

参考实现与延伸阅读

  • 渐进式同步核心实现:applicationset/progressivesync/progressive_sync.go
  • 配置校验问题模型:applicationset/progressivesync/validation_issues.go
  • 渐进式同步单元测试:applicationset/progressivesync/progressive_sync_test.go、applicationset/progressivesync/specchanged_regression_test.go
  • ApplicationSet 控制器集成逻辑:applicationset/controllers/applicationset_controller.go
  • 控制器启动参数与环境变量:cmd/argocd-applicationset-controller/commands/applicationset_controller.go
  • 配合使用的同步波次(Resource Hooks):docs/user-guide/sync-waves.md

注意事项与限制

  1. Beta 功能:开启后请先在非生产环境验证,关注控制器日志中的警告(例如自动同步被强制关闭、非法maxUpdate、重复选中、空步骤等提示);
  2. 不要混用自动同步:RollingSync 会强制关闭托管应用的自动同步并打印警告,请确保模板中未配置syncPolicy.automated,避免行为冲突;
  3. 未命中步骤的应用需手动同步:任何未被matchExpressions选中的应用都不会被自动更新;
  4. 删除依赖最终器:Reverse 删除依赖 ApplicationSet finalizer 保障顺序,请勿手动移除该 finalizer,否则可能破坏删除顺序保障。

【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询