一句话总结
安全规则写在文档里会被忽略, 写在代码里才会被执行.
策略即代码(Policy as Code)用声明式策略定义"什么是合规的", 由准入控制器自动拦截违规资源, 从"事后审计"变为"事前阻止".
为什么需要策略即代码
前几篇讲的安全配置(非 root, drop capabilities, NetworkPolicy...), 如何确保每个团队, 每个 Deployment 都遵守?
方式
问题
写文档 + 培训
人会忘, 会犯错, 新人不知道
Code Review 检查
YAML 变更容易遗漏安全字段
事后审计
违规资源已经在跑了, 发现时已经有风险
准入控制自动拦截
违规资源根本创建不出来
文档规定"不许闯红灯" vs 路口装了自动拦截栏杆.
前者靠人的自觉(总有人闯), 后者靠机制保证(物理上过不去).
策略即代码 = 给 K8s 集群装自动拦截栏杆.
Kyverno
Kyverno 是 K8s 原生的策略引擎, 用 YAML 定义策略(而非 Rego 这类专用语言), 学习成本极低.
策略类型
类型
作用
示例
Validate
校验资源是否合规
拒绝 privileged 容器
Mutate
自动修改资源
自动注入 securityContext 默认值
Generate
自动创建关联资源
新 Namespace 自动创建 NetworkPolicy
VerifyImages
验证镜像签名
拒绝未签名镜像
常见策略示例
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-privileged spec: validationFailureAction: Enforce rules: - name: deny-privileged match: any: - resources: kinds: ["Pod" ] validate: message: "Privileged containers are not allowed." pattern: spec: containers: - securityContext: privileged: "false"
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-latest-tag spec: validationFailureAction: Enforce rules: - name: deny-latest match: any: - resources: kinds: ["Pod" ] validate: message: "Using ':latest' tag is not allowed. Use a specific version." pattern: spec: containers: - image: "!*:latest"
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: require-resource-limits spec: validationFailureAction: Enforce rules: - name: check-limits match: any: - resources: kinds: ["Pod" ] validate: message: "CPU and memory limits are required." pattern: spec: containers: - resources: limits: memory: "?*" cpu: "?*"
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: add-default-security-context spec: rules: - name: add-security-defaults match: any: - resources: kinds: ["Pod" ] mutate: patchStrategicMerge: spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: add-default-deny-networkpolicy spec: rules: - name: generate-netpol match: any: - resources: kinds: ["Namespace" ] generate: kind: NetworkPolicy apiVersion: networking.k8s.io/v1 name: default-deny-ingress namespace: "{{request.object.metadata.name}} " data: spec: podSelector: {} policyTypes: - Ingress
OPA / Gatekeeper
OPA(Open Policy Agent)是通用策略引擎, Gatekeeper 是 OPA 的 K8s 准入控制器适配层. 用 Rego 语言编写策略.
OPA/Gatekeeper vs Kyverno
Kyverno
OPA/Gatekeeper
策略语言
YAML(K8s 原生)
Rego(专用语言)
学习曲线
低(会写 K8s YAML 就行)
高(需要学 Rego)
验证+变异+生成
全支持
主要做验证(变异有限)
镜像签名验证
内置 VerifyImages
需要额外组件
生态广度
K8s 专用
可用于 Terraform/CI/API 等多场景
适用场景
K8s 安全策略(大多数团队首选)
多平台统一策略, 复杂逻辑
选择建议
只做 K8s 准入策略 → Kyverno (简单直观, 功能完整).
需要跨平台策略(K8s + Terraform + CI pipeline)或复杂计算逻辑 → OPA/Gatekeeper.
两者不冲突, 可以共存.
Gatekeeper 示例
apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8srequiredlabels spec: crd: spec: names: kind: K8sRequiredLabels validation: openAPIV3Schema: type: object properties: labels: type: array items: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8srequiredlabels violation[{"msg": msg}] { provided := {label | input.review.object.metadata.labels[label]} required := {label | label := input.parameters.labels[_]} missing := required - provided count(missing) > 0 msg := sprintf("Missing required labels: %v", [missing]) } --- apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sRequiredLabels metadata: name: require-team-label spec: match: kinds: - apiGroups: ["apps" ] kinds: ["Deployment" ] parameters: labels: ["team" , "env" ]
合规基线
不需要从零开始写策略, 社区有现成的安全基线可以直接采用:
基线
来源
覆盖
Pod Security Standards
K8s 官方
Pod 安全最低要求
Kyverno Best Practices
Kyverno 社区
30+ 开箱即用的生产策略
CIS Kubernetes Benchmark
CIS
完整的集群安全基线(200+ 检查项)
NSA/CISA K8s Hardening Guide
美国 NSA
K8s 安全加固最佳实践
$ helm repo add kyverno https://kyverno.github.io/kyverno $ helm install kyverno kyverno/kyverno -n kyverno --create-namespace $ helm install kyverno-policies kyverno/kyverno-policies -n kyverno \ --set podSecurityStandard=restricted
策略测试与 CI 集成
策略测试
策略也是代码, 需要测试. Kyverno CLI 支持离线测试:
$ kyverno apply policy.yaml --resource bad-pod.yaml $ kyverno apply policy.yaml --resource good-pod.yaml
CI Pipeline 集成
- name: Test Kyverno policies run: | kyverno apply policies/ --resource k8s/*.yaml if [ $? -ne 0 ]; then echo "Policy violation detected!" exit 1 fi
左移安全(Shift Left)
在 CI 中验证策略 = 开发阶段就发现违规, 而非等到部署被 Admission Webhook 拒绝才知道出了问题.
CI 报错 → 开发者本地修复 → 再次提交. 体验远好于"kubectl apply 被拒绝然后手忙脚乱".
策略部署策略
Audit 模式起步 : 先 validationFailureAction: Audit, 只记录不拦截, 收集违规数据
修复存量违规 : 根据审计报告逐个修复不合规的 Deployment
切换 Enforce : 确认无误后切为拦截模式
持续监控 : 监控策略触发次数, 新策略总是先 Audit
快速回顾
策略即代码 : 安全规则声明式定义 + 准入控制器自动执行, 从"靠人"变为"靠机制"
Kyverno : K8s 原生 YAML 策略, 支持 Validate / Mutate / Generate / VerifyImages
OPA/Gatekeeper : Rego 语言, 适合复杂逻辑和多平台统一策略
合规基线 : CIS Benchmark / PSS / Kyverno Policies 开箱即用
策略测试 : kyverno CLI 离线测试 + CI 集成 = 左移安全
渐进部署 : Audit → 修复 → Enforce, 不要一上来就拦截
动手练习
Kyverno 基础策略 : 安装 Kyverno, 部署"禁止 privileged 容器"策略(Enforce 模式), 尝试创建 privileged Pod 验证被拒绝
Validate 策略编写 : 编写一条 Kyverno 策略要求所有 Deployment 必须有 team label, 先用 Audit 模式观察现有违规
Mutate 策略编写 : 编写 Mutate 策略, 自动为没有设置 securityContext 的 Pod 注入 runAsNonRoot: true
Generate 策略编写 : 编写 Generate 策略, 每创建一个新 Namespace 自动生成 default-deny NetworkPolicy + ResourceQuota
CI 集成测试 : 用 kyverno apply 命令在 CI 中验证 K8s YAML 是否合规