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 ControllersKyverno
Requires Go programming knowledgeRequires only YAML
One controller per rule; hundreds needed at org scaleOne engine; unlimited policies as custom resources
Rule change = code change + redeployRule change = edit a YAML policy
Hard to distribute knowledge across a DevOps teamPolicies 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

CapabilityWhat It DoesExample Use Case
ValidateBlock or audit resources that don’t match a declared patternRequire resource requests/limits on every Pod
MutateRewrite resources at admission timeInject default labels, sidecars, or image registries
GenerateCreate companion resources when a trigger appearsAuto-create a NetworkPolicy for every new Namespace
Verify ImagesCheck image signatures and provenanceOnly 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 optional exclude block carves out exceptions.
  • validate.pattern — the shape the resource must conform to. Changing the rule means editing the pattern: requiring a label is a metadata.labels pattern; enforcing a naming convention is a name pattern.
  • ClusterPolicy vs Policy — 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:

ModeBehaviorWhen to Use
auditResource is created; violation recorded in Kyverno logs, policy reports, metrics, and alertsRolling out a new rule without breaking teams; compliance reporting
enforceThe admission webhook denies the API request; kubectl returns an error immediatelyMature 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 required

Kyverno 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 automatically

Installation

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 clusterpolicy

Dedicated-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

DimensionKyvernoOPA Gatekeeper
Policy languagePlain YAML (Kubernetes-native)Rego (general-purpose language)
Learning curveLow for K8s operatorsSteeper; Rego is a new language
CapabilitiesValidate, mutate, generate, verifyImagesValidate, mutate (via Assign)
Best fitKubernetes-only governanceMulti-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


Tags: kubernetes kyverno policy-as-code admission-controller governance devsecops security