3. 第一个Kyverno策略:编写最简单的validate策略(禁止privileged容器)、策略YAML结构解析
在开始编写第一个Kyverno策略之前,我们需要理解策略引擎的核心工作模式。Kyverno作为Kubernetes原生的策略引擎,通过监听API Server的资源变更事件,在资源创建、更新或删除时触发策略校验。本节将从零开始编写一个最简单的validate策略,并深入解析策略YAML的每一层结构。
kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/main/config/install.yaml快速部署。
3.1 策略目标:禁止特权容器
特权容器是Kubernetes安全中最常见的风险点之一。当容器以privileged: true运行时,它将拥有宿主机内核的全部能力,可以访问所有设备、加载内核模块、绕过命名空间隔离。我们的第一个策略将拦截所有尝试创建特权容器的Pod。
3.2 策略YAML完整示例
下面是一个完整的Kyverno validate策略,用于禁止创建包含特权容器的Pod:
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"
privileged: "false"使用了字符串形式的"false",这是因为Kyverno的pattern字段在匹配布尔值时,需要使用字符串表示。如果直接写false(不带引号),Kyverno会将其解析为布尔类型,可能导致匹配行为不符合预期。
3.3 策略YAML结构逐层解析
为了深入理解策略的组成,我们将上述YAML拆解为四个核心层级,每一层都有其特定的职责和配置选项。
| 层级 | 字段路径 | 作用 | 关键配置项 |
|---|---|---|---|
| 策略元数据 | apiVersion / kind / metadata |
定义策略的API版本、资源类型和标识信息 | kyverno.io/v1、ClusterPolicy、name |
| 策略行为 | spec.validationFailureAction / spec.background |
控制策略的生效模式和扫描范围 | Enforce / Audit、true / false |
| 规则定义 | spec.rules[].match / spec.rules[].exclude |
指定策略适用的资源范围和排除条件 | any / all、resources.kinds、namespaces |
| 校验逻辑 | spec.rules[].validate |
定义具体的校验规则和失败时的提示信息 | message、pattern、anyPattern、deny |
3.4 核心字段详解
3.4.1 validationFailureAction:策略的两种模式
这个字段决定了策略在匹配失败时的行为:
Enforce(强制执行):当资源不符合策略时,Kyverno会直接拒绝该资源的创建或更新请求。这是生产环境推荐的模式。Audit(审计模式):当资源不符合策略时,Kyverno不会拒绝请求,但会在策略报告中生成一条违规记录。适用于策略上线前的灰度验证。
Audit模式下运行策略,观察违规报告,确认无误后再切换为Enforce模式。这样可以避免因策略配置错误导致生产服务中断。
3.4.2 background:存量资源扫描
当设置为true时,Kyverno会在策略创建后,对集群中已有的所有匹配资源进行扫描,并在策略报告中标记违规项。这对于发现历史遗留的安全问题非常有用。
3.4.3 match:资源匹配规则
match字段支持两种逻辑运算符:
any:只要满足任意一个条件即匹配。适用于多资源类型或多种标签场景。all:必须满足所有条件才匹配。适用于需要同时满足资源类型和命名空间等复合条件。
在我们的示例中,any下只定义了一个条件,即匹配所有Pod类型的资源。如果需要排除某些命名空间,可以在exclude字段中配置。
3.4.4 validate.pattern:声明式校验
pattern字段使用声明式语法定义资源的期望状态。Kyverno会将待校验的资源与pattern进行对比:
- 如果资源中的字段值等于
pattern中指定的值,则校验通过。 - 如果资源中的字段值不等于
pattern中指定的值,则校验失败。 - 如果资源中缺少
pattern中指定的字段,则校验通过(因为缺失字段意味着该字段未被设置,符合“非特权”的期望)。
在我们的策略中,privileged: "false"表示期望所有容器的securityContext.privileged字段要么不存在,要么被显式设置为false。任何设置为true的容器都会触发校验失败。
3.5 策略执行流程SVG
下图展示了Kyverno策略从创建到生效的完整执行流程,以及Enforce和Audit两种模式的分支路径:
3.6 部署与验证策略
将上述策略保存为disallow-privileged.yaml,然后执行以下命令部署到集群:
kubectl apply -f disallow-privileged.yaml
验证策略是否成功创建:
kubectl get clusterpolicy disallow-privileged-containers -o wide
输出应显示策略状态为Ready: true。
3.7 测试策略效果
创建一个测试Pod来验证策略是否生效:
kubectl run test-privileged --image=nginx --privileged=true
如果策略处于Enforce模式,你会看到类似以下的拒绝消息:
Error from server: admission webhook "validate.kyverno.svc" denied the request:
resource Pod/default/test-privileged was blocked due to the following policies:
disallow-privileged-containers:
validate-privileged: '特权容器是不允许的。请移除 ''securityContext.privileged: true'' 配置。'
message字段内容。这表明策略的validate逻辑和pattern匹配规则都正确工作。
3.8 策略结构总结SVG
下图以树形结构展示了Kyverno策略YAML的完整层级关系,帮助你在编写复杂策略时快速定位各字段的位置:
3.9 常见问题与避坑指南
| 问题 | 原因 | 解决方案 |
|---|---|---|
策略创建后状态为Ready: false |
YAML语法错误或引用了不存在的API版本 | 使用kubectl describe clusterpolicy <name>查看错误详情,检查apiVersion和字段拼写 |
| 策略未拦截特权容器 | validationFailureAction设置为Audit,或match规则未正确匹配Pod |
确认策略模式为Enforce,检查match中的kinds是否包含Pod |
| 策略报告中没有违规记录 | background设置为false,或存量资源已通过其他策略 |
将background改为true,等待几分钟后重新查看策略报告 |
| 布尔值匹配异常 | 在pattern中直接使用true/false而非字符串 |
将布尔值用引号包裹,如privileged: "false" |
kubectl kyverno test命令在本地测试策略。该命令会模拟Kyverno的校验逻辑,无需实际部署到集群。例如:kubectl kyverno test . --test-case=test.yaml,其中test.yaml包含待测试的Pod YAML和期望结果。
通过本节的学习,你已经掌握了Kyverno validate策略的完整编写流程和YAML结构。这个禁止特权容器的策略可以作为安全基线策略的起点,后续可以在此基础上扩展更多安全规则,如禁止宿主机网络、限制容器用户ID、强制只读根文件系统等。