Authorization tells Kubernetes what you are allowed to do. There is a third gate before a request is accepted: admission control. Even after successful authentication and authorization, requests must pass through admission controllers. This is where much platform governance lives — injecting defaults, enforcing quotas, validating configuration, mutating objects, and denying non-compliant requests.
Admission controllers run after authentication and authorization but before objects are persisted to etcd. Some admission controllers mutate objects (mutating admission controllers), while others only allow or deny requests (validating admission controllers).
Which admission plugins are active?
On many clusters the kube-apiserver runs as a pod. Inspect the kube-apiserver help output to see admission-related flags and which plugins are enabled. For example:--admission-control help text and the newer --enable-admission-plugins output. The important point for this demo: LimitRanger (a mutating admission controller) and ResourceQuota (a validating admission controller) are enabled on the cluster.
Note: --admission-control is deprecated in favor of --enable-admission-plugins / --disable-admission-plugins. See the Kubernetes API server docs for details:
LimitRanger (mutating) — injecting defaults
LimitRanger is a mutating admission controller enabled by default on many clusters. It can inject default resource requests and limits for containers based on a LimitRange object in the namespace. Inspect the LimitRange in the demo namespace:- If a container is created without resource requests, it will get a default
cpu: 100mandmemory: 128Mi. - If a container is created without resource limits, it will get a default
cpu: 500mandmemory: 512Mi.
pod-no-resources.yaml):
ResourceQuota (validating) — enforcing namespace resource usage
ResourceQuota is a validating admission controller: it denies requests that would exceed the hard limits set for a namespace. It does not mutate objects; it only accepts or rejects them. Inspect the ResourceQuota in the namespace:How LimitRange and ResourceQuota work together
- LimitRange (mutating): injects default resource requests/limits at admission time when an object is created or recreated.
- ResourceQuota (validating): counts the (possibly mutated) resources and rejects requests that would exceed the hard limits.
Demo: quota-buster deployment (5 replicas in namespace with pod quota 4)
Create a Deployment manifestquota-buster.yaml that requests 5 replicas:
admission-lab has a hard pod quota of 4, only four Pods can be admitted. The ReplicaSet/Deployment controller will attempt to create the fifth Pod, but ResourceQuota (validating) will cause that Pod creation to be rejected. The Deployment will end up in a state such as “4/5 ready” (4 available, 5 desired), illustrating the interaction between mutating defaults and validating quotas.
Important behavior note
- LimitRange defaults are applied only at admission time when an object is created or recreated. Updating a LimitRange later does not retroactively change resource requests/limits of already running Pods. Only new Pods or Pods that are deleted and recreated will pick up the new defaults.
Admission controllers run at admission time. Mutating controllers change the object before it’s stored; validating controllers accept or reject the request. Changes to defaults (e.g., a LimitRange) do not mutate already existing objects.