把运维中手动做的三件事变成按钮
目标
在 argocd-cm 的 resource.customizations.actions.<그룹>_<종류>(占位符依次为组、类型)中编写 discovery.lua 和操作定义来创建资源操作,根据情况让按钮变灰,并把操作产生的变更真正应用到 kwok 集群。
为什么重要
GitOps 做得好的话,生产环境里靠手工完成的事情应该消失,但有几件事会一直保留下来——暂时暂停、重新拉起、增加一个副本。如果让人用 kubectl 去做,仓库和集群就会分叉;如果干脆禁止,又会催生更危险的绕行办法。资源操作就是这样一种装置:只把这几件事做成界面上的按钮,并纳入权限与审计记录的管辖之下。 其设计要点有两个。第一,操作不会修改仓库——所以如果自动同步是开启的,下一次调谐时就会被还原。第二,要把什么做成按钮,都集中在 discovery.lua 这一处。根据状态开启或关闭的判断由这段代码而不是界面来做,所以可以通过设计避免对已经暂停的东西再次暂停这类事故。
步骤
- 在
/root/ga-actions/deploy.yaml中创建ga-actions命名空间的 Deploymentweb——spec.replicas为 2,一个容器(web,镜像nginx:1.25),选择器和标签为app: web。/root/ga-actions/argocd-cm.yaml是data: {}的空 ConfigMap。把argocd admin settings resource-overrides list-actions /root/ga-actions/deploy.yaml --argocd-cm-path /root/ga-actions/argocd-cm.yaml的输出保存到/root/ga-actions/none.txt。 - 在
/root/ga-actions/w-running.yaml中创建example.com/v1的Widget——名称为w-running,命名空间为ga-actions,spec.size为 3,status.phase为Running。在/root/ga-actions/argocd-cm-pause.yaml中放置键resource.customizations.actions.example.com_Widget,让discovery.lua只给出一个pause,并在definitions中写下该操作的action.lua(把spec.paused设为真)。把list-actions的输出保存到/root/ga-actions/list-pause.txt。 - 把
argocd admin settings resource-overrides run-action /root/ga-actions/w-running.yaml pause --argocd-cm-path /root/ga-actions/argocd-cm-pause.yaml的输出保存到/root/ga-actions/run-pause.txt。输出中必须能看到新增了paused: true。 - 创建
/root/ga-actions/w-paused.yaml——名称为w-paused,spec.size为 3,spec.paused为真,status.phase为Paused。在/root/ga-actions/argocd-cm-toggle.yaml中放置pause和resume两个操作,并让discovery.lua根据spec.paused的值,只让两者之一可用,方法是加上disabled。把针对这两个样本的list-actions输出分别保存到/root/ga-actions/list-running.txt和/root/ga-actions/list-paused.txt。 - 在
/root/ga-actions/argocd-cm-scale.yaml中,在第 4 步的两个操作之外再加一个scale-up——把spec.size增加 1。对于已暂停的 Widget,这个操作也必须变灰。把对w-running.yaml运行scale-up的输出保存到/root/ga-actions/run-scale.txt。必须能看到 3 变成 4。 - 在
/root/ga-actions/argocd-cm-full.yaml中原样保留第 5 步的 Widget 操作,再创建一个键resource.customizations.actions.apps_Deployment。操作名称为pin-image,把第一个容器的镜像改为nginx:1.27-hardened。把对deploy.yaml运行这个操作的输出保存到/root/ga-actions/run-pin.txt。 - 在 kwok 集群中创建命名空间
ga-actions并应用deploy.yaml。然后创建并应用/root/ga-actions/deploy-pinned.yaml,它是反映了第 6 步操作所指出变更的清单——集群中web容器的镜像必须变成操作所指定的值。 - 在
/root/ga-actions/actions-matrix.tsv中写至少四行<샘플파일이름>\t<동작이름>\t<바뀐 필드에서 찾을 글자>(占位符依次为样本文件名、操作名称、要在被修改字段中查找的字符)——必须出现三种以上的操作名称。/root/ga-actions/check-actions.sh读取这张表,用/root/ga-actions/argocd-cm-full.yaml运行每个操作,输出中有该字符则输出OK …,没有则输出MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到/root/ga-actions/actions-result.txt。
参考
- 键名是
resource.customizations.actions.<그룹>_<종류>(占位符依次为组、类型),分隔符是下划线。 - 值中包含
discovery.lua和definitions两项。 - discovery.lua 返回以操作名称为键的表,在值中放入
{["disabled"] = true}就会变灰。 - Lua 的数组下标从 1 开始——第一个容器是
containers[1]。 - 常见错误:期望
list-actions会列出内置操作。这条命令只读取 ConfigMap。 - 参考:https://argo-cd.readthedocs.io/en/stable/operator-manual/resource_actions/
这条命令只看 ConfigMap
在 /root/ga-actions/deploy.yaml 中创建 ga-actions 命名空间的 Deployment web——spec.replicas 为 2,一个容器(web,镜像 nginx:1.25),选择器和标签为 app: web。/root/ga-actions/argocd-cm.yaml 是 data: {} 的空 ConfigMap。把 argocd admin settings resource-overrides list-actions /root/ga-actions/deploy.yaml --argocd-cm-path /root/ga-actions/argocd-cm.yaml 的输出保存到 /root/ga-actions/none.txt。
在 Argo CD 界面上,Deployment 会显示 restart 之类的按钮。但这条命令的输出不同——想一想这条命令读取的是什么,就能明白原因。后面的步骤会一直把这两个文件当作材料。
决定显示哪些按钮的代码
在 /root/ga-actions/w-running.yaml 中创建 example.com/v1 的 Widget——名称为 w-running,命名空间为 ga-actions,spec.size 为 3,status.phase 为 Running。在 /root/ga-actions/argocd-cm-pause.yaml 中放置键 resource.customizations.actions.example.com_Widget,让 discovery.lua 只给出一个 pause,并在 definitions 中写下该操作的 action.lua(把 spec.paused 设为真)。把 list-actions 的输出保存到 /root/ga-actions/list-pause.txt。
一个键的值中包含 discovery.lua 和 definitions 两项。discovery 返回以名称为键的表,definitions 是带有名称和 action.lua 的列表。没有 spec 的资源也可能传进来,所以请在 action.lua 中检查。
运行操作就会得到被修改的字段
把 argocd admin settings resource-overrides run-action /root/ga-actions/w-running.yaml pause --argocd-cm-path /root/ga-actions/argocd-cm-pause.yaml 的输出保存到 /root/ga-actions/run-pause.txt。输出中必须能看到新增了 paused: true。
这条命令不会把修改后的资源整个返回,而只显示改了什么。因此可以一眼确认操作除了预期的修改之外还动了什么——编写操作时最需要小心的正是这一点。
根据情况让按钮变灰
创建 /root/ga-actions/w-paused.yaml——名称为 w-paused,spec.size 为 3,spec.paused 为真,status.phase 为 Paused。在 /root/ga-actions/argocd-cm-toggle.yaml 中放置 pause 和 resume 两个操作,并让 discovery.lua 根据 spec.paused 的值,只让两者之一可用,方法是加上 disabled。把针对这两个样本的 list-actions 输出分别保存到 /root/ga-actions/list-running.txt 和 /root/ga-actions/list-paused.txt。
在 discovery.lua 返回的表的值中放入 {["disabled"] = true},该操作就会变灰。对已经暂停的东西再次暂停的按钮会招来事故,所以根据状态开启或关闭的工作由这段代码而不是界面来做。
读取值并计算的操作
在 /root/ga-actions/argocd-cm-scale.yaml 中,在第 4 步的两个操作之外再加一个 scale-up——把 spec.size 增加 1。对于已暂停的 Widget,这个操作也必须变灰。把对 w-running.yaml 运行 scale-up 的输出保存到 /root/ga-actions/run-scale.txt。必须能看到 3 变成 4。
action.lua 可以读取资源并进行计算。这里要注意的是值不存在的情况——给 nil 加 1 会让脚本崩溃。本实验的样本里 size 总是存在,但如果是真正要使用的规则,就应该加入检查。
也给内置类型添加自己的操作
在 /root/ga-actions/argocd-cm-full.yaml 中原样保留第 5 步的 Widget 操作,再创建一个键 resource.customizations.actions.apps_Deployment。操作名称为 pin-image,把第一个容器的镜像改为 nginx:1.27-hardened。把对 deploy.yaml 运行这个操作的输出保存到 /root/ga-actions/run-pin.txt。
Lua 的数组下标不是从 0 开始,而是从 1 开始——containers[1] 是第一个容器。给内置类型添加自定义操作后,界面上会多出一个按钮,而内置操作仍然保留。
把操作产生的结果应用到真实集群
在 kwok 集群中创建命名空间 ga-actions 并应用 deploy.yaml。然后创建并应用 /root/ga-actions/deploy-pinned.yaml,它是反映了第 6 步操作所指出变更的清单——集群中 web 容器的镜像必须变成操作所指定的值。
run-action 不会保存修改后的资源,只会告知会改变什么。在真正的 Argo CD 中,这个结果由控制器来应用,而在这里,则由人把同样的变更写进清单再应用。如果命名空间不存在,应用会失败。
把操作所做的事整理成表,做回归检查
在 /root/ga-actions/actions-matrix.tsv 中写至少四行 <샘플파일이름>\t<동작이름>\t<바뀐 필드에서 찾을 글자>(占位符依次为样本文件名、操作名称、要在被修改字段中查找的字符)——必须出现三种以上的操作名称。/root/ga-actions/check-actions.sh 读取这张表,用 /root/ga-actions/argocd-cm-full.yaml 运行每个操作,输出中有该字符则输出 OK …,没有则输出 MISMATCH …,只写到标准输出,只要有一行不匹配就必须以非 0 退出码结束。把它的输出保存到 /root/ga-actions/actions-result.txt。
操作是写一次就会被遗忘的代码,资源 schema 改变的那天,它会悄悄开始修改不该动的字段。有了这张表,当天就会亮起红灯。如果脚本自己去写文件,评分器再次运行时就会覆盖学员的产出文件,所以请只输出到标准输出。