写了策略,和策略被遵守,是两回事
一句话总结
Kyverno 存在的理由就是阻止违规请求;在缺少阻止环节的环境中,除了写过策略之外,什么也验证不了。
为什么必须是真实 admission
在早期策略编写实验的仅加载 CRD 的环境中,必须区分保存成功与策略真正执行。本模块和 Webhook 故障实验会在控制器实际运行的 VM 中比较正常请求与违规请求。
Kyverno 是准入控制器。它的存在理由就是阻止违规请求,而之前的学习环境恰恰缺少这一阻止环节。
三种动作发生在不同时点
| 动作 | 何时 | 做什么 |
|---|---|---|
mutate |
admission,且在 validate 之前 | 修改请求 |
validate |
admission | 拒绝或放行 |
generate |
admission 之后,由独立控制器执行 | 创建其他对象 |
理解这个顺序后,就能组合策略。把“缺少时自动补上”(mutate)与“必须存在”(validate)放在一起,用户什么也不做也能通过。
而 generate 位于 admission 之外,会带来两个结果:需要独立权限,且资源不会立即生成。权限不足时,策略看似正常,却什么都不会创建,错误只会留在 Kyverno 日志中。
最危险的是静默失败
即使 Kyverno Pod 显示 Running,**没有 Webhook 配置也不会发生任何事情。**策略仍然存在,也没有错误。所有策略都已写好却一条都未应用的状态,看起来完全正常。
因此,写完策略后必须亲自测试它是否真的会阻止请求。
一条策略可能锁住整个集群
如果处于策略适用范围内的系统 Pod 不满足要求,它的重新创建请求可能被拒绝。但这并不表示所有策略都会阻止系统、现有 Pod 会立即终止,或连删除策略都必然受阻。必须确认实际请求类型、目标范围和恢复路径。
部署策略的顺序
新策略应先收集违规情况,给团队留出修复时间,再开始强制执行。
1. Audit + 보고서 적용 대상의 위반을 수집한다
2. 수정·예외·복구 시험 정상 요청과 위반 요청을 모두 시험한다
3. Enforce + 관찰 위반 요청을 거부하고 영향을 관찰한다
本实验的 Kyverno ClusterPolicy 采用 Audit → Enforce。Warn 不是该字段的第三个值。若要在响应中以警告形式通知 Audit 违规,还需同时设置 spec.emitWarning。不要把其他策略引擎的模式名称直接填入这个 API。
应在违规清单中区分需要修复的项目与已批准的例外,并按适用范围逐步切换。不能仅凭现有 Pod 仍在运行,就判断下一次部署也能通过。
# Kyverno — 지금 걸리는 것들
kubectl get policyreport -A -o json | jq -r '
.items[].results[] | select(.result=="fail") |
"\(.policy): \(.resources[0].namespace)/\(.resources[0].name)"' | sort | uniq -c
避免锁住自己
如果策略拒绝系统组件的恢复请求,可能会扩大故障。下面是标签规则中可使用的例外局部示例。它既不是应无条件应用于所有系统安全策略的列表,也不是排除 Webhook 调用的配置。
spec:
rules:
- name: require-nonroot
match:
any:
- resources: {kinds: [Pod]}
exclude:
any:
- resources:
namespaces: [kube-system, kyverno, gatekeeper-system]
如果已注册的 Webhook 调用失败,failurePolicy: Fail 会拒绝相应请求,而 Ignore 会跳过该 Webhook 并继续其余处理。即使设置为 Ignore,Webhook 正常响应并明确拒绝的策略违规仍然有效。策略对象不会因此被删除,其他策略的检查也不会被忽略。
策略规则的 exclude 在引擎内部应用。API 服务器的真实调用范围,应通过 WebhookConfiguration 的 rules、namespaceSelector、objectSelector 等设置确认。若要在引擎故障时排除其自身恢复请求,必须检查到这个调用层面。应权衡跳过验证的风险与可用性,并测试已批准的恢复路径。
Webhook 完全没有注册与已经注册但不响应也是两种不同状态。后续故障实验会分别制造这两种状态,并比较请求结果与实际注册情况。
变更(mutate)先于验证
admission 顺序是固定的。
변형 웹훅 → 스키마 검증 → 검증 웹훅 → etcd 저장
因此,把“填充默认值的策略”与“要求该字段存在的策略”放在一起时,请求会自动通过。即使用户没有填写,变更步骤也会补上字段,再由验证步骤确认。
但不要忘记:变更会在用户不知情的情况下修改对象。如果通过 kubectl get -o yaml 看到的已保存结果与自己写入的内容不同,很容易引发困惑。应在文档中说明变更策略会修改什么,并尽可能通过注解留下痕迹。
实践中真正重要的事项
**部署策略后,必须同时测试正常对象和违规对象。**控制器显示 Running 并不能保证 Webhook 已注册并正在处理请求。除了创建命令的退出码,还要确认拒绝消息与对象是否写入存储。
**扩大策略范围时,要测试系统恢复。**应区分规则例外与 Webhook 调用排除,并确认真实系统工作负载满足要求。不要把故障实验应用于整个生产集群。
**如果 generate 不工作,应同时检查目标匹配和 background 控制器权限。**日志中的 Forbidden 是调查权限的依据,但不能仅凭没有输出就断定原因。
下一项实验会在真实 Kyverno 上亲自验证这些内容。
通过官方文档确认
- Kubernetes:Webhook 调用范围与 failurePolicy
- Kyverno:Audit、Enforce、emitWarning 与策略设置
- Kyverno:ClusterPolicy 的支持范围与弃用计划
本实验固定使用 Kyverno 1.19.1。不要把最新文档中的 API 直接应用到现有 VM;应同时检查已安装版本的 CRD。