界面上的按钮从哪里来
一句话总结
Argo CD 的资源操作由写在 argocd-cm 中的两段 Lua 构成——决定显示什么的 discovery.lua,
和决定修改什么的 action.lua——并且可以用 argocd admin settings resource-overrides 在没有服务器的情况下测试。
为什么需要按钮
GitOps 的承诺是“修改集群的途径只有仓库一条”。然而在现场,这个承诺并不能被完全遵守。 有时配置被固化在缓存里,需要把 Pod 重新拉起一次;有时需要暂时暂停发布;有时故障期间只需要增加一个副本。 这类事情有一个共同点——要修改的并不是需要写进仓库的值。 没有东西可提交,却要求提交, 人们最终还是会去用 kubectl。
资源操作填补的就是这道缝隙。它把剩下的几件事做成预先定义的转换,以按钮的形式放在界面上, 再用 RBAC 决定谁可以点击这些按钮,并把点击者记录下来。关键在于,取代任意 kubectl 的, 只是一组事先约定好的操作。
工作原理
argocd-cm 的一个键中包含两段内容。
resource.customizations.actions.example.com_Widget: |
discovery.lua: |
actions = {}
actions["pause"] = {}
actions["resume"] = {["disabled"] = true}
if obj.spec ~= nil and obj.spec.paused == true then
actions["pause"] = {["disabled"] = true}
actions["resume"] = {}
end
return actions
definitions:
- name: pause
action.lua: |
obj.spec.paused = true
return obj
discovery.lua 决定对这个资源显示哪些按钮。它返回一个以操作名称为键的表,
如果在值中把 disabled 设为真,那个按钮就会变灰。这里有一个重要的设计决定——根据状态
开启或关闭按钮的判断,放在这段代码里,而不是界面上。 这样,对已经暂停的东西再次暂停的按钮,
从一开始就点不了。
definitions 中的 action.lua 接收资源并返回修改后的资源。 它不是创建新对象,
而是修改传入的 obj 后 return,所以很容易连带改动并非有意要改的字段。因此
run-action 不是把结果整个展示出来,而是只以 diff 展示被修改的字段,这一点很重要——
操作动过的地方一目了然。
Lua 方面有两点经常出问题。第一,数组下标从 1 开始。第一个容器是
containers[1]。第二,读取不存在的字段会得到 nil,对 nil 做算术运算会让脚本崩溃。
对于读取值再计算的操作,需要做检查。
最后要知道这个 CLI 的一个特性。list-actions 和 run-action 只读取 argocd-cm。
像 Deployment 的 restart 这样内置于 Argo CD 的操作不会出现在这条命令里,
没有配置时会回答“没有配置操作”。这不是与界面不一致而需要慌张的事,
把它理解成这条命令只测试你自己写的规则就可以了。
在现场相遇的样子
引入资源操作的团队最先遇到的误解是“点击按钮就修好了”。操作只会修改集群中的 对象,而不会修改仓库。如果自动同步和自我修复是开启的,下一次调谐时就会被还原。 所以操作只用于被还原也无妨的事——重新拉起就是典型。不能被还原的变更, 仍然要通过提交来做。
第二种是悄无声息的故障。升级 Operator 版本时字段名称变了,而 action.lua 原封不动。 按钮仍然显示,点下去要么什么也不发生,要么把值写到不该写的地方。不报错的那种更 危险。所以对资源操作同样需要养成把样本和期望整理成表的习惯——这次实验的最后一步 就是这个。
本实验环境的局限
实验 Pod 中既没有 Argo CD 控制器,也没有界面。 真正点击按钮,或者用 RBAC 拦住操作权限、 看它被拒绝,这些在这里都做不到。不过,真正执行 discovery.lua 和 action.lua 的代码 就在 CLI 里,所以会显示哪些按钮、会修改什么,都可以得到完全相同的结果。而且,操作 产生的变更会直接应用到 kwok 集群,亲眼看结果。
下一项实验要做什么
先用空的 ConfigMap 确认这条命令读取什么。然后为 Widget 创建 pause,让它根据状态与
resume 交替变灰,再加上读取值并计算的 scale-up。给内置类型 Deployment 也添加
操作来固定镜像,并把结果应用到 kwok 集群确认。最后制作一个脚本,把操作所做的事
整理成表,一次全部检查。