Skip to content


This chapter talks about controlling admission through imperative or declarative validation:

Validation Using CEL Validation#

CRDs (can be extended with validation rules written in CEL, with canonical examples on crd validation-rules.

    type: object
        type: object
          - rule: "self.minReplicas <= self.replicas"
            message: "replicas should be greater than or equal to minReplicas."
          - rule: "self.replicas <= self.maxReplicas"
            message: "replicas should be smaller than or equal to maxReplicas."
            type: integer
            type: integer
            type: integer
          - minReplicas
          - replicas
          - maxReplicas

If your controller object is a CRD you own, then this is the recommended way to include validation because it is much less error prone than writing an admission controller. The feature is GA on new clusters, but otherwise generally available as Beta unless your cluster is EOL:

Feature: CustomResourceValidationExpressions

This requires Kubernetes >=1.25 (where the feature is Beta), or Kubernetes >= 1.29 (where the feature is GA).

To include validation rules in the schemas you must add x-kubernetes-validations entries by schemas#overriding-members for the necessary types manually (or inject them more manually):

fn string_legality(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
        "type": "string",
        "x-kubernetes-validations": [{
            "rule": "self != 'illegal'",
            "message": "string cannot be illegal"

and this can be attached with a #[schemars(schema_with = "string_legality)] field attribute on some Option<String> (here). See #1372 too see interactions with errors and a larger struct and other validations.

Future work

Currently overriding the schema to include x-kubernetes-validations is awkward on larger types since you have override items (say) and other properties schemars usually generates. We hope this can be made more ergonomic with future improvements to the overall ecosystem. Help is welcome.

To write CEL expressions consider using the CEL playground. There are more examples in the CRD Validation Rules announcement blog and under crd validation-rules.

Validation Using Webhooks#

AKA writing an admission controller.

These controllers run as webservers rather than the traditional controller loop, and are given an AdmissionReview containing an AdmissionRequest that you must inspect and decide whether to deny or accept.

An admission controller can be Validating, Mutating or both.

See the kube::core::admission module for how to set this up, or the example mutating admission_controller using warp.

Admission controller management is hard

Creating an admission webhook requires a non-trivial amount of certificate management for the webhookconfiguration, and come with its fair share of footguns (see e.g. Benefits and Dangers of Admission Controllers KubeCon'23).

Consider CEL validation / CEL policies before writing an admission controllers.

Two examples of admission controllers in rust using kube:

Validation Using Policies#

External or native objects (that you do not wish to validate at the CRD level), can be validated externally using a ValidatingAdmissionPolicy.

These AdmissionPolicies let you inline CEL validation rules in an object similar to the WebhookConfiguration object for admission controllers, and tell Kubernetes to reject/accept for you based on simpler CEL expressions.

Feature: ValidatingAdmissionPolicy

This feature is available in Beta in 1.28. The talk Declarative Everything at KubeCon'23 shows the current status of the feature and its plans for mutation.

Validation Using Frameworks#

If your use-case is company-wide security policies, then rather than writing an admission controller, or waiting for AdmissionPolicy to handle your case, consider the currently available major tooling for admission policies:

If you are creating validation for a CRD on the other hand, then it's less ideal to tie the validation to a particular framework as this can limit adoption of your operator.