策略即代码:OPA Gatekeeper、Kyverno 与合规治理

深入 Kubernetes 准入控制与策略即代码:动态准入 Webhook 原理、OPA Gatekeeper 的 ConstraintTemplate/Constraint、Kyverno 策略、Gatekeeper 与 Kyverno 对比、NIST/PCI 合规映射、策略测试与 CI 集成、性能与故障排查。

“谁能部署什么、资源上限多少、镜像能不能带 latest 标签、secret 能不能明文”——这类规则如果靠人肉 review 或事后扫描,永远会漏。Kubernetes 的策略即代码(Policy-as-Code)把准入规则变成代码:在对象落库之前用 Webhook 拦截,不符合规则就拒绝。两大主流工具是 OPA Gatekeeper(Rego 语言)与 Kyverno(YAML 原生),本指南从准入控制原理讲起,深入两者的策略写法、合规(NIST/PCI)映射、测试与 CI 集成,以及性能与故障排查的实战经验。


目录


1. 准入控制与动态准入 Webhook

1.1 请求处理链路

kubectl apply 的请求经 API Server 认证/鉴权后,会经过准入插件。其中动态准入 Webhook(ValidatingWebhookConfiguration)会把 AdmissionReview 发给策略引擎,返回 allowed=true/false 与拒绝原因。关键点在于它在对象写入 etcd 之前拦截——不合规的对象根本不存在,这与"事后扫描"(审计)是互补的:准入防患于未然,审计用于取证。

1.2 两类 Webhook 与 failurePolicy

MutatingWebhook 可以修改对象(注入默认值、打标签),ValidatingWebhook 只能允许或拒绝。Gatekeeper/Kyverno 主要是 Validating(Kyverno 也做 Mutating)。failurePolicy 要慎重:Fail 表示 Webhook 挂了则拒绝所有请求(安全但可能"锁死集群"),Ignore 表示挂了则放行(可用性优先但有风险)。

ℹ️ 高可用第一课:策略引擎是集群的"看门人",一旦它挂了集群就瘫痪。生产必须多副本、有就绪探针,并认真权衡 failurePolicy。


2. OPA Gatekeeper:ConstraintTemplate 与 Constraint

2.1 两层抽象

Gatekeeper 用两层抽象把"规则"与"作用范围"分开:ConstraintTemplate 定义规则长什么样、用 Rego 写校验逻辑;Constraint 声明这条规则作用在哪些资源、参数是什么。工作流:安装 ConstraintTemplate(它本身是 CRD)→ 实例化 Constraint → 每次 Admission 把对象转成 JSON 跑 Rego,返回决策。

2.2 ConstraintTemplate 示例

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("缺少必需标签: %v", [missing])
        }

Rego 里的 violation[...] 集合每产生一条,就是一个拒绝原因;input.parameters 接收 Constraint 传入的参数。


3. Gatekeeper 策略实战

3.1 实例化 Constraint

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-app-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces: ["shop", "payment"]
  parameters:
    labels: ["app", "env"]

测试缺标签的 Pod 会被拒绝:Error: admission webhook "validation.gatekeeper.sh" denied the request: 缺少必需标签: set[env]。用 kubectl get constraints.gatekeeper.sh 查看所有约束与命中情况。

3.2 常用策略清单

生产最常用的一批策略:禁止 privileged 容器、强制声明 resource limits、禁止 hostPath/hostNetwork/hostPID、禁止 latest 镜像标签、强制 runAsNonRoot + seccomp、命名空间必须有 app/env 标签、Ingress 强制 TLS、禁止 NodePort。Rego 里判断 privileged 的核心片段是:c := input.review.object.spec.containers[_]; c.securityContext.privileged。

ℹ️ 参数化思维:把"哪些字段"写死在 Rego 里是坏味道;用 input.parameters 传参,让同一个模板可被不同约束复用。


4. Kyverno 策略即代码

4.1 纯 YAML 的策略

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Enforce   # Enforce=拒绝 / Audit=只记录
  rules:
    - name: require-app-env
      match:
        any:
          - resources:
              kinds: ["Pod"]
              namespaces: ["shop", "payment"]
      validate:
        message: "Pod 必须带有 app 与 env 标签"
        pattern:
          metadata:
            labels:
              app: "?*"
              env: "?*"

pattern 是声明式匹配,?* 表示"必须存在且非空"。validationFailureAction: Enforce 表示拒绝,Audit 表示只记录不拦截。

4.2 Mutating 与内置能力

Kyverno 不只是校验,还支持 mutate(注入默认值)、generate(策略触发时自动创建对象,如自动补 Namespace 配额)、verifyImages(镜像签名校验,对接 Sigstore/Cosign)。示例:用 mutate.patchStrategicMerge 给所有无 limits 的容器注入 limits: { cpu: "500m", memory: 512Mi }。


5. Gatekeeper 与 Kyverno 对比

5.1 功能对比

维度OPA GatekeeperKyverno
语言Rego(函数式)YAML pattern
学习成本高(Rego 有门槛)低(纯 YAML)
能力validatevalidate/mutate/generate/verifyImages
生态OPA 全家桶,社区大CNCF,与 K8s 绑定深
适合复杂规则/多平台统一快速见效/YAML 团队

5.2 怎么选

选 Gatekeeper 的场景:已有 OPA 生态(OPA 用于 IaC/API 校验)、需要"同一套策略语言贯穿所有平台"、规则复杂要强表达力。选 Kyverno 的场景:团队以 YAML 为主不想学新语言、需要 mutate/generate/镜像签名等内置能力、想装了就能写规则。

ℹ️ 中立建议:多数团队从 Kyverno 起步更快见效;规则复杂或已有 OPA 技术栈则选 Gatekeeper。别双跑两套引擎——决策不一致、维护翻倍。


6. 从实践到合规:NIST 与 PCI

6.1 合规框架映射

合规不是"装个策略工具",而是"用策略覆盖合规控制项"。NIST SP 800-53 的 CM-6(配置基线)→ 禁止宿主访问、强制最小权限;AC-6(最小特权)→ runAsNonRoot、禁止 privileged;SC-28(数据保护)→ 强制加密、禁止明文 secret;RA-5(漏洞管理)→ 镜像签名 + 禁止 latest。PCI DSS 的 Req 2(默认配置)→ 基线策略;Req 4(加密传输)→ Ingress 强制 TLS;Req 6(漏洞修复)→ 禁止高危镜像;Req 11(定期测试)→ 定期审计策略命中。

6.2 审计模式与证据链

合规要证据:先以 Audit 模式运行策略一段时间(Kyverno 的 validationFailureAction: Audit),生成策略命中报告(Gatekeeper 看 kubectl get constraints -o json | jq '.items[].status.violations';Kyverno 看 kubectl get policyreport),把报告接入合规平台,Webhook 审计日志留痕。

ℹ️ 合规落地顺序:先 Audit 摸清存量 → 定基线 → Enforce 拦增量 → 定期重扫存量。一步到位 Enforce 往往"一改就炸"。


7. 策略测试与 CI 集成

7.1 本地测试策略

Gatekeeper 用 conftest 在 CI 里跑 Rego:写测试用例 test_ok { ... not violation with input as {...} },用 conftest test --policy policy/ deploy.yaml 验证。Kyverno 用 CLI:kyverno apply ./policies/ --resource=deploy-bad.yaml 直接看策略对给定清单的结果。

7.2 在 CI 里做预检

jobs:
  policy-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Gatekeeper policy test
        run: conftest test --policy ./policy/ ./manifests/
      - name: Kyverno apply check
        run: kyverno apply ./kyverno-policies/ --resource=./manifests/

CI 预检的价值:开发在推送前就发现违规,而不是等集群准入时被打回;规则改动先过测试用例,避免"策略上线即误杀"。分层防御:CI 预检(快)+ 集群准入(权威)双保险。


8. 策略性能与故障排查

8.1 性能影响

每个请求都要过策略引擎,影响点:Rego 求值复杂度(循环/跨对象查询最贵)、策略数量(策略越多单请求越慢)、对象大小(大对象序列化耗 CPU)、并发(引擎副本数与限流)。经验:把策略按对象类型精确 match 收窄 scope,用 preconditions 减少无关请求,监控 webhook RTT 与副本 CPU,目标 < 10ms/请求。

8.2 故障排查清单

症状:kubectl apply 全被拒 → 检查 failurePolicy 与 webhook 服务健康
策略没生效 → 检查 match 的 kinds/namespaces 是否命中;
  Gatekeeper 看 Constraint status 编译错误;Kyverno 看是否还是 Audit
Rego 写错但能 apply → 看 ConstraintTemplate status.errors,用 OPA playground 调试
拒绝信息看不懂 → Gatekeeper 开 debug 日志;Kyverno 看 policy events

9. 生产最佳实践

9.1 Checklist

□ 先 Audit 摸清存量,再 Enforce 拦增量
□ 策略引擎多副本 + 就绪探针,慎重选 failurePolicy
□ 策略按对象类型收窄 match,控制性能
□ 建立策略测试集,本地/CI 先跑再上线
□ 用参数化模板,避免把字段写死进 Rego
□ 策略变更走 Git + 评审,先少数命名空间灰度
□ 定期审计策略命中报告,形成合规证据链

9.2 常见坑与对策

坑现象对策
failurePolicy=Fail 且挂了集群 apply 全锁死多副本 + 探针 + 评估 Fail/Ignore
策略太宽误杀正常业务先 Audit + 按命名空间灰度
Rego 跨对象查询性能暴跌收窄 scope、简化查询
规则无测试上线即误杀CI 跑 conftest/kyverno apply
双引擎决策不一致一套引擎为主

小结

策略即代码的核心是把"准入规则"从人肉 review 变成可测试、可审计、可灰度发布的代码。落地路径很清晰:先 Audit 摸清存量 → 定基线策略 → Enforce 拦增量 → 定期重扫存量 → 用 CI 预检把防线前移。工具选择上,YAML 原生的 Kyverno 上手最快,需要强表达力或已有 OPA 生态时选 Gatekeeper;无论选谁,都要记住三件事:策略引擎是高可用组件(多副本+探针)、策略先测试再上线、审计报告就是你的合规证据。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「云原生」更多文章

  1. Kubernetes 成本优化:FinOps、资源画像与降本实践
  2. 边缘与轻量 Kubernetes:K3s、KubeEdge 与资源受限环境
  3. Kubernetes 批处理:Job、CronJob 与工作队列