登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  业界新闻

云原生 Argo CD OutOfSync 怎样处理

来源:17golang原创

时间:2026-10-22 07:31:25 364浏览 收藏

我在排查 Argo CD 应用时,最容易误判的一种状态就是 OutOfSync:它不等于“部署一定失败”,而是 Argo CD 发现 Git 生成的期望状态与集群中的 live state 不完全相同。正确处理顺序是先看差异对象和字段,再决定是改 Git、接受 Kubernetes 的默认化,还是调整比较策略;直接重复点击 Sync 往往只会把原因藏起来。

官方地址:https://argo-cd.readthedocs.io/en/stable/

我现在会把这件事拆成一张“迁移变更单”:先确认比较输入,再区分差异类型,最后才决定是否启用自动修复。

先把 OutOfSync 看成两份状态差异

Argo CD 的 Application 不是把 Git 文件原样拿去和集群 YAML 做字符串比较。它会按照 Application 的仓库、路径、分支或提交、Helm/Kustomize 参数生成目标清单,再把目标状态与 Kubernetes API 返回的 live state 比较。只要二者有差异,应用就可能显示 OutOfSync。

我排查时先记录三件事:当前 Application 的 targetRevision,实际生成清单所对应的资源,以及集群对象中出现差异的字段。这样能先排除“看的不是同一个提交”“路径或参数改变”“对象被另一个控制器改写”这几类误会。

Argo CD 从 Git 期望状态、清单生成到 Kubernetes live state 的静态关系说明图
图1:状态关系说明图,展示 Git 期望状态、Argo CD Application 与集群 live state 的边界;这不是界面截图或运行证据。

先用 diff 找到真正变化的字段

如果应用刚 Sync 完就再次变成 OutOfSync,我不会先打开自动同步,而是先查看差异。CLI 可以这样做:

# 查看应用摘要,先确认同步状态、健康状态和目标 revision
argocd app get demo-api

# 查看期望清单与集群 live state 的字段差异
argocd app diff demo-api

# 只在需要重新读取仓库和集群信息时执行硬刷新
argocd app get demo-api --hard-refresh

输出通常可以归到三类。第一类是 Git 中确实改了副本数、镜像或环境变量,属于真实变更,应该把修改提交到正确分支后再同步。第二类是 Kubernetes 或 admission webhook 在落库时补了默认字段、调整了格式或修改了对象,典型现象是资源值被规范化,或者每次比较都出现同一批字段。第三类是集群里有不在目标清单中的资源,或者资源归属标签、引用的 Application 不符合预期。

当前 Argo CD 文档把 Legacy、Structured-Merge 和 Server-Side Diff 分开说明。Server-Side Diff 会以 dry-run 的 Server-Side Apply 预测 live state;如果团队在迁移比较策略,必须把它当作一次行为变化记录,而不是只改一个开关就结束。

按差异性质选择修复方式

真实漂移优先修 Git。比如镜像标签已经在仓库中改动,就不要用 ignore 规则掩盖它;应该确认分支、参数和提交,再让 Argo CD 同步。

如果差异是明确且可接受的字段默认化,再使用精确的 ignoreDifferences 规则,并把资源组、种类、名称和字段范围写窄。不要直接忽略整个资源,否则以后真正的配置漂移也可能不再显眼。

# 仅示意:只忽略由集群控制器维护的特定字段
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-api
spec:
  ignoreDifferences:
    - group: apps
      kind: Deployment
      name: demo-api
      jsonPointers:
        # 这里只放已经确认由集群侧维护的字段
        - /spec/replicas

如果问题是生成器留下的额外资源,可以在资源上使用 argocd.argoproj.io/compare-options: IgnoreExtraneous,但这只影响同步状态,不等于资源健康状态被忽略。需要自动删除资源时,还要单独评估 Prune,不能把两者混成一个开关。

Argo CD OutOfSync 差异类型与修复策略边界的静态关系说明图
图2:差异处理说明图,展示字段默认化、额外资源、比较配置和自动修复之间的静态关系;这不是运行结果截图。

迁移自动同步前检查 prune、selfHeal 和 ApplicationSet

自动同步只是在发现 OutOfSync 时尝试同步,并不自动替你判断变更是否安全。官方默认不会因为 Git 中删掉资源就自动 prune;打开 prune 后,删除行为才会进入自动同步范围。allowEmpty 还会影响目标清单为空时的保护边界,所以生产环境应先检查删除和空资源场景。

selfHeal 适合希望集群手工漂移能回到 Git 的场景,但它不是所有问题的补丁。若 live state 被 webhook 或其他控制器持续改写,开启 self-heal 可能让两个控制器不断互相覆盖。ApplicationSet 生成的子 Application 也要从父级模板检查同步策略,单独改子 Application 的字段未必能改变最终行为。

# 迁移前的最小示意:明确自动同步、修复漂移和删除资源各自的含义
spec:
  syncPolicy:
    automated:
      enabled: true
      # 只有确认 Git 删除即代表集群删除时才打开
      prune: false
      # 只有确认人工改动应被 Git 状态覆盖时才打开
      selfHeal: true

我的回归清单通常只有四项:目标 revision 是否正确;diff 是否只剩预期字段;prune 是否会触碰未纳入 Git 的资源;ApplicationSet 或 webhook 是否会在同步后再次修改对象。四项都能解释清楚,再把配置迁移到生产。

几个容易混淆的问题

Sync 成功后为什么仍然 OutOfSync?

先看同步后的 diff。Kubernetes 默认化、资源被 webhook 改写、额外资源或比较策略变化,都可能让同步成功但状态仍不一致;这不应直接归因于网络或 Argo CD 故障。

ignoreDifferences 能不能解决所有 OutOfSync?

不能。它只适合明确属于外部控制器或平台默认化的差异。业务字段、镜像、环境变量和副本数如果本来应该由 Git 管理,就应该修正源清单或变更归属。

什么时候适合 selfHeal?

当团队明确要求集群手工改动回到 Git,并且没有其他控制器持续改写同一字段时更合适。开启前先观察 diff 和事件,给 prune 保留独立的人工决策。

把 OutOfSync 当作差异分类信号,排查会比“反复 Sync”更稳定:真实变更回到 Git,预期差异精确配置,自动修复则在删除、漂移和控制器协作边界都清楚后再启用。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>