From 0c679cea688388e9f00e72e264ab45e232d3051a Mon Sep 17 00:00:00 2001 From: yongruilin Date: Fri, 6 Feb 2026 23:48:21 +0000 Subject: [PATCH] Introduce DeclarativeValidationBeta and deprecate Takeover gate This change introduces the DeclarativeValidationBeta feature gate in v1.36 as the global safety switch for Beta-stage validation rules and marks DeclarativeValidationTakeover as deprecated. Following KEP-5073. --- pkg/features/kube_features.go | 6 +++++ .../apiserver/pkg/features/kube_features.go | 26 ++++++++++++++++++- .../reference/feature_list.md | 3 ++- .../reference/versioned_feature_list.yaml | 10 +++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 77cf644b296..32e5a843e2b 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -1973,8 +1973,13 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA and LockToDefault in 1.36, remove in 1.39 }, + genericfeatures.DeclarativeValidationBeta: { + {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta}, + }, + genericfeatures.DeclarativeValidationTakeover: { {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.36"), Default: false, PreRelease: featuregate.Deprecated}, }, genericfeatures.DetectCacheInconsistency: { @@ -2452,6 +2457,7 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature genericfeatures.DeclarativeValidation: {}, + genericfeatures.DeclarativeValidationBeta: {genericfeatures.DeclarativeValidation}, genericfeatures.DeclarativeValidationTakeover: {genericfeatures.DeclarativeValidation}, genericfeatures.DetectCacheInconsistency: {}, diff --git a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go index 1726ff04eaa..d55d166cdc8 100644 --- a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go +++ b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go @@ -128,13 +128,32 @@ const ( // Enables running declarative validation of APIs, where declared. When enabled, APIs with // declarative validation rules will validate objects using the generated // declarative validation code and compare the results to the regular imperative validation. - // See DeclarativeValidationTakeover for more. + // See DeclarativeValidationBeta for more. DeclarativeValidation featuregate.Feature = "DeclarativeValidation" + // owner: @jpbetz @aaron-prindle @yongruilin + // kep: http://kep.k8s.io/5073 + // beta: v1.36 + // + // This feature gate acts as the Global Safety Switch for Beta-stage validation rules (+k8s:beta). + // It allows cluster admins to disable enforcement for validations in the Beta stage if + // regressions are found, forcing them back to Shadow mode. + // In Shadow mode, declarative validation is executed and mismatches against handwritten + // validation are logged as metrics, but failures do not reject requests. + // Handwritten validation remains authoritative and enforced. + // Enforcement logic for resources using WithDeclarativeEnforcement(): + // - Standard tags (no prefix): Always Enforced (Bypasses this gate). + // - Beta tags (+k8s:beta): Enforced when this gate is enabled (default), otherwise Shadowed. + // - Alpha tags (+k8s:alpha): Always Shadowed. + // This gate has no effect if the master DeclarativeValidation feature gate is disabled. + DeclarativeValidationBeta featuregate.Feature = "DeclarativeValidationBeta" + // owner: @jpbetz @aaron-prindle @yongruilin // kep: http://kep.k8s.io/5073 // beta: v1.33 // + // Deprecated: in favor of DeclarativeValidationBeta. + // // When enabled, declarative validation errors are returned directly to the caller, // replacing hand-written validation errors for rules that have declarative implementations. // When disabled, hand-written validation errors are always returned, effectively putting @@ -375,8 +394,13 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA and LockToDefault in 1.36, remove in 1.39 }, + DeclarativeValidationBeta: { + {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta}, + }, + DeclarativeValidationTakeover: { {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.36"), Default: false, PreRelease: featuregate.Deprecated}, }, DetectCacheInconsistency: { diff --git a/test/compatibility_lifecycle/reference/feature_list.md b/test/compatibility_lifecycle/reference/feature_list.md index 28c34478885..fbe4556124a 100644 --- a/test/compatibility_lifecycle/reference/feature_list.md +++ b/test/compatibility_lifecycle/reference/feature_list.md @@ -61,7 +61,8 @@ | DRAResourceClaimDeviceStatus | :ballot_box_with_check: 1.33+ | | 1.32 | 1.33– | | | | [code](https://cs.k8s.io/?q=%5CbDRAResourceClaimDeviceStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAResourceClaimDeviceStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DRASchedulerFilterTimeout | :ballot_box_with_check: 1.34+ | | | 1.34– | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRASchedulerFilterTimeout%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRASchedulerFilterTimeout%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DeclarativeValidation | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.36+ | | 1.33–1.35 | 1.36– | | | [code](https://cs.k8s.io/?q=%5CbDeclarativeValidation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDeclarativeValidation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| DeclarativeValidationTakeover | | | | 1.33– | | | DeclarativeValidation | [code](https://cs.k8s.io/?q=%5CbDeclarativeValidationTakeover%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDeclarativeValidationTakeover%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| DeclarativeValidationBeta | :ballot_box_with_check: 1.36+ | | | 1.36– | | | DeclarativeValidation | [code](https://cs.k8s.io/?q=%5CbDeclarativeValidationBeta%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDeclarativeValidationBeta%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| DeclarativeValidationTakeover | | | | 1.33–1.35 | | 1.36– | DeclarativeValidation | [code](https://cs.k8s.io/?q=%5CbDeclarativeValidationTakeover%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDeclarativeValidationTakeover%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DeploymentReplicaSetTerminatingReplicas | :ballot_box_with_check: 1.35+ | | 1.33–1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbDeploymentReplicaSetTerminatingReplicas%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDeploymentReplicaSetTerminatingReplicas%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DetectCacheInconsistency | :ballot_box_with_check: 1.34+ | | | 1.34– | | | | [code](https://cs.k8s.io/?q=%5CbDetectCacheInconsistency%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDetectCacheInconsistency%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DisableAllocatorDualWrite | :ballot_box_with_check: 1.34+ | :closed_lock_with_key: 1.35+ | 1.31–1.32 | 1.33 | 1.34– | | MultiCIDRServiceAllocator | [code](https://cs.k8s.io/?q=%5CbDisableAllocatorDualWrite%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDisableAllocatorDualWrite%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | diff --git a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml index 15756cc83ba..5a2f6fce362 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -413,12 +413,22 @@ lockToDefault: true preRelease: GA version: "1.36" +- name: DeclarativeValidationBeta + versionedSpecs: + - default: true + lockToDefault: false + preRelease: Beta + version: "1.36" - name: DeclarativeValidationTakeover versionedSpecs: - default: false lockToDefault: false preRelease: Beta version: "1.33" + - default: false + lockToDefault: false + preRelease: Deprecated + version: "1.36" - name: DeploymentReplicaSetTerminatingReplicas versionedSpecs: - default: false