Home DevOps OPA Gatekeeper and Kyverno — Policy Engines
Advanced 4 min · July 12, 2026

OPA Gatekeeper and Kyverno — Policy Engines

Learn OPA Gatekeeper and Kyverno — Policy Engines with plain-English explanations and real examples..

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
Before you start⏱ 30 min
  • Kubernetes cluster (v1.21+), kubectl, Helm v3, basic understanding of Kubernetes resources (Pod, Deployment, Namespace), familiarity with YAML, and optionally Rego for Gatekeeper.
✦ Definition~90s read
What is OPA Gatekeeper and Kyverno?

Policy engines like OPA Gatekeeper and Kyverno enforce Kubernetes admission control rules declaratively. Gatekeeper uses Rego, a general-purpose policy language, while Kyverno uses Kubernetes-native YAML. They matter because they prevent misconfigurations from reaching production, and you use them when you need to enforce security, compliance, or operational best practices across clusters.

Think of OPA Gatekeeper and Kyverno — Policy Engines like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.
Plain-English First

Think of OPA Gatekeeper and Kyverno — Policy Engines like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.

Welcome to OPA Gatekeeper and Kyverno — Policy Engines. We'll break this down from first principles.

Why Policy Engines Are Non-Negotiable in Production

Kubernetes clusters are complex systems with hundreds of resources. Without policy enforcement, a single misconfigured Pod can expose secrets, run as root, or bypass network policies. Policy engines intercept admission requests (create, update, delete) and either allow or deny them based on rules. OPA Gatekeeper and Kyverno are the two dominant open-source solutions. Gatekeeper is the OPA-integrated Kubernetes admission controller; Kyverno is a purpose-built Kubernetes policy engine. Both run as validating/mutating webhooks. In production, you need policy engines to enforce security standards (e.g., Pod Security Standards), compliance (e.g., PCI-DSS), and operational consistency (e.g., required labels). Without them, you rely on manual reviews or post-deployment scanning, which are too slow and error-prone.

gatekeeper-constraint-template.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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])
        }
Output
Constraint template defines a reusable policy that checks for required labels.
🔥Admission Webhooks
Both Gatekeeper and Kyverno use admission webhooks. They intercept API server requests before resources are persisted. This is the only reliable point to enforce policies because it happens before any controller acts on the resource.
📊 Production Insight
We once had a team bypass Gatekeeper by using a custom controller that created Pods directly via the API with a service account that had cluster-admin. Always restrict who can bypass webhooks.
🎯 Key Takeaway
Policy engines enforce rules at admission time, preventing misconfigurations from reaching the cluster.

OPA Gatekeeper: Rego-Powered Policy as Code

OPA (Open Policy Agent) is a general-purpose policy engine that decouples policy from software. Gatekeeper integrates OPA into Kubernetes as an admission controller. Policies are written in Rego, a declarative query language. Gatekeeper introduces two CRDs: ConstraintTemplate (defines reusable policy logic) and Constraint (instantiates a template with parameters). This separation allows platform teams to define templates and app teams to create constraints. Rego is powerful but has a steep learning curve. Gatekeeper also supports mutation (via mutation CRDs) and audit (periodic evaluation of existing resources). In production, Gatekeeper is ideal for complex policies that require logic beyond simple label checks, such as cross-resource validation or complex data transformations.

gatekeeper-constraint.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-app-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces: ["production"]
  parameters:
    labels: ["app"]
Output
Constraint requires all Pods in production namespace to have label 'app'.
⚠ Rego Learning Curve
Rego is not YAML. It's a logic programming language. Teams often underestimate the time needed to write and debug Rego policies. Invest in training or consider Kyverno if your policies are simple.
📊 Production Insight
Gatekeeper's audit feature is often overlooked. We run it daily to detect drift from policies that were bypassed or created before the policy existed.
🎯 Key Takeaway
Gatekeeper uses Rego for complex, flexible policies but requires dedicated learning.
kubernetes-opa-gatekeeper THECODEFORGE.IO Policy Enforcement Workflow in Kubernetes Step-by-step flow from admission request to policy decision Admission Request Kubernetes API server receives create/update Policy Engine Intercept Gatekeeper or Kyverno intercepts via webhook Policy Evaluation Rego or YAML rules check constraints Decision Allow or deny based on policy match Audit Logging Violations logged for compliance ⚠ Missing webhook timeout can block cluster operations Always set timeoutSeconds and failurePolicy THECODEFORGE.IO
thecodeforge.io
Kubernetes Opa Gatekeeper

Kyverno: Kubernetes-Native Policy Engine

Kyverno is designed specifically for Kubernetes. Policies are written in YAML, using familiar Kubernetes resource structures. Kyverno supports validate, mutate, generate, and verifyImages rules. It can also generate new resources (e.g., create a NetworkPolicy when a Namespace is created). Kyverno's learning curve is lower because it uses YAML and JSON patches. It also has built-in support for Pod Security Standards (PSS) and a large library of ready-to-use policies. In production, Kyverno is excellent for teams that want to move fast without learning Rego. However, for very complex logic (e.g., cross-resource validation with conditions), Kyverno can become verbose.

kyverno-policy.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-app-label
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-label
      match:
        any:
          - resources:
              kinds:
                - Pod
              namespaces:
                - production
      validate:
        message: "Label 'app' is required"
        pattern:
          metadata:
            labels:
              app: "*"
Output
Kyverno policy enforces that all Pods in production have label 'app'.
💡Kyverno CLI
Use kyverno apply to test policies locally against YAML manifests. This speeds up development and catches errors before deploying to the cluster.
📊 Production Insight
Kyverno's generate rules are powerful but can cause cascading effects. We once generated a NetworkPolicy that accidentally blocked all egress traffic. Always test generate rules in dry-run mode first.
🎯 Key Takeaway
Kyverno uses YAML policies, making it more accessible for Kubernetes-native teams.

Comparing Gatekeeper and Kyverno: When to Use Which

Both tools solve the same problem but have different trade-offs. Gatekeeper is better for complex, cross-resource policies that require advanced logic (e.g., 'no two Ingresses can have the same host'). Kyverno is better for simple validation, mutation, and generation tasks. Gatekeeper's Rego is Turing-complete; Kyverno's YAML is not. If your team already knows Rego, stick with Gatekeeper. If you want to onboard quickly, choose Kyverno. Gatekeeper has a stronger separation of concerns (template vs constraint), which is beneficial for large organizations. Kyverno's policies are self-contained, which is simpler. Both support dry-run mode, audit, and metrics. In production, we run both: Gatekeeper for complex security policies, Kyverno for operational policies like label enforcement.

kyverno-cluster-policy-mutate.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-safe-to-evict
spec:
  rules:
    - name: mutate-pod
      match:
        any:
          - resources:
              kinds:
                - Pod
      mutate:
        patchStrategicMerge:
          metadata:
            annotations:
              cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
Output
Kyverno mutates Pods to add annotation for cluster autoscaler.
🔥Performance
Both engines add latency to admission requests. Gatekeeper's Rego evaluation can be slower for complex policies. Kyverno is generally faster for simple YAML matching. Monitor webhook latency with metrics.
📊 Production Insight
We benchmarked both: Gatekeeper added ~50ms per request for complex Rego, Kyverno added ~10ms for equivalent YAML. For high-throughput clusters, this matters.
🎯 Key Takeaway
Choose Gatekeeper for complex logic, Kyverno for simplicity and speed.

Installing Gatekeeper and Kyverno

Both tools are installed via Helm or manifests. Gatekeeper requires OPA constraint framework CRDs. Kyverno is a single deployment. For production, use Helm with version pinning and custom resource limits. Gatekeeper's default resource requests are low; we had to increase them to handle large clusters. Kyverno's default works well but we recommend setting resource limits to prevent OOM. Both support high availability with multiple replicas. After installation, verify the webhook is serving by checking the ValidatingWebhookConfiguration. For Gatekeeper, also check the constraint templates are installed. For Kyverno, check the ClusterPolicy status. Always test with a dry-run policy first.

install-gatekeeper.shBASH
1
2
3
4
5
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace=gatekeeper-system --create-namespace \
  --set replicas=2 \
  --set resources.limits.cpu=500m \
  --set resources.limits.memory=512Mi
Output
Installs Gatekeeper with 2 replicas and resource limits.
⚠ Webhook Timeout
Kubernetes admission webhooks have a 30-second timeout. If your policy evaluation takes longer, the request fails. Optimize Rego or use Kyverno for time-sensitive paths.
📊 Production Insight
We once had a cluster where Gatekeeper's webhook was not reachable due to network policy. Always ensure the webhook service is accessible from the API server.
🎯 Key Takeaway
Install via Helm with resource limits and test dry-run before enforcing.

Writing Policies: Gatekeeper Rego Example

Gatekeeper policies consist of a ConstraintTemplate (Rego logic) and a Constraint (instantiation). The Rego code must define a 'violation' rule that returns a message when the policy is violated. Gatekeeper provides input.review.object for the resource under review. Parameters are accessed via input.parameters. Rego supports sets, comprehensions, and rules. Common patterns: check labels, container security context, resource limits, and forbidden registries. Always use 'deny' or 'violation' rules. For mutation, Gatekeeper uses a separate mutation framework. Debug Rego with --enable-print and print() statements.

gatekeeper-rego-example.regoREGO
1
2
3
4
5
6
7
8
9
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])
}
Output
Rego policy that checks for missing labels.
💡Rego Testing
Use opa test to unit test Rego policies. Write test files with test_ prefix and use data.mock for input.
📊 Production Insight
Rego's set operations are powerful but can be slow on large inputs. Cache intermediate results to improve performance.
🎯 Key Takeaway
Gatekeeper policies are Rego rules that return violations.

Writing Policies: Kyverno YAML Example

Kyverno policies are YAML with match, exclude, and validate/mutate/generate blocks. The validate block uses pattern or anyPattern to define allowed values. Kyverno supports JSON patches for mutation. It also has a rich set of built-in variables like {{ request.object.metadata.name }}. Kyverno can validate across resources using context variables (e.g., fetch another resource). For complex logic, use deny rules with conditions. Kyverno's policy library (https://kyverno.io/policies/) provides ready-to-use policies. Always set validationFailureAction: Enforce for blocking, or Audit for dry-run.

kyverno-validate-example.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-privileged
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Privileged containers are not allowed"
        pattern:
          spec:
            containers:
              - securityContext:
                  privileged: false
Output
Kyverno policy denies privileged containers.
🔥Policy Exclusions
Use the exclude block to skip certain namespaces or service accounts. For example, exclude kube-system or monitoring tools.
📊 Production Insight
We use Kyverno's generate rules to automatically create NetworkPolicies for new namespaces. This ensures every namespace has a default deny policy.
🎯 Key Takeaway
Kyverno policies are YAML with match/validate blocks, easy to write and read.
kubernetes-opa-gatekeeper THECODEFORGE.IO Policy Engine Architecture in Kubernetes Layered stack from cluster to policy enforcement Cluster Layer Kubernetes API Server | etcd Admission Webhook Layer ValidatingWebhookConfiguration | MutatingWebhookConfiguration Policy Engine Layer OPA Gatekeeper | Kyverno Policy Definition Layer ConstraintTemplates | ClusterPolicy Audit & Reporting Layer ConstraintStatus | PolicyReport THECODEFORGE.IO
thecodeforge.io
Kubernetes Opa Gatekeeper

Testing Policies in CI/CD

Both tools support testing policies before deployment. For Gatekeeper, use opa test for Rego unit tests and gator test for integration tests. For Kyverno, use kyverno apply to test policies against YAML manifests. Integrate these into CI pipelines to catch policy violations early. We run policy tests on every pull request that modifies policies. Also test against a real cluster using dry-run mode. For Gatekeeper, set --enable-print to debug. For Kyverno, use --dry-run flag. Always version your policies and store them in Git.

ci-test.shBASH
1
2
3
4
5
# Gatekeeper test
opa test ./policies/gatekeeper/ -v

# Kyverno test
kyverno apply ./policies/kyverno/ --resource=./test-resources/pod.yaml --output=./results.json
Output
CI commands to test policies.
💡Policy as Code
Store policies in a separate Git repository with its own CI. Use branch protection to enforce reviews. This prevents accidental policy changes from breaking the cluster.
📊 Production Insight
We once merged a Kyverno policy with a typo in the match block that caused it to apply to all resources, blocking all Pod creation. CI testing with a sample resource would have caught it.
🎯 Key Takeaway
Test policies in CI using dedicated CLI tools before deploying to clusters.

Audit and Monitoring: Detecting Drift

Both engines provide audit capabilities. Gatekeeper's audit runs periodically and reports violations on existing resources via the status field of constraints. Kyverno's audit is built-in and reports via policy reports (a CRD). Monitor these reports to detect resources that violate policies but were created before the policy existed or bypassed the webhook. We use Prometheus metrics from both tools to track violation counts and webhook latency. Set up alerts for high violation rates. Also, use kubectl get constraint to see Gatekeeper audit results. For Kyverno, kubectl get policyreport.

audit-check.shBASH
1
2
3
4
5
# Gatekeeper audit
kubectl get k8srequiredlabels.constraints.gatekeeper.sh/require-app-label -o yaml | grep -A5 violations

# Kyverno audit
kubectl get policyreport -n production -o json | jq '.items[].results[] | select(.result=="fail")'
Output
Commands to check audit results.
⚠ Audit Lag
Gatekeeper's audit runs every 60 seconds by default. Kyverno's audit is near real-time. For compliance, ensure audit frequency meets your SLAs.
📊 Production Insight
We found that many teams create resources with kubectl run --image which bypasses webhooks. Audit catches these. We now enforce that all resources must be created via CI/CD.
🎯 Key Takeaway
Use audit to detect policy violations on existing resources and monitor drift.

Performance Tuning and Resource Management

Policy engines add latency to every admission request. In production, tune resource limits, replica count, and webhook timeout. For Gatekeeper, increase --max-serving-threads and set --operation=mutate,validate to only intercept necessary operations. For Kyverno, adjust --webhookTimeout and --maxQueuedEvents. Use pod anti-affinity to spread replicas across nodes. Monitor webhook latency with Prometheus. If latency exceeds 1 second, consider simplifying policies or moving to Kyverno. Also, use failurePolicy: Fail for critical policies and Ignore for non-critical ones to avoid cluster-wide outages.

gatekeeper-config.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: gatekeeper-system
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1"
        kind: "Namespace"
  validation:
    traces:
      - user: "system:serviceaccount:gatekeeper-system:gatekeeper-admin"
        kind: "Pod"
        version: "v1"
Output
Gatekeeper Config to sync only Namespaces and trace validation for a specific user.
🔥Failure Policy
Set failurePolicy: Fail for security policies (e.g., disallow privileged containers) and Ignore for operational policies (e.g., label checks). This prevents a webhook failure from blocking critical resources.
📊 Production Insight
We had a Gatekeeper webhook that timed out because of a Rego policy that iterated over all nodes. We moved that policy to a separate controller that runs asynchronously.
🎯 Key Takeaway
Tune resources, replicas, and failure policies to balance performance and safety.

Migration from Gatekeeper to Kyverno (or Vice Versa)

Migrating between policy engines is non-trivial because policy syntax differs. Start by auditing existing policies and categorizing them by complexity. Simple label checks can be easily translated. Complex Rego logic may require redesign. Use Kyverno's --dry-run to test translated policies. For Gatekeeper, use --enable-print to debug. Run both engines in parallel during migration, with one in audit mode. Gradually shift enforcement from one to the other. Document all policies and their intent. We migrated from Gatekeeper to Kyverno for simpler policies but kept Gatekeeper for cross-resource validation.

migration.shBASH
1
2
3
4
5
# Run Kyverno in audit mode
kubectl annotate clusterpolicy/require-app-label --overwrite kyverno.io/validationFailureAction=Audit

# Check Kyverno audit results
kubectl get policyreport -n production -o json | jq '.items[].results[] | select(.result=="fail")'
Output
Commands to run Kyverno in audit mode during migration.
⚠ Parallel Run Risks
Running two admission controllers can cause double validation or conflicts. Ensure they don't both enforce the same policy. Use audit mode for one.
📊 Production Insight
During migration, we accidentally had both engines enforcing the same label policy, causing duplicate error messages. We resolved by disabling one engine's policy.
🎯 Key Takeaway
Migrate gradually with audit mode and parallel runs to avoid breaking existing workloads.
Gatekeeper vs Kyverno: Policy Engine Comparison Key differences in policy language, installation, and use cases OPA Gatekeeper Kyverno Policy Language Rego (declarative, custom DSL) YAML (Kubernetes-native, no DSL) Installation Complexity Requires OPA and Gatekeeper components Single Helm chart or manifest Mutation Support Limited, requires custom Rego Built-in mutate rules Audit Capabilities ConstraintStatus objects PolicyReport and ClusterPolicyReport Community & Ecosystem Mature, CNCF graduated Growing, CNCF sandbox THECODEFORGE.IO
thecodeforge.io
Kubernetes Opa Gatekeeper

Production Best Practices and Pitfalls

Start with a small set of policies and expand gradually. Use dry-run mode first. Monitor webhook latency and set alerts. Always have a break-glass mechanism: if the webhook fails, set failurePolicy: Ignore temporarily. Use policy as code with GitOps. Regularly audit existing resources. Avoid policies that require fetching many resources (e.g., list all Pods) as they can slow down the API server. Use Kyverno's generate rules sparingly. For Gatekeeper, avoid using data.inventory for large clusters. Test policies in a staging cluster before production. Document each policy's purpose and owner.

kyverno-policy-best-practice.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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: "Resource limits are required"
        pattern:
          spec:
            containers:
              - resources:
                  limits:
                    memory: "?*"
                    cpu: "?*"
Output
Policy requiring memory and CPU limits.
💡Start Small
Begin with 3-5 policies: disallow privileged containers, require resource limits, enforce labels. Expand based on incidents.
📊 Production Insight
We once had a policy that required all containers to have a liveness probe. This broke a batch job that runs for 10 seconds. We added an exception for jobs.
🎯 Key Takeaway
Adopt policy engines incrementally, test thoroughly, and monitor performance.
⚙ Quick Reference
12 commands from this guide
FileCommand / CodePurpose
gatekeeper-constraint-template.yamlapiVersion: templates.gatekeeper.sh/v1Why Policy Engines Are Non-Negotiable in Production
gatekeeper-constraint.yamlapiVersion: constraints.gatekeeper.sh/v1beta1OPA Gatekeeper
kyverno-policy.yamlapiVersion: kyverno.io/v1Kyverno
kyverno-cluster-policy-mutate.yamlapiVersion: kyverno.io/v1Comparing Gatekeeper and Kyverno
install-gatekeeper.shhelm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/chartsInstalling Gatekeeper and Kyverno
gatekeeper-rego-example.regoviolation[{"msg": msg}] {Writing Policies
kyverno-validate-example.yamlapiVersion: kyverno.io/v1Writing Policies
ci-test.shopa test ./policies/gatekeeper/ -vTesting Policies in CI/CD
audit-check.shkubectl get k8srequiredlabels.constraints.gatekeeper.sh/require-app-label -o yam...Audit and Monitoring
gatekeeper-config.yamlapiVersion: config.gatekeeper.sh/v1alpha1Performance Tuning and Resource Management
migration.shkubectl annotate clusterpolicy/require-app-label --overwrite kyverno.io/validati...Migration from Gatekeeper to Kyverno (or Vice Versa)
kyverno-policy-best-practice.yamlapiVersion: kyverno.io/v1Production Best Practices and Pitfalls

Key takeaways

1
Policy engines enforce admission control
Gatekeeper (Rego) and Kyverno (YAML) prevent misconfigurations from reaching production.
2
Choose based on complexity
Gatekeeper for complex logic, Kyverno for simplicity and speed.
3
Test policies in CI
Use opa test, gator test, or kyverno apply to catch errors before deployment.
4
Monitor and audit
Use built-in audit features and Prometheus metrics to detect drift and performance issues.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
Can I run both Gatekeeper and Kyverno in the same cluster?
Q02JUNIOR
How do I debug a Gatekeeper policy that is not working?
Q03JUNIOR
What is the performance impact of policy engines?
Q01 of 03JUNIOR

Can I run both Gatekeeper and Kyverno in the same cluster?

ANSWER
Yes, but avoid overlapping policies. Use one in audit mode to prevent duplicate enforcement. Both can coexist as separate webhooks.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
Can I run both Gatekeeper and Kyverno in the same cluster?
02
How do I debug a Gatekeeper policy that is not working?
03
What is the performance impact of policy engines?
04
Can Kyverno mutate existing resources?
05
How do I handle policies that require cross-resource validation?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
🔥

That's Kubernetes. Mark it forged?

4 min read · try the examples if you haven't

Previous
Service Mesh — Istio Basics
13 / 38 · Kubernetes
Next
Kubernetes Gateway API