OPA Gatekeeper and Kyverno — Policy Engines
Learn OPA Gatekeeper and Kyverno — Policy Engines with plain-English explanations and real examples..
20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.
- ✓Kubernetes cluster (v1.21+), kubectl, Helm v3, basic understanding of Kubernetes resources (Pod, Deployment, Namespace), familiarity with YAML, and optionally Rego for Gatekeeper.
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.
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.
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 apply to test policies locally against YAML manifests. This speeds up development and catches errors before deploying to the cluster.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.
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.
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 statements.print()
opa test to unit test Rego policies. Write test files with test_ prefix and use data.mock for input.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.
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.
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.
kubectl run --image which bypasses webhooks. Audit catches these. We now enforce that all resources must be created via CI/CD.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.
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.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.
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.
| File | Command / Code | Purpose |
|---|---|---|
| gatekeeper-constraint-template.yaml | apiVersion: templates.gatekeeper.sh/v1 | Why Policy Engines Are Non-Negotiable in Production |
| gatekeeper-constraint.yaml | apiVersion: constraints.gatekeeper.sh/v1beta1 | OPA Gatekeeper |
| kyverno-policy.yaml | apiVersion: kyverno.io/v1 | Kyverno |
| kyverno-cluster-policy-mutate.yaml | apiVersion: kyverno.io/v1 | Comparing Gatekeeper and Kyverno |
| install-gatekeeper.sh | helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts | Installing Gatekeeper and Kyverno |
| gatekeeper-rego-example.rego | violation[{"msg": msg}] { | Writing Policies |
| kyverno-validate-example.yaml | apiVersion: kyverno.io/v1 | Writing Policies |
| ci-test.sh | opa test ./policies/gatekeeper/ -v | Testing Policies in CI/CD |
| audit-check.sh | kubectl get k8srequiredlabels.constraints.gatekeeper.sh/require-app-label -o yam... | Audit and Monitoring |
| gatekeeper-config.yaml | apiVersion: config.gatekeeper.sh/v1alpha1 | Performance Tuning and Resource Management |
| migration.sh | kubectl annotate clusterpolicy/require-app-label --overwrite kyverno.io/validati... | Migration from Gatekeeper to Kyverno (or Vice Versa) |
| kyverno-policy-best-practice.yaml | apiVersion: kyverno.io/v1 | Production Best Practices and Pitfalls |
Key takeaways
opa test, gator test, or kyverno apply to catch errors before deployment.Interview Questions on This Topic
Can I run both Gatekeeper and Kyverno in the same cluster?
Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Lessons pulled from things that broke in production.
That's Kubernetes. Mark it forged?
4 min read · try the examples if you haven't