Argo CD 实战:用 argocd admin settings resource-overrides health 本地调试资源健康检查 Lua 脚本
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
本文围绕 Argo CD 的argocd admin settings resource-overrides health命令展开:它允许你在集群外、仅凭本地 YAML 文件和argocd-cm配置,直接对某个 Kubernetes 资源执行由 Lua 脚本定义的健康检查(health assessment),并打印状态与消息。读完本文,你将掌握该命令的完整用法与参数、其从 CLI 到 Lua 虚拟机(Lua VM)的调用链、健康状态的取值规则,以及如何用它快速排查resource.customizations中自定义 health 脚本不生效、输出不符合预期等问题。
命令定位:resource-overrides 排障命令族的一员
Argo CD 允许通过argocd-cmConfigMap 中的resource.customizations字段为任意 Group/Kind 的资源定制行为,包括健康评估(health)、忽略差异(ignoreDifferences)、忽略更新(ignoreResourceUpdates)以及自定义操作(actions)。为了在不必重启控制器、不必等待 informer 同步的情况下验证这些 Lua 脚本的行为,Argo CD CLI 提供了argocd admin settings resource-overrides命令族,其中:
health:评估资源健康(本文主角);ignore-differences:渲染被 diff 排除的字段;ignore-resource-updates:渲染被资源更新排除的字段;list-actions/run-action:列出并执行自定义资源操作。
该命令族在源码中由 NewResourceOverridesCommand 注册,本文聚焦的health子命令由 NewResourceHealthCommand 定义。
命令语法与参数
基本用法
argocd admin settings resource-overrides health RESOURCE_YAML_PATH [flags]命令说明(Synopsis 原文):
Assess resource health using the lua script configured in the 'resource.customizations' field of 'argocd-cm' ConfigMap
即:使用argocd-cmConfigMap 中resource.customizations字段配置的 Lua 脚本来评估给定资源 YAML 文件的健康状态。
官方示例
argocd admin settings resource-overrides health ./deploy.yaml --argocd-cm-path ./argocd-cm.yaml即把待检查的资源清单./deploy.yaml与本地导出/编写的argocd-cm.yaml一起传入,完全离线运行。
命令自身选项
-h, --help help for healthhealth子命令本身只带--help,其余关键行为由继承的父命令选项决定。
关键继承选项(节选)
完整列表可通过argocd admin settings resource-overrides health --help查看,其中与排障最相关的继承选项如下:
| 选项 | 说明 |
|---|---|
--argocd-cm-path string | 本地argocd-cm.yaml文件路径(本地调试时最常用) |
--argocd-secret-path string | 本地argocd-secret.yaml文件路径 |
--load-cluster-settings | 未提供本地文件路径时,直接从集群加载 ConfigMap 和 Secret |
--argocd-context string | 使用的 Argo CD server context 名称 |
--config string | Argo CD CLI 配置文件路径(默认~/.config/argocd/config) |
--core | 设为 true 时 CLI 直接与 Kubernetes 通信,而不是通过 Argo CD API server |
--kubeconfig/--kube-context/--server | 指定 kube 配置与上下文 |
--request-timeout string | 单次 server 请求超时(如30s),0表示不超时 |
--port-forward/--port-forward-namespace | 通过端口转发连接随机 argocd-server 端口 |
--redis-compress string | 取值gzip(默认)或none,需与 application controller 的 redis 压缩配置一致 |
其余继承选项(--as、--auth-token、--grpc-web、TLS 证书相关、--loglevel/--logformat等)均属于 CLI 通用的连接与认证控制,含义与argocd顶层命令一致,此处不再逐一罗列。
说明:当同时提供
--argocd-cm-path时,命令读取本地文件;否则从集群加载argocd-cm。排障场景推荐显式传入本地文件,避免受集群侧配置漂移影响。
源码解读:一条命令背后发生了什么
从源码结构看,health的执行路径非常清晰,全部逻辑集中在 cmd/argocd/commands/admin/settings.go 中。
第一步:读取资源 YAML 并解析为 Unstructured
命令首先调用公共函数 executeResourceOverrideCommand:
data, err := os.ReadFile(args[0]) errors.CheckError(err) res := unstructured.Unstructured{} errors.CheckError(yaml.Unmarshal(data, &res)) settingsManager, err := cmdCtx.createSettingsManager(ctx) errors.CheckError(err) overrides, err := settingsManager.GetResourceOverrides() errors.CheckError(err) gvk := res.GroupVersionKind() key := gvk.Kind if gvk.Group != "" { key = fmt.Sprintf("%s/%s", gvk.Group, gvk.Kind) } override := overrides[key]这里有两个值得注意的实现细节:
- 资源键(key)的构造规则:核心资源(Group 为空)用
Kind作为键,例如Pod;CRD 用Group/Kind,例如argoproj.io/Workflow。你在resource.customizations中定义的 YAML 文件名/键必须与此规则严格一致,否则脚本不会被命中——这也是“明明配置了脚本却提示未配置”的常见原因。 - overrides 的来源:
GetResourceOverrides()解析的就是argocd-cm中的resource.customizations字段,得到一个map[string]v1alpha1.ResourceOverride。
第二步:调用健康评估入口
health子命令的回调随后执行(见 settings.go#L501-L513):
resHealth, err := healthutil.GetResourceHealth(&res, lua.ResourceHealthOverrides(overrides)) switch { case err != nil: errors.CheckError(err) case resHealth == nil: fmt.Printf("Health script is not configured for '%s/%s'\n", gvk.Group, gvk.Kind) default: _, _ = fmt.Printf("STATUS: %s\n", resHealth.Status) _, _ = fmt.Printf("MESSAGE: %s\n", resHealth.Message) }输出因此只有三种形态:脚本未配置提示、Lua 执行报错(直接CheckError退出)、或两行STATUS:/MESSAGE:结果。
第三步:GetResourceHealth 的优先级链
healthutil.GetResourceHealth位于 gitops-engine 子模块的 pkg/health/health.go,其评估顺序是:
- 正在删除的资源:若资源带有 deletionTimestamp 且没有 hook finalizer,直接返回
Progressing / Pending deletion,不再执行任何脚本; - 覆盖脚本优先:如果
healthOverride(即从resource.customizations提取的脚本)对该资源有配置,则执行 Lua 脚本;脚本返回结果即为最终健康状态。Lua 执行出错时,状态被降级为Unknown,错误信息写入Message,同时向上返回错误(在本命令中会触发非零退出); - 回退内置检查:override 没有命中时,走 GetHealthCheckFunc 分发的内置 Go 实现,覆盖 Deployment、StatefulSet、ReplicaSet、DaemonSet、Ingress、APIService、Service、PVC、Pod、Job、HPA、argoproj.io/Workflow 等常见类型。
注意一个微妙点:当内置检查也存在时,Lua override 的返回值会完全覆盖内置评估。这正是用本命令验证自定义脚本价值的场景——它回答的问题是“我的脚本对这个资源会算出什么状态”,而不是“控制器最终会算什么”。
健康状态的取值空间
健康状态码定义于 gitops-engine/pkg/health/health.go,共六种:
| 状态 | 含义 |
|---|---|
Unknown | 健康评估失败,实际状态未知 |
Progressing | 尚未健康,但仍有希望达到健康状态 |
Healthy | 100% 健康 |
Suspended | 资源处于挂起/暂停状态,典型如 suspended 的 CronJob |
Degraded | 资源 status 表明失败,或在超时内无法达到健康状态 |
Missing | 资源在集群中缺失 |
源码中还有 healthOrder 与 IsWorse 用于在多资源之间比较“谁更不健康”,这是应用级健康汇总的逻辑,单资源命令本身不直接使用。
第四步:Lua 虚拟机的执行环境
真正执行脚本的是 util/lua/lua.go 中的VM:
- ResourceHealthOverrides 将 overrides map 适配为
HealthOverride接口,GetResourceHealth先通过GetHealthScript按资源 GVK 查找脚本(util/lua/lua_test.go 中存在getWildcardHealthOverride等测试,说明查找支持通配匹配),找不到脚本时返回nil, nil,对应命令输出 “Health script is not configured”; - 找到脚本后,
runLuaWithResourceActionParameters创建 Lua 状态并做安全加固:默认SkipOpenLibs,仅打开 package、base、table 库以及 Argo CD 提供的“安全版” OS 库(OpenSafeOs,见 util/lua/oslib_safe.go); - 整个执行挂在1 秒超时的 context 上(lua.go#L159),脚本若死循环会被强制中止;
- 资源对象本身被解码为 Lua 表并注入为全局变量
obj,脚本内直接obj.status...访问资源字段; - 编译结果经过 compiledScriptCache 缓存,同一段脚本只编译一次;编译失败不会被缓存,保证每次都能拿到新鲜错误。
由于这些约束,编写 health 脚本时应只依赖只读的资源字段,避免调用受限标准库,脚本必须及时返回。
实操:一个端到端的本地调试示例
下面用一个自定义 CRD 演示完整流程(该示例为本文构造,用于说明机制,不是仓库内置配置)。
第 1 步,准备待检查的资源文件deploy.yaml:
apiVersion: myexample.com/v1 kind: MyWidget metadata: name: widget-1 namespace: default status: phase: Ready第 2 步,准备argocd-cm.yaml,其中resource.customizations的键遵循Group/Kind规则:
apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm data: resource.customizations: | myexample.com/MyWidget: health.lua: | if obj.status and obj.status.phase == "Ready" then return {status = "Healthy", message = "widget is ready"} elseif obj.status and obj.status.phase == "Failed" then return {status = "Degraded", message = "widget failed"} else return {status = "Progressing", message = "waiting for widget"} end(Argo CD 内置的定制规则可参考 resource_customizations/ 目录:每种 Group/Kind 由一份 YAML 描述与同名 Lua 脚本组成,并由 resource_customizations/embed.go 嵌入二进制,其组织方式与上面argocd-cm中手写的条目一致。)
第 3 步,本地执行:
argocd admin settings resource-overrides health ./deploy.yaml --argocd-cm-path ./argocd-cm.yaml预期输出:
STATUS: Healthy MESSAGE: widget is ready第 4 步,验证“未命中”场景:把资源改为kind: MyGadget(未配置脚本)后再执行,会看到:
Health script is not configured for 'myexample.com/MyGadget'第 5 步,验证“脚本报错”场景:在 Lua 中写return obj.status.phase(返回非表),或触发语法错误,命令会以非零码退出并打印 Lua 错误信息(源码中 runLua 特意剥掉了默认的 Lua 堆栈跟踪,只把对用户有意义的错误传回),这正是把脚本先拿到 CLI 里跑一遍的价值所在。
与运行时行为的关系
本地命令与控制器侧共用同一套 override 与 Lua VM 实现,因此本地验证的结论可以直接外推到生产行为:
- application controller 的健康评估走 controller/health.go,同样是
lua.ResourceHealthOverrides(resourceOverrides); - 缓存层初始化时也会把同一份 override 传给 gitops-engine 的健康检查:controller/cache/cache.go;
- 同步路径的 hook 健康检查同样引用它,见 controller/hook.go。
也就是说,resource-overrides health命令等价于“在 controller 的健康评估函数上,用你本地的argocd-cm和本地资源文件做一次确定性单测”。区别仅在于:控制器面对的是集群中真实对象的完整status,本地调试时你需要自行准备贴近真实状态的 YAML(status 字段是健康脚本的主要输入,示例中的status.phase即为此)。
常见排障要点小结
- 提示 “Health script is not configured”:优先检查键名——核心资源用
Kind,CRD 用Group/Kind;再检查argocd-cm是否为resource.customizations而非其他字段名。 - 结果与集群内观察到的一致/不一致:确认本地 YAML 的
status与集群中实际对象一致;带 deletionTimestamp 的对象在本地调试时不会触发该分支,而在集群中会被判为Progressing / Pending deletion。 - 脚本超时或被安全策略拦截:Lua 执行有 1 秒超时且标准库受限(安全版
os),脚本应只读obj、快速返回。 - 想看 ignore-differences 效果:切换到同族的
argocd admin settings resource-overrides ignore-differences,它会输出被排除字段的 diff,而非健康状态。
延伸阅读
resource-overrides命令族总览文档:argocd admin settings resource-overrides 命令参考;- 命令实现:cmd/argocd/commands/admin/settings.go(
NewResourceHealthCommand及相关公共函数); - 健康状态码与评估优先级:gitops-engine/pkg/health/health.go;
- Lua 虚拟机与安全执行环境:util/lua/lua.go、util/lua/oslib_safe.go;
- 内置定制规则示例库:resource_customizations/。
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考