Kubernetes Policy Enforcement and Exceptions
Admission policies are how platform teams turn rules into guarantees: no privileged containers, every container has a memory limit, images come only from approved registries, every workload has an owner label. Written well, they prevent whole classes of incidents. Rolled out carelessly, they cause incidents of their own — a new policy blocks a critical deployment at 2 a.m., a webhook outage stops every pod from being created, or a long list of permanent exceptions quietly makes the policy meaningless.
This page covers the policy engines available, how to roll policies out in stages, how to manage exceptions so they stay rare and temporary, and how to diagnose a deployment that policy has blocked.
TL;DR
- Built-in options: Pod Security Admission (three standard profiles) and ValidatingAdmissionPolicy (CEL expressions, no webhook).
- Engines: Kyverno (YAML policies, mutation, generation, exceptions) and OPA Gatekeeper (Rego constraints).
- Roll out in stages: audit → warn → enforce, namespace by namespace, with reports of current violations.
- Exceptions must be scoped (namespace, workload, rule), owned, justified, and expiring.
- Webhook-based engines need high availability and deliberate failure policies, or they can block the cluster.
- Blocked pods often surface on the ReplicaSet, not the Deployment — check events there.
Quick Example
A built-in ValidatingAdmissionPolicy requiring memory limits, bound first in warn-and-audit mode for namespaces in rollout:
A scoped, expiring exception with Kyverno:
Core Concepts
Policy Options
See Kyverno and Infrastructure Drift and Policy as Code.
Enforcement Modes
Admission only sees creates and updates. Existing workloads that violate a new policy keep running until they are next changed — at which point they suddenly fail to deploy. Background reports reveal them in advance.
Exceptions
An exception should answer: which rule, which namespace and workloads, who owns it, why, and until when. Keep exceptions in Git next to the policies, review them like code, and alert or fail CI when an expiry date passes. Broad exceptions (whole namespaces, all rules) and undated ones are where policy programs decay.
Staged Rollout
- Write the policy with tests — sample manifests that must pass and fail — and run them in CI.
- Audit cluster-wide and publish the violation report per team.
- Warn in all namespaces so developers see messages in
kubectland pipelines. - Fix or file exceptions for remaining violations, with owners and dates.
- Enforce namespace by namespace, starting with new or low-risk ones.
- Shift left: run the same policies in CI against rendered manifests (for example
kyverno applyorgator test), so failures appear before deploy.
Diagnosing Blocked Deployments
kubectl apply --dry-run=server runs admission, including policies, without persisting anything — a useful pre-deploy check.
Webhook Availability
Webhook-based engines sit in the critical path of the API server. Run them with multiple replicas, PodDisruptionBudgets, and priority classes; exclude system namespaces so the cluster can recover if the webhook is down; set short timeouts; and choose failurePolicy per policy — Fail for security-critical rules, Ignore for hygiene rules where availability matters more.
Best Practices
Start With Pod Security Admission
Label namespaces with the restricted or baseline profile before writing custom policies; it covers the most important pod security controls with no extra components.
Write Actionable Messages
Every violation message should say what is wrong, how to fix it, and where to read more. Developers fix clear messages quickly and escalate vague ones.
Treat Policies as Code
Version policies and exceptions in Git, test them, review changes, and deploy them through the same pipeline as other platform components.
Report Exceptions Regularly
Publish counts of active, expiring, and expired exceptions per team. Visibility keeps exceptions temporary.
Common Mistakes
Enforcing on Day One
Permanent, Broad Exceptions
Unprotected Webhooks
FAQ
What is the difference between Pod Security Admission and Kyverno?
Pod Security Admission is built into Kubernetes and enforces three predefined pod security profiles per namespace. Kyverno is an add-on policy engine for arbitrary custom rules, mutation, resource generation, image verification, and managed exceptions.
What is ValidatingAdmissionPolicy?
A built-in Kubernetes API for admission validation using CEL expressions, evaluated inside the API server without running a webhook. Bindings attach policies to resources and choose actions such as Deny, Warn, or Audit.
How do I roll out a new policy without breaking deployments?
Start in audit mode to measure violations, move to warn so teams see messages, fix or grant scoped exceptions, then enforce gradually by namespace — and check the same policy in CI before deploy.
Why did my Deployment not create pods even though apply succeeded?
The Deployment object passed admission, but the ReplicaSet's pod creation was denied by a policy that matches pods. Look at events on the ReplicaSet with kubectl describe rs.
How should policy exceptions be managed?
Scope each to specific rules and workloads, record an owner, reason, and expiry date, keep it in version control, and alert when it expires so it is renewed deliberately or removed.
Related Topics
- Kubernetes — Admission in the API request flow
- Kyverno — Kubernetes-native policy engine
- Infrastructure Drift and Policy as Code — Policy across infrastructure
- Kubernetes Multi-Tenant Isolation — Policies as tenant guardrails
- Container Security — The controls policies enforce
- CI Pipeline Design and Quality Gates — Checking policies before deploy