在拦住之前先告知,这才叫开发者体验
一句话总结
护栏应分别安排“阻止”与“告知”。规则应在一处定义、在多处执行,而且每条规则都必须附带标识符与修复方法,才能既成为指标,也成为指引。
为什么需要它
平台团队决定强制规则时,通常首先想到 admission Webhook。但 admission 是最后一道关口。开发者编写代码、提交、运行流水线、构建镜像并点击部署后,才得知“缺少资源请求”。修复只需一分钟的问题,却花了三十分钟才发现。
反过来,如果所有规则都在前面阻止,也会产生问题。每条规则都变成强制要求时,想在一天内启动原型的团队会寻找绕过平台的方法。一旦开始绕过,规则数量不断增加,实际合规率却会下降,平台团队甚至不知道这一事实。
因此,要把问题拆成两个:违反这条规则会带来什么风险,以及在哪个位置提醒成本最低。
它如何工作
规则应附带标识符、严重度与修复方法
规则若只是一句话,就既无法统计,也无法指导。每条规则应同时定义以下三项。
| 项目 | 必要性 |
|---|---|
标识符(如 PR001) |
可按规则统计合规率,也可逐规则授予例外 |
| 严重度(block · warn) | 区分必须阻止与只需提醒,才能减少绕过 |
| 修复方法 | 让阅读诊断结果的人知道下一步该做什么 |
严重度不是个人偏好,而应判断违规是否会伤害他人。使用 latest 标签会导致无法回滚,并破坏整个集群的可重现性,值得阻止。没有 readiness probe 通常只影响该服务自身可用性,更适合告知后由团队决定。
在多个位置执行同一规则
规则定义放在一处,执行则分布在多个位置。
- 编辑器与本地命令——成本最低、反馈最快,但是否运行取决于个人。
- 提交钩子——在提交前运行。它是本地文件,可以绕过,不能成为最后防线。
- CI——第一个在仓库之外运行的位置,从这里开始,绕过行为会留下记录。
- admission——进入集群的最后关口。只在这里阻止,反馈最晚。
前端位置负责快速反馈,后端位置负责提供保证。只有前端就无法确保遵守,只有后端则会太晚发现问题。
同时提供人类输出与机器输出
诊断器为人输出易读文本,为程序输出 JSON,同一个工具就能用于多个位置。退出码也是契约:只要存在一项违规,就必须以非零值结束,流水线才能把它当作信号。没有这项契约,就会在各位置创建不同工具,规则也会逐渐产生差异。
合规率会成为采用指标
对全部仓库运行同一个诊断器,可以得到逐规则合规率。该数字能帮助平台团队决定下一步建设什么。若某条规则的合规率特别低,可能不是团队懒惰,而是我们让这条规则太难遵守。这提示我们应提供默认值、预先填入脚手架,或改善提示文字。
但要留意分母。诊断对象清单变化时,即使没人做任何事,合规率也会改变。查看数字时必须同时记录分母。
实际现场中的表现
LabHub 的评分器正采用这种结构。评分脚本失败时,规则要求它不能只写“检查失败”,而要同时说明当前值是什么、应当是什么。原因相同:不知道错在哪里的人只能猜测,猜错两三次后就会离开。
也发生过相反的事故:仓库曾存在多个“无论填写什么答案都会通过”的评分器,因为无人报告而长期保留。诊断器也是如此,什么都发现不了的诊断器比没有更糟,因为合规率显示为 100%,实际上根本没有检查。因此,必须用故意违规的样本测试反方向行为。
避免护栏变成高墙
平台护栏本应用于预防事故,但设计错误时,人们会先学会绕过它,最终既失去控制,也失去信任。
**阻止时在同一界面给出替代方案。**只说“不能使用 privileged”,用户就会去找其他集群。还应说明“请改用这个 capability;确有需要时按此流程申请例外”。拒绝消息不应只链接文档,而应给出下一步行动。
**从警告开始。**新策略先以审计模式运行,统计命中对象并向团队展示,再开始阻止。立即阻止会让当天全部部署失败,而这种记忆会保留很久。
把例外变成流程。没有例外,策略会崩溃;例外太容易,策略等于不存在。答案是带期限的例外:90 天后自动到期,并在到期前通知。
**自助服务优先于控制。**只要人们能轻松获得所需内容,就没有绕过理由。在创建命名空间需要等待三天审批的组织里,每个人都会借用别人的命名空间。
**把诊断交还给用户。**如果必须向平台团队询问“为什么我的 Pod 没启动”,该团队就会成为瓶颈。把事件、策略拒绝原因和资源不足集中到同一界面,多数问题都能自行解决。
kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -20
kubectl describe pod <파드> | sed -n '/Events:/,$p'
成功指标不是“阻止次数”。这个数字只衡量策略有多烦人。真正应衡量的是用户被拒绝后自行修复并成功的比例。比例低,说明消息写得不好。
下一项实验将做什么
我们会把五条黄金路径规则定义为带标识符和严重度的值,并构建实际判定这些规则的诊断器。分别创建合规样本和只违反特定规则的样本,进行正反测试;将结果输出为 JSON,并计算所有服务的合规率。最后把它接入提交钩子,确认只有 block 规则会真正阻止提交。