diff --git a/keps/prod-readiness/sig-api-machinery/4153.yaml b/keps/prod-readiness/sig-api-machinery/4153.yaml
new file mode 100644
index 00000000000..06aab41bbcc
--- /dev/null
+++ b/keps/prod-readiness/sig-api-machinery/4153.yaml
@@ -0,0 +1,3 @@
+kep-number: 4153
+alpha:
+ approver: "@deads2k"
diff --git a/keps/sig-api-machinery/4153-declarative-validation/README.md b/keps/sig-api-machinery/4153-declarative-validation/README.md
new file mode 100644
index 00000000000..25c0bf6286a
--- /dev/null
+++ b/keps/sig-api-machinery/4153-declarative-validation/README.md
@@ -0,0 +1,1838 @@
+
+# KEP-4153: Declarative Validation of Kubernetes Native Types
+
+
+
+
+
+
+- [Release Signoff Checklist](#release-signoff-checklist)
+- [Summary](#summary)
+- [Motivation](#motivation)
+ - [Goals](#goals)
+ - [Non-Goals](#non-goals)
+- [Proposal](#proposal)
+ - [Unions](#unions)
+ - [CEL Validation](#cel-validation)
+ - [Formats](#formats)
+ - [IDL tags](#idl-tags)
+- [Analysis of existing validation rules](#analysis-of-existing-validation-rules)
+ - [User Stories (Optional)](#user-stories-optional)
+ - [Kubernetes developer wishes to add a field to a existing API version](#kubernetes-developer-wishes-to-add-a-field-to-a-existing-api-version)
+ - [Kubernetes devekoper adds a v1beta2 version of an API](#kubernetes-devekoper-adds-a-v1beta2-version-of-an-api)
+ - [User wishes to validate the YAML of a kubernetes native type as a Git pre-submit check](#user-wishes-to-validate-the-yaml-of-a-kubernetes-native-type-as-a-git-pre-submit-check)
+ - [User wishes to use Kubebuilder to define a custom resource that embeds PodTemplate](#user-wishes-to-use-kubebuilder-to-define-a-custom-resource-that-embeds-podtemplate)
+ - [Notes/Constraints/Caveats (Optional)](#notesconstraintscaveats-optional)
+ - [Risks and Mitigations](#risks-and-mitigations)
+ - [Risk: Migration to Declarative Validation introduce breaking change to API validation](#risk-migration-to-declarative-validation-introduce-breaking-change-to-api-validation)
+ - [Mitigation: Ensure Invalid Objects Still Invalid](#mitigation-ensure-invalid-objects-still-invalid)
+ - [Mitigation: Ensure Valid Old Objects Still Valid](#mitigation-ensure-valid-old-objects-still-valid)
+ - [Risk: Reduced the fidelity of validation error messages](#risk-reduced-the-fidelity-of-validation-error-messages)
+ - [Mitigation: Fallback to CEL](#mitigation-fallback-to-cel)
+ - [Mitigation: Explore x-kubernetes extension for custom error messages](#mitigation-explore--extension-for-custom-error-messages)
+ - [Risk: Added latency to API request handling.](#risk-added-latency-to-api-request-handling)
+ - [Mitigation: Avoid Conversion to Internal Type](#mitigation-avoid-conversion-to-internal-type)
+ - [Mitigation: Avoid Unstructured Conversion](#mitigation-avoid-unstructured-conversion)
+ - [Mitigation: Use Value Validations Where Possible](#mitigation-use-value-validations-where-possible)
+ - [Mitigation: Go fast paths for hot validation code paths](#mitigation-go-fast-paths-for-hot-validation-code-paths)
+- [Design Details](#design-details)
+ - [Improve Current Schema Quality](#improve-current-schema-quality)
+ - [Publish Complex Validation Rules](#publish-complex-validation-rules)
+ - [Publish Declarative Defaults in Schema](#publish-declarative-defaults-in-schema)
+ - [Support Shared Template Schemas](#support-shared-template-schemas)
+ - [Add missing required fields](#add-missing--fields)
+ - [Zero-Valued Primitive Fields](#zero-valued-primitive-fields)
+ - [Required Zero Fields](#required-zero-fields)
+ - [Optional Zero Fields](#optional-zero-fields)
+ - [Code Generator Solution](#code-generator-solution)
+ - [Create a Library for Validation of Native Types](#create-a-library-for-validation-of-native-types)
+ - [Enrichment of schemas](#enrichment-of-schemas)
+ - [Unit Test Instrumentation](#unit-test-instrumentation)
+ - [E2E Test Instrumentation](#e2e-test-instrumentation)
+ - [Error Message Equivalence](#error-message-equivalence)
+ - [Using Schemas for Validation](#using-schemas-for-validation)
+ - [Request handling](#request-handling)
+ - [Validation of Unstructured input or Deserialized Go Type](#validation-of-unstructured-input-or-deserialized-go-type)
+ - [Deprecation of Legacy Validation](#deprecation-of-legacy-validation)
+ - [Prototype Notes](#prototype-notes)
+ - [Test Plan](#test-plan)
+ - [Prerequisite testing updates](#prerequisite-testing-updates)
+ - [Unit tests](#unit-tests)
+ - [Integration tests](#integration-tests)
+ - [e2e tests](#e2e-tests)
+ - [Graduation Criteria](#graduation-criteria)
+ - [Alpha](#alpha)
+ - [DeclarativeValidationExtensionsInOpenAPI](#)
+ - [DeclarativeValidation](#-1)
+ - [Beta](#beta)
+ - [DeclarativeValidationExtensionsInOpenAPI](#-2)
+ - [DeclarativeValidation](#-3)
+ - [GA](#ga)
+ - [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
+ - [Version Skew Strategy](#version-skew-strategy)
+- [Production Readiness Review Questionnaire](#production-readiness-review-questionnaire)
+ - [Feature Enablement and Rollback](#feature-enablement-and-rollback)
+ - [Rollout, Upgrade and Rollback Planning](#rollout-upgrade-and-rollback-planning)
+ - [Monitoring Requirements](#monitoring-requirements)
+ - [Dependencies](#dependencies)
+ - [Scalability](#scalability)
+ - [Troubleshooting](#troubleshooting)
+- [Implementation History](#implementation-history)
+- [Drawbacks](#drawbacks)
+- [Alternatives](#alternatives)
+ - [Validate On Storage Type Rather than Request Type](#validate-on-storage-type-rather-than-request-type)
+- [Infrastructure Needed (Optional)](#infrastructure-needed-optional)
+
+
+## Release Signoff Checklist
+
+
+
+Items marked with (R) are required *prior to targeting to a milestone / release*.
+
+- [x] (R) Enhancement issue in release milestone, which links to KEP dir in [kubernetes/enhancements] (not the initial KEP PR)
+- [x] (R) KEP approvers have approved the KEP status as `implementable`
+- [x] (R) Design details are appropriately documented
+- [x] (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input (including test refactors)
+ - [ ] e2e Tests for all Beta API Operations (endpoints)
+ - [ ] (R) Ensure GA e2e tests meet requirements for [Conformance Tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)
+ - [ ] (R) Minimum Two Week Window for GA e2e tests to prove flake free
+- [x] (R) Graduation criteria is in place
+ - [ ] (R) [all GA Endpoints](https://github.com/kubernetes/community/pull/1806) must be hit by [Conformance Tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)
+- [x] (R) Production readiness review completed
+- [x] (R) Production readiness review approved
+- [ ] "Implementation History" section is up-to-date for milestone
+- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io]
+- [ ] Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
+
+
+
+[kubernetes.io]: https://kubernetes.io/
+[kubernetes/enhancements]: https://git.k8s.io/enhancements
+[kubernetes/kubernetes]: https://git.k8s.io/kubernetes
+[kubernetes/website]: https://git.k8s.io/website
+
+## Summary
+
+With this enhancement, Kubernetes Developers will declare validation rules using
+IDL tags in the `types.go` files that to define the Kubernetes native API types.
+For example:
+
+```go
+// staging/src/k8s.io/api/core/v1/types.go
+
+// +validationRule="!self.hostNetwork || self.containers.all(c, c.containerPort.all(cp, cp.hostPort == cp.containerPort))"
+type PodSpec struct {
+ Containers []Container `json:...`
+}
+
+type Container struct {
+ // ...
+
+ Ports []ContainerPort `json:...`
+
+ // ...
+}
+
+type ContainerPort struct {
+ // ...
+
+ // ...
+ //
+ // +minimum=1
+ // +maximum=65535
+ HostPort int32 `json:...`
+
+ // ...
+ //
+ // +minimum=1
+ // +maximum=65535
+ ContainerPort int32 `json:...`
+
+ // ...
+}
+```
+
+In this example, both `+validationRule`, `+minimum` and `+maximum` are IDL tags.
+
+The declarative validation rules will be used by the kube-apiserver to
+validate API requests.
+
+The declarative validation rules will also be included in the published OpenAPI:
+
+```json
+// Pod Spec
+"openAPIV3Schema": {
+ "type": "object",
+ "x-kubernetes-validations": [
+ {
+ "rule": "!self.hostNetwork || self.containers.all(c, c.containerPort.all(cp, cp.hostPort == cp.containerPort))"
+ }
+ ],
+}
+
+...
+
+// Container Port
+"openAPIV3Schema": {
+ "type": "object",
+ "properties": {
+ "hostPort": {
+ "minimum": 1,
+ "maximum": 65535
+ ...
+ }
+ "containerPort": {
+ "minimum": 1,
+ "maximum": 65535
+ ...
+ }
+ }
+}
+```
+
+It is important to note that the declarative validation will use the same set of
+validation options available today for CRDs. namely:
+
+- [JSON Schema value validations](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00) (e.g. `format`, `maxItems`)
+- [CEL Validation Rules](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules) (e.g. `self.replicas <= self.maxReplicas`)
+- Relevant [merge strategy declarations](https://kubernetes.io/docs/reference/using-api/server-side-apply/#merge-strategy) (e.g. `listType=set`)
+
+## Motivation
+
+Kubernetes API validation rules are currently written by hand, which makes them
+difficult for users to access directly, review, maintain, and test.
+
+Declarative validation will benefit Kubernetes maintainers:
+
+- It will make it easier to develop, maintain and review APIs.
+- It will make it easier programatically inspect and analyze the API, enabling
+ new tools and improved documentation.
+- It will enable improvements to the API machinery. For example, a feature like
+ ratcheting validation will become more tractable to implement because the
+ feature can be implemented once in the declarative validation subsystem
+ rather than piecemeal across the 15k lines of hand written validation code.
+
+Declarative validation will also benefit Kubernetes users:
+
+- It will give users direct access to the most actual API validation rules, which
+ are currently only available to developers willing and able to find and read
+ the hand written validation rules.
+- It will enable clients to perform validation of native types earlier in
+ development worflows ("shift-left"), such as at with a Git pre-submit linter.
+- It will improve API composition. In particular CRDs that embed native types
+ (such as PodTemplate), which gain validation of the native type automatically.
+ This has the potential to simplify controller development and improve end
+ user experiences when using CRDs.
+- Validation is performed on versioned type, so error message and attributed field
+ path is more likely to be relevant to the user. (Though no known cases of misattributed field errors have yet occurred)
+
+Please feel free to try out the
+[prototype](https://github.com/jpbetz/kubernetes/blob/cel-for-native/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/README.md)
+to get hands on experience with this proposed enhancement.
+
+### Goals
+
+- Vast majority (95%+) of hand written validation are replaced with declarative
+validation. The remaining hand written rules will primarily be rules that _should
+not_ be published as part of the API, usually because server side state is
+involved in the validation decision.
+
+- `types.go` files become the de-facto IDL of Kubernetes for native types.
+It is worthing noting that `+enum` support, `+default` support and similar
+enhancements all moved our API development forward in this direction. This
+enhancement is an attempt to continue that story arc.
+
+- API Validations and Defaults are readable and manageable. The IDL should be
+a joy to use for API authors, reviewers and maintainers. Common Complex
+relationships have simple-to-express idioms in the IDL.
+
+- CRDs and native types are validated and published in OpenAPI in a consistent
+and uniform way. Improvement we make to CEL to enable declarative validation of
+native types will be made available to CRD authors and vis-versa.
+
+- No change to error message structure for clients. Difference to clients is
+limited to minimal changes to error detail strings.
+
+### Non-Goals
+
+- It is not a goal for _all_ validation rules to be published to OpenAPI. There
+ exist complex, stateful rules that should not be published in OpenAPI. These
+ will remain "server side only" validation rules.
+- It is not a goal to require that _all_ validation rules be written in CEL. We
+ will continue to support hand written validation rules indefinitely for use
+ cases that are a poor fit using the existing validation mechanism (or
+ something very similar).
+
+
+## Proposal
+
+Declarative validation will be performed against versioned APIs. This differs from the hand
+written validation, which is evaluated against internal types.
+
+Go IDL tags will be added to support the following declarative validation rules:
+
+| Type of valiation | Go IDL tag | OpenAPI validation field | Reason Type |
+| ---------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------- |
+| string format | `+format={format name}` | `format` | Invalid |
+| size limits | `+min{Length,Properties,Items}`, `+max{Length,Properties,Items}` | `min{Length,Properties,Items}`, `max{Length,Properties,Items}` | TooMany, TooLong |
+| numeric limits | `+minimum`, `+maximum`, `+exclusiveMinimum`, `+exclusiveMaximum` | `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum` | Invalid |
+| required fields | `+optional` (exists today) | `required` | Required |
+| enum values | `+enum` (exists today) | `enum` | NotSupported |
+| uniqueness | `listType=set` (sets and map keys) | `x-kubernetes-list-type` | Duplicate |
+| regex matches | `+pattern` | `pattern` | Invalid |
+| cross field validation | `validationRule="{CEL expression}"` | `x-kubernetes-validations` | user specified |
+| [transition rules][1] | `validationRule="{CEL expression using oldSelf}"` | `x-kubernetes-validations` | user specified |
+| special case: name format | `+nameFormat={format name}` | `x-kubernetes-validations` (see "format" section below for details) | Invalid |
+
+Specific reason types can be customized for `x-kubernetes-validations` to
+any [supported field.Error reason](https://github.com/kubernetes/kubernetes/blob/c5a8015bbae1e1095813d8e0719f017477dc7112/staging/src/k8s.io/apimachinery/pkg/util/validation/field/errors.go#L105-L140).
+
+xref: [Kubernetes mapping of OpenAPI value validations to response code](https://github.com/kubernetes/kubernetes/blob/7adcb3cb37084750ab572a179ba01b9878b8de5f/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation.go#L60)
+
+> During development we may add syntax sugar for common idioms we identify
+> such as +immutable or +mutally_exclusive, +contextual (for unions) that desugar
+> into equivalent CEL
+
+### Unions
+
+Unions are informally defined but common in built-in types.
+
+We will convert most union validation to CEL expressions. For example:
+
+```go
+// staging/src/k8s.io/api/apps/v1/types.go
+
+type DeploymentSpec struct {
+ // ...
+ //
+ // +minimum=0
+ Replicas string `json...`
+
+ // ...
+ //
+ // +validationRule="!(self.type == 'Recreate') || !has(self.rollingUpdate)",message="may not be specified when strategy `type` is Recreate",reason=Forbidden,field="rollingUpdate"
+ // +validationRule="!(self.type == 'RollingUpdate') || has(self.rollingUpdate)",message="this should be defaulted and never be nil",reason=Required,field="rollingUpdate"
+ Strategy DeploymentStrategy `json:...`
+
+ // ...
+}
+```
+
+For backward compatibility with existing validations, `reason` and `field` will
+be added to make it possible to declare a validation rule in CEL that matches
+not just the logic of the hand written validation it replaces, but also the
+exact field path and reason type.
+
+> There has been a past KEP to add support for Unions directly to OpenAPI, but it has since been dropped ([xref](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/1027-api-unions))
+
+### CEL Validation
+
+CEL will play a major role in declarative validation by offering a way to
+declare validation rules for use cases that are too complex to be declared using
+JSON Schema value validations. Using CEL to validate APIs has been successfully
+demonstrated by CRD Validation Rules, which are on track for GA in 1.28.
+
+CEL rules will typically be placed on struct or field declarations and access
+multiple fields nested below the level of the type or field where the CEL
+expression is declared, e.g.:
+
+```go
+
+ //+validationRule="!self.widgetType == 'Component' || !['badname2', 'badname2'].exists(notAllowed, self.componentName.contains(notAllowed))",reason=Forbidden
+ type FizzBuzzSpec struct {
+ Type WidgetType `json...`
+ ComponentName string `json...`
+ }
+```
+
+Note that the `+validationRule` IDL tags supports multiple optional fields after the expression string. The supported fields are:
+
+- `message`: A vailidation failure message string.
+- `messageExpression`: A CEL expression that evalutes to a validation failure message string. Takes precedence over message.
+- `reason`: Must be one of [Required, Forbidden, Invalid, RequestEntityTooLarge].
+- `field`: A JSONPath to the sub-field that a validation failure should be attributed to.
+
+We will need to extend our CEL libraries to make it possible to migrate all the
+validation rules that exist in the Kubernetes API today.
+
+- `isFormat() ` and `validateFormat() >` will be added to allow formats to be checked in CEL
+ expression and for format violations to be reported using `messageExpression: "self.validateFormat('ipv6')"`
+- IP and CIDR library:
+ - `isIP(string) bool`
+ - `ip(string) IP`
+ - `IP.is4() bool`
+ - `IP.is6() bool`
+ - `IP.isLoopback() bool`
+ - `isCIDR(string) bool`
+ - `cidr(string) CIDR`
+ - `CIDR.overlaps(CIDR) bool`
+ - `CIDR.containsIP(IP) bool`
+- UTF8 Library (for CRD validation, ManagedFields)
+ - IsValid
+ - IsPrint
+ - IsControl
+- Selectors
+ - `Matches(LabelSelector)`
+
+### Formats
+
+A significant portion of all validation rules in the API check that a field
+value conforms to a particular "format". A prominent example is `metadata.name`
+and `metadata.generateName` validation.
+
+We will extend the [available list of
+formats](https://github.com/kubernetes/kube-openapi/blob/7fbd8d59e5b89f2ca43a5dcececbffc0bb186c37/pkg/validation/strfmt/default.go#L128)
+to cover formats heavily used by the Kubernetes API, namely:
+
+| Format | Primary validate uses |
+| ---------------------------- | ---------------------------------- |
+| 'dns1123subdomain' | metadata name and generateName |
+| 'dns1123label' | metadata name and generateName |
+| 'dns1035label' | Scoped names and keys |
+
+We will add all of these to the supported list of formats in kube-openapi.
+We will also document all supported formats on the Kubernetes website.
+
+Other candidate format types are:
+
+- `APIVersion` (GroupVersion)
+- [Quantity](https://github.com/kubernetes/kubernetes/blob/c5a8015bbae1e1095813d8e0719f017477dc7112/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go#L31-L111)
+- [Qualified name](https://github.com/kubernetes/kubernetes/blob/12dc19d46fb97cbbfeb1e12b8a10ff7ae73d9515/pkg/apis/core/validation/validation.go#L138-L145)
+- [Fully qualified name](https://github.com/kubernetes/kubernetes/blob/c5a8015bbae1e1095813d8e0719f017477dc7112/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L73-L91)
+- [Fully qualified domain name](https://github.com/kubernetes/kubernetes/blob/c5a8015bbae1e1095813d8e0719f017477dc7112/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L93-L116)
+- [Label Value](https://github.com/kubernetes/kubernetes/blob/c5a8015bbae1e1095813d8e0719f017477dc7112/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L164-L176)
+- Integer (as opposed to any floating point)
+
+> Until CRD Validation Ratcheting is stable, these formats will be translated into an inline schema containing either the regex pattern or the CEL expression for the format.
+> Related Note: k8s also supports unused formats that should be removed over time: https://github.com/kubernetes/kubernetes/issues/97733
+
+### IDL tags
+
+IDL tags may be used directly on type declarations and indirectly on field and
+type aliases. For example:
+
+```go
+type Widget struct {
+ // +validationRule="self.matches('[a-z][1-9]+')"
+ Component PartId `json...`
+}
+
+// +maxLength=20
+type PartId = Identifier
+
+// +format=dns1123label
+type Identifier string
+
+type Contraption struct {
+ Component Identifier `json...`
+}
+```
+
+In the above example, the `widget.component` field is validated against all three
+IDL tags. But `contraption.component` is only validated against `+format=dns1123label`.
+
+Shared types present a challenge. For example, different Kubernetes resources
+have different validation rules for `metadata.name` and `metadata.generateName`.
+But all resources share the `ObjectMeta` type.
+
+We can support these uses cases with CEL validation rules:
+
+```go
+type ExampleSpec struct {
+
+ // +validationRule="!has(self.name) || self.name.isFormat('dns1123subdomain')",field="name"
+ // +validationRule="!has(self.generateName) || self.generateName.replace('-$', 'a').isFormat('dns1123subdomain')",field="generateName"
+ metav1.ObjectMeta `json...`
+}
+```
+
+Because the above use case is so common, we plan to offer a special tag to make
+declaring the above rules convenient:
+
+```go
+// +nameFormat='dns1123subdomain'
+metav1.ObjectMeta `json...`
+```
+
+Another example: Pod `container` and `initContainer` fields share the same
+`Container` type but have different validation rules. The rules that are the
+same for both can be declared on `Container` but any rules that are different
+can be declared on the `container` and `initContainer` fields using CEL. E.g.:
+
+```go
+// +validationRule="!has(self.RestartPolicy)"
+Containers []Container `json...`
+```
+
+## Analysis of existing validation rules
+
+At the time of writing this document, there are 1181 validation rules written in about
+15k lines of go code in [kubernetes/kubernetes/pkg/apis](https://github.com/kubernetes/kubernetes/commit/0c62b122c02bff9131b6db960042150a3638d3f3).
+
+Roughly 30% of validation rules may require CEL expressions. 15% of these are
+forbidden rules which primarily check which fields are allowed when a union
+discriminator is set. 10% are object name validations, and the remaining 10% are
+cross field validation checks, mainly mutual exclusion and some "transition
+rules" (e.g. immutability checks).
+
+The remaining 70% of validation rules can be represented using JSON Schema value
+validations. `optional`, `format` and `enum` will the the most frequently used.
+
+![Validation types](validation-types.svg)
+
+![Object metadata name validations](metadata-name-types.svg)
+
+![Complex Rules Which Require CEL](requires-cel.svg)
+
+### User Stories (Optional)
+
+
+
+#### Kubernetes developer wishes to add a field to a existing API version
+
+1. Developer add the field to the Go struct
+2. Developer adds needed IDL tags to Go struct
+3. Developer adds validation_test.go cases (same as today)
+4. API reviewers review IDL tags along with Go struct change
+
+#### Kubernetes devekoper adds a v1beta2 version of an API
+
+1. Develop copies over v1beta1 API and creates v1beta2
+2. Linter verifies that IDL tags match for both version of API (unless
+ exceptions are put in exception file)
+3. API reviewer can review change knowing that validation is consistent unless
+ there are lines added to exception file
+
+#### User wishes to validate the YAML of a kubernetes native type as a Git pre-submit check
+
+1. OpenAPI of native types is downloaded from kube-apiserver
+2. Tool that checks YAML against OpenAPI schema is used to validate YAML in a
+ Git pre-submit (there are tools being written now that will also handle
+ x-kubernetes-validations)
+
+#### User wishes to use Kubebuilder to define a custom resource that embeds PodTemplate
+
+1. Go struct that declares custom resource references the go struct of v1.PodTemplate.
+2. Kubebuilder recognizes the Go IDL tags introduced by this KEP (Note that
+ Kubebuidler already has IDL tags:
+ https://book.kubebuilder.io/reference/markers/crd-validation.html, but they
+ are different than what we propose here)
+3. Kubebuilder generates appropriate OpenAPI for the CRD resulting in full
+ validation of the PodTemplate
+
+### Notes/Constraints/Caveats (Optional)
+
+
+
+### Risks and Mitigations
+
+#### Risk: Migration to Declarative Validation introduce breaking change to API validation
+##### Mitigation: Ensure Invalid Objects Still Invalid
+
+Objects which previously did not pass validation must still not pass validation.
+This can be restated simply as: all currently handwritten validations must be
+included in the schema. If all validations are in the schema, it follows that the
+schema will reject the same set of objects as before.
+
+We can mitigate this by:
+
+1. All Validation Tests Have 100% Coverage
+2. All Validation Tests Succeed against native and schema-based validation backends
+
+To accomplish this, we will:
+
+1. New Presubmit Verify Script to Ensure 100% for future tests
+2. A General Validation Test Framework - Most tests are already written declaratively,
+we will refactor them to all use a general framework for validation tests. The
+framework will evaluate the validation test case first on native types, then convert
+the case to each supported version of the kind to ensure the error arises also
+from schema-based validation. The framework will have a way to make exceptions
+for certain errors which are version-specific.
+3. Refactor all `validation_tests.go` unit tests to have 100% coverage of their
+respective `validation.go` files as well as make use of the validation test framework.
+
+##### Mitigation: Ensure Valid Old Objects Still Valid
+
+Objects which previously passed validation must still pass validation. For our
+purposes this can be thought of as ensuring the schema-based validation does not
+raise new errors which previously did not exist.
+
+It is not possible to be 100% sure of this property, in fact, there may be
+new validations added to patch bugs in existing ones. But we can mitigate this
+risk:
+
+1. Catch and fix any significant differences in schema validations
+
+ During alpha and beta phases, we will run both validation systems in parallel
+ and return the errors from the old system to the user. We will report in logs
+ and metrics the differences. Over time we will reduce the number of reported
+ differences to zero as these issues are caught.
+
+ To help catch these errors faster, we will also refactor all e2e tests to
+ enable this feature and check for validation error differences.
+
+2. Minimize the impact of any new changes introduced
+
+ As a precondition of this KEP graduating to GA, the feature
+ `CRD Validation Ratcheting` must also reach GA. Validation Ratcheting would
+ reduce impact to users by allowing any new schema validations errors due to
+ this feature to be ignored for unchanged portions of an object.
+
+
+#### Risk: Reduced the fidelity of validation error messages
+
+OpenAPI value validations do not offer a way to specify an exact message or
+a reason type. It is also possible some of the more general api errors have error
+messages that contain context not found in OpenAPI Error.
+
+##### Mitigation: Fallback to CEL
+
+For cases where the potentially lost error message context must be retained,
+we can instead encode the rule as a CEL rule which allows for arbitrary error
+strings.
+
+##### Mitigation: Explore `x-kubernetes` extension for custom error messages
+
+An option to consider to all custom error messages to schema-based value
+validations if we see that we really need it is to introduce a new extension:
+`x-kubernetes-validation-errors` which maps schema validation fields to
+a custom error message for failing that field's validation:
+
+```yaml
+minLength: 0
+x-kubernetes-validation-errors:
+ minLength:
+ message: "this custom error message shows when violating minLength rather than default message"
+ reason: Invalid
+```
+
+#### Risk: Added latency to API request handling.
+
+The design decision to declaratively validate API versions has performance
+implications.
+
+Today, the apiserver's request handler decodes incoming versioned API requests
+to the versioned type and then immediately performs an "unsafe" conversion to
+the internal type when possible. All subsequent request processing uses the
+internal type as the "hub" type. Validation is written for the internal
+type and so are per-resource strategies.
+
+With this change, the internal type will no longer be responsible for
+validation.
+
+If we were to convert from the internal back to the version of the API request
+for validation, we would introduce one additional conversion. If we make this
+an "unsafe" conversion, than is will be low cost for the vast majority of requests.
+
+We will benchmark this approach and plan to use it for alpha.
+
+Long term, we could do better:
+
+Since the internal type will no longer be used for validation, it becomes a lot
+less important. It is still important to have a hub type. But why not pick one
+of the versioned types to be the hub type? The vast majority of APIs only have
+one version anyway. The obvious candidate version to choose for the hub version
+would the perferred storage version.
+
+Switching to a versioned type for the hub type would have a few implications:
+
+- We would eliminate the need for internal versions.
+- We would reduce the need for "unsafe" conversions (a small security win) since
+ most APIs only have a single v1 version and so the entire request handling process
+ would simply use that version.
+- We would introduce more conversion when API request version differs from the
+ hub version. But beta APIs are off-by-default and we expect a lot less mixed
+ version API usage than in the past.
+
+This "hub version" change feels like something that could be made somewhat
+independent of this KEP.
+
+
+##### Mitigation: Avoid Conversion to Internal Type
+
+Requests are received as the versioned type, so it should be feasible to avoid
+extra conversions for resources that have no need of handwritten validations.
+
+##### Mitigation: Avoid Unstructured Conversion
+
+SMD's [value](https://github.com/kubernetes-sigs/structured-merge-diff/tree/master/value)
+wrappers have already been benchmarked and shown to have low overhead.
+
+##### Mitigation: Use Value Validations Where Possible
+
+Most validations will be possible to evaluate with simple value validations
+in native OpenAPI (required checks, enum value checks, etc). The rest are
+CEL expressions which are expected to account for 30% of all validation rule.
+
+CEL evaluation is relatively efficient we will gather detailed benchmarks baselined against native types to demonstrate this.
+
+##### Mitigation: Go fast paths for hot validation code paths
+
+If CEL becomes a bottleneck, we may explore possibilities to run Go rather than
+interpreted CEL behind the scenes for certain hot code paths:
+ - Generate Go code from CEL expressions.
+ - Hand write validation code for select validations and call those
+ directly (or from CEL).
+
+## Design Details
+
+### Improve Current Schema Quality
+
+1. Add declarative defaulting support to OpenAPI code generator
+1. OpenAPI Gen Enhancements
+ - Add IDL tags for all possible types of validations. Similar to [kubebuilder crd markers](https://kubebuilder.io/reference/markers/crd-validation)
+ - Overridable defaults and validations of a reusable type
+ - Populate defaults for types defaulted to implicit zero
+ - Populate non-empty constraints for required fields
+ - Declarative Defaults to Constants
+ - IDL tags for common complex relationships we deem worthy (+immutable, +mutually_exclusive, +contextual)
+1. Introduce Feature Flag: `DeclarativeValidationExtensionsInOpenAPI` to expose
+ new extensions added to the schema.
+ - `x-kubernetes-validations`. This field is published already for CRDs, so
+ most clients should already be aware of handling it.
+ - Must support multi-line expression entry, and multiple lines for reason,
+ code, fieldpath of a single rule. Retaining whitespace is NOT a requirement.
+ May use `"""` or possibly explore Go-style multiline string literal.
+ - `x-kubernetes-errors`: Mapping of OpenAPI V3 schema fields to custom error
+ messages
+ - `x-kubernetes-strip-zero`: Informs consumers of the schema that the object
+ should be considered strip-zero if it takes on the given value
+2. Introduce new [CEL libraries](#cel-validation) that will be needed to verify native schemas.
+
+#### Publish Complex Validation Rules
+
+Until now most validation rules have not been included in the schema, since
+they are not expressible using OpenAPI's format.
+
+Now that Kubernetes has GA support for CEL in CRDs, it makes sense to use the
+same feature to express rules for native types.
+
+#### Publish Declarative Defaults in Schema
+
+A consumer of a schema cannot fully take advantage of the schema for validation
+or linting purposes unless the can ably populate defaults. Many of our defaults
+are stored in constants.
+
+We will add features to our code generation tools to refer to symbolic constants
+from `+default` annotations, and populate OpenAPI with a higher proportion of our
+defaults.
+
+A list of existing differences between handwritten and schema-populated defaults
+can be found [here](https://github.com/kubernetes/kubernetes/issues/119766).
+
+#### Support Shared Template Schemas
+
+Reusable template types pose a challenging problem since depending
+upon their usage they may have different defaults or validation constraints
+for multiple fields. This is not supported by our OpenAPI code generators.
+
+One example is `core.v1.PersistentVolume.Spec.Capacity`. When used in a
+regular `PersistentVolume` this field is required and cannot be empty.
+However, when used `inline` as a template, `Capacity` is no longer required.
+
+To address this we will need additional marker comments
+
+We will need to add the ability for fields that re-use a type to specify a
+field-level for its nested fields. Kube-openapi gen will inline the custom
+definition.
+
+#### Add missing `required` fields
+
+Our `kube-openapi` code generator adds to the schema's required fields
+any field that is not labelled with `+optional` or `omitempty` JSON tag:
+
+```go
+type Container struct {
+ // Name of the container specified as a DNS_LABEL.
+ // Each container in a pod must have a unique name (DNS_LABEL).
+ // Cannot be updated.
+ Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
+ ...
+}
+```
+
+```json
+ "io.k8s.api.core.v1.Container": {
+ "type": "object",
+ "description": "A single application container that you want to run within a pod.",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ ....
+ "name": {
+ "default": "",
+ "description": "Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated.",
+ "type": "string"
+ },
+ ....
+ },
+ }
+```
+
+But there are examples in our API where a required field is `omitempty`:
+
+```go
+type Rule struct {
+ // APIGroups is the API groups the resources belong to. '*' is all groups.
+ // If '*' is present, the length of the slice must be one.
+ // Required.
+ // +listType=atomic
+ APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,1,rep,name=apiGroups"`
+
+ ...
+}
+```
+
+These fields are not included in the `required` list. To fix this, we can simply
+add a `+required` field. All fields without `+required` or `+optional` explicitly
+will use `omitempty` to infer default behavior as it does today.
+
+#### Zero-Valued Primitive Fields
+
+Serialization to Go can impact declarative validation, which interprets the
+resource as an untyped JSON object, respecting go tags. Specifically zero is
+often considered to be the same as `unspecified`.
+
+Unless the fact that zero values are considered to be unset is captured in the
+schema:
+
+1. We won't be able to accurately capture the Go validations into CEL or
+JSONSchema, or they will be buggy
+2. CRDs and native types with the same schema will not have the same validation
+behavior. Downstream clients of the schema such as kubectl-validate and
+ValidatingAdmissionPolicy will trip over this.
+
+##### Required Zero Fields
+
+For `required` fields that are not labelled as a pointer, we check them by
+checking if their value is the empty value:
+
+`v1.Container.Name` is such an example:
+
+```go
+ namePath := path.Child("name")
+ if len(ctr.Name) == 0 {
+ allErrs = append(allErrs, field.Required(namePath, ""))
+ } else {
+ allErrs = append(allErrs, ValidateDNS1123Label(ctr.Name, namePath)...)
+ }
+```
+
+`apiregistration/v1.RuleWithOperations.APIGroups` is such an example:
+
+```go
+ if len(rule.APIGroups) == 0 {
+ allErrors = append(allErrors, field.Required(fldPath.Child("apiGroups"), ""))
+ }
+```
+
+This makes not only `unspecified` throw a required field error, but `""` strings, `[]`
+slices, and `{}` maps. The schema for all required fields must be
+updated to reflect that zero is considered unspecified.
+
+| Type | Annotation |
+|--------|----------------------------------------------------|
+| string | `x-kubernetes-strip-zero: true` |
+| int | `x-kubernetes-strip-zero: true` |
+| float | `x-kubernetes-strip-zero: true` |
+| slice | `x-kubernetes-strip-zero: true` |
+| map | `x-kubernetes-strip-zero: true` |
+| pointer| N/A (codegen forces optional) |
+| struct | N/A (codegen forces optional with `default: {}`) |
+
+
+One alternative approach would be to set `minimum`, `minLength`, etc. on necessary
+types. That approach has the drawback that the error messages will no longer say
+the field was required but instead that the minimum was not met. Additionally,
+`x-kubernetes-strip-zero: true` more directly expresses that empty is
+considered unset, and is also needed to solve a similar problem for `omitempty`
+fields.
+
+##### Optional Zero Fields
+
+Consider the following omitempty non-pointer field from `DeploymentSpec`:
+
+```go
+type DeploymentSpec struct {
+ ...
+
+ Paused bool `json:"paused,omitempty"`
+
+ ...
+}
+```
+
+K8s 1.28 and below represents this field with the spec:
+
+```json
+{
+ ...
+ "properties": {
+ ...
+ "paused": {
+ "type": "boolean"
+ }
+ ...
+ }
+}
+```
+
+`Paused` implicitly defaults in Go to `false`.
+
+This would surface as:
+1. `has(self.paused)` in CEL on the Container object always returns `false` if
+that value is `false`. But a CRD with identical schema would return `true`.
+A proof of concept example of how this bug could bite users of ValidatingAdmissionPolicy
+is [here](https://github.com/kubernetes/kubernetes/pull/120244).
+2. CEL and JSONSchema Validations of the field if they exist also will not run.
+This is a concern if empty values do not match the schema.
+
+For optional fields this can be solved by annotating all non-pointer fields with
+`x-kubernetes-strip-zero: true`.
+
+Optional fields for which the implicit default is treated as a set value should
+add a `+default=` annotation to their empty value. This will give better
+ergonomics in CEL for fields like `Paused`
+
+An exhaustive list of all 730 omit-empty non-pointer is [found here](https://gist.github.com/alexzielenski/05f594f3974aec9b3e74620b8dc7dde1). Struct types already have their
+defaults populated with the go zero value, so they are excluded from this list.
+
+##### Code Generator Solution
+
+A conservative change we can apply to the code generator would be to automatically
+annotate `x-kubernetes-strip-zero: true` to all non-pointer fields.
+
+Fields for which the implicit default is considered a set value can also add a
+`+default` marker to express it explicitly over time, but it is not required to
+correct the difference in native types vs CRDs. Defaulting should occur after
+zero values are stripped, so fields with both should have zero and nulls defaulted
+correctly.
+
+### Create a Library for Validation of Native Types
+
+We will need a library that provides a function similar to `Validate(schema, object, oldObject) error`.
+
+One might suggest to use the existing CRD validation logic for native types.
+There are quite a few reasons not to:
+
+1. `spec.Schema` uses refs, and is possibly (self and/or mutually) recursive (e.g.: JSON, JSONSchemaProps). Not all native schemas are convertible to the structural schema
+type used by CRD validation code path.
+
+2. Native types are validated directly, and CRDs are validated as unstructured.
+We'd like to avoid losing too much performance to declarative validation. It
+would be very expensive to convert every object to unstructured for validation.
+
+3. CEL validations in existing CRD validations do not work under quantifiers
+such as `allOf`, `anyOf`, `oneOf`. This restriction is to avoid modifying the
+existing schema validation logic to support CEL validation. This can be worked
+around for now with CEL rules higher in the schema, but it would be a nice win
+for users if they could intermingle CEL with schema validations in the JSONSchema structure.
+
+4. The `kube-openapi` openapi validation code is full of questionable third party
+code which is not ideal to depend on for the future. It is difficult to extend such as for [KEP-4008: CRD Validation Ratcheting](https://kep.k8s.io/4008). To change it
+to work for types other than `unstructured` without changing its behavior does
+not seem trivial.
+
+To avoid duplicating code, we would like the validation system used for native
+types to be used also by CRDs. If not immediately, then it should be possible
+eventually.
+
+To that end, given the constraints above, we will:
+
+1. Adapt existing CRD validation code to be performed against a common schema
+and value interface. We will re-use the one already employed by CEL for the same purpose of unifying native and CRD schema code.
+2. Create a version of the `kube-openapi` swagger validator that operates on
+`structured-merge-diff`'s benchmarked `value.Value` interface used by Server-Side-Apply
+`value.Value` can be constructed from both native types and `unstructured`. In the best case we can re-use the same instance and perform validation with 0 conversions.
+
+After doing so, we are able to use the same code to efficiently validate both
+CRDs and native types.
+
+### Enrichment of schemas
+
+Before enriching schemas, we must create a framework for validation tests
+that runs both native and schema validators and compares the results.
+
+Once we have a framework we will publish a tracking issue with an example of a group-version being annotated and instrumented with the framework. The issue
+will also include a guide for contributors to:
+1. Add declarative validation rules using [Go IDL tags](#proposal).
+1. Instrument validation_test.go unit tests to ensure declarative
+ and handwritten validation produce the same errors, and have
+ complete coverage of handwritten validation code.
+1. Instrument e2e testing to catch errors in declarative validation errors
+1. Report issues if they come up
+
+#### Unit Test Instrumentation
+
+To gain confidence that all existing validations are performed within the schema,
+we will add:
+
+1. A verify script that ensures `validation_test.go` code coverage of
+ `validation.go` for all resources is equal to a value specified in a file
+ committed to the repository so we may ratched coverage upwards over time.
+2. A resource testing framework general enough to be used for all resource's
+validation tests, as well as make possible exceptions for errors which only
+occur in specific versions of a type. The framework will validate the test case
+against all versions and both handwritten and schema backends.
+
+Over time we will instrument all resources to use the framework and increase
+coverage to as close to 100% as possible for all resources.
+
+##### E2E Test Instrumentation
+
+To assist in finding discrepencies in errors faster, we will add method of running
+all e2e tests with Declarative Validation enabled to flag discrepencies in errors
+triggered by the e2e testing suite.
+
+##### Error Message Equivalence
+
+Some error messages will be phrased differently but preserve the same semantic
+meaning when converted to the declarative validation system. For our testing to
+check if errors are changed we have two options:
+
+1. Write trusted regexes to match equivalence that work pretty well but have no guarantee of being complete.
+
+ We may choose to do this for cases where the probability of false equivalence
+is near-zero. e.g. `field.Required(fldPath, "")` might have a slightly difference
+error from the standard openapi `required`, but they should be seen as equivalent.
+2. For any other API field that might have a changed error message, we note the
+pairing in an exception file somewhere reachable from the comparison code.
+
+### Using Schemas for Validation
+
+Once a critical mass of original resources have been annotated, and we have
+confidence in our tool, we will begin to use the schemas for validation:
+1. New Feature Flag `DeclarativeValidation`
+ - Enables validation through schemas generated from the IDL tags
+ - Enables populating defaults from their values in the schemas
+ - Logs differences between native and schema-validation in an easily accessible way
+ - Only applies to resources (or groupversions, TBD) marked as supporting declarative validation
+2. Instrumentation of e2e tests - Instrument e2e tests with a method to run with
+declarative-validation enabled, and track all errors raised. This will help us
+ensure that support is complete before moving forward.
+
+#### Request handling
+
+Write requests are decoded, converted to internal, processed by any mutating admission
+plugins, processed before any create handlers, validated, then converted to the storage
+version and stored.
+
+Our plan:
+
+- Early Alphas: If feature flag is set, convert from internal back to versioned
+ type (via unsafe where possible) for declarative validation. Because all CEL
+ evaluation is currently written for unstructured values, we will convert to
+ unstructured before declarative validation.
+- Before graduation to Beta: Benchmark performance. Decide if we should invest
+ in the "Switch hub version to be an API version" idea proposed in the
+ performance risk section of this KEP. Also decide if we should invest in using
+ using SMD value wrappers to avoid conversion to unstructured.
+
+#### Validation of Unstructured input or Deserialized Go Type
+
+Rather than validate directly on the unstructured JSON/YAML input, before validation we must deserialize the object into its Go type first.
+
+We must validate after declarative and handwritten defaults, mutating admission,
+and other mutations are performed on a request object by the APIServer before
+the object is validated. It would be a large refactor to remove all Go type
+serialization from the APIServer request path. To do so is a non-goal of this KEP.
+
+Declarative Validation will be performed upon an unstructured representation or
+view into the deserialized Go type, and not directly on user input.
+
+### Deprecation of Legacy Validation
+
+1. After DeclarativeValidation reaches GA and becomes default
+3. Deprecation of Legacy Validation is Announced
+4. ...Deprecation wait period passes...
+5. Legacy validation code that is being validated declaratively can safely be deleted
+
+### Prototype Notes
+
+The core changes proposed here can be implemented with only a small set of code
+changes. A working
+[prototype](https://github.com/jpbetz/kubernetes/blob/cel-for-native/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/README.md)
+was built quite quickly by leveraging code that was merged recently as part of
+other CEL work. The main changes were:
+
+- Extend kube-openapi to add the needed Go tag support (Draft PR:
+ https://github.com/kubernetes/kube-openapi/pull/381)
+- Reuse the same validator as used today for CRDs, but generalize it to work with native types
+ - This was be done by leveraging
+ https://github.com/kubernetes/kubernetes/pull/113312 and
+ https://github.com/kubernetes/kubernetes/pull/116267 to handle the
+ resolution and conversion of native type schemas
+
+### Test Plan
+
+
+
+[x] I/we understand the owners of the involved components may require updates to
+existing tests to make this code solid enough prior to committing the changes necessary
+to implement this enhancement.
+
+##### Prerequisite testing updates
+
+
+None
+
+##### Unit tests
+
+
+
+
+
+See [Unit Test Instrumentation](#unit-test-instrumentation) for unit testing plan.
+
+- `k8s.io/apiserver/pkg/cel/openapi`: `10/02/2023` - `84.8`
+- `k8s.io/apiserver/pkg/cel/library`: `10/02/2023` - `69`
+- `k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model`: `10/02/2023` - `83.3`
+
+##### Integration tests
+
+
+We will have tests to ensure that a validator can be successfully created for
+each resource type's schema, and a valid object can be successfully validated
+for each resource type against its schema.
+
+
+
+##### e2e tests
+
+
+
+We will instrument as many e2e tests as possible to be able to use the feature
+gating, cross checking and logging of declarative validation and legacy
+validation. Any differences should result in a test failure. We may be able to
+produce a report via k8s CI after running all e2e tests with the feature
+enabled showing validation differences.
+
+### Graduation Criteria
+
+
+#### Alpha
+
+##### `DeclarativeValidationExtensionsInOpenAPI`
+
+- Code generator supports OpenAPI IDL tags
+- `x-kubernetes-validations` populated by openapi-gen from IDL tag
+- x-kubernetes-validations stripped if flag not enabled
+- Unit tests
+- Enablement/Disablement tests
+
+##### `DeclarativeValidation`
+
+- Validation of Native Objects is performed for enabled resources and differences are logged
+- Validation Library based on `common.Schema`
+- Validation Library Unit tests
+- Enablement/Disablement tests
+- Initial e2e tests completed and enabled
+
+#### Beta
+
+##### `DeclarativeValidationExtensionsInOpenAPI`
+- `x-kubernetes-strip-zero` and `x-kubernetes-errors` support added, or solution to
+problems they intend to solve found.
+
+##### `DeclarativeValidation`
+- Have annotated and enabled declarative validation for all native groupversions
+- Have instrumented annotated resources validation unit tests to run against versioned schema.
+
+#### GA
+
+- Have instrumented all annotated resources validation unit tests to run against versioned schema.
+- All Unit and Integration tests pass with no errors or only well-understood
+ exceptional errors sourced from a file in the repository
+
+### Upgrade / Downgrade Strategy
+
+
+
+For the introduction of new formats in CRDs:
+
+Today, [supported formats](https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats.go) is used strip out unsupported
+formats when used in older version of the kube-apiserver. We will extend this to have
+two lists: `supported` and `storage`. All new formats will be added to `storage` for
+at least one minor release of Kubernetes before the format is added to `supported` so
+that any usages of the new formats written to CRDs downgrade safely.
+
+### Version Skew Strategy
+
+
+This change does not affect any communications going out of the apiserver.
+This change may affect the validation codepath used for mutating client requests.
+
+Due to this change we may choose to support additional `format` strings in schemas.
+To mitigate risk from this and possible other new validations added we
+will implement validation ratcheting on the validation of the native types,
+similar as is done for CRDS in [KEP-4008](https://kep.k8s.io/4008). This would
+ensure old values that fail new validation strategies will remain validating.
+
+New values written passing the new validation system should be expected also to
+pass the old validation: we do not expect to loosen any validation rules, though
+a few may be tightened.
+
+## Production Readiness Review Questionnaire
+
+
+
+### Feature Enablement and Rollback
+
+
+
+###### How can this feature be enabled / disabled in a live cluster?
+
+
+
+- [x] Feature gate (also fill in values in `kep.yaml`)
+ - Feature gate name: DeclarativeValidation, DeclarativeValidationExtensionsInOpenAPI
+ - Components depending on the feature gate: kube-apiserver
+- [ ] Other
+ - Describe the mechanism:
+ - Will enabling / disabling the feature require downtime of the control
+ plane?
+ - Will enabling / disabling the feature require downtime or reprovisioning
+ of a node? (Do not assume `Dynamic Kubelet Config` feature is enabled).
+
+###### Does enabling the feature change any default behavior?
+
+
+
+- `DeclarativeValidationExtensionsInOpenAPI`
+
+ Exposes new `x-kubernetes` extensions proposed by this KEP in the OpenAPI schema
+ for native types.
+
+- `DeclarativeValidation`
+ - Alpha: Runs both declarative and native validation. Returns native
+ validations to user. Report differences in validations in logs and metrics
+ - Alpha: Runs both declarative and native validation. Returns native
+ validations to user. Report differences in validations in logs and metrics
+ - GA: Uses schema based validation for user errors. Legacy validations removed over time.
+
+###### Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
+
+
+
+- DeclarativeValidationExtensionsInOpenAPI: Yes, this feature only changes
+ published OpenAPI schema and does not affect rollbacks.
+- DeclarativeValidation:
+ - Alpha: Native Validations are still used to decide whether objects are
+ persisted to storage
+ - Beta & GA: Since validation is used to persist objects to storage, if there was a
+ mistake and it permits objects that should not be persisted, rollback
+ may be impacted by preventing updates on that object until the error is fixed.
+
+###### What happens if we reenable the feature if it was previously rolled back?
+
+- DeclarativeValidationExtensionsInOpenAPI: Yes, this feature only changes
+ published OpenAPI schema and does not affect rollbacks.
+- DeclarativeValidation: If the port to declarative validation is not accurate,
+ during an update, old parts of an object may be seen as invalid and need
+ to be ratcheted.
+
+###### Are there any tests for feature enablement/disablement?
+
+
+Before targeting to beta, this enhancement will have tests for:
+
+1. Ensuring x-kubernetes-validations is present if the feature is enabled
+1. Ensuring x-kubernetes-validations is not present if the feature is disabled
+2. Ensuring schema validation errors are used/logged if the feature is enabled
+2. Ensuring schema validation errors are not used/logged if the feature is disabled
+
+### Rollout, Upgrade and Rollback Planning
+
+> This section must be completed when targeting beta to a release.
+
+###### How can a rollout or rollback fail? Can it impact already running workloads?
+
+
+
+Beta & GA:
+
+A rollout can fail by being too strict with updates. If the ported declarative
+validations are stricter than native validations then workloads may not be able
+to execute their update operations.
+
+A rollback can fail if our declarative validations are too loose. Workloads wont
+be able to update objects with an invalid field until the object is corrected.
+
+###### What specific metrics should inform a rollback?
+
+
+
+###### Were upgrade and rollback tested? Was the upgrade->downgrade->upgrade path tested?
+
+
+
+###### Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?
+
+
+No.
+
+### Monitoring Requirements
+
+> This section must be completed when targeting beta to a release.
+>
+> For GA, this section is required: approvers should be able to confirm the
+> previous answers based on experience in the field.
+
+###### How can an operator determine if the feature is in use by workloads?
+
+
+
+`apiserver_declarative_validation_difference_total > 0`
+
+###### How can someone using this feature know that it is working for their instance?
+
+
+
+- [ ] Events
+ - Event Reason:
+- [ ] API .status
+ - Condition name:
+ - Other field:
+- [ ] Other (treat as last resort)
+ - Details:
+
+###### What are the reasonable SLOs (Service Level Objectives) for the enhancement?
+
+
+
+###### What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
+
+
+
+- [x] Metrics
+ - Metric name: apiserver_declarative_validation_difference_total (counter)
+ - (only in Alpha and Beta releases, GA will not execute both validation backends)
+ - Metric name: apiserver_declarative_validation_difference_seconds (histogram)
+ - (only in Alpha and Beta releases, GA will not execute both validation backends)
+ - Metric name: apiserver_declarative_validation_seconds (histogram)
+ - Components exposing the metric: kube-apiserver
+
+###### Are there any missing metrics that would be useful to have to improve observability of this feature?
+
+
+
+### Dependencies
+
+> This section must be completed when targeting beta to a release.
+
+###### Does this feature depend on any specific services running in the cluster?
+
+
+
+### Scalability
+
+> For alpha, this section is encouraged: reviewers should consider these questions
+and attempt to answer them.
+>
+> For beta, this section is required: reviewers must answer these questions.
+>
+> For GA, this section is required: approvers should be able to confirm the
+> previous answers based on experience in the field.
+
+###### Will enabling / using this feature result in any new API calls?
+
+
+No
+
+###### Will enabling / using this feature result in introducing new API types?
+
+
+No
+
+###### Will enabling / using this feature result in any new calls to the cloud provider?
+
+
+No
+
+###### Will enabling / using this feature result in increasing size or count of the existing API objects?
+
+
+No
+
+###### Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
+
+
+
+DeclarativeValidationsInOpenAPI: No.
+
+DeclarativeValidation: Yes, when enabled feature may impact validation time. Benchmarks will be
+taken to measure impact.
+
+###### Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, ...) in any components?
+
+
+
+
+DeclarativeValidationsInOpenAPI: No.
+
+DeclarativeValidation: Yes, when enabled feature may impact validation CPU and
+RAM usage. Benchmarks will be taken to measure impact.
+
+###### Can enabling / using this feature result in resource exhaustion of some node resources (PIDs, sockets, inodes, etc.)?
+
+
+No
+
+### Troubleshooting
+
+> This section must be completed when targeting beta to a release.
+>
+> For GA, this section is required: approvers should be able to confirm the
+> previous answers based on experience in the field.
+
+
+
+###### How does this feature react if the API server and/or etcd is unavailable?
+
+No change in behavior.
+
+###### What are other known failure modes?
+
+
+- Fail to create validator due to invalid generated schema on native type:
+ - Detection: API server crashes on startup due to error creating validator
+ - Mitigations: Update Kubernetes (in unlikely event we ever ship a release where this occurs)
+ - Diagnostics: Errors in log about failure to create validator and why
+ - Testing: We have an integration test in the testing plan to ensure that
+ all builtin resources can successfully create a validator and validate a
+ stub object
+
+###### What steps should be taken if SLOs are not being met to determine the problem?
+
+## Implementation History
+
+
+
+## Drawbacks
+
+
+
+## Alternatives
+
+
+### Validate On Storage Type Rather than Request Type
+
+
+## Infrastructure Needed (Optional)
+
+
+
+* [1]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#transition-rules
diff --git a/keps/sig-api-machinery/4153-declarative-validation/kep.yaml b/keps/sig-api-machinery/4153-declarative-validation/kep.yaml
new file mode 100644
index 00000000000..e38d8cd2b2a
--- /dev/null
+++ b/keps/sig-api-machinery/4153-declarative-validation/kep.yaml
@@ -0,0 +1,54 @@
+title: Declarative Validation
+kep-number: 4153
+authors:
+ - "@alexzielenski"
+ - "@jpbetz"
+owning-sig: sig-api-machinery
+status: implementable
+creation-date: 2023-08-20
+reviewers:
+ - apelisse
+ - jpbetz
+ - thockin
+ - robscott
+approvers:
+ - thockin
+ - jpbetz
+ - deads2k
+
+see-also:
+ - "/keps/sig-api-machinery/692-crd-openapi-schema"
+ - "/keps/sig-api-machinery/1929-built-in-default"
+ - "/keps/sig-api-machinery/2876-crd-validation-expression-language"
+ - "/keps/sig-api-machinery/2887-openapi-enum-types"
+ - "/keps/sig-api-machinery/4008-crd-ratcheting"
+
+# The target maturity stage in the current dev cycle for this KEP.
+stage: alpha
+
+# The most recent milestone for which work toward delivery of this KEP has been
+# done. This can be the current (upcoming) milestone, if it is being actively
+# worked on.
+latest-milestone: "v1.29"
+
+# The milestone at which this feature was, or is targeted to be, at each stage.
+milestone:
+ alpha: "v1.29"
+
+# The following PRR answers are required at alpha release
+# List the feature gate name and the components for which it must be enabled
+feature-gates:
+ # Exposes x-kubernetes-validations in published OpenAPI schema
+ - name: DeclarativeValidationExtensionsInOpenAPI
+ components:
+ - kube-apiserver
+ # Switches apiserver to use OpenAPI-based validation instead of handwritten
+ # wherever possible
+ - name: DeclarativeValidation
+ components:
+ - kube-apiserver
+disable-supported: true
+
+# The following PRR answers are required at beta release
+metrics:
+# - my_feature_metric
diff --git a/keps/sig-api-machinery/4153-declarative-validation/metadata-name-types.svg b/keps/sig-api-machinery/4153-declarative-validation/metadata-name-types.svg
new file mode 100644
index 00000000000..5d097a203e8
--- /dev/null
+++ b/keps/sig-api-machinery/4153-declarative-validation/metadata-name-types.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/keps/sig-api-machinery/4153-declarative-validation/requires-cel.svg b/keps/sig-api-machinery/4153-declarative-validation/requires-cel.svg
new file mode 100644
index 00000000000..9d0dba082b7
--- /dev/null
+++ b/keps/sig-api-machinery/4153-declarative-validation/requires-cel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/keps/sig-api-machinery/4153-declarative-validation/validation-types.svg b/keps/sig-api-machinery/4153-declarative-validation/validation-types.svg
new file mode 100644
index 00000000000..c5811d3d586
--- /dev/null
+++ b/keps/sig-api-machinery/4153-declarative-validation/validation-types.svg
@@ -0,0 +1 @@
+
\ No newline at end of file