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

Enforcing Kubernetes Policy With Kyverno Admission Rules

Reviews catch bad manifests inconsistently. Kyverno enforces your rules at admission time, in YAML, with no Rego to learn.

  • #kubernetes
  • #kyverno
  • #policy
  • #security
  • #admission-control
  • #governance

Every team I’ve worked with has a list of rules nobody enforces: don’t run as root, always set resource limits, never pull :latest, label everything with a cost-center. Those rules live in a wiki, get ignored under deadline pressure, and surface in a postmortem. Kyverno moves them out of the wiki and into the cluster’s admission path, where they’re enforced on every apply — and unlike its predecessors, you write them in plain YAML instead of learning a policy language. This is how I roll it out without breaking everyone’s deploys on day one.

What Kyverno does

Kyverno is a Kubernetes admission controller. When any resource is created or updated, the API server calls Kyverno, which checks the resource against your ClusterPolicy objects. It can do three things:

  • Validate — block resources that violate a rule (or just warn).
  • Mutate — fill in or fix fields automatically (add a default label, inject a securityContext).
  • Generate — create companion resources (a default NetworkPolicy for every new namespace).

The headline win over OPA/Gatekeeper is that policies are Kubernetes-native YAML. No Rego. Your team can read and write them without a new language.

Installing

helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
kubectl get pods -n kyverno

Start in Audit, not Enforce

This is the rule that keeps you employed: deploy every new policy in Audit mode first. Audit reports violations without blocking anything. You learn what would break before it breaks. Only after the reports are clean do you flip to Enforce.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Audit   # flip to Enforce once clean
  rules:
  - name: require-limits
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "CPU and memory limits are required."
      pattern:
        spec:
          containers:
          - resources:
              limits:
                memory: "?*"
                cpu: "?*"

The ?* pattern means “any non-empty value.” Apply this in Audit, watch the policy reports, and you’ll discover exactly how many existing workloads lack limits before you start rejecting them.

Reading the violations

kubectl get policyreport -A
kubectl get clusterpolicyreport

These reports are gold. They tell you the blast radius of a policy across everything already running, not just new applies. I let a policy sit in Audit for a sprint, drive the report to zero by fixing the offenders, then promote to Enforce.

A validate policy with teeth

Once you’re confident, enforce. Disallowing :latest image tags is a classic:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
spec:
  validationFailureAction: Enforce
  rules:
  - name: require-image-tag
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "Images must specify an explicit, non-latest tag."
      pattern:
        spec:
          containers:
          - image: "!*:latest"

Now any pod trying to use :latest is rejected at admission with a clear message. The rule is enforced uniformly, on every namespace, every time — no reviewer required.

Mutate to fix things automatically

Validation blocks bad input; mutation fixes it. Instead of rejecting pods that lack a securityContext, inject a safe default:

  rules:
  - name: default-security-context
    match:
      any:
      - resources:
          kinds: [Pod]
    mutate:
      patchStrategicMerge:
        spec:
          securityContext:
            runAsNonRoot: true
            seccompProfile:
              type: RuntimeDefault

Mutation is friendlier than validation for org-wide defaults — teams get the secure baseline for free instead of a wall of rejections. I use mutate for defaults and validate for hard prohibitions.

Generate to bootstrap namespaces

A favorite: every new namespace automatically gets a default-deny NetworkPolicy, so no namespace is ever born wide open.

  rules:
  - name: default-deny
    match:
      any:
      - resources:
          kinds: [Namespace]
    generate:
      apiVersion: networking.k8s.io/v1
      kind: NetworkPolicy
      name: default-deny
      namespace: "{{request.object.metadata.name}}"
      data:
        spec:
          podSelector: {}
          policyTypes: [Ingress, Egress]

This is policy that builds secure defaults rather than just rejecting insecure ones.

Rollout discipline

  • Scope your matches. A Pod policy with no exclusions also hits kube-system and your CNI pods. Exclude system namespaces, or you’ll wedge cluster components and lock yourself out.
  • Mind the failurePolicy. If Kyverno’s webhook is down and failurePolicy: Fail, admissions get blocked cluster-wide. Understand this tradeoff and ensure Kyverno is highly available before enforcing critically.
  • Exclude controllers thoughtfully. Some operators create pods that legitimately violate your rules. Use exclude blocks rather than weakening the policy for everyone.
  • Version-control policies. They’re as load-bearing as your application code. Treat them the same.

Because a single Enforce policy with a too-broad match can block every deploy in the cluster, get these reviewed before promoting them out of Audit. Our AI code review flags policies missing system-namespace exclusions and the kind of overbroad match that takes down kube-system.

Kyverno turns your “rules nobody follows” wiki page into enforced, auditable cluster behavior — written in the YAML your team already knows. For more security and governance guides, see the Kubernetes & Helm category.

Admission policies can block legitimate workloads. Always run new policies in Audit mode and review their scope against your own cluster before enforcing.

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.