TT Lab
开始
学习 学习路径 课程

GitOps 与 Argo CD

亮着绿灯却没人知道依据——亲手编写健康规则

在 TT Lab 中继续学习

目标

在 argocd-cm 的 resource.customizations.health.<그룹>_<종류>(占位符依次为组、类型)中编写 Lua 规则,把 CRD 的健康状态分成 Healthy、Progressing、Degraded、Suspended 四类,并把样本与期望整理成表,做回归检查。

为什么重要

人在 Argo CD 界面上实际看的不是同步,而是健康状态。Deployment、Service、Job 这样的内置类型由控制器自动判定,但 CRD 没有内置规则。 如果 Operator 创建的资源在界面上总是同一种颜色,那并不意味着运行良好,而是意味着没有可供判定的依据。亲手编写规则之所以重要,有两个原因。第一,必须把“还在创建中”和“已经坏掉”区分开,才能配置告警。第二,规则一旦写好就会被遗忘,所以必须把样本和期望一起放进仓库,这样以后 status 字段变化时,规则才不会悄悄出错。

步骤

  1. 把 /root/ga-health/argocd-cm.yaml 创建为 data: {} 的空 argocd-cm ConfigMap,并在 /root/ga-health/deploy.yaml 中放置 ga-health 命名空间的 Deployment web——spec.replicas 为 3,status 中写入 observedGeneration: 1、replicas: 3、updatedReplicas: 2、readyReplicas: 1、availableReplicas: 1。把 argocd admin settings resource-overrides health /root/ga-health/deploy.yaml --argocd-cm-path /root/ga-health/argocd-cm.yaml 的输出保存到 /root/ga-health/builtin.txt。
  2. 在 /root/ga-health/w-ready.yaml 中创建 example.com/v1 的 Widget——名称为 w-ready,命名空间为 ga-health,spec.size 为 3,status.phase 为 Ready。用第 1 步的空 argocd-cm 查询这个文件的健康状态,把输出保存到 /root/ga-health/nocustom.txt。
  3. 在 /root/ga-health/argocd-cm-healthy.yaml 中放置键 resource.customizations.health.example.com_Widget,并编写 Lua:当 status.phase 为 Ready 时返回 Healthy,其他情况返回 Progressing。两种情况都要填写 hs.message。把用这个 ConfigMap 判定 /root/ga-health/w-ready.yaml 的输出保存到 /root/ga-health/healthy.txt。
  4. 创建 /root/ga-health/w-failed.yaml——名称为 w-failed,status.phase 为 Failed,status.reason 为 DiskFull。/root/ga-health/argocd-cm-degraded.yaml 要在第 3 步的规则上增加 Failed 分支并返回 Degraded,且 hs.message 中必须包含该资源的 status.reason 值。把判定输出保存到 /root/ga-health/degraded.txt。
  5. 创建 /root/ga-health/w-building.yaml(status.phase 为 Building,名称为 w-building)和 /root/ga-health/w-nostatus.yaml(完全没有 status,名称为 w-nostatus)。用第 4 步的 ConfigMap 依次判定这两个文件,把输出追加到 /root/ga-health/progressing.txt。两者都必须是 Progressing。
  6. 创建 /root/ga-health/w-paused.yaml——名称为 w-paused,spec.paused 为 true,status.phase 为 Ready。/root/ga-health/argocd-cm-full.yaml 要在前面的规则上再增加一个分支:当 spec.paused 为真时,先于其他条件返回 Suspended。把判定输出保存到 /root/ga-health/suspended.txt。
  7. 创建 /root/ga-health/argocd-cm-typo.yaml——内容与第 6 步相同,只是把键名写成 resource.customizations.health.example.com_Widgets(类型写成复数)。把用这个 ConfigMap 判定 /root/ga-health/w-ready.yaml 的输出保存到 /root/ga-health/typo.txt。
  8. 在 /root/ga-health/health-matrix.tsv 中写至少四行 <샘플파일이름>\t<기대 STATUS>(占位符依次为样本文件名、期望的 STATUS)——Healthy、Degraded、Progressing、Suspended 都必须至少出现一次。/root/ga-health/check-health.sh 读取这张表,用 /root/ga-health/argocd-cm-full.yaml 判定每个样本,匹配则输出 OK …,不匹配则输出 MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到 /root/ga-health/health-result.txt。

参考

先看内置判定

把 /root/ga-health/argocd-cm.yaml 创建为 data: {} 的空 argocd-cm ConfigMap,并在 /root/ga-health/deploy.yaml 中放置 ga-health 命名空间的 Deployment web——spec.replicas 为 3,status 中写入 observedGeneration: 1、replicas: 3、updatedReplicas: 2、readyReplicas: 1、availableReplicas: 1。把 argocd admin settings resource-overrides health /root/ga-health/deploy.yaml --argocd-cm-path /root/ga-health/argocd-cm.yaml 的输出保存到 /root/ga-health/builtin.txt。

Deployment 有内置的健康规则,所以即使 argocd-cm 是空的也能得出判定。期望是三个,却只就绪了一个,请预测会得出什么状态。输出的第一行就是 STATUS。

CRD 根本没有规则

在 /root/ga-health/w-ready.yaml 中创建 example.com/v1 的 Widget——名称为 w-ready,命名空间为 ga-health,spec.size 为 3,status.phase 为 Ready。用第 1 步的空 argocd-cm 查询这个文件的健康状态,把输出保存到 /root/ga-health/nocustom.txt。

对于不认识的类型,Argo CD 不会凭空编造判定。在界面上,这样的资源通常看起来像绿灯,实际上意思是“没有可供判定的依据”。请原样读一读输出的句子。

用 Lua 写出绿灯的条件

在 /root/ga-health/argocd-cm-healthy.yaml 中放置键 resource.customizations.health.example.com_Widget,并编写 Lua:当 status.phase 为 Ready 时返回 Healthy,其他情况返回 Progressing。两种情况都要填写 hs.message。把用这个 ConfigMap 判定 /root/ga-health/w-ready.yaml 的输出保存到 /root/ga-health/healthy.txt。

Lua 片段通过名为 obj 的全局变量接收资源,并 return 填好 hs.status 和 hs.message 的表。完全没有 status 的资源也会传进来,所以请先检查 obj.status ~= nil。键名的分隔符不是点,而是下划线——<그룹>_<종류>(占位符依次为组、类型)。

红灯必须同时给出原因

创建 /root/ga-health/w-failed.yaml——名称为 w-failed,status.phase 为 Failed,status.reason 为 DiskFull。/root/ga-health/argocd-cm-degraded.yaml 要在第 3 步的规则上增加 Failed 分支并返回 Degraded,且 hs.message 中必须包含该资源的 status.reason 值。把判定输出保存到 /root/ga-health/degraded.txt。

如果消息写成固定字符串,在界面上就看不出是哪个资源、因为什么而失效。Lua 中拼接字符串用 ..,而值可能不存在,所以要像 (obj.status.reason or "unknown") 这样设置默认值。

未知状态与没有状态,归入同一类

创建 /root/ga-health/w-building.yaml(status.phase 为 Building,名称为 w-building)和 /root/ga-health/w-nostatus.yaml(完全没有 status,名称为 w-nostatus)。用第 4 步的 ConfigMap 依次判定这两个文件,把输出追加到 /root/ga-health/progressing.txt。两者都必须是 Progressing。

写规则时容易漏掉的是“控制器还没有写 status 的那一刻”。这时如果给出 Degraded,新建的资源每次都会以红灯开始。这就是把默认分支设为 Progressing 的原因。

有意停下的不是故障

创建 /root/ga-health/w-paused.yaml——名称为 w-paused,spec.paused 为 true,status.phase 为 Ready。/root/ga-health/argocd-cm-full.yaml 要在前面的规则上再增加一个分支:当 spec.paused 为真时,先于其他条件返回 Suspended。把判定输出保存到 /root/ga-health/suspended.txt。

Suspended 是 Argo CD 认识的第四种健康状态——这是人有意停下的东西,不应该触发告警的位置。调换一下分支顺序,就能立刻看出为什么它必须放在最前面(phase 是 Ready,所以绿灯分支会先命中)。

键名错一个字母,规则就整条消失

创建 /root/ga-health/argocd-cm-typo.yaml——内容与第 6 步相同,只是把键名写成 resource.customizations.health.example.com_Widgets(类型写成复数)。把用这个 ConfigMap 判定 /root/ga-health/w-ready.yaml 的输出保存到 /root/ga-health/typo.txt。

键名中的类型必须与清单中的 kind 逐字相同。写错时不会报错,只是表现得像没有规则一样——这类错误只有看界面才会发现。请与第 2 步的输出比较一下。

把样本和期望整理成表,对规则做回归检查

在 /root/ga-health/health-matrix.tsv 中写至少四行 <샘플파일이름>\t<기대 STATUS>(占位符依次为样本文件名、期望的 STATUS)——Healthy、Degraded、Progressing、Suspended 都必须至少出现一次。/root/ga-health/check-health.sh 读取这张表,用 /root/ga-health/argocd-cm-full.yaml 判定每个样本,匹配则输出 OK …,不匹配则输出 MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到 /root/ga-health/health-result.txt。

只写样本文件名、由脚本补上路径,表会更短。只想取出 STATUS 这一行,用 sed -n 's/^STATUS: //p' 比较方便。如果脚本自己去写文件,评分器再次运行时就会覆盖学员的产出文件,所以请只输出到标准输出。