Argo CD 同步后应用仍显示 OutOfSync 怎么定位并忽略无关字段差异?
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
执行一次 Sync 成功之后,Application 的状态却仍然停在OutOfSync。这种情况在 Argo CD 中并不罕见:同步操作本身没有失败,而是 Git 中的期望状态和集群里的实际状态之间存在一些"预期内"的差异,导致 diff 无法收敛。
这篇文章针对的排查路径是:先在 UI 中定位具体是哪个资源、哪个字段产生了差异,判断差异来源,然后使用 Argo CD 的 diffing customization(ignoreDifferences等配置)把无关字段从 diff 中排除,最后重新触发比较验证状态恢复。依据来自 docs/faq.md 和 docs/user-guide/diffing.md。
先定位:确认差异出在哪个资源的哪个字段
文档列出了同步成功后仍可能OutOfSync的典型原因(见 docs/user-guide/diffing.md):
- manifest 本身有 bug,包含真实 K8s spec 之外的额外/未知字段。这些字段在从 Kubernetes 查询 live state 时会被丢弃,于是出现"检测到字段缺失"的
OutOfSync; - 同步时禁用了 pruning(pruning disabled),而 Git 中已删除的资源还存在于集群,需要被删除;
- 某个 controller 或 mutating webhook 在对象提交到 Kubernetes 之后修改了它,使其与 Git 中的版本不一致;
- Helm chart 使用了
randAlphaNum这类模板函数,每次调用helm template生成不同数据; - HPA 对象的
spec.metrics会被 HPA controller 按特定顺序重排(见 kubernetes issue #74099)。文档给出的规避方式是:在 Git 中把spec.metrics排成 controller 偏好的顺序。
另外 docs/faq.md 还补充了两个常见现象:
- resource limits 等带单位字段的"假漂移":Kubernetes 应用时会规范化数值,例如
'1000m'变成'1'、'0.1'变成'100m'、'3072Mi'变成'3Gi'、8760h变成8760h0m0s。Git 里的原始值和集群里规范化后的值不相等,diff 就报差异。这类问题用后文的knownTypeFields定制解决。 app.kubernetes.io/instance标签被其他工具抢先写入:Argo CD 自动设置该标签并靠它判定哪些资源属于应用;如果 Kustomize common labels 这类工具也在设置它,会造成冲突。解决办法是在argocd-cm中设置application.instanceLabelKey(文档推荐argocd.argoproj.io/instance)。注意:做这个改动后,所有应用会变为 out of sync,需要重新同步(文档原文 NOTE)。
定位时,先在 Argo CD UI 打开应用页面查看 SYNC STATUS 下各资源的差异明细,确认差异字段属于上面哪一类:是 manifest 自身问题、webhook/controller 注入字段、模板随机值,还是数值规范化差异。差异字段能对上号之后,才决定用哪条忽略路径。
应用级:在 Application spec 中配置 ignoreDifferences
上游问题无法修复时,Argo CD 允许按 JSON path 忽略差异,支持 RFC6902 JSON pointer(jsonPointers)和 JQ path 表达式(jqPathExpressions),也可以按 live 资源metadata.managedFields中的 manager 忽略(managedFieldsManagers)。
在 Application 的spec.ignoreDifferences中声明。文档示例:忽略该应用下所有 Deployment 的spec.replicas差异:
spec: ignoreDifferences: - group: apps kind: Deployment jsonPointers: - /spec/replicasgroup是 Kubernetes API group 去掉版本号的部分。作用范围可以进一步收窄到具体名称和命名空间:
spec: ignoreDifferences: - group: apps kind: Deployment name: guestbook namespace: default jsonPointers: - /spec/replicas忽略列表中的某些元素时,用 JQ 表达式按内容定位列表项,例如忽略某个被注入的 init container:
spec: ignoreDifferences: - group: apps kind: Deployment jqPathExpressions: - .spec.template.spec.initContainers[] | select(.name == "injected-init-container")忽略 live 资源中由特定 manager 拥有的字段(group/kind可用'*'通配整个应用的所有资源):
spec: ignoreDifferences: - group: '*' kind: '*' managedFieldsManagers: - kube-controller-manager两个容易踩的写法细节:
- pointer 路径中含有
/时必须转义为~1,例如忽略 Node 标签node-role.kubernetes.io/worker:
spec: ignoreDifferences: - kind: Node jsonPointers: - /metadata/labels/node-role.kubernetes.io~1worker- 如果集群里存在
field not declared in schema报错,managedFieldsManagers这类依赖静态 schema 的功能会受影响(见 docs/faq.md 的field not declared in schema一节),需要升级到包含相应 schema 的 Argo CD 版本,或按文档给出的绕行方式处理。
系统级:通过 argocd-cm 配置忽略差异
需要对该 Argo CD 实例的多个应用统一生效时,把定制放在argocd-cmConfigMap 的resource.customizations下,按<group>_<kind>命名 key。
忽略特定资源类型的指定字段(文档示例:忽略MutatingWebhookConfigurationwebhooks 的caBundle):
data: resource.customizations.ignoreDifferences.admissionregistration.k8s.io_MutatingWebhookConfiguration: | jqPathExpressions: - '.webhooks[]?.clientConfig.caBundle'按 manager 忽略,作用到指定类型(忽略Deployment上由kube-controller-manager造成的变更):
data: resource.customizations.ignoreDifferences.apps_Deployment: | managedFieldsManagers: - kube-controller-manager对实例内所有应用的全部资源生效(key 使用all):
data: resource.customizations.ignoreDifferences.all: | managedFieldsManagers: - kube-controller-manager jsonPointers: - /spec/replicas关闭 status 字段比较。很多资源的status会被提交到 Git,但status是 controller 用来持久化当前状态、不能作为期望配置下发的字段。通过resource.compareoptions关闭:
data: resource.compareoptions: | # 'crd' - CustomResourceDefinitions # 'all' - all resources (default) # 'none' - disabled ignoreResourceStatusField: all文档 NOTE:由于 CRD 的status常被提交进 Git,建议在这类场景使用crd而不是none。
忽略 Aggregated ClusterRole 带来的rules漂移。如果你使用 Aggregated ClusterRoles 且不想让 Argo CD 把rules变化当作需要 sync 的漂移事件:
apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm data: resource.compareoptions: | ignoreAggregatedRoles: trueCRD 复用内置 K8s 类型导致的序列化差异。一些 CRD 复用了 Kubernetes 基础数据结构(如argoproj.io/Rollout复用core/v1/PodSpec),自定义序列化器可能把cpu: 100m重新序列化为cpu: 0.1,造成误报漂移。解决方法是在argocd-cm中声明哪些 CRD 字段使用了内置类型:
apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm namespace: argocd labels: app.kubernetes.io/name: argocd-cm app.kubernetes.io/part-of: argocd data: resource.customizations.knownTypeFields.argoproj.io_Rollout: | - field: spec.template.spec type: core/v1/PodSpec支持的 Kubernetes 类型列表见仓库内的 util/argo/normalizers/diffing_known_types.txt,另外还支持core/Quantity和meta/v1/Duration。
辅助手段与边界配置
把多余资源排除出 sync 状态。某些资源由工具生成、不希望影响应用整体 sync 状态时,可以给资源加注解(见 docs/user-guide/compare-options.md):
metadata: annotations: argocd.argoproj.io/compare-options: IgnoreExtraneous文档 NOTE 明确:该注解只影响 sync status,如果资源健康度退化,应用健康度仍然会退化。Kustomize 用户可以通过configMapGenerator的generatorOptions.annotations自动给生成的 configmap/secret 加这个注解;文档建议可与Prune=falsesync option 搭配使用。
JQ 表达式超时。JQPathExpression 求值默认限制 1 秒;如果复杂表达式报 "JQ patch execution timed out",在argocd-cmd-params-cmConfigMap 中延长超时:
apiVersion: v1 kind: ConfigMap metadata: name: argocd-cmd-params-cm data: ignore.normalizer.jq.timeout: '5s'验证配置是否生效
以上配置分别落在 Application 的spec和argocd-cm/argocd-cmd-params-cmConfigMap 中。修改完成后按下面的方式核对:
- 检查配置内容:
kubectl get configmap argocd-cm -n argocd -o yaml,确认resource.customizations各 key 拼写正确,<group>_<kind>与目标资源一致;Application 侧用kubectl get application <name> -n <ns> -o yaml查看spec.ignoreDifferences。 - 触发重新比较后,在 UI(或
argocd app get <name>)查看应用 SYNC STATUS:之前被忽略的字段不再出现在资源差异中。若差异确实只来自被忽略的字段,应用状态应从OutOfSync回到Synced;如果仍OutOfSync,说明还有未覆盖的字段差异,回到"先定位"一节继续核对差异明细。 - 注意各机制的适用范围:
IgnoreExtraneous只影响 sync status 不影响健康度;ServerSideDiff默认不包含 mutation webhook 的改动,是否纳入需按 docs/user-guide/diff-strategies.md 单独配置注解。
限制与边界
- 忽略差异只能用于"预期内的差异"。manifest 自身的字段错误(多余的未知字段)应优先修 manifest,而不是用
jsonPointers绕过。 managedFieldsManagers、Server-Side Apply 等依赖静态 schema 的能力在 schema 缺少字段时会报field not declared in schema,升级版本是文档给出的根治方式。- 修改
application.instanceLabelKey会让所有应用变为 out of sync,必须重新同步,变更前先评估影响面。
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考