4. 第一个准入策略:编写 Validate 规则禁止特权容器,测试准入拦截效果

本章将带领你编写第一条 Kyverno Validate 策略,用于禁止在集群中创建特权容器。通过该实践,你将掌握策略的 YAML 结构、规则匹配逻辑以及准入拦截的验证方法。

4.1 策略目标与设计思路

特权容器拥有宿主机内核的全部权限,是容器逃逸攻击的主要入口。本策略的目标是:

  • 拦截:拒绝任何设置了 securityContext.privileged: true 的 Pod 创建请求。
  • 告警:对于违反规则的请求,返回明确的拒绝原因。
  • 覆盖:同时适用于 Pod 和 Deployment、DaemonSet 等工作负载资源。
关键概念:Validate 策略在准入阶段对资源进行校验,如果规则条件不满足,则拒绝该资源进入集群。这是实现合规性基线最直接的手段。

4.2 编写 Validate 策略 YAML

以下是一个完整的 Kyverno ClusterPolicy,用于禁止特权容器:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: validate-privileged
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "特权容器是不允许的。请移除 securityContext.privileged: true。"
        pattern:
          spec:
            containers:
              - securityContext:
                  privileged: "false"
            initContainers:
              - securityContext:
                  privileged: "false"
            ephemeralContainers:
              - securityContext:
                  privileged: "false"

4.3 策略字段解析

字段 值 说明
validationFailureAction Enforce 设置为 Enforce 表示直接拒绝违规请求;若设为 Audit 则仅记录告警。
background true 启用后台扫描,对集群中已有资源进行合规检查。
match.any.resources.kinds ["Pod"] 匹配的资源类型。Kyverno 会自动处理 Deployment 等控制器生成的 Pod 模板。
validate.pattern 嵌套字段 定义期望的资源状态模式。此处要求 privileged 字段必须为字符串 "false"。
validate.message 自定义字符串 当规则被违反时,返回给用户的拒绝原因。
提示:Kyverno 使用 pattern 进行声明式匹配,而非编程式条件。当资源字段与 pattern 不一致时,即触发拦截。

4.4 策略工作流程

下图展示了 Kyverno 准入控制器在处理 Pod 创建请求时的完整流程:

Kyverno Validate 策略准入拦截流程 用户创建 Pod API Server 接收请求 Kyverno 准入控制器拦截 匹配 disallow-privileged-containers 通过 → 创建成功 拒绝 → 返回错误 privileged: false privileged: true

4.5 部署策略到集群

将上述 YAML 保存为 disallow-privileged.yaml,然后执行以下命令:

kubectl apply -f disallow-privileged.yaml

验证策略是否成功创建:

kubectl get clusterpolicy disallow-privileged-containers -o wide

输出应显示 READY 状态为 true,表示策略已生效。

4.6 测试准入拦截效果

创建两个测试 Pod,一个合规,一个违规:

4.6.1 合规 Pod(应被允许)

kubectl run nginx-non-privileged --image=nginx --restart=Never

预期结果:Pod 创建成功。

4.6.2 违规 Pod(应被拒绝)

kubectl run nginx-privileged --image=nginx --restart=Never --privileged

预期结果:返回类似以下错误信息:

Error from server: admission webhook "validate.kyverno.svc" denied the request:

resource Pod/default/nginx-privileged was blocked due to the following policies

disallow-privileged-containers:
  validate-privileged: '特权容器是不允许的。请移除 securityContext.privileged: true。'
注意:如果使用 --privileged 参数时命令未报错,请检查你的 kubectl 版本是否支持该参数。也可以直接使用 YAML 文件创建 Pod 进行测试。

4.7 使用 YAML 文件测试

创建违规 Pod 的 YAML 文件 privileged-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: privileged-pod
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      privileged: true

执行创建:

kubectl apply -f privileged-pod.yaml

此时应收到明确的拒绝消息,包含策略名称和自定义的拒绝原因。

4.8 策略效果对比

测试场景 Pod 配置 预期结果 实际行为
合规容器 未设置 privileged 或显式设为 false 创建成功 Pod 正常运行
违规容器 securityContext.privileged: true 创建被拒绝 返回 Kyverno 拒绝消息
工作负载控制器 Deployment 中设置 privileged: true 创建被拒绝 Deployment 创建失败,Pod 模板未通过校验

4.9 常见问题与排查

  • 策略未生效:检查 Kyverno Pod 是否正常运行,以及 Webhook 配置是否正确。
  • 误拦截合规 Pod:确认 pattern 中 privileged 字段的值是否为字符串 "false",而非布尔值 false。
  • 仅拦截 Pod 资源:如需拦截 Deployment 等控制器,可在 match 中添加更多 kinds,或使用 podControllers 自动匹配。
最佳实践:在生产环境中,建议先将 validationFailureAction 设为 Audit,观察一段时间确认无误报后,再切换为 Enforce。

4.10 本章小结

通过本节的实践,你已经完成了以下关键任务:

  • 编写了第一条 Kyverno Validate 策略,禁止特权容器。
  • 理解了 pattern 匹配机制和 validationFailureAction 的作用。
  • 成功测试了准入拦截效果,验证了策略的合规性保障能力。