绿灯是谁点亮的
一句话总结
Argo CD 的健康状态由各类型不同的判定规则产生;没有内置规则的 CRD 必须在 argocd-cm 中用 Lua 亲手写出来,
而这条规则无需服务器,用 argocd admin settings resource-overrides health 就能当场测试。
为什么健康状态要与同步分开
学习 GitOps 时最先遇到的一条轴是同步——仓库里写的内容与集群里的内容是否一致。但仅凭这条轴, 还有一个问题回答不了。一致是一致,可它运行得好吗? 即使仓库中写的镜像标签并不存在, Deployment 对象本身也会与仓库一模一样地创建出来。同步这条轴是绿色的,而 Pod 一个都没有起来。 所以 Argo CD 把轴分成两条。同步回答“声明和实物是否一致”,健康状态回答“实物是否在履行它的职责”。 只有这两条轴分开,才能表达“Synced 但 Degraded”这种在现场最常遇到的状态。
健康状态的取值有六种——Healthy、Progressing、Degraded、Suspended、Missing、Unknown。
应用整体的健康状态,是汇总子资源的值后取最差的一侧来确定的。因此,只要有一个子资源的规则写错了,
整个应用就会显示成错误的颜色。
工作原理
对于 Deployment、StatefulSet、Service、Ingress、Job、PVC 这样的内置类型,Argo CD 内部已经有判定代码。
例如 Deployment 会查看 status 中的 updatedReplicas、readyReplicas、availableReplicas 和
observedGeneration,如果还没有全部就绪,就给出 Progressing,并生成“几个中的几个”这样的消息。
CRD 没有这样的代码。所以要在 argocd-cm 中添加规则。键的名称很重要。
data:
resource.customizations.health.example.com_Widget: |
hs = {}
if obj.status ~= nil and obj.status.phase == "Ready" then
hs.status = "Healthy"
hs.message = "widget is ready"
return hs
end
hs.status = "Progressing"
hs.message = "waiting for widget"
return hs
格式是 <그룹>_<종류>(占位符依次为组、类型),分隔符是下划线。如果在这里把类型名称写得与清单中的 kind 不同,
不会报错——只是表现得像没有规则一样。这类错误之所以能存活很久,原因就在这里。
Lua 片段通过名为 obj 的全局变量整体接收资源,并返回填好 status 和 message 的表。
写规则时最常漏掉的,是还没有 status 的那一刻。刚刚创建、控制器还没处理过的资源,
连 status 本身都没有。如果在这里给出 Degraded,新建的资源每次都会以红灯开始,
配置了告警的团队很快就会把这条告警关掉。默认分支应该是 Progressing。
Suspended 值得单独说一说。它指的是人为有意停下的东西——正在维护的流水线、暂停的
CronJob。如果把它判为 Degraded,每次计划内的维护都会让呼叫器响起。此外,分支的
顺序会改变结果。如果被暂停的资源的 status.phase 仍然是 Ready,那么先写 Ready 分支的
规则就会给出绿灯。
在现场相遇的样子
最常见的事故是“CRD 总是绿灯”。Operator 创建的数据库资源已经好几个小时配置失败了, 界面上却没有任何提示。并不是 Argo CD 在说谎,而是没有人为它写过判定规则, 这个资源根本没有参与健康状态的计算。告警通常是用户先发出的。
第二常见的是规则悄悄过时。升级 Operator 版本时,status.phase 变成了
status.conditions,而 argocd-cm 中的 Lua 却原封不动。规则现在总是走默认分支,
所有资源都固化为 Progressing。没有人能看到任何错误。所以写了规则之后,把样本资源和
期望判定整理成表,一起放在仓库里,与规则本身同样重要。把这张表在 CI 中运行一次,
字段名称改变的当天就会亮起红灯。
本实验环境的局限
实验 Pod 中没有 Argo CD 控制器。 因此无法看到“应用规则后界面颜色变了”, 也无法确认像“健康状态为 Degraded 所以同步停止”这样的控制器行为。不过,真正执行判定的 那段代码就原样包含在 CLI 里,所以只需一份 argocd-cm 和一份资源 YAML,就能得到同样的答案。
下一项实验要做什么
先看内置判定,再确认没有规则的 CRD 会给出怎样的一句话。然后一种一种地增加 Lua, 把 Healthy、Degraded、Progressing、Suspended 四种都做出来,再亲眼看看键名错一个字母会发生什么。 最后制作一个检查脚本,把样本和期望整理成表,一次全部运行。