mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Graduate APIListChunking to GA
This commit is contained in:
		@@ -265,7 +265,7 @@ fi
 | 
			
		||||
RUN_CCM_CONTROLLERS="${RUN_CCM_CONTROLLERS:-*,-gkenetworkparamset}"
 | 
			
		||||
 | 
			
		||||
# List of the set of feature gates recognized by the GCP CCM
 | 
			
		||||
export CCM_FEATURE_GATES="APIListChunking,APIPriorityAndFairness,APIResponseCompression,APIServerIdentity,APIServerTracing,AllAlpha,AllBeta,CustomResourceValidationExpressions,KMSv2,OpenAPIEnums,OpenAPIV3,RemainingItemCount,ServerSideFieldValidation,StorageVersionAPI,StorageVersionHash"
 | 
			
		||||
export CCM_FEATURE_GATES="APIPriorityAndFairness,APIResponseCompression,APIServerIdentity,APIServerTracing,AllAlpha,AllBeta,CustomResourceValidationExpressions,KMSv2,OpenAPIEnums,OpenAPIV3,RemainingItemCount,ServerSideFieldValidation,StorageVersionAPI,StorageVersionHash"
 | 
			
		||||
 | 
			
		||||
# Optional: set feature gates
 | 
			
		||||
# shellcheck disable=SC2034 # Variables sourced in other scripts.
 | 
			
		||||
 
 | 
			
		||||
@@ -316,7 +316,7 @@ if [[ -n "${NODE_ACCELERATORS}" ]]; then
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# List of the set of feature gates recognized by the GCP CCM
 | 
			
		||||
export CCM_FEATURE_GATES="APIListChunking,APIPriorityAndFairness,APIResponseCompression,APIServerIdentity,APIServerTracing,AllAlpha,AllBeta,CustomResourceValidationExpressions,KMSv2,OpenAPIEnums,OpenAPIV3,RemainingItemCount,ServerSideFieldValidation,StorageVersionAPI,StorageVersionHash"
 | 
			
		||||
export CCM_FEATURE_GATES="APIPriorityAndFairness,APIResponseCompression,APIServerIdentity,APIServerTracing,AllAlpha,AllBeta,CustomResourceValidationExpressions,KMSv2,OpenAPIEnums,OpenAPIV3,RemainingItemCount,ServerSideFieldValidation,StorageVersionAPI,StorageVersionHash"
 | 
			
		||||
 | 
			
		||||
# Optional: Install cluster DNS.
 | 
			
		||||
# Set CLUSTER_DNS_CORE_DNS to 'false' to install kube-dns instead of CoreDNS.
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,7 @@ func createAggregatorConfig(
 | 
			
		||||
	// we assume that the etcd options have been completed already.  avoid messing with anything outside
 | 
			
		||||
	// of changes to StorageConfig as that may lead to unexpected behavior when the options are applied.
 | 
			
		||||
	etcdOptions := *commandOptions.Etcd
 | 
			
		||||
	etcdOptions.StorageConfig.Paging = utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIListChunking)
 | 
			
		||||
	etcdOptions.StorageConfig.Paging = true
 | 
			
		||||
	etcdOptions.StorageConfig.Codec = aggregatorscheme.Codecs.LegacyCodec(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion)
 | 
			
		||||
	etcdOptions.StorageConfig.EncodeVersioner = runtime.NewMultiGroupVersioner(v1.SchemeGroupVersion, schema.GroupKind{Group: v1beta1.GroupName})
 | 
			
		||||
	etcdOptions.SkipHealthEndpoints = true // avoid double wiring of health checks
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,7 @@ import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	"k8s.io/apiserver/pkg/admission"
 | 
			
		||||
	"k8s.io/apiserver/pkg/features"
 | 
			
		||||
	"k8s.io/apiserver/pkg/server"
 | 
			
		||||
	"k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/apiserver/pkg/util/webhook"
 | 
			
		||||
	"k8s.io/client-go/informers"
 | 
			
		||||
 | 
			
		||||
@@ -52,7 +50,7 @@ func CreateAPIExtensionsConfig(
 | 
			
		||||
	// we assume that the etcd options have been completed already.  avoid messing with anything outside
 | 
			
		||||
	// of changes to StorageConfig as that may lead to unexpected behavior when the options are applied.
 | 
			
		||||
	etcdOptions := *commandOptions.Etcd
 | 
			
		||||
	etcdOptions.StorageConfig.Paging = feature.DefaultFeatureGate.Enabled(features.APIListChunking)
 | 
			
		||||
	etcdOptions.StorageConfig.Paging = true
 | 
			
		||||
	// this is where the true decodable levels come from.
 | 
			
		||||
	etcdOptions.StorageConfig.Codec = apiextensionsapiserver.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion, v1.SchemeGroupVersion)
 | 
			
		||||
	// prefer the more compact serialization (v1beta1) for storage until https://issue.k8s.io/82292 is resolved for objects whose v1 serialization is too big but whose v1beta1 serialization can be stored
 | 
			
		||||
 
 | 
			
		||||
@@ -1191,7 +1191,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
 | 
			
		||||
 | 
			
		||||
	genericfeatures.AggregatedDiscoveryEndpoint: {Default: true, PreRelease: featuregate.Beta},
 | 
			
		||||
 | 
			
		||||
	genericfeatures.APIListChunking: {Default: true, PreRelease: featuregate.Beta},
 | 
			
		||||
	genericfeatures.APIListChunking: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32
 | 
			
		||||
 | 
			
		||||
	genericfeatures.APIPriorityAndFairness: {Default: true, PreRelease: featuregate.Beta},
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@ const (
 | 
			
		||||
	// owner: @smarterclayton
 | 
			
		||||
	// alpha: v1.8
 | 
			
		||||
	// beta: v1.9
 | 
			
		||||
	// stable: 1.29
 | 
			
		||||
	//
 | 
			
		||||
	// Allow API clients to retrieve resource lists in chunks rather than
 | 
			
		||||
	// all at once.
 | 
			
		||||
@@ -231,7 +232,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
 | 
			
		||||
 | 
			
		||||
	AdmissionWebhookMatchConditions: {Default: true, PreRelease: featuregate.Beta},
 | 
			
		||||
 | 
			
		||||
	APIListChunking: {Default: true, PreRelease: featuregate.Beta},
 | 
			
		||||
	APIListChunking: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.32
 | 
			
		||||
 | 
			
		||||
	APIPriorityAndFairness: {Default: true, PreRelease: featuregate.Beta},
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,9 +25,7 @@ import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
	"k8s.io/apiserver/pkg/features"
 | 
			
		||||
	"k8s.io/apiserver/pkg/storage/storagebackend"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/klog/v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +154,7 @@ func NewDefaultStorageFactory(
 | 
			
		||||
	resourceConfig APIResourceConfigSource,
 | 
			
		||||
	specialDefaultResourcePrefixes map[schema.GroupResource]string,
 | 
			
		||||
) *DefaultStorageFactory {
 | 
			
		||||
	config.Paging = utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
 | 
			
		||||
	config.Paging = true
 | 
			
		||||
	if len(defaultMediaType) == 0 {
 | 
			
		||||
		defaultMediaType = runtime.ContentTypeJSON
 | 
			
		||||
	}
 | 
			
		||||
@@ -185,14 +183,6 @@ func (s *DefaultStorageFactory) SetEtcdPrefix(groupResource schema.GroupResource
 | 
			
		||||
	s.Overrides[groupResource] = overrides
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetDisableAPIListChunking allows a specific resource to disable paging at the storage layer, to prevent
 | 
			
		||||
// exposure of key names in continuations. This may be overridden by feature gates.
 | 
			
		||||
func (s *DefaultStorageFactory) SetDisableAPIListChunking(groupResource schema.GroupResource) {
 | 
			
		||||
	overrides := s.Overrides[groupResource]
 | 
			
		||||
	overrides.disablePaging = true
 | 
			
		||||
	s.Overrides[groupResource] = overrides
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetResourceEtcdPrefix sets the prefix for a resource, but not the base-dir.  You'll end up in `etcdPrefix/resourceEtcdPrefix`.
 | 
			
		||||
func (s *DefaultStorageFactory) SetResourceEtcdPrefix(groupResource schema.GroupResource, prefix string) {
 | 
			
		||||
	overrides := s.Overrides[groupResource]
 | 
			
		||||
 
 | 
			
		||||
@@ -725,15 +725,14 @@ func shouldDelegateList(opts storage.ListOptions) bool {
 | 
			
		||||
	resourceVersion := opts.ResourceVersion
 | 
			
		||||
	pred := opts.Predicate
 | 
			
		||||
	match := opts.ResourceVersionMatch
 | 
			
		||||
	pagingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
 | 
			
		||||
	consistentListFromCacheEnabled := utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache)
 | 
			
		||||
 | 
			
		||||
	// Serve consistent reads from storage if ConsistentListFromCache is disabled
 | 
			
		||||
	consistentReadFromStorage := resourceVersion == "" && !consistentListFromCacheEnabled
 | 
			
		||||
	// Watch cache doesn't support continuations, so serve them from etcd.
 | 
			
		||||
	hasContinuation := pagingEnabled && len(pred.Continue) > 0
 | 
			
		||||
	hasContinuation := len(pred.Continue) > 0
 | 
			
		||||
	// Serve paginated requests about revision "0" from watch cache to avoid overwhelming etcd.
 | 
			
		||||
	hasLimit := pagingEnabled && pred.Limit > 0 && resourceVersion != "0"
 | 
			
		||||
	hasLimit := pred.Limit > 0 && resourceVersion != "0"
 | 
			
		||||
	// Watch cache only supports ResourceVersionMatchNotOlderThan (default).
 | 
			
		||||
	unsupportedMatch := match != "" && match != metav1.ResourceVersionMatchNotOlderThan
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -117,8 +117,7 @@ func (e *listWorkEstimator) estimate(r *http.Request, flowSchemaName, priorityLe
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	limit := numStored
 | 
			
		||||
	if utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking) && listOptions.Limit > 0 &&
 | 
			
		||||
		listOptions.Limit < numStored {
 | 
			
		||||
	if listOptions.Limit > 0 && listOptions.Limit < numStored {
 | 
			
		||||
		limit = listOptions.Limit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -165,15 +164,14 @@ func key(requestInfo *apirequest.RequestInfo) string {
 | 
			
		||||
func shouldListFromStorage(query url.Values, opts *metav1.ListOptions) bool {
 | 
			
		||||
	resourceVersion := opts.ResourceVersion
 | 
			
		||||
	match := opts.ResourceVersionMatch
 | 
			
		||||
	pagingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
 | 
			
		||||
	consistentListFromCacheEnabled := utilfeature.DefaultFeatureGate.Enabled(features.ConsistentListFromCache)
 | 
			
		||||
 | 
			
		||||
	// Serve consistent reads from storage if ConsistentListFromCache is disabled
 | 
			
		||||
	consistentReadFromStorage := resourceVersion == "" && !consistentListFromCacheEnabled
 | 
			
		||||
	// Watch cache doesn't support continuations, so serve them from etcd.
 | 
			
		||||
	hasContinuation := pagingEnabled && len(opts.Continue) > 0
 | 
			
		||||
	hasContinuation := len(opts.Continue) > 0
 | 
			
		||||
	// Serve paginated requests about revision "0" from watch cache to avoid overwhelming etcd.
 | 
			
		||||
	hasLimit := pagingEnabled && opts.Limit > 0 && resourceVersion != "0"
 | 
			
		||||
	hasLimit := opts.Limit > 0 && resourceVersion != "0"
 | 
			
		||||
	// Watch cache only supports ResourceVersionMatchNotOlderThan (default).
 | 
			
		||||
	unsupportedMatch := match != "" && match != metav1.ResourceVersionMatchNotOlderThan
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ func (o *WardleServerOptions) Config() (*apiserver.Config, error) {
 | 
			
		||||
		return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	o.RecommendedOptions.Etcd.StorageConfig.Paging = utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
 | 
			
		||||
	o.RecommendedOptions.Etcd.StorageConfig.Paging = true
 | 
			
		||||
 | 
			
		||||
	o.RecommendedOptions.ExtraAdmissionInitializers = func(c *genericapiserver.RecommendedConfig) ([]admission.PluginInitializer, error) {
 | 
			
		||||
		client, err := clientset.NewForConfig(c.LoopbackClientConfig)
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ var _ = SIGDescribe("Servers with support for API chunking", func() {
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ginkgo.It("should return chunks of results for list calls", func(ctx context.Context) {
 | 
			
		||||
	framework.ConformanceIt("should return chunks of results for list calls", func(ctx context.Context) {
 | 
			
		||||
		ns := f.Namespace.Name
 | 
			
		||||
		c := f.ClientSet
 | 
			
		||||
		client := c.CoreV1().PodTemplates(ns)
 | 
			
		||||
@@ -123,7 +123,7 @@ var _ = SIGDescribe("Servers with support for API chunking", func() {
 | 
			
		||||
		gomega.Expect(list.Items).To(gomega.HaveLen(numberOfTotalResources))
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ginkgo.It("should support continue listing from the last key if the original version has been compacted away, though the list is inconsistent [Slow]", func(ctx context.Context) {
 | 
			
		||||
	framework.ConformanceIt("should support continue listing from the last key if the original version has been compacted away, though the list is inconsistent [Slow]", func(ctx context.Context) {
 | 
			
		||||
		ns := f.Namespace.Name
 | 
			
		||||
		c := f.ClientSet
 | 
			
		||||
		client := c.CoreV1().PodTemplates(ns)
 | 
			
		||||
 
 | 
			
		||||
@@ -53,16 +53,13 @@ import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/watch"
 | 
			
		||||
	"k8s.io/apiserver/pkg/endpoints/handlers"
 | 
			
		||||
	"k8s.io/apiserver/pkg/features"
 | 
			
		||||
	"k8s.io/apiserver/pkg/storage/storagebackend"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	"k8s.io/client-go/dynamic"
 | 
			
		||||
	clientset "k8s.io/client-go/kubernetes"
 | 
			
		||||
	appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
 | 
			
		||||
	"k8s.io/client-go/metadata"
 | 
			
		||||
	restclient "k8s.io/client-go/rest"
 | 
			
		||||
	"k8s.io/client-go/tools/pager"
 | 
			
		||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
			
		||||
	"k8s.io/klog/v2"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
 | 
			
		||||
	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
 | 
			
		||||
@@ -381,8 +378,6 @@ func TestListOptions(t *testing.T) {
 | 
			
		||||
			ctx, cancel := context.WithCancel(ctx)
 | 
			
		||||
			defer cancel()
 | 
			
		||||
 | 
			
		||||
			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.APIListChunking, true)()
 | 
			
		||||
 | 
			
		||||
			var storageTransport *storagebackend.TransportConfig
 | 
			
		||||
			clientSet, _, tearDownFn := framework.StartTestServer(ctx, t, framework.TestServerSetup{
 | 
			
		||||
				ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
 | 
			
		||||
@@ -576,9 +571,8 @@ func testListOptionsCase(t *testing.T, rsClient appsv1.ReplicaSetInterface, watc
 | 
			
		||||
 | 
			
		||||
	// Cacher.GetList defines this for logic to decide if the watch cache is skipped. We need to know it to know if
 | 
			
		||||
	// the limit is respected when testing here.
 | 
			
		||||
	pagingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
 | 
			
		||||
	hasContinuation := pagingEnabled && len(opts.Continue) > 0
 | 
			
		||||
	hasLimit := pagingEnabled && opts.Limit > 0 && opts.ResourceVersion != "0"
 | 
			
		||||
	hasContinuation := len(opts.Continue) > 0
 | 
			
		||||
	hasLimit := opts.Limit > 0 && opts.ResourceVersion != "0"
 | 
			
		||||
	skipWatchCache := opts.ResourceVersion == "" || hasContinuation || hasLimit || isExact
 | 
			
		||||
	usingWatchCache := watchCacheEnabled && !skipWatchCache
 | 
			
		||||
 | 
			
		||||
@@ -627,8 +621,6 @@ func TestListResourceVersion0(t *testing.T) {
 | 
			
		||||
			ctx, cancel := context.WithCancel(ctx)
 | 
			
		||||
			defer cancel()
 | 
			
		||||
 | 
			
		||||
			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.APIListChunking, true)()
 | 
			
		||||
 | 
			
		||||
			clientSet, _, tearDownFn := framework.StartTestServer(ctx, t, framework.TestServerSetup{
 | 
			
		||||
				ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
 | 
			
		||||
					opts.Etcd.EnableWatchCache = tc.watchCacheEnabled
 | 
			
		||||
@@ -685,7 +677,6 @@ func TestListResourceVersion0(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAPIListChunking(t *testing.T) {
 | 
			
		||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.APIListChunking, true)()
 | 
			
		||||
	ctx, clientSet, _, tearDownFn := setup(t)
 | 
			
		||||
	defer tearDownFn()
 | 
			
		||||
 | 
			
		||||
@@ -753,7 +744,6 @@ func TestAPIListChunking(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAPIListChunkingWithLabelSelector(t *testing.T) {
 | 
			
		||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.APIListChunking, true)()
 | 
			
		||||
	ctx, clientSet, _, tearDownFn := setup(t)
 | 
			
		||||
	defer tearDownFn()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user