把什么排除在比较之外
一句话总结
忽略规则是把特定字段从同步判定中排除的装置;如果写得太宽,噪声消失的同时,真正的漂移也会一并消失,
所以必须用 argocd admin settings resource-overrides ignore-differences 亲眼确认被删掉的行,然后再提交。
为什么需要这种装置
GitOps 的理想是“仓库里写的就是集群”。现实并非如此。集群里会不断出现无法写进仓库的值。HPA 会修改 spec.replicas,
sidecar 注入 Webhook 会多插入一个容器,控制器会添加 deployment.kubernetes.io/revision 这样的注解。
这些值没办法写进仓库——一旦写进去,这个值就被固定住了,那么 HPA 或 Webhook 也就没有存在的意义了。
所以才有了忽略规则。它是用来声明“这个字段的差异不算 OutOfSync”的地方。问题在于,这个装置有一种 只往一个方向倾斜的力。忽略得宽,界面就安静下来;忽略得窄,界面就一直吵闹。安静这一侧的代价,要在几个月之后才会到来。
工作原理
规则可以写在两个位置。全局规则写在 argocd-cm 的
resource.customizations.ignoreDifferences.<그룹>_<종류>(占位符依次为组、类型)中,按应用的规则则写在 Application 的
spec.ignoreDifferences 列表中。两者会合并后生效——所以先在全局范围内放宽,再在应用里收窄,这是行不通的。
收窄方向的规则,从一开始就应该放在应用一侧。
规则块中可以写三种列表。
resource.customizations.ignoreDifferences.apps_Deployment: |
jsonPointers:
- /spec/replicas
jqPathExpressions:
- .spec.template.spec.containers[] | select(.name == "sidecar").image
managedFieldsManagers:
- kubectl
jsonPointers 是沿斜杠向下的路径。它很简单,但数组只能按位置编号来指向,所以一旦容器的
顺序改变,就会忽略掉不该忽略的元素。jqPathExpressions 可以用条件来挑选——像上面的例子那样,
可以指定“名称为 sidecar 的容器的 image”,这是指针无法稳定做到的。
managedFieldsManagers 则属于另一类。它不是按字段路径,而是按最后写入该字段的管理者名称
来选择要忽略的对象。由于它依据的是服务端应用留下的所有权记录,光看资源 YAML 是无法算出会排除什么的。
这就是预览命令仅凭这个列表什么也渲染不出来的原因。
还有一个名字相近的旋钮。ignoreResourceUpdates 决定的是要不要唤醒调谐循环。
它是一个性能旋钮,用来避免每当一个注解变化时控制器就重新计算整个应用,
而不会改变同步判定。因为名字相似,它常被混淆,但两者的目的完全不同。
在现场相遇的样子
最常见的场景是这样的。十个应用全部亮黄灯,原因是 HPA。着急的人在全局 argocd-cm 中加了一行,
把 apps_Deployment 的 /spec 整个忽略掉。界面安静了下来,再也没有人回头看这一行。几个月后,
有人在生产环境里手工修改了镜像标签。Argo CD 依然是绿色。
一个号称把仓库当作唯一可信来源的系统,从那天起开始说谎,而没有任何界面会告诉你这一点。
第二种是顺序问题。为了忽略 sidecar,写了 /spec/template/spec/containers/1,结果有一天 Webhook
把 sidecar 插到了前面。现在被忽略的是应用容器。这样的规则不会发出写错了的信号——
它悄悄地朝相反的方向起作用。
所以对于忽略规则,需要养成两个习惯。第一,写入之前先渲染,看一看被删掉的行。 第二,在写入规则的那一行旁边,注明这条规则为什么需要。理由消失时,能把规则删掉的, 只有知道这个理由的人。
本实验环境的局限
实验 Pod 中没有 Argo CD 控制器。 因此无法看到“加入规则后 OutOfSync 变成了 Synced”,
也无法通过预览确认 managedFieldsManagers 实际会过滤掉哪些字段。
不过,解析规则并删除字段的那段代码就在 CLI 里,所以哪些行会从比较中排除,
可以看到完全相同的结果。
下一项实验要做什么
以同一份 Deployment 为材料,逐条修改规则并渲染。亲自看一看指针与 jq 表达式的差别,
并确认把 /spec 整个忽略时,连 image 那一行也会消失。管理者名称规则和
ignoreResourceUpdates 在预览中是什么样子,也会如实记录下来。最后把应用级规则加到 Application 上,
部署到 kwok 集群,并制作“这条规则会不会删掉这个字符”的表,一次全部检查。