Admission Controllers in Kubernetes
Every object that enters your cluster passes through a final checkpoint that can change it, approve it, or turn it away. This guide explains how that checkpoint works, from the built-in plugins to webhooks, CEL policies, and the habits that keep it reliable in production.
Imagine a large office building with a front desk. You have already shown your ID badge, and the guard has checked that your badge is allowed to enter the building. You might think that is enough. But before you walk to the elevator, a second person at the desk looks at the package you are carrying. They might stick a visitor label on it, they might ask you to open it, or they might say, “Sorry, nothing like that is allowed upstairs.” That second person is the admission controller of the building.
Kubernetes works in a very similar way. Proving who you are and having permission to act are not the whole story. Once a request to create or change something passes those two checks, it still has to pass through admission control, where the content of the request is examined and sometimes rewritten. This is where clusters enforce company rules, add default settings, inject helper containers, and stop risky workloads before they ever start.
In this guide we move step by step. We start with the basic idea, follow a request through the API server, learn the two kinds of admission, tour the built-in plugins, and then go deeper into webhooks, the newer policy objects written in CEL, and the operational lessons that separate a smooth cluster from a fragile one. No earlier knowledge is assumed, and every new term is explained when it first appears.
1What Is an Admission Controller?
An admission controller is a piece of code inside the Kubernetes API server that looks at a request after it has been authorized and before the object is saved.
The Short Definition
Kubernetes keeps all of its state, such as Pods, Services, Deployments, and Secrets, in a database called etcd. The only front door to that database is the API server. Whenever you run a command, apply a manifest, or a tool like a CI pipeline talks to your cluster, the request arrives at the API server. An admission controller is a plugin in that front door which gets a chance to inspect, modify, or reject the request before it is written to etcd.
Two words matter here: “inspect” and “modify”. Some admission controllers only look and then say yes or no. Others actually change the object, for example by filling in a missing default value. Both kinds exist, and we will separate them clearly in a later chapter.
Think of a school reception office. The receptionist already knows you are a registered parent (authentication) and that parents may collect students (authorization). Still, before handing over a child, they check the paperwork: Is today a valid day? Is the pickup form complete? Is there a note from the teacher? They may even stamp the form with the date. That final paperwork check, with the power to stamp or refuse, is admission control.
Why Do We Need It?
Authentication answers “who are you?” and authorization answers “are you allowed to do this kind of action?” Neither one looks deeply at the thing you are asking for. Authorization might say “Maya can create Pods in the payments namespace,” but it cannot say “Maya may create Pods only if they do not run as the root user and only if they pull images from our company registry.” Rules about the content of an object need a different layer, and admission control is that layer.
Without it, every team would need to remember every rule by heart, and one forgotten setting could expose the whole cluster. With it, the rules live in one central place and are applied to everyone automatically, whether the request comes from a human, a script, or another controller.
What It Does Not Do
It is just as important to know the limits. Admission controllers do not run on read requests, so they cannot hide or filter what people see. They also do not watch objects that already exist in the cluster; they only see requests as those requests arrive. If you create a bad object before a rule exists, the rule will not remove it later. It will only react the next time someone tries to update that object. Keep this in mind, because it explains many surprises in real clusters.
The “connect” operation deserves a short note. It covers actions like opening a shell inside a running container or forwarding a port. These are not changes to stored objects, but they are sensitive, so admission can still examine them.
Authorization decides whether you may perform an action. Admission decides whether the specific object you are submitting is acceptable. Two different questions, two different layers.
2Where Admission Fits in the Request Lifecycle
To understand admission, it helps to follow a single request from the moment it leaves your laptop until it is stored.
The Journey of One Request
Suppose you ask Kubernetes to create a Deployment. Your request is sent over a secure connection to the API server. From that moment it passes through a fixed series of stages, always in the same order. The diagram below shows the full path.
flowchart LR
A["Client request"] --> B["Authentication"]
B --> C["Authorization"]
C --> D["Mutating admission"]
D --> E["Schema validation"]
E --> F["Validating admission"]
F --> G["Saved to etcd"]
B -. "rejected" .-> X["Error returned"]
C -. "rejected" .-> X
D -. "rejected" .-> X
E -. "rejected" .-> X
F -. "rejected" .-> X
Authentication
The API server works out who is calling, using a certificate, a token, or an identity provider. If it cannot identify the caller, the request stops here.
Authorization
The server checks whether this caller may perform this action on this kind of resource. This is usually decided by role-based access control, often shortened to RBAC.
Mutating Admission
Plugins and webhooks that are allowed to change the object run one after another. They might add labels, set defaults, or attach a sidecar container.
Object Schema Validation
The server checks that the final object, after all the changes, still matches the official shape of that resource type. Unknown fields or wrong value types are rejected.
Validating Admission
Plugins and webhooks that may only approve or reject now look at the final object. They cannot change it. If any one of them says no, the whole request fails.
Persistence
Only after every earlier stage has agreed is the object written to etcd, and only then can controllers in the cluster begin acting on it.
Why the Order Matters
The order is not an accident. Changing the object comes before the final validation so that the validators judge the object that will actually be stored, not an early draft. If validation came first, a mutating step could silently break a rule that had just been checked. By putting every mutation before every validation, Kubernetes gives validators the last word.
Another consequence is that rejection is final and early. If any admission step says no, the request fails immediately and the user receives an error message explaining why. Nothing is stored, and no later stage runs.
People often assume admission runs when a Pod actually starts on a node. It does not. Admission happens at the API server, long before any scheduling or container start. A rejected Pod never exists at all.
3Mutating vs Validating Admission
Admission controllers come in two roles, and understanding the difference is the single most useful idea in this whole topic.
Mutating Controllers
A mutating controller is allowed to modify the incoming object. Typical jobs include adding a default storage class to a volume claim, setting a default service account on a Pod, attaching standard labels, or injecting an extra container next to your application container. Mutation is about convenience and consistency: the user does not have to remember each detail because the cluster fills it in.
Because one mutation can affect the next, mutating controllers run one after another in a defined order. Each one sees the result of the previous one.
Validating Controllers
A validating controller can only say yes or no. It receives the final version of the object and decides whether it follows the rules. Since it cannot change anything, there is no risk of one validator interfering with another, so validating controllers can be evaluated independently of each other, and the request is accepted only if every single one approves.
Picture a restaurant kitchen. The prep cooks are mutating controllers: they trim, season, and plate the dish, and each cook works on what the previous cook handed over. The head chef at the pass is the validating controller: tasting the final plate and saying either “send it out” or “back to the kitchen.” The chef never adds salt; the chef only approves or refuses.
| Aspect | Mutating | Validating |
|---|---|---|
| Can change the object | Yes | No |
| Can reject the request | Yes | Yes |
| When it runs | Before schema validation | After schema validation |
| Execution style | One after another, in order | Independent checks, all must pass |
| Sees the final object | No, later mutations may follow | Yes |
| Typical purpose | Defaults, injection, labels | Policy, security, compliance |
Some Plugins Do Both
Several built-in plugins are both mutating and validating. They simply take part in both phases: first they may adjust the object, and later they check it. The Kubernetes documentation marks which plugins act in which phase, so it is worth checking when you rely on a particular one.
Whenever you can, use a validating rule instead of a mutating one. Silent changes can surprise users, while a clear rejection with a helpful message teaches them what to fix. Reserve mutation for cases where a sensible default or an automatic injection genuinely helps.
4The Built-in Admission Controllers
Kubernetes ships with a long list of admission plugins that are compiled directly into the API server. Many are switched on by default, and you probably rely on several of them without knowing.
How They Are Switched On and Off
The API server has settings that enable additional plugins and disable default ones. A cluster administrator who controls the control plane can tune these. Be aware that on most managed Kubernetes services, the provider decides the plugin list, and you may not be allowed to change it. This is one reason the webhook and policy approaches in later chapters are so popular: they work on any cluster without touching the API server settings.
A Tour of Important Plugins
The list below is not complete, but it covers the plugins most engineers meet in daily work. Each card explains what the plugin is for in plain words.
NamespaceLifecycle
Blocks new objects from being created inside a namespace that is being deleted, and protects the core system namespaces from removal.
LimitRanger
Applies default CPU and memory requests and limits, and rejects Pods that fall outside the minimum and maximum set for the namespace.
ResourceQuota
Enforces the total amount of resources or objects a namespace may use, so one team cannot consume the entire cluster.
ServiceAccount
Automatically attaches a service account to Pods that do not name one, so every Pod has an identity inside the cluster.
DefaultStorageClass
Assigns the default storage class to a volume claim that does not request one, so storage requests work without extra detail.
NodeRestriction
Limits what each node agent may modify, so a compromised node can only touch its own Node object and the Pods assigned to it.
PodSecurity
Applies the Pod Security Standards at the namespace level, deciding which Pod settings are acceptable. A full chapter covers it below.
Priority
Resolves a named priority class into a numeric priority on the Pod, and rejects names that do not exist.
Two Plugins That Open the Door to Extension
Among the built-in plugins, three are special because they let you add your own logic without rebuilding the API server. They are the mutating webhook plugin, the validating webhook plugin, and the validating admission policy plugin. They act like sockets: the built-in code is fixed, but what plugs into it is yours to define. Chapters 5 through 9 are about these.
Some plugins, such as ones that force images to always be pulled or that restrict scheduling by namespace, are not on by default. If a behavior you expect is missing, check whether the plugin is actually enabled on your cluster rather than assuming it is.
5Dynamic Admission: Webhooks
Built-in plugins cover common needs, but every company has its own rules. Admission webhooks let you run those rules in a separate service of your own.
What Is a Webhook?
A webhook is simply a web address that gets called when something happens. In this case, “something happens” means a matching request has reached the admission stage. The API server pauses the request, sends a description of it to your service over a secure connection, waits for your answer, and then continues or stops depending on what you say.
Your service can be anything that speaks the right format: a small program you wrote, a full policy engine, or a vendor product. It usually runs inside the cluster as an ordinary Deployment with a Service in front of it, though it can also live outside the cluster at a public address.
sequenceDiagram
participant U as User
participant A as API Server
participant M as Mutating Webhook
participant V as Validating Webhook
participant E as etcd
U->>A: Create Pod request
A->>M: Admission review with the object
M-->>A: Allowed, plus a list of changes
A->>A: Apply changes and check schema
A->>V: Admission review with final object
V-->>A: Allowed or denied with a reason
A->>E: Store the object
A-->>U: Success response
Registering a Webhook
You do not tell the API server about your service in a command-line flag. Instead, you create a Kubernetes object that describes it. There are two such objects: one for mutating webhooks and one for validating webhooks. Each object lists which requests to send (by resource type, operation, and optionally namespace or labels), where to send them, and how to behave if something goes wrong. We study those settings in Chapter 7.
Registering a webhook is like putting a note on the building’s front desk: “For any package addressed to the third floor, call extension 214 before letting it through.” The desk staff do not need to know why; they just follow the note, wait for the answer on the phone, and act on it.
Security of the Conversation
The API server only talks to webhooks over encrypted connections. Your service needs a valid certificate, and the registration object carries the certificate authority that the API server should trust when it connects. If that certificate expires or the trust information goes stale, the API server can no longer reach your service. Depending on settings, the result is either blocked requests or skipped checks, and both are painful. Many teams automate certificate renewal for exactly this reason.
Use Case: Sidecar Injection
Service meshes and secret-delivery tools use mutating webhooks to add an extra container to every new Pod in selected namespaces. Developers write a plain Pod, and the webhook quietly adds the proxy or agent that makes it part of the mesh.
Use Case: Enforcing Company Rules
A validating webhook can reject any workload that pulls an image from an untrusted registry, lacks an owner label, or asks for more memory than the team budget allows. The error message tells the developer exactly which rule was broken.
6Anatomy of an Admission Request and Response
Webhooks and the API server talk using a small, well-defined message called an AdmissionReview. Knowing what is inside it makes debugging far easier.
The Question the API Server Asks
When the API server calls your webhook, it sends one message called an AdmissionReview. Inside the request part of this message you will find a set of useful facts. Think of it as a form that the API server fills in before handing it to your service.
Unique ID
A unique identifier for this exact request. Your answer must repeat it so the API server can match reply to question.
Kind and Resource
What type of object this is, such as a Pod or a Deployment, and which API group and version it belongs to.
Operation
Whether the user is creating, updating, deleting, or connecting. Many rules only care about one of these.
User Information
The name, groups, and extra attributes of the caller, which lets you apply different rules to people and to automated systems.
New Object
The full object as the user submitted it, including any changes made by earlier mutating steps.
Old Object
For updates and deletes, the version currently stored. Comparing old and new lets you block risky changes, such as editing an immutable setting.
Namespace and Name
Where the object lives and what it is called. For creates with generated names, the name may be empty at this point.
Dry Run Flag
Tells you the request is only a rehearsal and must not cause real-world effects outside the cluster.
The Answer Your Webhook Gives
Your service replies with a response that repeats the unique ID and states whether the request is allowed. A denial can include a status with a human-readable message and a code, and that message is shown to the user, so write it clearly. A good denial says which rule was broken and how to fix it, not just “forbidden.”
A mutating webhook can also return a list of changes, written in a standard format called JSON Patch. It is a precise recipe, such as “add this label” or “replace that value,” which the API server applies to the object. A response may also carry warnings: short messages shown to the user even though the request succeeded. Warnings are a gentle way to announce that a rule will soon become strict. There are also audit annotations, small notes added to the audit log entry for the request, which help security teams trace decisions later.
Use warnings to roll out new rules gently. First warn for a few weeks so teams can fix their manifests, then switch the same rule to deny. This avoids the angry surprise of suddenly blocked deployments.
Versions of the Message
The message format is versioned, and the registration object lists which versions your service understands. The API server picks one that both sides support. Always support the current stable version, because older formats are removed in newer clusters.
7Webhook Configuration Settings That Matter
A webhook is only as safe as its registration. A handful of settings decide whether your cluster stays healthy when something goes wrong.
Choosing What Gets Sent
Not every request needs to reach your webhook. Sending everything wastes time and increases risk. The registration lets you narrow things down in several ways. Rules pick the API groups, resource types, and operations. A namespace selector includes or excludes whole namespaces by their labels. An object selector filters by the labels on the object itself. Newer clusters also support match conditions, small expressions written in CEL, a safe expression language we meet in the next chapter, which let the API server skip the call entirely when a condition is not met. Filtering before the network call is the cheapest optimization available.
Failure Policy: The Most Important Choice
What should happen if your webhook is down, slow, or broken? The failure policy answers that question, and it has two options.
Fail Closed
- Requests are rejected when the webhook cannot answer
- No rule can be bypassed during an outage
- Right choice for critical security controls
- Predictable and easy to reason about
Fail Open
- Requests are allowed when the webhook cannot answer
- Cluster keeps working during webhook outages
- Rules may be silently skipped in that window
- Suited to helpful but non-critical mutations
There is no universal answer. A webhook that blocks privileged containers should usually fail closed, because skipping it would defeat its purpose. A webhook that adds optional labels can usually fail open. What matters is that you make the choice on purpose, write it down, and test what really happens when the service disappears.
Timeouts, Side Effects, and Re-invocation
Timeout
The registration sets how long the API server will wait, within a small allowed range of seconds. Every admission call adds to user-visible latency, so shorter is better. Aim for answers in milliseconds.
Side Effects Declaration
You must state whether your webhook changes anything outside the cluster, such as calling an external system. Dry-run requests go through admission too, so a webhook with hidden side effects could do real damage during a rehearsal. Declare honestly, and skip side effects on dry runs.
Match Policy
A resource can be reachable through more than one API version. The match policy decides whether your rule also catches equivalent versions, so that a request cannot dodge the rule by using a different version name.
Reinvocation Policy
Because mutating steps run in sequence, a later webhook may change something an earlier webhook cared about. The reinvocation policy lets a mutating webhook be called a second time if later steps altered the object. Your logic must therefore be safe to run more than once with the same result.
Problem
A webhook is registered to fail closed and to intercept every Pod in every namespace, including the namespace where the webhook service itself runs.
Why It’s Harmful
If the webhook Pods ever restart, the API server asks the webhook for permission to create the very Pods that would answer the question. The answer never comes, so the service can never return. This deadlock can also block critical system components.
Correct Approach
Exclude the webhook’s own namespace and the core system namespaces using a namespace selector, run several replicas spread across nodes, and keep the failure policy decision deliberate for each webhook.
8ValidatingAdmissionPolicy and CEL
Running a separate service just to say “no” to a few bad configurations is a lot of machinery. Kubernetes now lets you write such rules as plain objects, evaluated inside the API server itself.
The Problem with Webhooks
Webhooks are powerful, but they come with costs. You must build and maintain a service, keep certificates fresh, make it highly available, and accept the extra network hop on every matching request. For simple rules, this is like hiring a security company to check whether a form has a signature.
What CEL Is
CEL, short for Common Expression Language, is a small, safe language for writing conditions. It cannot loop forever, cannot access files, and cannot call the network. Because it is so limited, the API server can run it directly with predictable cost. A CEL rule looks at the incoming object and returns true or false. For example, a rule can express “every container must have a memory limit” or “replica count must not exceed ten.”
The Two Objects
The feature uses two cooperating objects. The first is the policy, which describes which resources it applies to, optional variables, and one or more validation rules with their messages. The second is the binding, which connects a policy to a scope, such as particular namespaces, and decides what happens on a violation. Splitting the two means one policy can be reused with different scopes and different strictness.
Deny
The request is rejected, and the user sees your message. This is the enforcement mode.
Warn
The request succeeds, but the user receives a warning message. Ideal for announcing upcoming rules.
Audit
The request succeeds, and the violation is recorded in the audit log for later review by the security team.
Parameters Make Policies Reusable
A policy can point to a separate parameter object, for example a small configuration holding the maximum allowed replica count. Different bindings can supply different parameter objects, so the same rule can be strict in production and relaxed in development without copying the policy.
A policy is like a speed limit sign design: “vehicles must not exceed the posted number.” The binding is where you actually put the sign, and the parameter is the number written on it. The same sign design works on a quiet village road with one number and on a motorway with another.
Advantages
- No extra service to run, patch, or scale
- Evaluated inside the API server with low latency
- No certificate management or network failure modes
- Rules are declarative and easy to review in version control
- Warn and audit modes make safe rollouts simple
Disadvantages / Trade-offs
- Validation only; it cannot call external systems
- Logic is limited to what CEL can express
- Complex rules can become hard to read
- Needs a cluster version that supports the feature
Start with a CEL policy for any rule that only needs to look at the object itself. Reach for a webhook only when you need outside data, such as a database lookup or a signature check on an image.
9Mutating with Policies Instead of Webhooks
The same idea that replaced simple validating webhooks is being extended to mutation, so common defaults can also be declared without running your own service.
The Idea
A mutating admission policy follows the same model as its validating cousin. You describe the resources it applies to and express the change you want using CEL, and the API server applies it. Typical examples include adding a default label, setting a safe default value, or adding a standard annotation. As there is no webhook service, there is no network call, no certificate, and no outage risk from a missing service.
This capability is newer than validating policies and has been maturing across recent Kubernetes releases. Whether it is available, and whether it is on by default, depends on your cluster version and its feature settings. Always read the release notes and the official documentation for your version before depending on it.
When Webhooks Are Still the Better Tool
Policies are intentionally limited. If your mutation needs complex logic, needs to generate a lot of content such as a full sidecar definition based on external templates, or needs to talk to another system, a webhook remains the right answer. Think of policies as the everyday tool and webhooks as the specialist tool.
| Need | Best Fit | Reason |
|---|---|---|
| Simple yes or no rule on the object | Validating policy with CEL | Fast, no service to run |
| Add a label or default value | Mutating policy, where available | Declarative and low risk |
| Inject a sidecar container | Mutating webhook | Needs rich, template-based logic |
| Check against an external database | Validating webhook | CEL cannot call outside systems |
| Enforce rules across many clusters | Policy engine | Central management and reporting |
10Policy Engines: Kyverno and OPA Gatekeeper
Writing and maintaining raw webhooks for every rule does not scale. Policy engines package the webhook, the certificates, and a friendly rule language into a ready-made product.
What a Policy Engine Does
A policy engine is a program you install in the cluster that registers its own admission webhooks. You then write rules in the engine’s own format, and the engine decides how each incoming request should be handled. It also usually adds extras: reports on existing objects that already violate a rule, tools to test policies before release, and exception handling for teams that need a rare bypass.
Kyverno
Designed specifically for Kubernetes. Policies are written as Kubernetes resources using familiar structure, and it can validate, mutate, and even generate new objects. Many teams find it the gentlest to learn.
OPA Gatekeeper
Brings the general-purpose Open Policy Agent to Kubernetes. Rules are written in a dedicated policy language and organized as reusable templates plus constraints that apply them. Very flexible, with a steeper learning curve.
How to Choose
If your team wants to stay inside Kubernetes-style configuration and values quick adoption, an engine built around Kubernetes resources is attractive. If your organization already uses the same policy language for other systems such as pipelines or cloud access, a general-purpose engine gives you one language everywhere. Many engines also support the native policy objects from the previous chapters, so the choice is not as final as it once was.
Running two engines, or an engine plus several custom webhooks, multiplies the number of network calls on every request and makes it hard to tell which component rejected something. Decide who owns which category of rule and keep it simple.
11Pod Security Admission
One built-in admission plugin deserves its own chapter because almost every cluster uses it: the one that stops dangerous Pods.
From PodSecurityPolicy to Pod Security Admission
Older clusters used an object called PodSecurityPolicy to control risky Pod settings. It was confusing to use and was removed in Kubernetes 1.25. Its replacement is Pod Security Admission, a built-in plugin that enforces a set of published rules called the Pod Security Standards. It is much simpler: you choose a level for each namespace by adding labels to that namespace.
Three Levels
Privileged
No restrictions at all. Meant for trusted system components, such as storage drivers and networking agents, that genuinely need deep access to the node.
Baseline
Blocks the most dangerous settings, such as sharing the host network or running fully privileged containers, while staying friendly to typical applications that were not written with security in mind.
Restricted
Follows current hardening best practice, for example requiring containers to run as a non-root user, dropping extra Linux capabilities, and using a default seccomp profile. This is the target for new applications.
Three Modes
For each namespace you can choose how a violation is handled, and you can use more than one mode at the same time. Enforce rejects violating Pods. Audit allows them but records the violation in the audit log. Warn allows them but shows a warning to the user. A very effective migration plan is to enforce at baseline while auditing and warning at restricted, so teams see what they must fix before the stricter level is switched on.
Start with Warn and Audit
Label namespaces to warn and audit at the target level. Nothing breaks, but you learn which workloads would fail.
Fix the Workloads
Work with application teams to adjust the flagged settings. Most fixes are small, such as choosing a non-root user.
Turn on Enforce
When the warnings go quiet, switch the namespace to enforce. New violations are now blocked at the door.
Pod Security Admission looks at Pods, and it also checks the Pod templates inside higher-level objects when you use warn and audit modes. Enforce mode applies only to Pods themselves, so a Deployment may be accepted even though its Pods are later refused. Watch for Deployments that show fewer running Pods than expected.
12Inside the API Server: The Admission Chain
So far we have treated admission as one box. Now we open the box and see how the individual plugins are lined up, who calls whom, and why a single user action can trigger several rounds of admission.
A Chain of Small Decisions
Inside the API server, admission is not one big program. It is a chain of small plugins, and each plugin is asked about the request in turn. The built-in plugins are compiled into the server and run first or alongside the extension points. The webhook plugin is itself just another link in the chain: when its turn comes, it looks at all the registered webhooks, filters out the ones that do not match the request, and calls the rest.
The order of the built-in plugins is fixed by the server, and you should not try to depend on it. Likewise, when several mutating webhooks match the same request, you should not write one webhook that silently relies on another having run first. If two mutations really depend on each other, merge them into one component. Code that works only because of an accidental order tends to break during upgrades, when ordering details change.
Think of airport security. Your bag goes through several stations: a document check, an X-ray, a liquids check, and a random swab test. Each station is small and focused, and any one of them can stop you. No station knows how the others work, and the airport may rearrange them from time to time. A passenger who only sees “security” does not notice the chain, but anyone designing the airport must.
One Action, Many Requests
A very common surprise is that one human action produces several API requests, and each of them goes through admission separately. When you create a Deployment, the Deployment controller creates a ReplicaSet, and the ReplicaSet controller creates Pods. These controllers are programs inside the cluster, and they talk to the API server just like you do. That means your Deployment is checked once, the ReplicaSet is checked again, and each Pod is checked a third time.
This is why the rule coverage matters so much. A rule that blocks bad Pods will fire even if the bad settings were hidden inside a Deployment template, but the error will appear in the ReplicaSet events rather than in your command output. The Deployment itself may look healthy, with the Pods simply never appearing. Knowing the chain makes this behavior easy to diagnose.
flowchart TD
U["User creates a Deployment"] --> A1["Admission check 1: Deployment"]
A1 --> D["Deployment controller"]
D --> A2["Admission check 2: ReplicaSet"]
A2 --> R["ReplicaSet controller"]
R --> A3["Admission check 3: Pod"]
A3 --> P["Pod stored and scheduled"]
A3 -. "rejected" .-> E["Event on the ReplicaSet"]
What Each Plugin Sees
Each plugin receives a structured description of the request: who is calling, which resource, what operation, and the object itself. Plugins do not see the network connection, the command the user typed, or the tool used. A request from a command-line tool, a pipeline, or a controller looks the same except for the caller identity. This is a feature, not a limitation, because rules apply equally to every path into the cluster.
When a Deployment seems stuck, look at the ReplicaSet and its events before looking at the webhook. The denial message from admission is usually recorded there, because the ReplicaSet controller was the caller that received the rejection.
13Subresources, Updates, and Deletes: The Tricky Corners
Creating a new object is the easy case. Most real-world surprises come from the other operations, and from the parts of an object that have their own separate address.
Subresources
Many objects have subresources, which are special sub-addresses for particular actions. A Pod has a status subresource used by node agents to report health, an ephemeral containers subresource used for debugging, and connection subresources used for opening a shell or forwarding a port. A Deployment has a scale subresource that autoscalers use to change the replica count. An eviction subresource is used when draining nodes.
Why does this matter for admission? Because a rule written for a Pod does not automatically cover its subresources. The registration must name the subresource explicitly, or it will not be consulted. If you want to stop engineers from opening shells inside production containers, you must write a rule about the connection subresource, not about the Pod itself. A surprisingly large number of security gaps come from rules that forgot the subresources.
Updates Need Two Versions
An update request carries both the new object and the old one. This is powerful, because a rule can compare them. A rule can say “the storage size may grow but never shrink,” or “the owner label may never change after creation.” Without the old object you could only judge the new state, which cannot express the idea of a forbidden change.
There is a trap, though. Controllers constantly update objects to record their own progress: a status here, a counter there. If your rule is too strict about updates, you can accidentally block the cluster’s own housekeeping. Rules that apply to updates should be as narrow as possible, and they should usually ignore changes that only touch the status subresource.
Judge the New Object
There is no old version. Rules check that the new object follows policy from the start.
Compare Old and New
Rules can forbid specific changes, protect fields that must stay constant, and avoid blocking routine controller writes.
Protect What Matters
Rules can stop the deletion of critical objects, such as a production namespace or a shared database claim, until a human removes a protection marker.
Watch Sensitive Actions
Rules can log or block shell access and port forwarding to selected workloads, giving a clear trail of who entered what.
Deletes Are Admission Events Too
Admission also sees delete requests. Teams use this to build a safety net: for example, a rule that refuses to delete a namespace unless it carries a label saying deletion is approved. Remember that the old object is available for deletes, so the rule can examine what is about to be removed.
Problem
A strict update rule is applied to every change of a resource, including the progress updates written by controllers and autoscalers.
Why It’s Harmful
Controllers cannot record their progress, scaling stops working, and rollouts appear frozen. The root cause is hard to spot because the denials are written by system components, not by people.
Correct Approach
Limit update rules to the fields you truly care about, exclude status changes, and exempt trusted system identities where appropriate. Test the rule by running a normal rollout and a scaling event in a staging cluster.
14Testing Rules Safely: Dry Run and Staging
An untested admission rule is a risk to the whole cluster. Fortunately, Kubernetes gives you several ways to rehearse a rule before it matters.
Server-side Dry Run
Most clients can send a request in dry-run mode. The API server then does everything it would normally do, including authentication, authorization, every admission step, and validation, but it stops before saving anything. The response tells you what would have happened. This makes dry run the best everyday tool for testing a rule: apply a sample object in dry-run mode and see whether it is accepted, changed, or rejected.
Because dry-run requests pass through webhooks, remember that your webhook must honor the dry-run flag. A webhook that sends an email or writes to an external database on every request would do so even for a rehearsal, which defeats the purpose. That is why the side effects declaration exists.
A Practical Test Plan
Collect Good and Bad Examples
Write a small set of objects that should pass and another set that should be rejected. Keep these files with the policy so they grow together.
Run Them in Dry-Run Mode
Send each example against a test cluster and confirm the result matches what you expect. Check that the denial messages are readable.
Test the Awkward Cases
Try updates, deletes, subresources, and objects created by controllers, not only direct creates by a person.
Simulate Failure
Stop the webhook, expire its certificate in the test environment, and slow it down. Observe whether the cluster behaves as you intended.
Promote in Stages
Move from a development cluster to staging and then to production, with audit or warn mode first at each step.
Use Case: A Pipeline That Tests Policies
A platform team keeps all rules and their sample files in one repository. Every proposed change triggers an automatic run that applies the good and bad samples to a temporary test cluster. A change that lets a bad sample through, or blocks a good one, fails the build and never reaches production.
A rule that looks harmless on paper can block system components you forgot about, such as networking agents or storage drivers. A staging cluster that resembles production reveals these surprises while they are still cheap to fix.
15Security Considerations
Admission controllers sit in one of the most powerful positions in the cluster, which makes them both a strong defense and an attractive target.
The Webhook Is a Powerful Citizen
A mutating webhook can change any object that matches its rules. If an attacker takes control of your webhook service, they can quietly rewrite workloads, for example by changing the image a Pod runs or adding a malicious container. A validating webhook under attacker control could approve anything. That is why the service must be treated as part of the control plane in terms of care, even though it is just a Deployment.
Imagine the front desk guard who stamps and approves every package. If a thief replaces that guard, the thief now controls everything entering the building. So the guard’s uniform, key, and phone line must be protected more carefully than any ordinary employee’s.
Lock Down the Service
Run the webhook with a minimal service account, a restrictive network policy that only lets the API server reach it, and no unnecessary permissions.
Guard the Registration
Only a few trusted administrators should be able to create or edit webhook registration objects, since changing one can disable or redirect all checks.
Protect the Certificates
Keep private keys in secrets with tight access, rotate them on a schedule, and monitor expiry so renewals never come as a surprise.
Trust Only the Object
Treat all fields in the request as untrusted input. Validate carefully, and avoid decisions based on easily forged labels alone.
Policies Can Be Bypassed If You Are Not Careful
A rule is only as strong as its coverage. If a rule checks Pods but not Deployments, a user could try to sidestep it by creating the higher-level object in a way that produces a bad Pod later. If a rule is excluded for certain namespaces, anyone who can create objects in those namespaces can ignore it. Review exclusions regularly and keep them as short as possible.
Also remember that admission controllers only see requests, not existing state. A new rule does not fix old objects. Combine admission with periodic scanning, which most policy engines offer, to find existing violations.
Giving the webhook service broad cluster-admin rights “to be safe.” The opposite is true: a compromised service with wide rights is a direct path to the whole cluster. Grant only what it must have.
16Reliability and Performance
Because admission sits in the middle of every matching write, a slow or broken webhook slows or breaks the entire cluster.
Latency Adds Up
Each webhook call happens while a user waits. If three webhooks each take half a second, every matching request becomes one and a half seconds slower. Worse, controllers inside the cluster also write objects constantly, so a slow webhook can create a backlog that affects scaling, rollouts, and recovery. Keep webhook logic small, avoid calling other services during a decision when possible, and cache anything you must look up.
Availability Practices
Run Multiple Replicas
A single webhook Pod is a single point of failure for every request it guards. Run several, and add a disruption budget so maintenance never takes them all down at once.
Spread Across Failure Zones
Use scheduling rules so replicas land on different nodes and, when possible, different availability zones, so one failure cannot remove the whole service.
Give It Priority
Assign a high priority class so that under resource pressure the webhook Pods are among the last to be evicted.
Narrow the Scope
Match only what you truly need using rules, selectors, and match conditions. Fewer calls means less load and fewer chances to fail.
Test the Outage
Deliberately stop the webhook in a test cluster and observe. Learn the real effect of your failure policy before an incident teaches it to you.
Since policies written in CEL run inside the API server, they remove an entire class of failures: no network hop, no certificate expiry, no missing service. For simple rules, this is a real reliability win.
17Monitoring, Logging, and Metrics
You cannot manage what you cannot see. Admission control gives you several windows into what is happening.
Metrics from the API Server
The API server publishes metrics that describe admission activity. They include the time spent in each admission step, the time spent calling each webhook, counts of rejected requests, and counts of requests that were let through because a webhook failed while set to fail open. Collect these in your monitoring system and chart them. A sudden rise in webhook duration or in rejections is often the first sign of trouble.
Webhook Duration
How long each webhook takes to answer. Alert when it climbs, because users will feel it before you do.
Rejection Count
How often requests are denied, broken down by webhook. A spike may mean a new rule or a broken deployment pipeline.
Fail-Open Count
How many requests skipped a check because the webhook was unreachable. Any steady number deserves an investigation.
Certificate Expiry
Days remaining on the webhook certificate. Alert well ahead of the date so renewal is never an emergency.
Audit Logs and Annotations
The cluster audit log records requests, and admission decisions can add annotations to those entries. When a policy audits a violation, or a webhook returns audit annotations, the note appears next to the request. This gives security teams a searchable trail of who tried to do what, and which rule reacted.
Logging Inside the Webhook
Your own service should log each decision with the request ID, the resource, the user, and the outcome, while avoiding the logging of sensitive data from Secrets or tokens. When a developer says “my deployment was rejected,” a log search by request ID should answer within a minute.
flowchart TD
R["Incoming request"] --> A["API server admission step"]
A --> M["Metrics: duration and rejections"]
A --> L["Audit log with annotations"]
A --> W["Webhook service logs"]
M --> D["Dashboards and alerts"]
L --> S["Security review"]
W --> T["Troubleshooting"]
18Design Patterns and Anti-patterns
Teams that use admission control for years tend to converge on the same good habits, and to repeat the same mistakes.
Patterns Worth Copying
Pattern: Warn, Then Enforce
Introduce every new rule in warn or audit mode first. Publish a date, let teams fix their configuration, and only then switch to deny. This keeps goodwill high and surprises low.
Pattern: Guardrails, Not Gates
Design rules to prevent clearly dangerous outcomes, such as privileged containers or missing resource limits, instead of trying to control every preference. Fewer, clearer rules are easier to explain and to keep.
Pattern: Helpful Error Messages
Every denial should name the rule, explain why it exists, and say how to comply. A good message turns a blocked developer into a self-sufficient one.
Pattern: Policy as Code
Keep policies in version control, review changes like any other code, and promote them from test to production clusters through the same pipeline as applications.
Pattern: Idempotent Mutation
Write mutations so that running them twice produces the same result as running them once. This keeps reinvocation and retries safe.
Problem
Using mutating webhooks to silently “fix” configurations, for example overwriting a value the developer set on purpose.
Why It’s Harmful
The running object no longer matches what the developer wrote. Debugging becomes confusing, deployment tools may keep fighting the webhook over the difference, and trust in the platform drops.
Correct Approach
Mutate only to fill in missing values or to add clearly documented injections. When a value is wrong, reject it with a clear message instead of changing it behind the scenes.
Problem
Creating a long chain of independent webhooks, each owned by a different team, with no overall plan.
Why It’s Harmful
Latency adds up, mutation order produces surprising results, and nobody knows which component caused a rejection. Outages in any one webhook can block the whole cluster.
Correct Approach
Consolidate rules into a small number of well-owned components, prefer native policies for simple checks, and document who owns each registration.
19Best Practices and Common Mistakes
A condensed checklist of what works, and of the traps that catch even experienced teams.
Best Practices
- Prefer built-in plugins and native CEL policies before building custom webhooks
- Choose the failure policy deliberately for each webhook
- Exclude system namespaces and the webhook’s own namespace
- Keep decisions fast and free of slow external calls
- Run several replicas with disruption budgets
- Automate certificate renewal and alert on expiry
- Roll out new rules with warn and audit first
- Test policies in a staging cluster before production
Common Mistakes
- Forgetting that admission ignores objects that already exist
- Letting certificates expire and blocking the cluster
- Matching every resource when only a few are needed
- Writing vague denial messages that frustrate users
- Declaring no side effects while actually causing some
- Trusting labels that any user can set freely
- Running a single webhook replica for a critical rule
A Safe Rollout Plan for a New Rule
Define the Goal
Write down what harm the rule prevents. If you cannot explain it in a sentence, the rule is probably too complicated.
Try It in Audit Mode
Apply it so violations are only recorded. Read the audit results to see who would be affected.
Add Warnings and Announce
Turn on warnings, tell teams the enforcement date, and offer help for the common fixes.
Enforce and Monitor
Switch to deny, watch rejection counts closely for the first days, and keep a quick path to roll back if something unexpected breaks.
20Real-World Examples
Admission control is not a theory topic. Several tools you may already use depend on it every day.
Service Meshes Such as Istio and Linkerd
These meshes use a mutating webhook to add a proxy container to Pods in labeled namespaces. Developers deploy ordinary applications, and the proxy that provides encryption and traffic control appears automatically.
Secret Delivery with Vault Agent Injector
HashiCorp Vault can add an agent container to Pods that carry specific annotations, so credentials are fetched and delivered to the application without the developer writing integration code.
Certificate Management with cert-manager
cert-manager uses its own webhook to validate the certificate-related objects people create, rejecting malformed requests early with a clear message instead of failing later in the process.
Platform Guardrails with Kyverno or Gatekeeper
Platform teams in many companies use these engines to require ownership labels, restrict image registries, demand resource limits, and block risky settings, making the paved road the easy road for every application team.
Multi-Tenant Clusters
When several teams share a cluster, resource quotas, limit ranges, and Pod Security levels per namespace work together so that each team gets a fair, safe slice without constant manual review.
In every example, the person deploying never has to remember the rule. The cluster remembers for them, consistently, every time. That is the real value of admission control.
21Troubleshooting Admission Problems
When something is rejected or the cluster feels stuck, a calm, step-by-step approach finds the cause quickly.
When a Request Is Rejected
Start with the error message itself. Webhook denials include the name of the webhook and the message it returned. Native policy denials name the policy and the failed rule. If the message is vague, check the policy engine’s logs and the audit log for the request.
When Everything Seems Blocked
If many unrelated requests are failing with errors that mention a webhook call failing, the webhook service is probably unreachable. Check whether its Pods are running, whether its Service has healthy endpoints, and whether its certificate is still valid. Remember that a webhook set to fail closed will block every matching request while it is down.
Read the Error Text
It names the webhook or policy responsible. That tells you where to look next.
Check the Service Health
Confirm that the webhook Pods are ready, the Service has endpoints, and nothing blocks traffic from the API server.
Verify the Certificate
Look at expiry dates and confirm the registration holds the correct certificate authority.
Inspect the Registration
Review its rules, selectors, and failure policy to see why the request was sent to it at all.
Use the Emergency Exit if Needed
If the cluster is truly stuck, an administrator can temporarily remove or loosen the registration object to restore normal operation, then fix the root cause and restore it.
Removing a security webhook opens a window with no protection. Do it only with approval, keep the window short, and review what was created in the meantime once the rule is back.
22Admission Control Compared with Other Guardrails
Admission control is one guardrail among several. Understanding what the others do keeps you from asking admission to solve problems that belong elsewhere.
Each Layer Has Its Own Job
A healthy platform layers its defenses. RBAC answers who may perform which action. Network policies decide which Pods may talk to which other Pods. Admission control checks the content of objects as they enter. Scanning in the delivery pipeline catches problems before a change even reaches the cluster. Runtime security tools watch what containers actually do after they start. No single layer can replace the others, and removing one leaves a gap that the rest cannot fill.
| Layer | Question It Answers | When It Acts | Blind Spot |
|---|---|---|---|
| RBAC | Is this caller allowed to do this action? | Before admission | Cannot judge object contents |
| Admission control | Is this specific object acceptable? | When the request arrives | Ignores existing objects and runtime behavior |
| Network policy | Who may talk to whom? | While traffic flows | Says nothing about object settings |
| Pipeline scanning | Does the change look safe before deploying? | Before the cluster | Can be bypassed by direct access |
| Runtime security | Is a container behaving badly now? | After start | Reacts late, after the workload runs |
Consider a bank. The ID check at the door is RBAC, the teller reviewing each form is admission control, the cameras and alarms inside are runtime security, and the audit done before the form is even handed over is pipeline scanning. A bank with only one of these would be easy to rob.
Validation Rules in Custom Resources
Kubernetes also lets authors of custom resource types embed validation rules, written in CEL, directly in the type definition. These rules travel with the type, so every cluster that installs it gets the same checks. They are the right place for rules that describe what a valid object of that type means, such as “the maximum must not be smaller than the minimum.” Admission policies, in contrast, are the right place for rules that describe your organization’s preferences, which can differ between clusters.
If a rule is true for everyone who uses an object type, put it in the type. If it reflects your company’s policy, put it in an admission policy. If it checks who may act, use RBAC. Placing each rule in the right layer keeps the system understandable.
23A Complete Walkthrough: Guardrails for a Shared Cluster
Let us put everything together with a story. A platform team runs one cluster used by several product teams and wants safe defaults without slowing anyone down.
The Situation
The platform team supports about a dozen application teams. Incidents keep repeating: a Pod without memory limits crashes a node, an image from an unknown registry is deployed, and nobody knows who owns a mysterious workload. The team decides to use admission control to address the three problems, without becoming a bottleneck.
Start with Built-ins
They enable quotas and limit ranges per namespace so each team has a defined budget and every container gets sensible default limits. No custom code is needed, and the memory incidents drop right away.
Turn On Pod Security in Warn Mode
They label every application namespace to warn at the restricted level and enforce at baseline. Teams see warnings in their normal deploy output and begin fixing their Pod settings over the following weeks.
Add a CEL Policy for Ownership
A native validating policy requires an owner label on every workload. It starts in warn mode, with a clear message explaining the label and pointing to a short guide. The binding applies only to application namespaces.
Use a Policy Engine for the Registry Rule
Restricting images to approved registries needs a list that changes often, so they use a policy engine that supports exceptions and reports on existing violations. The engine runs several replicas with a considered failure policy.
Announce, Then Enforce
After a published grace period, the warnings turn into denials one rule at a time. Dashboards track rejection counts, and a support channel handles questions during the first week.
Review Every Quarter
The team reviews exclusions, retires rules that no longer help, checks certificate renewals, and verifies that policies still work on the current cluster version.
What They Did Right
Chose the Lightest Tool for Each Rule
Built-in plugins for quotas, native policies for object-only checks, and a policy engine only where outside data and exceptions were needed. Each choice reduced moving parts.
Treated People as Users
Every denial explained itself, every rule had a warning period, and the team answered questions quickly. The result was cooperation instead of workarounds.
Kept Visibility
Metrics, audit logs, and reports on existing objects meant the team could always say which rule fired and why, and could find old violations that admission alone would have missed.
24Upgrades, Versions, and Long-Term Maintenance
Admission rules are not a one-time project. Clusters, tools, and certificates all change, and rules must keep up.
Cluster Upgrades
Kubernetes releases new versions several times per year. Each release can promote features from experimental to stable, deprecate old interfaces, and eventually remove them. Admission is touched by these changes in several ways. A policy feature may become available only after you upgrade. The message format used by webhooks may gain a new stable version while an old one is removed. A built-in plugin may change its default behavior. Reading release notes with admission in mind should be a standard step of every upgrade.
Webhook Message Versions
Confirm your webhook service understands the current stable message version before the cluster is upgraded.
Feature Availability
Verify that any policy features you rely on are available and enabled on the target version, especially newer ones.
Policy Engine Compatibility
Make sure the engine version you run supports the new cluster version, and upgrade it in a safe order.
Behavior During the Upgrade
During a control plane upgrade, API servers restart one at a time. Confirm that webhook availability and failure policies keep working through the transition.
Keeping Rules Healthy
Rules grow stale. Teams change, tools are retired, and exceptions pile up. A rule created for a long-forgotten incident can keep blocking a legitimate new workflow. Assign an owner to every rule and webhook, record why it exists, and review the list on a schedule. Retire rules that no longer protect against a real risk, because every extra rule adds latency, confusion, and potential failure.
Problem
A webhook is installed, works well for a year, and is then forgotten. Nobody owns it, its certificate is set to expire, and its container image is never updated.
Why It’s Harmful
One day the certificate expires, the API server cannot reach the service, and a fail-closed webhook blocks all matching requests. The people on call do not know the webhook exists, let alone how to fix it.
Correct Approach
Name an owning team, automate certificate renewal, include the webhook in regular patching, add alerts for expiry and latency, and document an emergency procedure.
25Capacity Planning: The Cost of Admission
Every check has a price. Planning for that price early prevents slow clusters and surprising outages later.
Where the Time Goes
Built-in plugins and native policies run inside the API server and are usually very cheap. Webhooks add a network round trip, the time your service needs to think, and the cost of encrypting the connection. If many matching requests arrive at once, such as during a large rollout or when a node fails and hundreds of Pods are recreated, the webhook sees a burst of traffic that is far higher than its normal level.
Sizing a Webhook Service
Measure the Real Request Rate
Look at the API server metrics for how many matching requests arrive normally and at their peaks, not only on a quiet day.
Load Test the Webhook
Send bursts at the service in a test environment and watch its answer times. Find the point where it slows down and keep a comfortable margin below it.
Watch the Slowest Answers
Track the slowest few percent of answers, not just the average. The slow tail is what users and controllers feel during busy moments.
Reduce What Reaches It
Tighten rules and selectors so only the necessary requests are sent. This is cheaper than adding more replicas.
Scale Automatically with Care
Use automatic scaling where it helps, but keep a healthy minimum number of replicas, because scaling up takes time and the burst may arrive faster.
A slow webhook can slow down the controllers that create Pods, which delays recovery, which creates more requests. During an incident this loop makes things worse. Keeping webhooks fast and well provisioned is part of keeping the cluster resilient.
26A Decision Guide: Choosing the Right Mechanism
With so many options, a simple decision path helps teams pick a tool without a long debate.
flowchart TD
S["New rule needed"] --> Q1{"Does a built-in plugin already do this?"}
Q1 -- "Yes" --> B["Enable and configure the built-in plugin"]
Q1 -- "No" --> Q2{"Does the rule need only the object itself?"}
Q2 -- "Yes" --> Q3{"Validate or change?"}
Q3 -- "Validate" --> V["Native validating policy with CEL"]
Q3 -- "Change" --> M["Mutating policy if available, otherwise webhook"]
Q2 -- "No" --> Q4{"Is it one of many rules needing exceptions and reports?"}
Q4 -- "Yes" --> P["Policy engine"]
Q4 -- "No" --> W["Custom webhook with care"]
Reading the Chart in Words
First ask whether Kubernetes already does what you want. Quotas, default limits, default storage classes, and Pod security levels are built in, and using them costs almost nothing. If nothing built in fits, ask whether the rule depends only on the object. If it does, a native CEL policy is the simplest and most reliable choice. Only when you need outside information, complex generated content, or a whole family of managed rules with exceptions and reporting do you move to policy engines or custom webhooks.
A Few Final Checks Before You Ship
Ready to Ship When
- The rule has a clear owner and a written purpose
- Good and bad samples pass tests in staging
- The failure policy was chosen and tested on purpose
- Denial messages explain how to comply
- Metrics, alerts, and audit visibility are in place
- A rollback path is documented
Not Ready If
- Nobody can say who owns the rule
- It was never tested against updates and subresources
- It has no warning period for existing teams
- The webhook runs as a single replica
- Certificate renewal is manual
27Frequently Asked Questions
No. They apply to create, update, delete, and connect operations only. Reading data is controlled by authorization, not admission.
Authorization decides whether you may perform a kind of action on a kind of resource. Admission examines the specific object in the request and can change it or reject it based on its contents.
No. Admission only sees incoming requests. Existing objects are untouched until someone updates them. Use scanning or reporting features to find existing violations.
Usually not. Cloud providers control the API server settings. This is why webhooks and native policies, which need no API server changes, are so widely used.
Fail closed for controls that protect security or compliance, and fail open for optional conveniences. Whatever you choose, run multiple replicas and test what happens during an outage.
Yes. All mutation completes first, so validation judges the final object that would be stored.
Choose a CEL policy when the rule needs only the object itself, and choose a webhook when you must consult outside data or need complex logic that CEL cannot express.
The Deployment was accepted, but the Pods it tried to create were rejected, often by Pod Security Admission or a policy. Check the events and the status of the related ReplicaSet to see the denial message.
Yes, if it is set to fail closed and its own namespace is not excluded. Always exclude the webhook’s namespace and the system namespaces from its scope.
Yes. That is why webhooks must declare whether they have side effects, and why they must avoid those effects when a request is marked as a dry run.
Yes. Every matching validating rule is consulted, and the request is accepted only if all of them approve. The user may see one or several denial messages, so each message should stand alone and explain its own rule clearly.
Yes. Controllers talk to the API server like any other client, so the ReplicaSets and Pods they create are checked separately from the Deployment you submitted. Rules must therefore tolerate normal controller behavior, including routine status updates.
Nothing. Running Pods keep running exactly as they are. The rule applies the next time something creates or updates a matching object, which is why scanning and reports are needed to find older violations.
Shell access uses a connection subresource of the Pod. A rule written only for the Pod itself does not cover it, so the registration must name the subresource explicitly.
It is the safe default for rules that could block critical components, but exclusions should be kept short and reviewed. Anyone who can create objects in an excluded namespace can bypass the rule there, so control access to those namespaces tightly.
Switch it from deny to warn or audit mode, or remove its binding or registration. Because rules are objects stored in version control, rollback is usually a quick, reviewed change. Keep that procedure documented before you need it.
Usually not. A few well-owned components, native policies, and a shared policy engine are easier to secure, monitor, and keep available than many separate webhooks. Offer teams a simple way to request or propose rules instead.
State which rule was broken, explain in one sentence why the rule exists, and tell the person exactly what to change. A message that names the field, the allowed values, and a link to internal guidance saves a support conversation every time.
A small platform or security team should own the shared rules and the tooling, while application teams propose changes through the normal review process. Clear ownership means someone always answers when a rule blocks a deployment or a certificate is about to expire.
28Summary and Key Takeaways
Admission controllers are the cluster’s last checkpoint before an object is stored. They run after authentication and authorization, first changing requests where allowed, then validating the final result. Built-in plugins handle common needs such as defaults, quotas, and Pod security. Webhooks extend the system with your own logic, while CEL-based policies and policy engines make common rules simpler and safer to run. Used thoughtfully, with clear messages, careful failure settings, and good monitoring, admission control turns your cluster rules from a document people forget into behavior the platform guarantees.
Key Takeaways
- Admission is a content check — it runs after authentication and authorization and examines the actual object being created, updated, deleted, or connected to.
- Mutate first, validate last — all changes happen before the final checks, so validators always judge the object that would really be stored.
- Prefer simple tools first — built-in plugins and native CEL policies avoid the cost and risk of running your own webhook service.
- Choose failure behavior on purpose — decide between fail open and fail closed for each webhook, exclude system namespaces, and test real outages.
- Treat webhooks as control-plane components — secure them, run several replicas, keep answers fast, and automate certificate renewal.
- Roll out gradually — use warn and audit modes before enforcing, and write denial messages that tell people how to fix the problem.
- Remember the limits — admission sees only new requests, so pair it with scanning to find old violations and keep visibility through metrics and audit logs.