饮墨

子安饮墨馀三斗,留与卿儿作赋来

Kyverno 实战:用 YAML 原生策略引擎替代 OPA Gatekeeper,5 步落地 Kubernetes 准入控制

痛点

Kubernetes 集群治理离不开准入控制策略——限制特权容器、强制资源 Limits、禁止 latest 标签等。传统方案 OPA Gatekeeper 功能强大,但 Rego 语言学习曲线陡峭,运维团队写一条策略往往要翻半天文档。ValidatingAdmissionPolicy(CEL)虽是原生方案,但仅支持验证、不支持资源变更(Mutate),且需要 K8s 1.30+ 才 GA。

核心矛盾:运维需要快速落地策略,但现有工具要么门槛高,要么能力不够。

Kyverno 用纯 YAML/JSON 编写策略,零学习新语言成本,同时覆盖 Validate/Mutate/Generate/Cleanup 四大场景,已成为 CNCF Graduated 项目。

方案

Kyverno 采用 Kubernetes-native 设计——策略本身就是 CRD(ClusterPolicy / Policy),运维像写 Deployment 一样写策略,kubectl apply 即生效。

核心能力矩阵:

能力 OPA Gatekeeper Kyverno ValidatingAdmissionPolicy
验证 (Validate) ✅ Rego ✅ YAML ✅ CEL
变更 (Mutate)
生成 (Generate)
清理 (Cleanup)
语言 Rego YAML CEL
最低 K8s 版本 1.16 1.25 1.30

实操步骤

第 1 步:安装 Kyverno(Helm)

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update

helm install kyverno kyverno/kyverno \
  --namespace kyverno --create-namespace \
  --set replicaCount=3 \
  --set admissionController.replicas=3 \
  --set backgroundController.replicas=2 \
  --set resources.limits.memory=512Mi \
  --set resources.limits.cpu=500m

生产环境建议至少 3 副本保证高可用,避免单点导致 API Server 请求阻塞。

第 2 步:禁止特权容器(Validate 策略)

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
  annotations:
    policies.kyverno.io/severity: high
spec:
  validationFailureAction: Enforce  # Audit 仅告警,Enforce 直接拒绝
  background: true
  rules:
  - name: deny-privileged
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "特权容器被禁止,请移除 securityContext.privileged 或设为 false"
      pattern:
        spec:
          containers:
          - securityContext:
              privileged: "!true"
kubectl apply -f disallow-privileged.yaml
# 测试:尝试创建特权 Pod
kubectl run test --image=nginx --overrides='{"spec":{"containers":[{"name":"test","image":"nginx","securityContext":{"privileged":true}}]}}'
# 预期输出: Error - admission webhook denied the request

第 3 步:自动注入资源 Limits(Mutate 策略)

开发者经常忘记设置资源限制,Kyverno 可自动注入默认值:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-resources
spec:
  rules:
  - name: add-default-limits
    match:
      any:
      - resources:
          kinds:
          - Pod
    mutate:
      patchStrategicMerge:
        spec:
          containers:
          - (name): "*"
            resources:
              limits:
                +(memory): "512Mi"
                +(cpu): "500m"
              requests:
                +(memory): "128Mi"
                +(cpu): "100m"

+() 语法表示「仅在字段不存在时添加」,不会覆盖已设置的值。

第 4 步:自动生成 NetworkPolicy(Generate 策略)

每个新 Namespace 自动创建默认拒绝入站流量的 NetworkPolicy:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: generate-default-deny-networkpolicy
spec:
  rules:
  - name: default-deny-ingress
    match:
      any:
      - resources:
          kinds:
          - Namespace
    exclude:
      any:
      - resources:
          namespaces:
          - kube-system
          - kyverno
    generate:
      synchronize: true
      apiVersion: networking.k8s.io/v1
      kind: NetworkPolicy
      name: default-deny-ingress
      namespace: "{{request.object.metadata.name}}"
      data:
        spec:
          podSelector: {}
          policyTypes:
          - Ingress

synchronize: true 确保策略源变更时自动同步到所有已生成资源。

第 5 步:策略报告与合规巡检

Kyverno 后台扫描已有资源并生成 PolicyReport CRD:

# 查看集群级策略报告
kubectl get clusterpolicyreport -o wide

# 查看某 Namespace 违规详情
kubectl get policyreport -n production -o yaml | grep -A5 "result: fail"

# 配合 Prometheus 采集策略指标
# Kyverno 内置 /metrics 端点,关键指标:
# kyverno_admission_requests_total{action="enforce|audit"}
# kyverno_policy_results_total{rule_result="pass|fail|warn"}

避坑指南

坑 1:Webhook 超时导致 API Server 请求全挂

Kyverno 宕机时 Webhook failurePolicy 默认 Fail,会阻塞所有资源创建。生产环境建议:

# Helm values
admissionController:
  failurePolicy: Ignore  # 宕机时放行,优于全集群不可用

同时配置 PDB 确保至少 2 副本存活。

坑 2:Mutate 策略顺序问题

多条 Mutate 策略可能互相冲突。用 spec.rules[].preconditions 做条件判断,并通过 Policy 的 annotation pod-policies.kyverno.io/autogen-controllers 控制自动生成逻辑。

坑 3:Background Scan 对大集群性能影响

超过 5000 Pod 的集群,首次全量扫描会占用大量内存。解决方案:

# 限制后台扫描并发
backgroundController:
  resources:
    limits:
      memory: 1Gi
# 或按 Namespace 分批启用
spec:
  background: false  # 先关闭后台扫描,仅对新资源生效

总结

Kyverno 的核心优势是零新语言成本——YAML 写策略、kubectl 管理、CRD 存储,完全融入 K8s 原生工作流。对于已有 OPA Gatekeeper 的团队,建议渐进迁移:先用 Kyverno 的 Mutate/Generate 能力补充 OPA 的短板,再逐步替换 Validate 策略。

推荐落地路径: Audit 模式上线 → PolicyReport 观测违规 → 逐步切 Enforce → 配合 CI 在 PR 阶段预检(kyverno apply --cluster=false)。

您还没有登录,请登录后发表评论。