diff --git a/pkg/controller/namespace/deletion/namespaced_resources_deleter.go b/pkg/controller/namespace/deletion/namespaced_resources_deleter.go index f4ac1f5a612..50eda4e2a0d 100644 --- a/pkg/controller/namespace/deletion/namespaced_resources_deleter.go +++ b/pkg/controller/namespace/deletion/namespaced_resources_deleter.go @@ -32,11 +32,9 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/discovery" v1clientset "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/metadata" - "k8s.io/kubernetes/pkg/features" ) // NamespacedResourcesDeleterInterface is the interface to delete a namespace with all resources in it. @@ -530,7 +528,7 @@ func (d *namespacedResourcesDeleter) deleteAllContent(ctx context.Context, ns *v } podsGVR := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} - if _, hasPods := groupVersionResources[podsGVR]; hasPods && utilfeature.DefaultFeatureGate.Enabled(features.OrderedNamespaceDeletion) { + if _, hasPods := groupVersionResources[podsGVR]; hasPods { // Ensure all pods in the namespace are deleted first gvrDeletionMetadata, err := d.deleteAllContentForGroupVersionResource(ctx, podsGVR, namespace, namespaceDeletedAt) if err != nil { @@ -564,7 +562,7 @@ func (d *namespacedResourcesDeleter) deleteAllContent(ctx context.Context, ns *v // Proceed with deleting other resources in the namespace for gvr := range groupVersionResources { - if utilfeature.DefaultFeatureGate.Enabled(features.OrderedNamespaceDeletion) && gvr.Group == podsGVR.Group && + if gvr.Group == podsGVR.Group && gvr.Version == podsGVR.Version && gvr.Resource == podsGVR.Resource { continue } diff --git a/pkg/controlplane/apiserver/config.go b/pkg/controlplane/apiserver/config.go index c646ef44336..cffce59984a 100644 --- a/pkg/controlplane/apiserver/config.go +++ b/pkg/controlplane/apiserver/config.go @@ -23,8 +23,6 @@ import ( "net/http" "time" - noopoteltrace "go.opentelemetry.io/otel/trace/noop" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" utilnet "k8s.io/apimachinery/pkg/util/net" @@ -168,10 +166,8 @@ func BuildGenericConfig( if lastErr = s.EgressSelector.ApplyTo(genericConfig); lastErr != nil { return } - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerTracing) { - if lastErr = s.Traces.ApplyTo(genericConfig.EgressSelector, genericConfig); lastErr != nil { - return - } + if lastErr = s.Traces.ApplyTo(genericConfig.EgressSelector, genericConfig); lastErr != nil { + return } // wrap the definitions to revert any changes from disabled features getOpenAPIDefinitions = openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(getOpenAPIDefinitions) @@ -189,11 +185,7 @@ func BuildGenericConfig( if genericConfig.EgressSelector != nil { s.Etcd.StorageConfig.Transport.EgressLookup = genericConfig.EgressSelector.Lookup } - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerTracing) { - s.Etcd.StorageConfig.Transport.TracerProvider = genericConfig.TracerProvider - } else { - s.Etcd.StorageConfig.Transport.TracerProvider = noopoteltrace.NewTracerProvider() - } + s.Etcd.StorageConfig.Transport.TracerProvider = genericConfig.TracerProvider storageFactoryConfig := kubeapiserver.NewStorageFactoryConfigEffectiveVersion(genericConfig.EffectiveVersion) storageFactoryConfig.APIResourceConfig = genericConfig.MergedResourceConfig diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 6490a263052..63b5f213733 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -692,12 +692,6 @@ const ( // Enables opportunistic batching in the scheduler. OpportunisticBatching featuregate.Feature = "OpportunisticBatching" - // owner: @cici37 - // kep: https://kep.k8s.io/5080 - // - // Enables ordered namespace deletion. - OrderedNamespaceDeletion featuregate.Feature = "OrderedNamespaceDeletion" - // owner: @tallclair // // Enables relisting individual pods on-demand. @@ -1043,14 +1037,6 @@ const ( // Enables support for the StorageVersionMigrator controller. StorageVersionMigrator featuregate.Feature = "StorageVersionMigrator" - // owner: @serathius - // Allow API server JSON encoder to encode collections item by item, instead of all at once. - StreamingCollectionEncodingToJSON featuregate.Feature = "StreamingCollectionEncodingToJSON" - - // owner: serathius - // Allow API server Protobuf encoder to encode collections item by item, instead of all at once. - StreamingCollectionEncodingToProtobuf featuregate.Feature = "StreamingCollectionEncodingToProtobuf" - // owner: @danwinship // kep: https://kep.k8s.io/4858 // @@ -1675,12 +1661,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.35"), Default: true, PreRelease: featuregate.Beta}, }, - OrderedNamespaceDeletion: { - {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.37 - }, - PLEGOnDemandRelist: { {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta}, }, @@ -1950,16 +1930,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.35"), Default: false, PreRelease: featuregate.Beta}, }, - StreamingCollectionEncodingToJSON: { - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - - StreamingCollectionEncodingToProtobuf: { - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - StrictIPCIDRValidation: { {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Alpha}, {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta}, @@ -2087,12 +2057,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Beta}, }, - genericfeatures.APIServerTracing: { - {Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.37 - }, - genericfeatures.APIServingWithRoutine: { {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -2111,11 +2075,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, }, - genericfeatures.BtreeWatchCache: { - {Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - genericfeatures.CBORServingAndStorage: { {Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -2124,12 +2083,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta}, }, - genericfeatures.ConsistentListFromCache: { - {Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - genericfeatures.ConsistentListFromCacheSkipTimeoutFallback: { {Version: version.MustParse("1.37"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -2193,17 +2146,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, }, - genericfeatures.ResilientWatchCacheInitialization: { - {Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - - genericfeatures.RetryGenerateName: { - {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA}, - }, - genericfeatures.SeparateCacheWatchRPC: { {Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta}, {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Deprecated}, @@ -2480,8 +2422,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature OpportunisticBatching: {}, - OrderedNamespaceDeletion: {}, - PLEGOnDemandRelist: {}, PersistentVolumeClaimUnusedSinceTime: {}, @@ -2592,10 +2532,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature StorageVersionMigrator: {}, - StreamingCollectionEncodingToJSON: {}, - - StreamingCollectionEncodingToProtobuf: {}, - StrictIPCIDRValidation: {}, SupplementalGroupsPolicy: {}, @@ -2646,8 +2582,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature genericfeatures.APIServerIdentity: {}, - genericfeatures.APIServerTracing: {}, - genericfeatures.APIServingWithRoutine: {}, genericfeatures.AggregatedDiscoveryRemoveBetaType: {}, @@ -2656,15 +2590,11 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature genericfeatures.AllowUnsafeMalformedObjectDeletion: {}, - genericfeatures.BtreeWatchCache: {}, - genericfeatures.CBORServingAndStorage: {}, genericfeatures.ConcurrentWatchObjectDecode: {}, - genericfeatures.ConsistentListFromCache: {}, - - genericfeatures.ConsistentListFromCacheSkipTimeoutFallback: {genericfeatures.ConsistentListFromCache}, + genericfeatures.ConsistentListFromCacheSkipTimeoutFallback: {}, genericfeatures.ConstrainedImpersonation: {}, @@ -2687,10 +2617,6 @@ var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]feature genericfeatures.RemoteRequestHeaderUID: {}, - genericfeatures.ResilientWatchCacheInitialization: {}, - - genericfeatures.RetryGenerateName: {}, - genericfeatures.SeparateCacheWatchRPC: {}, genericfeatures.ShardedListAndWatch: {}, diff --git a/pkg/registry/core/pod/strategy.go b/pkg/registry/core/pod/strategy.go index f4cf111c322..f79b882e7c2 100644 --- a/pkg/registry/core/pod/strategy.go +++ b/pkg/registry/core/pod/strategy.go @@ -40,7 +40,6 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" utilvalidation "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" - apiserverfeatures "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage" @@ -452,15 +451,11 @@ func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { // MatchPod returns a generic matcher for a given label and field selector. func MatchPod(label labels.Selector, field fields.Selector) storage.SelectionPredicate { - var indexFields = []string{"spec.nodeName"} - if utilfeature.DefaultFeatureGate.Enabled(features.StorageNamespaceIndex) && !utilfeature.DefaultFeatureGate.Enabled(apiserverfeatures.BtreeWatchCache) { - indexFields = append(indexFields, "metadata.namespace") - } return storage.SelectionPredicate{ Label: label, Field: field, GetAttrs: GetAttrs, - IndexFields: indexFields, + IndexFields: []string{"spec.nodeName"}, } } @@ -478,24 +473,11 @@ func NodeNameIndexFunc(obj interface{}) ([]string, error) { return []string{pod.Spec.NodeName}, nil } -// NamespaceIndexFunc return value name of given object. -func NamespaceIndexFunc(obj interface{}) ([]string, error) { - pod, ok := obj.(*api.Pod) - if !ok { - return nil, fmt.Errorf("not a pod") - } - return []string{pod.Namespace}, nil -} - // Indexers returns the indexers for pod storage. func Indexers() *cache.Indexers { - var indexers = cache.Indexers{ + return &cache.Indexers{ storage.FieldIndex("spec.nodeName"): NodeNameIndexFunc, } - if utilfeature.DefaultFeatureGate.Enabled(features.StorageNamespaceIndex) && !utilfeature.DefaultFeatureGate.Enabled(apiserverfeatures.BtreeWatchCache) { - indexers[storage.FieldIndex("metadata.namespace")] = NamespaceIndexFunc - } - return &indexers } // ToSelectableFields returns a field set that represents the object diff --git a/pkg/registry/core/rest/storage_core_generic.go b/pkg/registry/core/rest/storage_core_generic.go index 9d82ca85633..a8547008ecb 100644 --- a/pkg/registry/core/rest/storage_core_generic.go +++ b/pkg/registry/core/rest/storage_core_generic.go @@ -73,16 +73,13 @@ func (c *GenericConfig) NewRESTStorage(apiResourceConfigSource serverstorage.API ParameterCodec: legacyscheme.ParameterCodec, NegotiatedSerializer: legacyscheme.Codecs, } - opts := []serializer.CodecFactoryOptionsMutator{} + opts := []serializer.CodecFactoryOptionsMutator{ + serializer.WithStreamingCollectionEncodingToJSON(), + serializer.WithStreamingCollectionEncodingToProtobuf(), + } if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) { opts = append(opts, serializer.WithSerializer(cbor.NewSerializerInfo)) } - if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) { - opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON()) - } - if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) { - opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf()) - } if len(opts) != 0 { apiGroupInfo.NegotiatedSerializer = serializer.NewCodecFactory(legacyscheme.Scheme, opts...) } diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index 18c08fbead6..59d1f477e48 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -888,7 +888,6 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd clusterScoped := crd.Spec.Scope == apiextensionsv1.ClusterScoped // CRDs explicitly do not support protobuf, but some objects returned by the API server do - streamingCollections := utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) negotiatedSerializer := unstructuredNegotiatedSerializer{ typer: typer, creator: creator, @@ -902,11 +901,11 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd MediaTypeType: "application", MediaTypeSubType: "json", EncodesAsText: true, - Serializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{StreamingCollectionsEncoding: streamingCollections}), + Serializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{StreamingCollectionsEncoding: true}), PrettySerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{Pretty: true}), StrictSerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{ Strict: true, - StreamingCollectionsEncoding: streamingCollections, + StreamingCollectionsEncoding: true, }), StreamSerializer: &runtime.StreamSerializerInfo{ EncodesAsText: true, @@ -930,7 +929,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd MediaTypeType: "application", MediaTypeSubType: "vnd.kubernetes.protobuf", Serializer: protobuf.NewSerializerWithOptions(creator, typer, protobuf.SerializerOptions{ - StreamingCollectionsEncoding: utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf), + StreamingCollectionsEncoding: true, }), StreamSerializer: &runtime.StreamSerializerInfo{ Serializer: protobuf.NewRawSerializer(creator, typer), @@ -1007,16 +1006,13 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd scaleScope := *requestScopes[v.Name] scaleConverter := scale.NewScaleConverter() scaleScope.Subresource = "scale" - var opts []serializer.CodecFactoryOptionsMutator + opts := []serializer.CodecFactoryOptionsMutator{ + serializer.WithStreamingCollectionEncodingToJSON(), + serializer.WithStreamingCollectionEncodingToProtobuf(), + } if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) { opts = append(opts, serializer.WithSerializer(cbor.NewSerializerInfo)) } - if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) { - opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON()) - } - if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) { - opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf()) - } scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme(), opts...) scaleScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale") scaleScope.Namer = handlers.ContextBasedNaming{ 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 c214ad9db0b..183185df3f5 100644 --- a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go +++ b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go @@ -44,11 +44,6 @@ const ( // Assigns each kube-apiserver an ID in a cluster. APIServerIdentity featuregate.Feature = "APIServerIdentity" - // owner: @dashpole - // - // Add support for distributed tracing in the API Server - APIServerTracing featuregate.Feature = "APIServerTracing" - // owner: @linxiulei // // Enables serving watch requests in separate goroutines. @@ -75,11 +70,6 @@ const ( // resources using the Kubernetes API only. AllowUnsafeMalformedObjectDeletion featuregate.Feature = "AllowUnsafeMalformedObjectDeletion" - // owner: @serathius - // - // Replaces watch cache hashmap implementation with a btree based one, bringing performance improvements. - BtreeWatchCache featuregate.Feature = "BtreeWatchCache" - // owner: @benluddy // kep: https://kep.k8s.io/4222 // @@ -91,12 +81,6 @@ const ( // Enables concurrent watch object decoding to avoid starving watch cache when conversion webhook is installed. ConcurrentWatchObjectDecode featuregate.Feature = "ConcurrentWatchObjectDecode" - // owner: @serathius - // kep: http://kep.k8s.io/2340 - // - // Allow the API server to serve consistent lists from cache - ConsistentListFromCache featuregate.Feature = "ConsistentListFromCache" - // owner: @yedou37 // // Skip the timeout fallback to storage when a consistent LIST from cache cannot be served, @@ -205,17 +189,6 @@ const ( // headers when forwarding requests to the servers serving the aggregated API. RemoteRequestHeaderUID featuregate.Feature = "RemoteRequestHeaderUID" - // owner: @wojtek-t - // - // Enables resilient watchcache initialization to avoid controlplane - // overload. - ResilientWatchCacheInitialization featuregate.Feature = "ResilientWatchCacheInitialization" - - // owner: @jpbetz - // Resource create requests using generateName are retried automatically by the apiserver - // if the generated name conflicts with an existing resource name, up to a maximum number of 7 retries. - RetryGenerateName featuregate.Feature = "RetryGenerateName" - // owner: @cici37 // // Allow watch cache to create a watch on a dedicated RPC. @@ -246,14 +219,6 @@ const ( // document. StorageVersionHash featuregate.Feature = "StorageVersionHash" - // owner: @serathius - // Allow API server JSON encoder to encode collections item by item, instead of all at once. - StreamingCollectionEncodingToJSON featuregate.Feature = "StreamingCollectionEncodingToJSON" - - // owner: @serathius - // Allow API server Protobuf encoder to encode collections item by item, instead of all at once. - StreamingCollectionEncodingToProtobuf featuregate.Feature = "StreamingCollectionEncodingToProtobuf" - // owner: @aramase, @enj, @nabokihms // kep: https://kep.k8s.io/3331 // @@ -331,12 +296,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.26"), Default: true, PreRelease: featuregate.Beta}, }, - APIServerTracing: { - {Version: version.MustParse("1.22"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.37 - }, - APIServingWithRoutine: { {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -355,11 +314,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, }, - BtreeWatchCache: { - {Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - CBORServingAndStorage: { {Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -368,12 +322,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Beta}, }, - ConsistentListFromCache: { - {Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - ConsistentListFromCacheSkipTimeoutFallback: { {Version: version.MustParse("1.37"), Default: false, PreRelease: featuregate.Alpha}, }, @@ -437,17 +385,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, }, - ResilientWatchCacheInitialization: { - {Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - - RetryGenerateName: { - {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA}, - }, - SeparateCacheWatchRPC: { {Version: version.MustParse("1.28"), Default: true, PreRelease: featuregate.Beta}, {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Deprecated}, @@ -471,16 +408,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.15"), Default: true, PreRelease: featuregate.Beta}, }, - StreamingCollectionEncodingToJSON: { - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - - StreamingCollectionEncodingToProtobuf: { - {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - StructuredAuthenticationConfigurationEgressSelector: { {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.Beta}, }, diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go index 587a43dc292..e77c10960e2 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go @@ -452,7 +452,7 @@ const maxNameGenerationCreateAttempts = 8 // hooks). Tests which call this might want to call DeepCopy if they expect to // be able to examine the input and output objects for differences. func (e *Store) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.RetryGenerateName) && needsNameGeneration(obj) { + if needsNameGeneration(obj) { return e.createWithGenerateNameRetry(ctx, obj, createValidation, options) } diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go index fda39e9862f..fed8b7bf69d 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store_test.go @@ -45,12 +45,10 @@ import ( "k8s.io/apimachinery/pkg/selection" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/apimachinery/pkg/util/version" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/apis/example" examplev1 "k8s.io/apiserver/pkg/apis/example/v1" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/storage" @@ -59,9 +57,7 @@ import ( "k8s.io/apiserver/pkg/storage/names" "k8s.io/apiserver/pkg/storage/storagebackend/factory" storagetesting "k8s.io/apiserver/pkg/storage/testing" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/cache" - featuregatetesting "k8s.io/component-base/featuregate/testing" ) var scheme = runtime.NewScheme() @@ -451,38 +447,6 @@ func TestStoreCreateWithRetryNameGenerate(t *testing.T) { } } -func TestStoreCreateWithRetryNameGenerateFeatureDisabled(t *testing.T) { - // Preserve testing of disabled RetryGenerateName feature gate since it can still be disabled when emulation version is set. - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RetryGenerateName, false) - namedObj := func(id int) *example.Pod { - return &example.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("prefix-%d", id), Namespace: "test"}, - Spec: example.PodSpec{NodeName: "machine"}, - } - } - - generateNameObj := &example.Pod{ - ObjectMeta: metav1.ObjectMeta{GenerateName: "prefix-", Namespace: "test"}, - Spec: example.PodSpec{NodeName: "machine"}, - } - - testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") - destroyFunc, registry := NewTestGenericStoreRegistry(t) - defer destroyFunc() - - registry.CreateStrategy = &testRESTStrategy{scheme, &sequentialNameGenerator{}, true, false, true} - - _, err := registry.Create(testContext, namedObj(0), rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - _, err = registry.Create(testContext, generateNameObj, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if err == nil || !errors.IsAlreadyExists(err) { - t.Error("Expected already exists error") - } -} - func TestNewCreateOptionsFromUpdateOptions(t *testing.T) { f := randfill.New().NilChance(0.0).NumElements(1, 1) @@ -2464,13 +2428,11 @@ func newTestGenericStoreRegistry(t *testing.T, scheme *runtime.Scheme, hasCacheE if err != nil { t.Fatalf("Couldn't create cacher: %v", err) } - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - // The tests assume that Get/GetList/Watch calls shouldn't fail. - // However, 429 error can now be returned if watchcache is under initialization. - // To avoid rewriting all tests, we wait for watchcache to initialize. - if err := cacher.Wait(context.Background()); err != nil { - t.Fatal(err) - } + // The tests assume that Get/GetList/Watch calls shouldn't fail. + // However, 429 error can now be returned if watchcache is under initialization. + // To avoid rewriting all tests, we wait for watchcache to initialize. + if err := cacher.Wait(context.Background()); err != nil { + t.Fatal(err) } d := destroyFunc delegator := cacherstorage.NewCacheDelegator(cacher, s) @@ -2990,76 +2952,3 @@ func TestValidateIndexers(t *testing.T) { } } } - -type predictableNameGenerator struct { - index int -} - -func (p *predictableNameGenerator) GenerateName(base string) string { - p.index++ - return fmt.Sprintf("%s%d", base, p.index) -} - -func TestStoreCreateGenerateNameConflict(t *testing.T) { - // Preserve testing of disabled RetryGenerateName feature gate since it can still be disabled when emulation version is set. - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RetryGenerateName, false) - - // podA will be stored with name foo12345 - podA := &example.Pod{ - ObjectMeta: metav1.ObjectMeta{Name: "foo1", Namespace: "test"}, - Spec: example.PodSpec{NodeName: "machine"}, - } - // podB will generate the same name as podA "foo1" in the first try - podB := &example.Pod{ - ObjectMeta: metav1.ObjectMeta{GenerateName: "foo", Namespace: "test"}, - Spec: example.PodSpec{NodeName: "machine2"}, - } - - testContext := genericapirequest.WithNamespace(genericapirequest.NewContext(), "test") - destroyFunc, registry := NewTestGenericStoreRegistry(t) - defer destroyFunc() - // re-define delete strategy to have graceful delete capability - defaultCreateStrategy := &testRESTStrategy{scheme, &predictableNameGenerator{}, true, false, true} - registry.CreateStrategy = defaultCreateStrategy - - // create the object (DeepCopy because the registry mutates the objects) - objA, err := registry.Create(testContext, podA.DeepCopy(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // get the object - checkobjA, err := registry.Get(testContext, podA.Name, &metav1.GetOptions{}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // verify objects are equal - if e, a := objA, checkobjA; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } - - // now try to create the second pod (DeepCopy because the registry mutate the objects) - _, err = registry.Create(testContext, podB.DeepCopy(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if !errors.IsAlreadyExists(err) { - t.Errorf("Unexpected error: %+v", err) - } - - // check the 'alraedy exists' msg correspond to the generated name - msg := &err.(*errors.StatusError).ErrStatus.Message - if !strings.Contains(*msg, "already exists, the server was not able to generate a unique name for the object") { - t.Errorf("Unexpected error without the 'was not able to generate a unique name' in message: %v", err) - } - - // now try to create the second pod again - objB, err := registry.Create(testContext, podB.DeepCopy(), rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if objB.(*example.Pod).Name != "foo2" && objB.(*example.Pod).GenerateName != "foo" { - t.Errorf("Unexpected object: %+v", objB) - } - -} diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index 894ce0ac604..e465237bd79 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -1069,9 +1069,7 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler { // WithTracing comes after authentication so we can allow authenticated // clients to influence sampling. - if c.FeatureGate.Enabled(genericfeatures.APIServerTracing) { - handler = genericapifilters.WithTracing(handler, c.TracerProvider) - } + handler = genericapifilters.WithTracing(handler, c.TracerProvider) failedHandler = filterlatency.TrackCompleted(failedHandler) handler = filterlatency.TrackCompleted(handler) handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences, c.Authentication.RequestHeaderConfig) diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go index 0a04fb9efed..d6cee7a29ef 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -1017,16 +1017,13 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV // NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values // exposed for easier composition from other packages func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo { - opts := []serializer.CodecFactoryOptionsMutator{} + opts := []serializer.CodecFactoryOptionsMutator{ + serializer.WithStreamingCollectionEncodingToJSON(), + serializer.WithStreamingCollectionEncodingToProtobuf(), + } if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) { opts = append(opts, serializer.WithSerializer(cbor.NewSerializerInfo)) } - if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) { - opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON()) - } - if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) { - opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf()) - } if len(opts) != 0 { codecs = serializer.NewCodecFactory(scheme, opts...) } diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/coreapi.go b/staging/src/k8s.io/apiserver/pkg/server/options/coreapi.go index 12a65517e1f..d8f1fd6e375 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/coreapi.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/coreapi.go @@ -21,9 +21,7 @@ import ( "time" "github.com/spf13/pflag" - "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/server" - "k8s.io/apiserver/pkg/util/feature" clientgoinformers "k8s.io/client-go/informers" clientgoclientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -72,9 +70,7 @@ func (o *CoreAPIOptions) ApplyTo(config *server.RecommendedConfig) error { return err } } - if feature.DefaultFeatureGate.Enabled(features.APIServerTracing) { - kubeconfig.Wrap(tracing.WrapperFor(config.TracerProvider)) - } + kubeconfig.Wrap(tracing.WrapperFor(config.TracerProvider)) clientgoExternalClient, err := clientgoclientset.NewForConfig(kubeconfig) if err != nil { return fmt.Errorf("failed to create Kubernetes clientset: %v", err) diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/tracing.go b/staging/src/k8s.io/apiserver/pkg/server/options/tracing.go index b0cce593761..e8393edc950 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/tracing.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/tracing.go @@ -34,7 +34,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver/install" - "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/egressselector" "k8s.io/apiserver/pkg/util/feature" @@ -87,9 +86,6 @@ func (o *TracingOptions) ApplyTo(es *egressselector.EgressSelector, c *server.Co if o == nil || o.ConfigFile == "" { return nil } - if !feature.DefaultFeatureGate.Enabled(features.APIServerTracing) { - return fmt.Errorf("APIServerTracing feature is not enabled, but tracing config file was provided") - } traceConfig, err := ReadTracingConfiguration(o.ConfigFile) if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go index 326ed27c80d..fe09fc67108 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go @@ -521,19 +521,9 @@ func (c *Cacher) Watch(ctx context.Context, key string, opts storage.ListOptions return nil, err } - var readyGeneration int - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - var err error - var downtime time.Duration - readyGeneration, downtime, err = c.ready.checkAndReadGeneration() - if err != nil { - return nil, errors.NewTooManyRequests(err.Error(), calculateRetryAfterForUnreadyCache(downtime)) - } - } else { - readyGeneration, err = c.ready.waitAndReadGeneration(ctx) - if err != nil { - return nil, errors.NewServiceUnavailable(err.Error()) - } + readyGeneration, downtime, err := c.ready.checkAndReadGeneration() + if err != nil { + return nil, errors.NewTooManyRequests(err.Error(), calculateRetryAfterForUnreadyCache(downtime)) } // determine the namespace and name scope of the watch, first from the request, secondarily from the field selector @@ -760,16 +750,10 @@ func (c *Cacher) GetList(ctx context.Context, key string, opts storage.ListOptio attribute.Stringer("type", c.groupResource)) defer span.End(500 * time.Millisecond) - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if downtime, err := c.ready.check(); err != nil { - // If Cacher is not initialized, reject List requests - // as described in https://kep.k8s.io/4568 - return errors.NewTooManyRequests(err.Error(), calculateRetryAfterForUnreadyCache(downtime)) - } - } else { - if err := c.ready.wait(ctx); err != nil { - return errors.NewServiceUnavailable(err.Error()) - } + if downtime, err := c.ready.check(); err != nil { + // If Cacher is not initialized, reject List requests + // as described in https://kep.k8s.io/4568 + return errors.NewTooManyRequests(err.Error(), calculateRetryAfterForUnreadyCache(downtime)) } span.AddEvent("Ready") diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go index 7fceb88a00c..5cb1b564813 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_test.go @@ -32,7 +32,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/rand" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/version" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/apis/example" examplev1 "k8s.io/apiserver/pkg/apis/example/v1" @@ -181,36 +180,30 @@ func TestListPaging(t *testing.T) { } func TestLists(t *testing.T) { - for _, consistentRead := range []bool{true, false} { - for _, listFromCacheSnapshot := range []bool{true, false} { - t.Run(fmt.Sprintf("ConsistentListFromCache=%v,ListFromCacheSnapshot=%v", consistentRead, listFromCacheSnapshot), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, listFromCacheSnapshot) - if !consistentRead { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.33")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, false) - } - t.Run("List", func(t *testing.T) { - t.Parallel() - ctx, cacher, server, terminate := testSetupWithEtcdServer(t) - t.Cleanup(terminate) - storagetesting.RunTestList(ctx, t, cacher, compactStore(cacher, server.V3Client.Client), true, server.V3Client.Kubernetes.(*storagetesting.KubernetesRecorder)) - }) - - t.Run("ConsistentList", func(t *testing.T) { - t.Parallel() - ctx, cacher, server, terminate := testSetupWithEtcdServer(t) - t.Cleanup(terminate) - storagetesting.RunTestConsistentList(ctx, t, cacher, increaseRVFunc(server.V3Client.Client), true, consistentRead, listFromCacheSnapshot) - }) - - t.Run("GetListNonRecursive", func(t *testing.T) { - t.Parallel() - ctx, cacher, server, terminate := testSetupWithEtcdServer(t) - t.Cleanup(terminate) - storagetesting.RunTestGetListNonRecursive(ctx, t, increaseRVFunc(server.V3Client.Client), cacher) - }) + for _, listFromCacheSnapshot := range []bool{true, false} { + t.Run(fmt.Sprintf("ListFromCacheSnapshot=%v", listFromCacheSnapshot), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, listFromCacheSnapshot) + t.Run("List", func(t *testing.T) { + t.Parallel() + ctx, cacher, server, terminate := testSetupWithEtcdServer(t) + t.Cleanup(terminate) + storagetesting.RunTestList(ctx, t, cacher, compactStore(cacher, server.V3Client.Client), true, server.V3Client.Kubernetes.(*storagetesting.KubernetesRecorder)) }) - } + + t.Run("ConsistentList", func(t *testing.T) { + t.Parallel() + ctx, cacher, server, terminate := testSetupWithEtcdServer(t) + t.Cleanup(terminate) + storagetesting.RunTestConsistentList(ctx, t, cacher, increaseRVFunc(server.V3Client.Client), true, true, listFromCacheSnapshot) + }) + + t.Run("GetListNonRecursive", func(t *testing.T) { + t.Parallel() + ctx, cacher, server, terminate := testSetupWithEtcdServer(t) + t.Cleanup(terminate) + storagetesting.RunTestGetListNonRecursive(ctx, t, increaseRVFunc(server.V3Client.Client), cacher) + }) + }) } } @@ -592,13 +585,11 @@ func testSetupWithEtcdServer(t testing.TB, opts ...setupOption) (context.Context t.Fatalf("Failed to inject list errors: %v", err) } - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - // The tests assume that Get/GetList/Watch calls shouldn't fail. - // However, 429 error can now be returned if watchcache is under initialization. - // To avoid rewriting all tests, we wait for watchcache to initialize. - if err := cacher.Wait(ctx); err != nil { - t.Fatal(err) - } + // The tests assume that Get/GetList/Watch calls shouldn't fail. + // However, 429 error can now be returned if watchcache is under initialization. + // To avoid rewriting all tests, we wait for watchcache to initialize. + if err := cacher.Wait(ctx); err != nil { + t.Fatal(err) } delegator := NewCacheDelegator(cacher, wrappedStorage) terminate := func() { @@ -613,11 +604,6 @@ func testSetupWithEtcdServer(t testing.TB, opts ...setupOption) (context.Context func testSetupWithEtcdAndCreateWrapper(t *testing.T, opts ...setupOption) (storage.Interface, tearDownFunc) { _, cacher, _, tearDown := testSetupWithEtcdServer(t, opts...) - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.cacher.ready.wait(context.TODO()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } return &createWrapper{CacheDelegator: cacher}, tearDown } @@ -647,35 +633,17 @@ func (c *createWrapper) Create(ctx context.Context, key string, obj, out runtime func BenchmarkStoreCreateList(b *testing.B) { klog.SetLogger(logr.Discard()) - storeOptions := []struct { - name string - btreeEnabled bool - }{ - { - name: "Btree", - btreeEnabled: true, - }, - { - name: "Map", - btreeEnabled: false, - }, - } - for _, store := range storeOptions { - b.Run(fmt.Sprintf("Store=%s", store.name), func(b *testing.B) { - featuregatetesting.SetFeatureGateDuringTest(b, utilfeature.DefaultFeatureGate, features.BtreeWatchCache, store.btreeEnabled) - for _, rvm := range []metav1.ResourceVersionMatch{metav1.ResourceVersionMatchNotOlderThan, metav1.ResourceVersionMatchExact} { - b.Run(fmt.Sprintf("RV=%s", rvm), func(b *testing.B) { - for _, useIndex := range []bool{true, false} { - b.Run(fmt.Sprintf("Indexed=%v", useIndex), func(b *testing.B) { - opts := []setupOption{} - if useIndex { - opts = append(opts, withNodeNameAndNamespaceIndex) - } - ctx, cacher, _, terminate := testSetupWithEtcdServer(b, opts...) - b.Cleanup(terminate) - storagetesting.RunBenchmarkStoreListCreate(ctx, b, cacher, rvm) - }) + for _, rvm := range []metav1.ResourceVersionMatch{metav1.ResourceVersionMatchNotOlderThan, metav1.ResourceVersionMatchExact} { + b.Run(fmt.Sprintf("RV=%s", rvm), func(b *testing.B) { + for _, useIndex := range []bool{true, false} { + b.Run(fmt.Sprintf("Indexed=%v", useIndex), func(b *testing.B) { + opts := []setupOption{} + if useIndex { + opts = append(opts, withNodeNameAndNamespaceIndex) } + ctx, cacher, _, terminate := testSetupWithEtcdServer(b, opts...) + b.Cleanup(terminate) + storagetesting.RunBenchmarkStoreListCreate(ctx, b, cacher, rvm) }) } }) @@ -709,36 +677,18 @@ func BenchmarkStoreList(b *testing.B) { for _, dims := range dimensions { b.Run(fmt.Sprintf("Namespaces=%d/Pods=%d/Nodes=%d", dims.namespaceCount, dims.namespaceCount*dims.podPerNamespaceCount, dims.nodeCount), func(b *testing.B) { data := storagetesting.PrepareBenchchmarkData(dims.namespaceCount, dims.podPerNamespaceCount, dims.nodeCount) - storeOptions := []struct { - name string - btreeEnabled bool - }{ - { - name: "Btree", - btreeEnabled: true, - }, - { - name: "Map", - btreeEnabled: false, - }, + ctx, cacher, _, terminate := testSetupWithEtcdServer(b, withNodeNameAndNamespaceIndex) + b.Cleanup(terminate) + var out example.Pod + for _, pod := range data.Pods { + err := cacher.Create(ctx, computePodKey(pod), pod, &out, 0) + if err != nil { + b.Fatal(err) + } } - for _, store := range storeOptions { - b.Run(fmt.Sprintf("Store=%s", store.name), func(b *testing.B) { - featuregatetesting.SetFeatureGateDuringTest(b, utilfeature.DefaultFeatureGate, features.BtreeWatchCache, store.btreeEnabled) - ctx, cacher, _, terminate := testSetupWithEtcdServer(b, withNodeNameAndNamespaceIndex) - b.Cleanup(terminate) - var out example.Pod - for _, pod := range data.Pods { - err := cacher.Create(ctx, computePodKey(pod), pod, &out, 0) - if err != nil { - b.Fatal(err) - } - } - for _, useIndex := range []bool{true, false} { - b.Run(fmt.Sprintf("Indexed=%v", useIndex), func(b *testing.B) { - storagetesting.RunBenchmarkStoreList(ctx, b, cacher, data, useIndex) - }) - } + for _, useIndex := range []bool{true, false} { + b.Run(fmt.Sprintf("Indexed=%v", useIndex), func(b *testing.B) { + storagetesting.RunBenchmarkStoreList(ctx, b, cacher, data, useIndex) }) } }) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go index 01a75da4116..6a022de0488 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go @@ -43,7 +43,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/sharding" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/version" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" "k8s.io/apiserver/pkg/apis/example" @@ -106,13 +105,11 @@ func newTestCacher(s storage.Interface) (*Cacher, storage.Versioner, error) { return nil, versioner, err } - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - // The tests assume that Get/GetList/Watch calls shouldn't fail. - // However, 429 error can now be returned if watchcache is under initialization. - // To avoid rewriting all tests, we wait for watcache to initialize. - if err := cacher.Wait(context.Background()); err != nil { - return nil, storage.APIObjectVersioner{}, err - } + // The tests assume that Get/GetList/Watch calls shouldn't fail. + // However, 429 error can now be returned if watchcache is under initialization. + // To avoid rewriting all tests, we wait for watcache to initialize. + if err := cacher.Wait(context.Background()); err != nil { + return nil, storage.APIObjectVersioner{}, err } return cacher, versioner, nil } @@ -296,67 +293,46 @@ func TestShouldDelegateList(t *testing.T) { snapshotAvailableOverrides[opts{Recursive: true, ResourceVersion: oldRV, ResourceVersionMatch: metav1.ResourceVersionMatchExact}] = false snapshotAvailableOverrides[opts{Recursive: true, ResourceVersion: oldRV, ResourceVersionMatch: metav1.ResourceVersionMatchExact, Limit: 100}] = false - t.Run("ConsistentListFromCache=false", func(t *testing.T) { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.33")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, false) - t.Run("ListFromCacheSnapshot=false", func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, false) - runTestCases(t, false, testCases) - }) + // TODO(p0lyn0mial): the following tests assume that etcdfeature.DefaultFeatureSupportChecker.Supports(storage.RequestWatchProgress) + // evaluates to true. Otherwise the cache will be bypassed and the test will fail. + // + // If you were to run only TestGetListCacheBypass you would see that the test fail. + // However in CI all test are run and there must be a test(s) that properly + // initialize the storage layer so that the mentioned method evaluates to true + forceRequestWatchProgressSupport(t) - t.Run("ListFromCacheSnapshot=true", func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, true) - t.Run("SnapshotAvailable=false", func(t *testing.T) { - runTestCases(t, false, testCases, listFromSnapshotEnabledOverrides) - }) - t.Run("SnapshotAvailable=true", func(t *testing.T) { - runTestCases(t, true, testCases, listFromSnapshotEnabledOverrides, snapshotAvailableOverrides) - }) - }) + consistentListFromCacheOverrides := map[opts]bool{} + for _, recursive := range []bool{true, false} { + consistentListFromCacheOverrides[opts{Recursive: recursive}] = false + consistentListFromCacheOverrides[opts{Limit: 100, Recursive: recursive}] = false + } + + t.Run("ListFromCacheSnapshot=false", func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, false) + runTestCases(t, false, testCases, consistentListFromCacheOverrides) }) - t.Run("ConsistentListFromCache=true", func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, true) - // TODO(p0lyn0mial): the following tests assume that etcdfeature.DefaultFeatureSupportChecker.Supports(storage.RequestWatchProgress) - // evaluates to true. Otherwise the cache will be bypassed and the test will fail. - // - // If you were to run only TestGetListCacheBypass you would see that the test fail. - // However in CI all test are run and there must be a test(s) that properly - // initialize the storage layer so that the mentioned method evaluates to true - forceRequestWatchProgressSupport(t) + t.Run("ListFromCacheSnapshot=true", func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, true) - consistentListFromCacheOverrides := map[opts]bool{} - for _, recursive := range []bool{true, false} { - consistentListFromCacheOverrides[opts{Recursive: recursive}] = false - consistentListFromCacheOverrides[opts{Limit: 100, Recursive: recursive}] = false - } - - t.Run("ListFromCacheSnapshot=false", func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, false) - runTestCases(t, false, testCases, consistentListFromCacheOverrides) + consistentReadWithSnapshotOverrides := map[opts]bool{} + // Continues with negative RV are same as consistent read. + consistentReadWithSnapshotOverrides[opts{Recursive: true, Limit: 0, Continue: continueOnNegativeRV}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, Limit: 100, Continue: continueOnNegativeRV}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Limit: 0, Continue: continueOnNegativeRV}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Limit: 100, Continue: continueOnNegativeRV}] = false + // Exact on RV not yet observed by cache + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: etcdRV, Limit: 100}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: etcdRV, ResourceVersionMatch: metav1.ResourceVersionMatchExact}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: etcdRV, ResourceVersionMatch: metav1.ResourceVersionMatchExact, Limit: 100}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, Continue: continueOnEtcdRV}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Continue: continueOnEtcdRV}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, Continue: continueOnEtcdRV, Limit: 100}] = false + consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Continue: continueOnEtcdRV, Limit: 100}] = false + t.Run("SnapshotAvailable=false", func(t *testing.T) { + runTestCases(t, false, testCases, listFromSnapshotEnabledOverrides, consistentListFromCacheOverrides, consistentReadWithSnapshotOverrides) }) - t.Run("ListFromCacheSnapshot=true", func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ListFromCacheSnapshot, true) - - consistentReadWithSnapshotOverrides := map[opts]bool{} - // Continues with negative RV are same as consistent read. - consistentReadWithSnapshotOverrides[opts{Recursive: true, Limit: 0, Continue: continueOnNegativeRV}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, Limit: 100, Continue: continueOnNegativeRV}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Limit: 0, Continue: continueOnNegativeRV}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Limit: 100, Continue: continueOnNegativeRV}] = false - // Exact on RV not yet observed by cache - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: etcdRV, Limit: 100}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: etcdRV, ResourceVersionMatch: metav1.ResourceVersionMatchExact}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: etcdRV, ResourceVersionMatch: metav1.ResourceVersionMatchExact, Limit: 100}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, Continue: continueOnEtcdRV}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Continue: continueOnEtcdRV}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, Continue: continueOnEtcdRV, Limit: 100}] = false - consistentReadWithSnapshotOverrides[opts{Recursive: true, ResourceVersion: "0", Continue: continueOnEtcdRV, Limit: 100}] = false - t.Run("SnapshotAvailable=false", func(t *testing.T) { - runTestCases(t, false, testCases, listFromSnapshotEnabledOverrides, consistentListFromCacheOverrides, consistentReadWithSnapshotOverrides) - }) - t.Run("SnapshotAvailable=true", func(t *testing.T) { - runTestCases(t, true, testCases, listFromSnapshotEnabledOverrides, consistentListFromCacheOverrides, consistentReadWithSnapshotOverrides, snapshotAvailableOverrides) - }) + t.Run("SnapshotAvailable=true", func(t *testing.T) { + runTestCases(t, true, testCases, listFromSnapshotEnabledOverrides, consistentListFromCacheOverrides, consistentReadWithSnapshotOverrides, snapshotAvailableOverrides) }) }) } @@ -371,12 +347,11 @@ func mustAtoi(s string) int { func TestConsistentReadFallback(t *testing.T) { tcs := []struct { - name string - consistentReadsEnabled bool - skipStorageFallback bool - watchCacheRV string - storageRV string - fallbackError bool + name string + skipStorageFallback bool + watchCacheRV string + storageRV string + fallbackError bool expectError bool expectTooManyRequests bool @@ -387,7 +362,6 @@ func TestConsistentReadFallback(t *testing.T) { }{ { name: "Success", - consistentReadsEnabled: true, watchCacheRV: "42", storageRV: "42", expectRV: "42", @@ -400,7 +374,6 @@ apiserver_watch_cache_consistent_read_total{fallback="false", group="", resource }, { name: "Fallback", - consistentReadsEnabled: true, watchCacheRV: "2", storageRV: "42", expectRV: "42", @@ -414,7 +387,6 @@ apiserver_watch_cache_consistent_read_total{fallback="true", group="", resource= }, { name: "Fallback Failure", - consistentReadsEnabled: true, watchCacheRV: "2", storageRV: "42", fallbackError: true, @@ -429,7 +401,6 @@ apiserver_watch_cache_consistent_read_total{fallback="true", group="", resource= }, { name: "Skip Storage Fallback", - consistentReadsEnabled: true, skipStorageFallback: true, watchCacheRV: "2", storageRV: "42", @@ -443,23 +414,10 @@ apiserver_watch_cache_consistent_read_total{fallback="true", group="", resource= apiserver_watch_cache_consistent_read_total{fallback="skipped", group="", resource="pods", success="false"} 1 `, }, - { - name: "Disabled", - watchCacheRV: "2", - storageRV: "42", - expectRV: "42", - expectRequestsToStorage: 1, - expectMetric: ``, - }, } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - if tc.consistentReadsEnabled { - forceRequestWatchProgressSupport(t) - } else { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.33")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, false) - } + forceRequestWatchProgressSupport(t) if tc.skipStorageFallback { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCacheSkipTimeoutFallback, true) } @@ -646,53 +604,10 @@ func TestMatchExactResourceVersionFallback(t *testing.T) { } } -func TestGetListNonRecursiveCacheBypass(t *testing.T) { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.33")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, false) - backingStorage := &cachertesting.MockStorage{} - cacher, _, err := newTestCacher(backingStorage) - if err != nil { - t.Fatalf("Couldn't create cacher: %v", err) - } - defer cacher.Stop() - delegator := NewCacheDelegator(cacher, backingStorage) - defer delegator.Stop() - - pred := storage.SelectionPredicate{ - Limit: 500, - } - result := &example.PodList{} - - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - - // Inject error to underlying layer and check if cacher is not bypassed. - backingStorage.InjectGetListError(errDummy) - err = delegator.GetList(context.TODO(), "/pods/ns", storage.ListOptions{ - ResourceVersion: "0", - Predicate: pred, - }, result) - if err != nil { - t.Errorf("GetList with Limit and RV=0 should be served from cache: %v", err) - } - - err = delegator.GetList(context.TODO(), "/pods/ns", storage.ListOptions{ - ResourceVersion: "", - Predicate: pred, - }, result) - if !errors.Is(err, errDummy) { - t.Errorf("GetList with Limit without RV=0 should bypass cacher: %v", err) - } -} - func TestGetListNonRecursiveCacheWithConsistentListFromCache(t *testing.T) { - // Set feature gates once at the beginning since we only care about ConsistentListFromCache=true and ListFromCacheSnapshot=false + // Set feature gates once at the beginning since we only care about ListFromCacheSnapshot=false featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.ConsistentListFromCache: true, - features.ListFromCacheSnapshot: false, + features.ListFromCacheSnapshot: false, }) forceRequestWatchProgressSupport(t) @@ -821,12 +736,6 @@ func TestGetCacheBypass(t *testing.T) { result := &example.Pod{} - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - // Inject error to underlying layer and check if cacher is not bypassed. backingStorage.InjectGetListError(errDummy) err = delegator.Get(context.TODO(), "/pods/ns/pod-0", storage.GetOptions{ @@ -856,12 +765,6 @@ func TestWatchCacheBypass(t *testing.T) { delegator := NewCacheDelegator(cacher, backingStorage) defer delegator.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - _, err = delegator.Watch(context.TODO(), "/pods/ns", storage.ListOptions{ ResourceVersion: "0", Predicate: storage.Everything, @@ -879,46 +782,6 @@ func TestWatchCacheBypass(t *testing.T) { } } -func TestTooManyRequestsNotReturned(t *testing.T) { - // Ensure that with ResilientWatchCacheInitialization feature disabled, we don't return 429 - // errors when watchcache is not initialized. - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.33")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ResilientWatchCacheInitialization, false) - - dummyErr := fmt.Errorf("dummy") - backingStorage := &cachertesting.MockStorage{GetListErr: dummyErr} - cacher, _, err := newTestCacherWithoutSyncing(backingStorage, clock.RealClock{}) - if err != nil { - t.Fatalf("Couldn't create cacher: %v", err) - } - defer cacher.Stop() - delegator := NewCacheDelegator(cacher, backingStorage) - defer delegator.Stop() - - opts := storage.ListOptions{ - ResourceVersion: "0", - Predicate: storage.Everything, - } - - // Cancel the request so that it doesn't hang forever. - listCtx, listCancel := context.WithTimeout(context.Background(), 250*time.Millisecond) - defer listCancel() - - result := &example.PodList{} - err = delegator.GetList(listCtx, "/pods/ns", opts, result) - if err != nil && apierrors.IsTooManyRequests(err) { - t.Errorf("Unexpected 429 error without ResilientWatchCacheInitialization feature for List") - } - - watchCtx, watchCancel := context.WithTimeout(context.Background(), 250*time.Millisecond) - defer watchCancel() - - _, err = delegator.Watch(watchCtx, "/pods/ns", opts) - if err != nil && apierrors.IsTooManyRequests(err) { - t.Errorf("Unexpected 429 error without ResilientWatchCacheInitialization feature for Watch") - } -} - func TestEmptyWatchEventCache(t *testing.T) { server, etcdStorage := newEtcdTestStorage(t, etcd3testing.PathPrefix()) defer server.Terminate(t) @@ -1033,14 +896,8 @@ func TestWatchNotHangingOnStartupFailure(t *testing.T) { // Ensure that it terminates when its context is cancelled // (e.g. the request is terminated for whatever reason). _, err = cacher.Watch(ctx, "/pods/ns", storage.ListOptions{ResourceVersion: "0"}) - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err == nil || err.Error() != apierrors.NewServiceUnavailable(context.Canceled.Error()).Error() { - t.Errorf("Unexpected error: %#v", err) - } - } else { - if err == nil || !strings.Contains(err.Error(), "storage is (re)initializing") { - t.Errorf("Unexpected error: %#v", err) - } + if err == nil || !strings.Contains(err.Error(), "storage is (re)initializing") { + t.Errorf("Unexpected error: %#v", err) } } @@ -1052,12 +909,6 @@ func TestWatcherNotGoingBackInTime(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - // Ensure there is some budget for slowing down processing. cacher.dispatchTimeoutBudget.returnUnused(100 * time.Millisecond) @@ -1141,12 +992,6 @@ func TestCacherDontAcceptRequestsStopped(t *testing.T) { delegator := NewCacheDelegator(cacher, backingStorage) defer delegator.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - w, err := delegator.Watch(context.Background(), "/pods/ns", storage.ListOptions{ResourceVersion: "0", Predicate: storage.Everything}) if err != nil { t.Fatalf("Failed to create watch: %v", err) @@ -1177,14 +1022,8 @@ func TestCacherDontAcceptRequestsStopped(t *testing.T) { IgnoreNotFound: true, ResourceVersion: "1", }, result) - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err == nil { - t.Fatalf("Success to create Get: %v", err) - } - } else { - if err != nil { - t.Fatalf("Failed to get object: %v:", err) - } + if err != nil { + t.Fatalf("Failed to get object: %v:", err) } listResult := &example.PodList{} @@ -1195,14 +1034,8 @@ func TestCacherDontAcceptRequestsStopped(t *testing.T) { Limit: 500, }, }, listResult) - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err != nil { - t.Fatalf("Failed to create GetList: %v", err) - } - } else { - if err != nil { - t.Fatalf("Failed to list objects: %v", err) - } + if err != nil { + t.Fatalf("Failed to list objects: %v", err) } select { @@ -1329,12 +1162,6 @@ func TestCacherNoLeakWithMultipleWatchers(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - pred := storage.Everything pred.AllowWatchBookmarks = true @@ -1410,11 +1237,6 @@ func testCacherSendBookmarkEvents(t *testing.T, allowWatchBookmarks, expectedBoo } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } pred := storage.Everything pred.AllowWatchBookmarks = allowWatchBookmarks @@ -1510,12 +1332,6 @@ func TestInitialEventsEndBookmark(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - makePod := func(index uint64) *example.Pod { return &example.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1611,11 +1427,6 @@ func TestCacherSendsMultipleWatchBookmarks(t *testing.T) { // resolution how frequency we recompute. cacher.bookmarkWatchers.bookmarkFrequency = time.Second - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } pred := storage.Everything pred.AllowWatchBookmarks = true @@ -1682,12 +1493,6 @@ func TestDispatchingBookmarkEventsWithConcurrentStop(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - // Ensure there is some budget for slowing down processing. cacher.dispatchTimeoutBudget.returnUnused(100 * time.Millisecond) @@ -1761,12 +1566,6 @@ func TestBookmarksOnResourceVersionUpdates(t *testing.T) { // Ensure that bookmarks are sent more frequently than every 1m. cacher.bookmarkWatchers = newTimeBucketWatchers(clock.RealClock{}, 2*time.Second) - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - makePod := func(i int) *examplev1.Pod { return &examplev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1840,12 +1639,6 @@ func TestStartingResourceVersion(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - // Ensure there is some budget for slowing down processing. // We use the fakeTimeBudget to prevent this test from flaking under // the following conditions: @@ -1921,12 +1714,6 @@ func TestDispatchEventWillNotBeBlockedByTimedOutWatcher(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - // Ensure there is some budget for slowing down processing. // We use the fakeTimeBudget to prevent this test from flaking under // the following conditions: @@ -2064,12 +1851,6 @@ func TestCachingDeleteEvents(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - fooPredicate := storage.SelectionPredicate{ Label: labels.SelectorFromSet(map[string]string{"foo": "true"}), Field: fields.Everything(), @@ -2147,12 +1928,6 @@ func testCachingObjects(t *testing.T, watchersCount int) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - dispatchedEvents := []*watchCacheEvent{} cacher.watchCache.eventHandler = func(event *watchCacheEvent) { dispatchedEvents = append(dispatchedEvents, event) @@ -2244,12 +2019,6 @@ func TestCacheIntervalInvalidationStopsWatch(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - // Ensure there is enough budget for slow processing since // the entire watch cache is going to be served through the // interval and events won't be popped from the cacheWatcher's @@ -2324,8 +2093,7 @@ func TestCacheIntervalInvalidationStopsWatch(t *testing.T) { func TestWaitUntilWatchCacheFreshAndForceAllEvents(t *testing.T) { featuregatetesting.SetFeatureGatesDuringTest(t, utilfeature.DefaultFeatureGate, featuregatetesting.FeatureOverrides{ - features.WatchList: true, - features.ConsistentListFromCache: true, + features.WatchList: true, }) forceRequestWatchProgressSupport(t) @@ -2455,12 +2223,6 @@ func TestWaitUntilWatchCacheFreshAndForceAllEvents(t *testing.T) { } defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - w, err := cacher.Watch(context.Background(), "/pods/ns", scenario.opts) require.NoError(t, err, "failed to create watch: %v") defer w.Stop() @@ -2619,12 +2381,6 @@ func TestWatchListIsSynchronisedWhenNoEventsFromStoreReceived(t *testing.T) { require.NoError(t, err, "failed to create cacher") defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - pred := storage.Everything pred.AllowWatchBookmarks = true opts := storage.ListOptions{ @@ -2651,12 +2407,6 @@ func TestForgetWatcher(t *testing.T) { require.NoError(t, err) defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - assertCacherInternalState := func(expectedWatchersCounter, expectedValueWatchersCounter int) { cacher.Lock() defer cacher.Unlock() @@ -3045,12 +2795,6 @@ func TestGetBookmarkAfterResourceVersionLockedFunc(t *testing.T) { defer cacher.Stop() - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if err := cacher.ready.wait(context.Background()); err != nil { - t.Fatalf("unexpected error waiting for the cache to be ready") - } - } - cacher.watchCache.UpdateResourceVersion(fmt.Sprintf("%d", scenario.watchCacheResourceVersion)) parsedResourceVersion := 0 if len(scenario.opts.ResourceVersion) > 0 { @@ -3291,9 +3035,6 @@ func TestListIndexer(t *testing.T) { } func TestRetryAfterForUnreadyCache(t *testing.T) { - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - t.Skipf("the test requires %v to be enabled", features.ResilientWatchCacheInitialization) - } backingStorage := &cachertesting.MockStorage{} clock := testingclock.NewFakeClock(time.Now()) cacher, _, err := newTestCacherWithoutSyncing(backingStorage, clock) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator.go index 4ce39140553..bfc46a1e4bc 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator.go @@ -146,33 +146,18 @@ func (c *CacheDelegator) Get(ctx context.Context, key string, opts storage.GetOp return c.storage.Get(ctx, key, opts, objPtr) } - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if !c.cacher.Ready() { - // If Cache is not initialized, delegator Get requests to storage - // as described in https://kep.k8s.io/4568 - span.AddEvent("About to Get from underlying storage - cache not initialized") - return c.storage.Get(ctx, key, opts, objPtr) - } + if !c.cacher.Ready() { + // If Cache is not initialized, delegator Get requests to storage + // as described in https://kep.k8s.io/4568 + span.AddEvent("About to Get from underlying storage - cache not initialized") + return c.storage.Get(ctx, key, opts, objPtr) } // If resourceVersion is specified, serve it from cache. // It's guaranteed that the returned value is at least that // fresh as the given resourceVersion. - getRV, err := c.cacher.versioner.ParseResourceVersion(opts.ResourceVersion) - if err != nil { + if _, err := c.cacher.versioner.ParseResourceVersion(opts.ResourceVersion); err != nil { return err } - // Do not create a trace - it's not for free and there are tons - // of Get requests. We can add it if it will be really needed. - if !utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if getRV == 0 && !c.cacher.Ready() { - // If Cacher is not yet initialized and we don't require any specific - // minimal resource version, simply forward the request to storage. - return c.storage.Get(ctx, key, opts, objPtr) - } - if err := c.cacher.ready.wait(ctx); err != nil { - return errors.NewServiceUnavailable(err.Error()) - } - } span.AddEvent("About to fetch object from cache") return c.cacher.Get(ctx, key, opts, objPtr) } @@ -190,23 +175,14 @@ func (c *CacheDelegator) GetList(ctx context.Context, key string, opts storage.L return c.storage.GetList(ctx, key, opts, listObj) } - listRV, err := c.cacher.versioner.ParseResourceVersion(opts.ResourceVersion) - if err != nil { + if _, err := c.cacher.versioner.ParseResourceVersion(opts.ResourceVersion); err != nil { return err } - if utilfeature.DefaultFeatureGate.Enabled(features.ResilientWatchCacheInitialization) { - if !c.cacher.Ready() && shouldDelegateListOnNotReadyCache(opts) { - // If Cacher is not initialized, delegator List requests to storage - // as described in https://kep.k8s.io/4568 - return c.storage.GetList(ctx, key, opts, listObj) - } - } else { - if listRV == 0 && !c.cacher.Ready() { - // If Cacher is not yet initialized and we don't require any specific - // minimal resource version, simply forward the request to storage. - return c.storage.GetList(ctx, key, opts, listObj) - } + if !c.cacher.Ready() && shouldDelegateListOnNotReadyCache(opts) { + // If Cacher is not initialized, delegator List requests to storage + // as described in https://kep.k8s.io/4568 + return c.storage.GetList(ctx, key, opts, listObj) } err = c.cacher.GetList(ctx, key, opts, listObj) success := "true" diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator/interface.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator/interface.go index 1cdf5145e48..2fefb46b9b2 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator/interface.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator/interface.go @@ -18,10 +18,8 @@ package delegator import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/storage" etcdfeature "k8s.io/apiserver/pkg/storage/feature" - utilfeature "k8s.io/apiserver/pkg/util/feature" ) func ShouldDelegateListMeta(opts *metav1.ListOptions, cache Helper) (Result, error) { @@ -107,7 +105,5 @@ func (c CacheWithoutSnapshots) ShouldDelegateConsistentRead() (Result, error) { // ConsistentReadSupported returns whether cache can be used to serve reads with RV not yet observed by cache, including both consistent reads. // Function is located here to avoid import cycles between staging/src/k8s.io/apiserver/pkg/storage/cacher/delegator.go and staging/src/k8s.io/apiserver/pkg/util/flow_control/request/list_work_estimator.go. func ConsistentReadSupported() bool { - consistentListFromCacheEnabled := utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) - requestWatchProgressSupported := etcdfeature.DefaultFeatureSupportChecker.Supports(storage.RequestWatchProgress) - return consistentListFromCacheEnabled && requestWatchProgressSupported + return etcdfeature.DefaultFeatureSupportChecker.Supports(storage.RequestWatchProgress) } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/store/store.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/store/store.go index 00dbc212987..89de895d9c0 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/store/store.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/store/store.go @@ -22,8 +22,6 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apiserver/pkg/features" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/cache" ) @@ -79,10 +77,7 @@ type OrderedLister interface { } func NewIndexer(indexers *cache.Indexers) Indexer { - if utilfeature.DefaultFeatureGate.Enabled(features.BtreeWatchCache) { - return newThreadedBtreeStoreIndexer(ElementIndexers(indexers), btreeDegree) - } - return cache.NewIndexer(ElementKey, ElementIndexers(indexers)) + return newThreadedBtreeStoreIndexer(ElementIndexers(indexers), btreeDegree) } // Computing a key of an object is generally non-trivial (it performs diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go index 548bf0f94fe..6b88daade87 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/watch_cache_test.go @@ -35,7 +35,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/version" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" "k8s.io/apiserver/pkg/features" @@ -554,7 +553,6 @@ func TestWaitUntilFreshAndGetList(t *testing.T) { } func TestWaitUntilFreshAndListFromCache(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, true) forceRequestWatchProgressSupport(t) ctx := context.Background() store := newTestWatchCache(3, DefaultEventFreshDuration, &cache.Indexers{}) @@ -609,54 +607,33 @@ func TestWaitUntilFreshAndGet(t *testing.T) { } func TestWaitUntilFreshAndListTimeout(t *testing.T) { - tcs := []struct { - name string - ConsistentListFromCache bool - }{ - { - name: "FromStorage", - ConsistentListFromCache: false, - }, - { - name: "FromCache", - ConsistentListFromCache: true, - }, + ctx := context.Background() + store := newTestWatchCache(3, DefaultEventFreshDuration, &cache.Indexers{}) + defer store.Stop() + fc := store.clock.(*testingclock.FakeClock) + + // In background, step clock after the below call starts the timer. + go func() { + for !fc.HasWaiters() { + time.Sleep(time.Millisecond) + } + store.Add(makeTestPod("foo", 2)) + store.bookmarkRevision <- 3 + fc.Step(blockTimeout) + + // Add an object to make sure the test would + // eventually fail instead of just waiting + // forever. + time.Sleep(30 * time.Second) + store.Add(makeTestPod("bar", 4)) + }() + + _, _, err := store.WaitUntilFreshAndGetList(ctx, "", storage.ListOptions{ResourceVersion: "4", Predicate: storage.Everything}) + if !errors.IsTimeout(err) { + t.Errorf("expected timeout error but got: %v", err) } - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - if !tc.ConsistentListFromCache { - featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.33")) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ConsistentListFromCache, tc.ConsistentListFromCache) - } - ctx := context.Background() - store := newTestWatchCache(3, DefaultEventFreshDuration, &cache.Indexers{}) - defer store.Stop() - fc := store.clock.(*testingclock.FakeClock) - - // In background, step clock after the below call starts the timer. - go func() { - for !fc.HasWaiters() { - time.Sleep(time.Millisecond) - } - store.Add(makeTestPod("foo", 2)) - store.bookmarkRevision <- 3 - fc.Step(blockTimeout) - - // Add an object to make sure the test would - // eventually fail instead of just waiting - // forever. - time.Sleep(30 * time.Second) - store.Add(makeTestPod("bar", 4)) - }() - - _, _, err := store.WaitUntilFreshAndGetList(ctx, "", storage.ListOptions{ResourceVersion: "4", Predicate: storage.Everything}) - if !errors.IsTimeout(err) { - t.Errorf("expected timeout error but got: %v", err) - } - if !storage.IsTooLargeResourceVersion(err) { - t.Errorf("expected 'Too large resource version' cause in error but got: %v", err) - } - }) + if !storage.IsTooLargeResourceVersion(err) { + t.Errorf("expected 'Too large resource version' cause in error but got: %v", err) } } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go index 1a55e72b28a..eab07113a14 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go @@ -200,9 +200,7 @@ func New(c *kubernetes.Client, compactor Compactor, codec runtime.Codec, newFunc w.getCurrentStorageRV = func(ctx context.Context) (uint64, error) { return s.GetCurrentResourceVersion(ctx) } - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) || utilfeature.DefaultFeatureGate.Enabled(features.WatchList) { - etcdfeature.DefaultFeatureSupportChecker.CheckClient(c.Ctx(), c, storage.RequestWatchProgress) - } + etcdfeature.DefaultFeatureSupportChecker.CheckClient(c.Ctx(), c, storage.RequestWatchProgress) return s, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go index 6b60601a784..0482c8aa84e 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go @@ -319,17 +319,15 @@ var newETCD3Client = func(c storagebackend.TransportConfig) (*kubernetes.Client, grpc.WithChainUnaryInterceptor(grpcpromClientMetrics.UnaryClientInterceptor()), grpc.WithChainStreamInterceptor(grpcpromClientMetrics.StreamClientInterceptor()), } - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerTracing) { - tracingOpts := []otelgrpc.Option{ - otelgrpc.WithMessageEvents(otelgrpc.ReceivedEvents, otelgrpc.SentEvents), - otelgrpc.WithPropagators(tracing.Propagators()), - otelgrpc.WithTracerProvider(c.TracerProvider), - } - // Even with Noop TracerProvider, the otelgrpc still handles context propagation. - // See https://github.com/open-telemetry/opentelemetry-go/tree/main/example/passthrough - dialOptions = append(dialOptions, - grpc.WithStatsHandler(otelgrpc.NewClientHandler(tracingOpts...))) + tracingOpts := []otelgrpc.Option{ + otelgrpc.WithMessageEvents(otelgrpc.ReceivedEvents, otelgrpc.SentEvents), + otelgrpc.WithPropagators(tracing.Propagators()), + otelgrpc.WithTracerProvider(c.TracerProvider), } + // Even with Noop TracerProvider, the otelgrpc still handles context propagation. + // See https://github.com/open-telemetry/opentelemetry-go/tree/main/example/passthrough + dialOptions = append(dialOptions, + grpc.WithStatsHandler(otelgrpc.NewClientHandler(tracingOpts...))) if egressDialer != nil { dialer := func(ctx context.Context, addr string) (net.Conn, error) { if strings.Contains(addr, "//") { diff --git a/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go b/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go index 669af09d73c..c6de1df9ae9 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go @@ -709,14 +709,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com pred: storage.Everything, expectedOut: []example.Pod{*updatedPod}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/first/", - }, - } + return nil }, }, { @@ -878,14 +871,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com pred: storage.Everything, expectedOut: []example.Pod{}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/non-existing/", - }, - } + return nil }, }, { @@ -897,14 +883,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, expectedOut: []example.Pod{}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/first/", - }, - } + return nil }, }, { @@ -932,15 +911,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectContinueExact: encodeContinueOrDie(createdPods[1].Name+"\x00", int64(mustAtoi(currentRV))), expectedRemainingItemCount: ptr.To[int64](1), expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/second/", - ListOptions: kubernetes.ListOptions{Revision: 0, Limit: 1}, - }, - } + return nil }, }, { @@ -1151,14 +1122,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com pred: storage.Everything, expectedOut: []example.Pod{*createdPods[1], *createdPods[2]}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/second/", - }, - } + return nil }, }, { @@ -1180,23 +1144,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectedOut: []example.Pod{*createdPods[3]}, expectContinue: true, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Limit: 1}, - }, - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: int64(continueRV) + 1, Limit: 2, Continue: "/registry/pods/first/bar\x00"}, - }, - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: int64(continueRV) + 1, Limit: 4, Continue: "/registry/pods/second/foo\x00"}, - }, - } + return nil }, }, { @@ -1224,19 +1172,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectedOut: []example.Pod{*createdPods[3]}, expectContinue: false, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: 0, Limit: 2}, - }, - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: int64(continueRV) + 1, Limit: 4, Continue: "/registry/pods/second/bar\x00"}, - }, - } + return nil }, }, { @@ -1276,15 +1212,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectContinue: true, expectedOut: []example.Pod{*updatedPod, *createdPods[1]}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: 0, Limit: 2}, - }, - } + return nil }, }, { @@ -1310,19 +1238,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, expectedOut: []example.Pod{*createdPods[2], *createdPods[4]}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: 0, Limit: 2}, - }, - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: int64(continueRV) + 1, Limit: 4, Continue: "/registry/pods/second/bar\x00"}, - }, - } + return nil }, }, { @@ -1417,15 +1333,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, expectedOut: []example.Pod{*createdPods[2], *createdPods[4]}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: 0, Limit: 5}, - }, - } + return nil }, }, { @@ -1450,15 +1358,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com }, expectedOut: []example.Pod{*createdPods[3]}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - ListOptions: kubernetes.ListOptions{Revision: 0, Limit: 5}, - }, - } + return nil }, }, { @@ -1479,14 +1379,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com pred: storage.Everything, expectedOut: []example.Pod{*updatedPod, *createdPods[1], *createdPods[2], *createdPods[3], *createdPods[4]}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/", - }, - } + return nil }, }, { @@ -1529,14 +1422,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectRV: currentRV, expectedOut: []example.Pod{}, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) { - return nil - } - return []RecordedList{ - { - Key: "/registry/pods/empty/", - }, - } + return nil }, }, { @@ -1725,7 +1611,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com rvMatch: metav1.ResourceVersionMatchExact, expectRV: fmt.Sprint(continueRV + 1), expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) && utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { + if utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { return nil } return []RecordedList{ @@ -1955,7 +1841,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectContinueExact: encodeContinueOrDie(updatedPod.Namespace+"/"+updatedPod.Name+"\x00", int64(continueRV+1)), expectedRemainingItemCount: ptr.To[int64](4), expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) && utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { + if utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { return nil } return []RecordedList{ @@ -2148,7 +2034,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectContinueExact: encodeContinueOrDie(createdPods[1].Namespace+"/"+createdPods[1].Name+"\x00", int64(continueRV+1)), expectedRemainingItemCount: ptr.To[int64](3), expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) && utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { + if utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { return nil } return []RecordedList{ @@ -2170,7 +2056,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectedOut: []example.Pod{*createdPods[1], *createdPods[2], *createdPods[3], *createdPods[4]}, expectRV: currentRV, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) && utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { + if utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { return nil } return []RecordedList{ @@ -2196,7 +2082,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectRV: currentRV, expectedRemainingItemCount: ptr.To[int64](2), expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) && utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { + if utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { return nil } return []RecordedList{ @@ -2218,7 +2104,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface, com expectedOut: []example.Pod{*createdPods[3], *createdPods[4]}, expectRV: currentRV, expectCacherRequestsToEtcd: func() []RecordedList { - if utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache) && utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { + if utilfeature.DefaultFeatureGate.Enabled(features.ListFromCacheSnapshot) { return nil } return []RecordedList{ diff --git a/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go b/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go index 0816b45a102..6ccc5fa8cdd 100644 --- a/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/util/webhook/authentication.go @@ -29,9 +29,7 @@ import ( corev1 "k8s.io/api/core/v1" utilnet "k8s.io/apimachinery/pkg/util/net" - "k8s.io/apiserver/pkg/features" egressselector "k8s.io/apiserver/pkg/server/egressselector" - "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" @@ -59,9 +57,7 @@ func NewDefaultAuthenticationInfoResolverWrapper( if err != nil { return nil, err } - if feature.DefaultFeatureGate.Enabled(features.APIServerTracing) { - ret.Wrap(tracing.WrapperFor(tp)) - } + ret.Wrap(tracing.WrapperFor(tp)) if egressSelector != nil { networkContext := egressselector.ControlPlane.AsNetworkContext() @@ -84,9 +80,7 @@ func NewDefaultAuthenticationInfoResolverWrapper( if err != nil { return nil, err } - if feature.DefaultFeatureGate.Enabled(features.APIServerTracing) { - ret.Wrap(tracing.WrapperFor(tp)) - } + ret.Wrap(tracing.WrapperFor(tp)) if egressSelector != nil { networkContext := egressselector.Cluster.AsNetworkContext() diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go index ed9cd4592a0..ee763b8f461 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go @@ -167,7 +167,7 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { proxyRoundTripper = transport.NewAuthProxyRoundTripper(user.GetName(), userUID, user.GetGroups(), user.GetExtra(), proxyRoundTripper) - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerTracing) && !upgrade { + if !upgrade { tracingWrapper := tracing.WrapperFor(r.tracerProvider) proxyRoundTripper = tracingWrapper(proxyRoundTripper) } diff --git a/test/compatibility_lifecycle/reference/feature_list.md b/test/compatibility_lifecycle/reference/feature_list.md index 3c80fc87d6d..15cf5fb3580 100644 --- a/test/compatibility_lifecycle/reference/feature_list.md +++ b/test/compatibility_lifecycle/reference/feature_list.md @@ -7,7 +7,6 @@ |---------|---------|--------|-------|------|----|------------|--------------|-------| | APIResponseCompression | :ballot_box_with_check: 1.16+ | | 1.8–1.15 | 1.16– | | | | [code](https://cs.k8s.io/?q=%5CbAPIResponseCompression%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAPIResponseCompression%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | APIServerIdentity | :ballot_box_with_check: 1.26+ | | 1.20–1.25 | 1.26– | | | | [code](https://cs.k8s.io/?q=%5CbAPIServerIdentity%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAPIServerIdentity%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| APIServerTracing | :ballot_box_with_check: 1.27+ | :closed_lock_with_key: 1.34+ | 1.22–1.26 | 1.27–1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbAPIServerTracing%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAPIServerTracing%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | APIServingWithRoutine | | | 1.30– | | | | | [code](https://cs.k8s.io/?q=%5CbAPIServingWithRoutine%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAPIServingWithRoutine%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | AggregatedDiscoveryRemoveBetaType | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.35+ | | | 1.0–1.32 | 1.33– | | [code](https://cs.k8s.io/?q=%5CbAggregatedDiscoveryRemoveBetaType%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAggregatedDiscoveryRemoveBetaType%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | AllowDNSOnlyNodeCSR | :ballot_box_with_check: 1.0+ | | | | 1.0–1.30 | 1.31– | | [code](https://cs.k8s.io/?q=%5CbAllowDNSOnlyNodeCSR%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAllowDNSOnlyNodeCSR%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | @@ -18,7 +17,6 @@ | AllowUnsafeMalformedObjectDeletion | | | 1.32– | | | | | [code](https://cs.k8s.io/?q=%5CbAllowUnsafeMalformedObjectDeletion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAllowUnsafeMalformedObjectDeletion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | AtomicFIFO | :ballot_box_with_check: 1.36+ | | | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbAtomicFIFO%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAtomicFIFO%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | AuthorizePodWebsocketUpgradeCreatePermission | :ballot_box_with_check: 1.35+ | | | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbAuthorizePodWebsocketUpgradeCreatePermission%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbAuthorizePodWebsocketUpgradeCreatePermission%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| BtreeWatchCache | :ballot_box_with_check: 1.32+ | :closed_lock_with_key: 1.33+ | | 1.32 | 1.33– | | | [code](https://cs.k8s.io/?q=%5CbBtreeWatchCache%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbBtreeWatchCache%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | CBORServingAndStorage | | | 1.32– | | | | | [code](https://cs.k8s.io/?q=%5CbCBORServingAndStorage%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbCBORServingAndStorage%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | CPUManagerPolicyAlphaOptions | | | 1.23– | | | | | [code](https://cs.k8s.io/?q=%5CbCPUManagerPolicyAlphaOptions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbCPUManagerPolicyAlphaOptions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | CPUManagerPolicyBetaOptions | :ballot_box_with_check: 1.23+ | | | 1.23– | | | | [code](https://cs.k8s.io/?q=%5CbCPUManagerPolicyBetaOptions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbCPUManagerPolicyBetaOptions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | @@ -41,8 +39,7 @@ | ComponentFlagz | :ballot_box_with_check: 1.36+ | | 1.32–1.35 | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbComponentFlagz%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbComponentFlagz%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ComponentStatusz | :ballot_box_with_check: 1.36+ | | 1.32–1.35 | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbComponentStatusz%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbComponentStatusz%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ConcurrentWatchObjectDecode | | | | 1.31– | | | | [code](https://cs.k8s.io/?q=%5CbConcurrentWatchObjectDecode%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbConcurrentWatchObjectDecode%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| ConsistentListFromCache | :ballot_box_with_check: 1.31+ | :closed_lock_with_key: 1.34+ | 1.28–1.30 | 1.31–1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbConsistentListFromCache%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbConsistentListFromCache%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| ConsistentListFromCacheSkipTimeoutFallback | | | 1.37– | | | | ConsistentListFromCache | [code](https://cs.k8s.io/?q=%5CbConsistentListFromCacheSkipTimeoutFallback%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbConsistentListFromCacheSkipTimeoutFallback%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| ConsistentListFromCacheSkipTimeoutFallback | | | 1.37– | | | | | [code](https://cs.k8s.io/?q=%5CbConsistentListFromCacheSkipTimeoutFallback%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbConsistentListFromCacheSkipTimeoutFallback%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ConstrainedImpersonation | :ballot_box_with_check: 1.36+ | | 1.35 | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbConstrainedImpersonation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbConstrainedImpersonation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ContainerCheckpoint | :ballot_box_with_check: 1.30+ | | 1.25–1.29 | 1.30– | | | | [code](https://cs.k8s.io/?q=%5CbContainerCheckpoint%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbContainerCheckpoint%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ContainerRestartRules | :ballot_box_with_check: 1.35+ | | 1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbContainerRestartRules%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbContainerRestartRules%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | @@ -138,7 +135,6 @@ | NominatedNodeNameForExpectation | :ballot_box_with_check: 1.35+ | | 1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbNominatedNodeNameForExpectation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNominatedNodeNameForExpectation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | OpenAPIEnums | :ballot_box_with_check: 1.24+ | | 1.23 | 1.24– | | | | [code](https://cs.k8s.io/?q=%5CbOpenAPIEnums%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbOpenAPIEnums%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | OpportunisticBatching | :ballot_box_with_check: 1.35+ | | | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbOpportunisticBatching%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbOpportunisticBatching%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| OrderedNamespaceDeletion | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.34+ | | 1.30–1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbOrderedNamespaceDeletion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbOrderedNamespaceDeletion%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | PLEGOnDemandRelist | :ballot_box_with_check: 1.36+ | | | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbPLEGOnDemandRelist%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbPLEGOnDemandRelist%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | PersistentVolumeClaimUnusedSinceTime | | | 1.36– | | | | | [code](https://cs.k8s.io/?q=%5CbPersistentVolumeClaimUnusedSinceTime%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbPersistentVolumeClaimUnusedSinceTime%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | PodAndContainerStatsFromCRI | | | 1.23– | | | | | [code](https://cs.k8s.io/?q=%5CbPodAndContainerStatsFromCRI%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbPodAndContainerStatsFromCRI%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | @@ -168,11 +164,9 @@ | ReloadKubeletClientCAFile | :ballot_box_with_check: 1.36+ | | | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbReloadKubeletClientCAFile%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbReloadKubeletClientCAFile%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ReloadKubeletServerCertificateFile | :ballot_box_with_check: 1.31+ | | | 1.31– | | | | [code](https://cs.k8s.io/?q=%5CbReloadKubeletServerCertificateFile%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbReloadKubeletServerCertificateFile%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | RemoteRequestHeaderUID | :ballot_box_with_check: 1.33+ | | 1.32 | 1.33– | | | | [code](https://cs.k8s.io/?q=%5CbRemoteRequestHeaderUID%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbRemoteRequestHeaderUID%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| ResilientWatchCacheInitialization | :ballot_box_with_check: 1.31+ | :closed_lock_with_key: 1.34+ | | 1.31–1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbResilientWatchCacheInitialization%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbResilientWatchCacheInitialization%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ResourceHealthStatus | :ballot_box_with_check: 1.36+ | | 1.31–1.35 | 1.36– | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbResourceHealthStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbResourceHealthStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | ResourceHealthStatusMessage | :ballot_box_with_check: 1.36+ | | | 1.36– | | | ResourceHealthStatus | [code](https://cs.k8s.io/?q=%5CbResourceHealthStatusMessage%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbResourceHealthStatusMessage%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | RestartAllContainersOnContainerExits | :ballot_box_with_check: 1.36+ | | 1.35 | 1.36– | | | ContainerRestartRules
NodeDeclaredFeatures | [code](https://cs.k8s.io/?q=%5CbRestartAllContainersOnContainerExits%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbRestartAllContainersOnContainerExits%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| RetryGenerateName | :ballot_box_with_check: 1.31+ | :closed_lock_with_key: 1.32+ | 1.30 | 1.31 | 1.32– | | | [code](https://cs.k8s.io/?q=%5CbRetryGenerateName%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbRetryGenerateName%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | RotateKubeletServerCertificate | :ballot_box_with_check: 1.12+ | | 1.7–1.11 | 1.12– | | | | [code](https://cs.k8s.io/?q=%5CbRotateKubeletServerCertificate%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbRotateKubeletServerCertificate%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | RuntimeClassInImageCriApi | | | 1.29– | | | | | [code](https://cs.k8s.io/?q=%5CbRuntimeClassInImageCriApi%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbRuntimeClassInImageCriApi%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | SELinuxChangePolicy | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.36+ | 1.32 | 1.33–1.35 | 1.36– | | | [code](https://cs.k8s.io/?q=%5CbSELinuxChangePolicy%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbSELinuxChangePolicy%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | @@ -201,8 +195,6 @@ | StorageVersionAPI | | | 1.20– | | | | APIServerIdentity | [code](https://cs.k8s.io/?q=%5CbStorageVersionAPI%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStorageVersionAPI%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | StorageVersionHash | :ballot_box_with_check: 1.15+ | | 1.14 | 1.15– | | | | [code](https://cs.k8s.io/?q=%5CbStorageVersionHash%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStorageVersionHash%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | StorageVersionMigrator | | | 1.30–1.34 | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbStorageVersionMigrator%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStorageVersionMigrator%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| StreamingCollectionEncodingToJSON | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.34+ | | 1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbStreamingCollectionEncodingToJSON%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStreamingCollectionEncodingToJSON%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| StreamingCollectionEncodingToProtobuf | :ballot_box_with_check: 1.33+ | :closed_lock_with_key: 1.34+ | | 1.33 | 1.34– | | | [code](https://cs.k8s.io/?q=%5CbStreamingCollectionEncodingToProtobuf%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStreamingCollectionEncodingToProtobuf%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | StrictIPCIDRValidation | :ballot_box_with_check: 1.36+ | | 1.33–1.35 | 1.36– | | | | [code](https://cs.k8s.io/?q=%5CbStrictIPCIDRValidation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStrictIPCIDRValidation%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | StructuredAuthenticationConfigurationEgressSelector | :ballot_box_with_check: 1.34+ | | | 1.34– | | | | [code](https://cs.k8s.io/?q=%5CbStructuredAuthenticationConfigurationEgressSelector%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStructuredAuthenticationConfigurationEgressSelector%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | StructuredAuthenticationConfigurationJWKSMetrics | :ballot_box_with_check: 1.35+ | | | 1.35– | | | | [code](https://cs.k8s.io/?q=%5CbStructuredAuthenticationConfigurationJWKSMetrics%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbStructuredAuthenticationConfigurationJWKSMetrics%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 fd65c1803c4..e20df18c8ab 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -87,20 +87,6 @@ lockToDefault: false preRelease: Beta version: "1.26" -- name: APIServerTracing - versionedSpecs: - - default: false - lockToDefault: false - preRelease: Alpha - version: "1.22" - - default: true - lockToDefault: false - preRelease: Beta - version: "1.27" - - default: true - lockToDefault: true - preRelease: GA - version: "1.34" - name: APIServingWithRoutine versionedSpecs: - default: false @@ -113,16 +99,6 @@ lockToDefault: false preRelease: Beta version: "1.35" -- name: BtreeWatchCache - versionedSpecs: - - default: true - lockToDefault: false - preRelease: Beta - version: "1.32" - - default: true - lockToDefault: true - preRelease: GA - version: "1.33" - name: CBORServingAndStorage versionedSpecs: - default: false @@ -207,20 +183,6 @@ lockToDefault: false preRelease: Beta version: "1.31" -- name: ConsistentListFromCache - versionedSpecs: - - default: false - lockToDefault: false - preRelease: Alpha - version: "1.28" - - default: true - lockToDefault: false - preRelease: Beta - version: "1.31" - - default: true - lockToDefault: true - preRelease: GA - version: "1.34" - name: ConsistentListFromCacheSkipTimeoutFallback versionedSpecs: - default: false @@ -1281,20 +1243,6 @@ lockToDefault: false preRelease: Beta version: "1.35" -- name: OrderedNamespaceDeletion - versionedSpecs: - - default: false - lockToDefault: false - preRelease: Beta - version: "1.30" - - default: true - lockToDefault: false - preRelease: Beta - version: "1.33" - - default: true - lockToDefault: true - preRelease: GA - version: "1.34" - name: PersistentVolumeClaimUnusedSinceTime versionedSpecs: - default: false @@ -1585,16 +1533,6 @@ lockToDefault: false preRelease: Beta version: "1.33" -- name: ResilientWatchCacheInitialization - versionedSpecs: - - default: true - lockToDefault: false - preRelease: Beta - version: "1.31" - - default: true - lockToDefault: true - preRelease: GA - version: "1.34" - name: ResourceHealthStatus versionedSpecs: - default: false @@ -1621,20 +1559,6 @@ lockToDefault: false preRelease: Beta version: "1.36" -- name: RetryGenerateName - versionedSpecs: - - default: false - lockToDefault: false - preRelease: Alpha - version: "1.30" - - default: true - lockToDefault: false - preRelease: Beta - version: "1.31" - - default: true - lockToDefault: true - preRelease: GA - version: "1.32" - name: RotateKubeletServerCertificate versionedSpecs: - default: false @@ -1899,26 +1823,6 @@ lockToDefault: false preRelease: Beta version: "1.35" -- name: StreamingCollectionEncodingToJSON - versionedSpecs: - - default: true - lockToDefault: false - preRelease: Beta - version: "1.33" - - default: true - lockToDefault: true - preRelease: GA - version: "1.34" -- name: StreamingCollectionEncodingToProtobuf - versionedSpecs: - - default: true - lockToDefault: false - preRelease: Beta - version: "1.33" - - default: true - lockToDefault: true - preRelease: GA - version: "1.34" - name: StrictIPCIDRValidation versionedSpecs: - default: false