Kyverno and OPA/Gatekeeper answer the same question: how to automatically validate or mutate a Kubernetes resource at admission time, before it enters the cluster. Both rely on the same underlying mechanism (an admission webhook), but express policy rules in two radically different languages.
Kyverno: policies in native YAML
Kyverno writes its rules in the same language as the rest of the Kubernetes ecosystem: declarative YAML, with no separate query language to learn.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Enforce
rules:
- name: check-limits
match:
resources:
kinds: [Pod]
validate:
message: "Every container must declare CPU and memory limits"
pattern:
spec:
containers:
- resources:
limits:
cpu: "?*"
memory: "?*"
This declarative syntax makes a simple policy readable by anyone already familiar with Kubernetes manifests, no detour through a third-party language. The trade-off shows up on complex rules (nested conditional logic, aggregation across multiple resources): the YAML quickly becomes as hard to follow as an overloaded Helm chart’s nested conditionals.
OPA/Gatekeeper: Rego, a dedicated query language
Gatekeeper embeds Open Policy Agent (OPA), a general-purpose policy engine used well beyond Kubernetes (API gateways, CI/CD, application authorization). Rules are written in Rego, a query language dedicated to policy evaluation:
package kubernetes.limits
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.cpu
msg := "Every container must declare a CPU limit"
}
Rego has a real learning curve, distinct from anything a Kubernetes engineer already knows. The benefit shows up on complex rules: Rego naturally expresses aggregation logic, policy composition, and unit tests (opa test) that stay artificial to simulate in pure YAML. The advantage pairs with portability: the same Rego policy can, in theory, apply beyond Kubernetes resources too.
The real criterion: rule complexity, not preference
A team writing mostly simple rules (forbidden resource types, required fields, mandatory labels) gets little benefit from Rego’s power and pays the learning cost with no real return: Kyverno solves that case in a few lines of YAML, readable by the whole team without dedicated training. A team that needs to express complex cross-resource rules (a constraint depending on several related objects, policy logic reused outside Kubernetes) finds in Rego an expressiveness Kyverno’s YAML pattern-matching was never meant to cover.
What stays the same regardless of the tool
The enforcement mode (Enforce, which blocks a non-compliant resource, versus Audit, which logs without blocking) exists in both tools, with the same progressive-rollout logic: start in audit mode on an existing cluster to measure real impact before blocking anything in production. Skipping that step and jumping straight to strict mode is the most common cause of a legitimate deployment blocked by a security policy nobody had tested against the cluster’s actual reality.
Takeaway
Kyverno and OPA/Gatekeeper validate the same Kubernetes admissions through two opposite languages: native YAML, immediately readable but limited on complex logic, versus Rego, more powerful but with a real learning curve. The deciding criterion is the actual complexity of the rules the team needs to express, not a syntax preference. Both deploy in audit mode before enforce, a discipline that matters more than the tool itself as part of a CI/CD industrialization.