Kyverno
Kyverno is a Kubernetes-native policy engine — a dynamic admission controller that lets platform teams enforce, mutate, generate, and audit cluster configurations using plain YAML policies instead of hand-written Go admission controllers. It is the policy-as-code answer to Kubernetes governance: organizational compliance rules expressed as versioned custom resources. Source: Enforce Kubernetes Security with Kyverno
The Problem Kyverno Solves
Every organization has compliance rules for its clusters: no :latest image tags, mandatory resource requests and limits, required labels, per-team Namespace quotas. Governance is the continuous process of verifying that every resource created in the cluster follows these standards.
Kubernetes provides admission controllers as the enforcement point, but writing custom ones means writing Go controllers, deploying them, and maintaining one per rule:
| Hand-Written Admission Controllers | Kyverno |
|---|---|
| Requires Go programming knowledge | Requires only YAML |
| One controller per rule; hundreds needed at org scale | One engine; unlimited policies as custom resources |
| Rule change = code change + redeploy | Rule change = edit a YAML policy |
| Hard to distribute knowledge across a DevOps team | Policies are self-documenting and shareable |
Kyverno runs as a controller in its own kyverno Namespace, watches for Policy/ClusterPolicy custom resources, and automatically generates the validating/mutating webhook configurations that intercept requests at the kube-apiserver — the final stage of the API request pipeline.
The Four Capabilities
| Capability | What It Does | Example Use Case |
|---|---|---|
| Validate | Block or audit resources that don’t match a declared pattern | Require resource requests/limits on every Pod |
| Mutate | Rewrite resources at admission time | Inject default labels, sidecars, or image registries |
| Generate | Create companion resources when a trigger appears | Auto-create a NetworkPolicy for every new Namespace |
| Verify Images | Check image signatures and provenance | Only allow Cosign-signed images in production |
Start with validate — it is the highest-value capability and the simplest to reason about. The others layer on top of the same policy structure. Source: Enforce Kubernetes Security with Kyverno
Policy Anatomy
A policy’s spec divides into rules: each rule has a match block (which resources it applies to) and an action block (validate, mutate, or generate):
apiVersion: kyverno.io/v1
kind: ClusterPolicy # cluster-wide; use Policy for namespace-scoped
metadata:
name: require-requests-limits
annotations:
policies.kyverno.io/description: >-
Every Pod must declare CPU/memory requests and limits.
spec:
validationFailureAction: enforce # enforce = block; audit = record only
rules:
- name: validate-resources
match:
resources:
kinds: [Pod]
validate:
pattern:
spec:
containers:
- resources:
requests: {}
limits: {}match.resources.kinds— the API objects the rule targets (Pod, Deployment, Namespace, …). An optionalexcludeblock carves out exceptions.validate.pattern— the shape the resource must conform to. Changing the rule means editing the pattern: requiring a label is ametadata.labelspattern; enforcing a naming convention is anamepattern.ClusterPolicyvsPolicy— ClusterPolicy monitors all Namespaces; Policy is bound to one.
The kyverno/policies repository ships a large catalog of ready-made examples (require-*, add-*, restrict-*) — learning the pattern language against these examples takes roughly an hour. Source: Enforce Kubernetes Security with Kyverno
Audit vs Enforce
validationFailureAction controls what happens when a resource violates the policy:
| Mode | Behavior | When to Use |
|---|---|---|
audit | Resource is created; violation recorded in Kyverno logs, policy reports, metrics, and alerts | Rolling out a new rule without breaking teams; compliance reporting |
enforce | The admission webhook denies the API request; kubectl returns an error immediately | Mature rules that must never be violated |
The rollout pattern is audit → observe → enforce. In enforce mode, creating a non-compliant resource fails at admission time:
$ kubectl create deployment nginx --image=nginx
# → admission webhook "validate.kyverno.svc" denied the request:
# resource requests and limits are requiredKyverno also performs continuous background scanning: existing resources created before a policy was activated are evaluated and reported, not just new admission requests. Source: Enforce Kubernetes Security with Kyverno
GitOps: Managing Policies with Argo CD
Policies are YAML, so they belong in Git. Storing ClusterPolicy manifests in a repository and syncing them with Argo CD turns compliance changes into pull requests — with review, diff, audit trail, and rollback. This is the policy-as-code principle from DevSecOps Fundamentals applied to cluster governance, and it inherits the hardening practices of GitOps Security:
# Manual tier: apply policies directly
kubectl apply -f enforce-pod-requests-limits.yml
# GitOps tier: Argo CD Application watching a policies/ directory
# → every merged PR updates cluster enforcement automaticallyInstallation
Kyverno installs via raw manifests or its Helm chart:
# Manifests
kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/main/config/install.yaml
# Helm
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
# Verify the controller
kubectl get pods -n kyverno
kubectl get clusterpolicyDedicated-namespace installation (kyverno) keeps controller resources isolated for metrics, RBAC, and operational clarity — the same pattern used for Argo CD and other cluster add-ons.
Kyverno vs OPA Gatekeeper
| Dimension | Kyverno | OPA Gatekeeper |
|---|---|---|
| Policy language | Plain YAML (Kubernetes-native) | Rego (general-purpose language) |
| Learning curve | Low for K8s operators | Steeper; Rego is a new language |
| Capabilities | Validate, mutate, generate, verifyImages | Validate, mutate (via Assign) |
| Best fit | Kubernetes-only governance | Multi-system policy (K8s + Terraform + APIs) |
Both appear in the deploy-time control tier of a shift-left pipeline and the defense-in-depth stack. Kyverno’s differentiator is that Kubernetes operators already speak YAML.
Preventive vs detective: Kyverno acts before a resource is persisted (admission-time prevention); Falco acts after the workload is running (syscall-level runtime detection). A hardened cluster runs both — policy keeps bad configurations out, runtime detection catches bad behavior that gets in. Source: Falco CKS Scenarios
See Also
- Kubernetes Admission Controllers — the interception layer Kyverno automates
- Kubernetes Resource Requests and Limits — the canonical first policy target
- Kubernetes Namespaces — multi-tenancy boundary that policies govern
- Kubernetes Authentication & Authorization — admission control in the API pipeline
- DevSecOps Fundamentals — policy-as-code as a core principle
- Shift Left Security — admission control as deploy-time gate
- Container Security — Kyverno in the defense-in-depth deploy layer
- GitOps Security — securing the Git repo that holds policies
- Helm — Kyverno’s Helm chart installation path
- Falco — the runtime-detection counterpart to admission-time policy
- Runtime Security — the detection phase that complements admission control
- Abhishek Veeramalla — creator of the Kyverno security project source
- Enforce Kubernetes Security with Kyverno — the source video and project walkthrough
- Falco for Kubernetes Security — CKS Scenarios — runtime detection companion video
Tags: kubernetes kyverno policy-as-code admission-controller governance devsecops security