LabHub
学习 学习路径 课程

KCA — Kyverno 认证助理

把 validate 规则和内置策略比一比

在 LabHub 中继续学习

目标

使用 Kyverno ClusterPolicy 编写强制标签和禁止标签规则,并在真实集群中用 Kubernetes 内置的 ValidatingAdmissionPolicy 实现相同检查,以比较这两种方法的差异。

为什么重要

要判断是否需要引入策略引擎,必须了解内置功能的能力边界。如果全部需求只是用 CEL 检查一个字段,那么 ValidatingAdmissionPolicy 就已足够;这样既能减少一个需要运维的组件,也少了一项管理 Webhook 证书续期的工作。真正能够证明 Kyverno 价值的,是 generate、mutate、镜像验证等内置策略无法完成的任务。在本实验中并排创建两份清单,可以切身体会这条边界在哪里。此外,练习为每条规则设置不同的强制级别,也是实际引入流程的关键。

步骤

  1. 创建 /root/kca-validate/ 目录,在 policy.yaml 中填写 apiVersion kyverno.io/v1、kind ClusterPolicymetadata.name kca-require-app-label,并将 spec.rules[0].name 设为 check-app-label
  2. spec.rules[0].match.any[0].resources.kinds 中加入 PodDeployment,并在同一位置的 namespaces 中加入 kca-app
  3. 填写 spec.rules[0].validate.message,并通过 validate.pattern 要求 metadata.labels 中的 app.kubernetes.io/name 必须是非空值。
  4. spec.rules[0].validate.failureAction 设为 Enforce。不要使用策略级别的 spec.validationFailureAction
  5. 添加第二条规则 deny-latest-tag。填写 validate.message,在 validate.deny.conditions.all[0] 中加入指向容器镜像的 key、operator、value,并将该规则的 validate.failureAction 设为 Audit
  6. spec.rules[0].exclude.any[0].resources.namespaces 中加入 kube-systemkyverno
  7. 在集群中实际创建 ValidatingAdmissionPolicy kca-require-app-labelspec.failurePolicy 设为 Failspec.matchConstraints 应匹配 apps 组中的 deployments,操作为 CREATE、UPDATE;spec.validations[0].expression 必须是检查 app.kubernetes.io/name 标签是否存在的 CEL 表达式。
  8. 在集群中创建命名空间 kca-app 并添加标签 kca=enforced,再实际创建 ValidatingAdmissionPolicyBinding kca-require-app-label-bindingspec.policyName 设为 kca-require-app-labelspec.validationActions 中加入 Denyspec.matchResources.namespaceSelector.matchLabels 中加入 kca: enforced

参考

搭建 ClusterPolicy 骨架

创建 /root/kca-validate/ 目录,在 policy.yaml 中填写 apiVersion kyverno.io/v1、kind ClusterPolicymetadata.name kca-require-app-label,并将 spec.rules[0].name 设为 check-app-label

ClusterPolicy 是 kyverno.io 组中的集群范围资源。rules 是数组,每条规则都必须有名称。

选择要匹配的对象

spec.rules[0].match.any[0].resources.kinds 中加入 PodDeployment,并在同一位置的 namespaces 中加入 kca-app

match.any 是数组,每个元素的 resources 中可以放入 kinds、namespaces、names、selector。同时缩小资源类型和命名空间范围,可以减少经过 Webhook 的请求数量。

通过模式匹配要求必备标签

填写 spec.rules[0].validate.message,并通过 validate.pattern 要求 metadata.labels 中的 app.kubernetes.io/name 必须是非空值。

pattern 按照待检查对象的形状原样绘制,并在值的位置填入运算符。请回想要求非空值应使用哪个运算符。

按规则设置强制级别

spec.rules[0].validate.failureAction 设为 Enforce。不要使用策略级别的 spec.validationFailureAction

策略级字段已被弃用,因此不能保留。强制级别已下移到 validate 块中;未指定时默认为观察模式。

用 deny.conditions 添加第二条规则

添加第二条规则 deny-latest-tag。填写 validate.message,在 validate.deny.conditions.all[0] 中加入指向容器镜像的 key、operator、value,并将该规则的 validate.failureAction 设为 Audit

条件包含 key、operator、value 三部分。使用 all 还是 any 来组合多个条件,会改变其含义。只将这条规则设为观察模式。

排除系统命名空间

spec.rules[0].exclude.any[0].resources.namespaces 中加入 kube-systemkyverno

exclude 的结构与 match 相同。如果策略阻止了 Kyverno 自身或控制平面组件,恢复会非常困难。

用内置策略实现相同规则

在集群中实际创建 ValidatingAdmissionPolicy kca-require-app-labelspec.failurePolicy 设为 Failspec.matchConstraints 应匹配 apps 组中的 deployments,操作为 CREATE、UPDATE;spec.validations[0].expression 必须是检查 app.kubernetes.io/name 标签是否存在的 CEL 表达式。

ValidatingAdmissionPolicy 不是 CRD,而是 Kubernetes 内置资源,可以直接 apply。表达式使用 CEL,并通过 object 访问检查对象。

绑定策略并选择目标命名空间

在集群中创建命名空间 kca-app 并添加标签 kca=enforced,再实际创建 ValidatingAdmissionPolicyBinding kca-require-app-label-bindingspec.policyName 设为 kca-require-app-labelspec.validationActions 中加入 Denyspec.matchResources.namespaceSelector.matchLabels 中加入 kca: enforced

内置策略中的策略与绑定是一对资源。没有绑定时,策略只会存在,却不会作用于任何请求;具体执行什么动作也由绑定决定。