Kubernetes AdmissionReview Management
Kubernetes AdmissionReview Management controls resource changes via webhooks, ensuring compliance and security in Kubernetes clusters.
Kubernetes AdmissionReview Management is the practice of correctly handling the AdmissionReview API object across its supported versions, ensuring a webhook service parses incoming requests and constructs responses in a form the API server can understand, and maintaining that compatibility as Kubernetes itself evolves. Because the AdmissionReview object is the sole channel of communication between the API server and every registered webhook, mismanaging its version or structure breaks admission silently or with confusing errors, independent of whatever policy logic the webhook was designed to enforce.
AdmissionReview Versions
v1 as the Stable, Recommended Version
The admission.k8s.io/v1 version of AdmissionReview is the current stable form, and webhook configurations should declare support for it via admissionReviewVersions: ["v1"]; the now-deprecated v1beta1 version remains supported for backward compatibility on many clusters but should not be relied upon for new webhook implementations.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: example
webhooks:
- name: check.example.com
admissionReviewVersions: ["v1"]
Negotiating the Version to Use
The API server selects the first version listed in a webhook's admissionReviewVersions that it itself supports, meaning a webhook implementation must be prepared to receive and correctly respond in whichever version is actually selected — listing a version the implementation cannot parse results in every matching request failing at the webhook call itself.
Structure of Request and Response
Required Fields in the Request
An incoming AdmissionReview request carries a uid that must be echoed back unchanged in the response, the kind, resource, and operation describing the request, userInfo identifying the caller, and object (and oldObject for updates and deletes) containing the actual submitted content.
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"request": {
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"kind": {"group": "", "version": "v1", "kind": "Pod"},
"resource": {"group": "", "version": "v1", "resource": "pods"},
"operation": "CREATE"
}
}
Required Fields in the Response
The response must set apiVersion and kind matching the request, echo the same uid, and set allowed explicitly; omitting the uid or mismatching it causes the API server to reject the webhook's response entirely, treating it as a malformed reply rather than a valid admission decision.
{
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"allowed": true
}
}
Managing Compatibility Across Kubernetes Upgrades
New Fields Appearing Over Time
As Kubernetes evolves, new optional fields may be added to the AdmissionRequest object (additional userInfo extras, new operation-specific metadata); webhook implementations should parse the request permissively, ignoring unrecognized fields rather than failing on their presence, to remain forward-compatible with future Kubernetes releases.
Testing Against Multiple Kubernetes Versions
Organizations running webhooks across clusters on different Kubernetes versions should test the webhook implementation against each version's actual AdmissionReview payload shape, since subtle differences in populated fields between versions can otherwise go unnoticed until a webhook encounters a payload shape it has not been exercised against.
Common AdmissionReview Handling Mistakes
Losing the uid
A webhook that constructs its response from scratch rather than copying the uid from the incoming request produces a response the API server cannot correlate to the original call, resulting in the request failing even though the webhook itself believed it approved the request.
Mishandling dryRun
The dryRun field on the request indicates the change will not actually be persisted regardless of the webhook's decision; a webhook that performs external side effects (writing an audit record to a system of record, for instance) must check this field and suppress those side effects during a dry run to avoid recording actions that never actually occurred.
if request.get("dryRun"):
return allow_without_side_effects()
Returning Patches Outside the Mutating Phase
A validating webhook that mistakenly includes a patch field in its response has no effect, since only mutating webhooks are permitted to modify the object — confirming a webhook is registered in the correct configuration type (MutatingWebhookConfiguration versus ValidatingWebhookConfiguration) for its intended behavior avoids this category of confusion entirely.