Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for DevOps Security & Hardening By James Joyner IV · · 8 min read

OPA/Gatekeeper vs Kyverno: Choosing a Kubernetes Policy Engine You'll Actually Maintain

Both engines block bad pods at admission time. The real question is which one your team can write, debug, and live with. Here's an honest comparison.

  • #security
  • #hardening
  • #kubernetes
  • #opa
  • #kyverno
  • #admission-control

Admission control is where Kubernetes security stops being aspirational and starts being enforced. A policy engine sits in front of the API server and rejects the pod that runs as root, the deployment without resource limits, the image from an untrusted registry. The two dominant choices are OPA/Gatekeeper and Kyverno. Both work. The decision that actually matters isn’t features — it’s which one your team can write and debug at 2am without dreading it.

I’ve run both in production. Here’s the comparison I give people when they ask which to pick.

The fundamental difference: Rego vs YAML

Gatekeeper uses Rego, the policy language from Open Policy Agent. Kyverno uses Kubernetes-native YAML. That single difference drives almost everything else.

A Gatekeeper policy to block privileged containers needs a ConstraintTemplate written in Rego:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8sdenyprivileged
spec:
  crd:
    spec:
      names:
        kind: K8sDenyPrivileged
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenyprivileged
        violation[{"msg": msg}] {
          c := input.review.object.spec.containers[_]
          c.securityContext.privileged
          msg := sprintf("privileged container not allowed: %v", [c.name])
        }

Then a separate constraint that uses the template. The same rule in Kyverno is one resource, no new language:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: deny-privileged
spec:
  validationFailureAction: Enforce
  rules:
    - name: privileged-containers
      match:
        any:
          - resources:
              kinds: ["Pod"]
      validate:
        message: "Privileged containers are not allowed."
        pattern:
          spec:
            containers:
              - =(securityContext):
                  =(privileged): "false"

For most teams, the Kyverno version is the one they can read in six months. That’s not nothing — the policy you can’t understand is the policy you’ll disable the first time it blocks a deploy.

When Rego earns its complexity

Rego looks like a tax until you hit a policy that needs real logic: cross-referencing multiple resources, set operations, complex conditionals, policies that reason about relationships between objects. Rego is a genuine query language; Kyverno’s pattern matching, while it has grown context lookups and JMESPath expressions, hits a ceiling sooner.

If your org already uses OPA outside Kubernetes — for API authorization, Terraform plan validation, CI gates — then Gatekeeper lets you standardize on one policy language across all of it. That consolidation is a real argument. A platform team fluent in Rego gets leverage; a product team that just wants pods to not run as root does not.

Capabilities beyond blocking

Kyverno does three things Gatekeeper historically didn’t, and they matter:

  • Mutation — inject default securityContext settings, add labels, set imagePullPolicy. Fix the manifest instead of just rejecting it.
  • Generation — auto-create NetworkPolicies, default ResourceQuotas, or PodDisruptionBudgets when a namespace appears.
  • Image verification — native cosign signature checks built in, no extra controller.

Gatekeeper has added mutation, but it’s the bolt-on, not the headline. If you want “every new namespace gets a default-deny NetworkPolicy automatically,” Kyverno does it in one policy.

Both ship a hardening baseline

You don’t have to author the basics yourself. Both projects ship the Pod Security Standards as ready policies — baseline and restricted profiles covering host namespaces, privilege escalation, dropped capabilities, read-only root filesystem, and so on. Start from those rather than reinventing. Apply the library in Audit/warn mode first, watch what would have been blocked for a week, then flip to Enforce. Skipping the audit phase is how you discover at 5pm on a Friday that half your DaemonSets need host networking.

Operational realities

A few things that only show up after you run these for a while:

  • Failure mode matters. Decide what happens when the policy webhook is down. failurePolicy: Fail means a broken policy controller blocks all deploys, including the fix. Ignore means policies silently stop being enforced. Both are bad in different ways — pick deliberately and monitor controller health.
  • Exclude system namespaces. kube-system and your CNI will violate restrictive policies. Scope policies to exclude them or you’ll wedge the cluster.
  • Test policies in CI. Both have CLI tools (gator for Gatekeeper, kyverno test/kyverno apply for Kyverno) to run policies against manifests before they hit the cluster. Use them — catch the violation in the PR, not at admission.

My actual recommendation

If you’re a product or platform team whose main goal is enforcing security baselines and you don’t already live in Rego: Kyverno. Lower cognitive load, native mutation and image verification, YAML your team already reads.

If you already run OPA elsewhere, need genuinely complex cross-resource logic, or want one policy language spanning Kubernetes, Terraform, and CI: Gatekeeper.

Either way, the engine is the easy part. The hard part is rolling policies out in audit mode, building the exemption process for legitimate exceptions, and resisting the urge to write fifty policies before you’ve gotten one to stick. Start with the Pod Security Standards baseline, enforce it, then expand.

More cluster hardening lives in our security and hardening guides. When a teammate’s PR adds or loosens a policy, the AI code review assistant helps catch the over-broad exclusion that quietly defeats the whole control.

Policy examples are starting points. Test against your own workloads in audit mode before enforcing, and tune exclusions for system namespaces.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.