“谁能部署什么、资源上限多少、镜像能不能带 latest 标签、secret 能不能明文”——这类规则如果靠人肉 review 或事后扫描,永远会漏。Kubernetes 的策略即代码(Policy-as-Code)把准入规则变成代码:在对象落库之前用 Webhook 拦截,不符合规则就拒绝。两大主流工具是 OPA Gatekeeper(Rego 语言)与 Kyverno(YAML 原生),本指南从准入控制原理讲起,深入两者的策略写法、合规(NIST/PCI)映射、测试与 CI 集成,以及性能与故障排查的实战经验。
目录
- 1. 准入控制与动态准入 Webhook
- 2. OPA Gatekeeper:ConstraintTemplate 与 Constraint
- 3. Gatekeeper 策略实战
- 4. Kyverno 策略即代码
- 5. Gatekeeper 与 Kyverno 对比
- 6. 从实践到合规:NIST 与 PCI
- 7. 策略测试与 CI 集成
- 8. 策略性能与故障排查
- 9. 生产最佳实践
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 Gatekeeper | Kyverno |
|---|---|---|
| 语言 | Rego(函数式) | YAML pattern |
| 学习成本 | 高(Rego 有门槛) | 低(纯 YAML) |
| 能力 | validate | validate/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;无论选谁,都要记住三件事:策略引擎是高可用组件(多副本+探针)、策略先测试再上线、审计报告就是你的合规证据。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。