From a5dd2ec0ea35e6b462176bd1c56282a99b0a3d27 Mon Sep 17 00:00:00 2001 From: kaiyou <dev@kaiyou.fr> Date: Sat, 7 Oct 2023 15:06:11 +0200 Subject: [PATCH] Fix CRD on 1.27 --- k8s/storage.go | 32 +++++++++++++++++--------------- services/apiserver.go | 9 +++++++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/k8s/storage.go b/k8s/storage.go index 6bbc8f8..1b885ec 100644 --- a/k8s/storage.go +++ b/k8s/storage.go @@ -4,9 +4,11 @@ import ( "fmt" "time" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/registry/generic" + "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/server/storage" "k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/util/flowcontrol/request" @@ -22,7 +24,7 @@ type RestOptionsFactory struct { func (f *RestOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) { storageConfig, err := f.StorageFactory.NewConfig(resource) if err != nil { - return generic.RESTOptions{}, fmt.Errorf("unable to find storage destination for %v, due to %v", resource, err.Error()) + return generic.RESTOptions{}, fmt.Errorf("cannot find storage destination for %v, due to %v", resource, err.Error()) } return generic.RESTOptions{ StorageConfig: storageConfig, @@ -39,26 +41,26 @@ func PrepareStorage(codecs runtime.StorageSerializer, scheme *runtime.Scheme, re // Etcd backend supports being created with a specific codec, however later created storage // factories override that codec at runtime thanks to using DefaultStorageFactory instead // of vanilla SimpleStorageFactory, so we create the backend with no pre-configured codec - etcdConfig := storagebackend.NewDefaultConfig("/registry", nil) + etcdConfig := storagebackend.NewDefaultConfig("/registry", unstructured.UnstructuredJSONScheme) etcdConfig.Transport.ServerList = []string{"http://[::1]:2379"} - // The rest options getter abstracts all storage for the server, by specifying the scheme and codecs + // The storage factory getter abstracts all storage for the server, by specifying the scheme and codecs // on top of the storage backend. Vanilla code sets a special multi-group versionner to avoid issues // with large objects (cee cmd/kube-apiserver/app/apiextensions.go), which we ignore here - return &RestOptionsFactory{ - // TODO: be careful about the default factory using the resourcename as prefix, which might - // cause collisions in the future - StorageFactory: storage.NewDefaultStorageFactory( - *etcdConfig, // copied as value, so the factory may alter some fields - runtime.ContentTypeJSON, // media type, somewhat inefficient but good enough + var storageFactory storage.StorageFactory + if codecs == nil { + storageFactory = &options.SimpleStorageFactory{StorageConfig: *etcdConfig} + } else { + storageFactory = storage.NewDefaultStorageFactory( + *etcdConfig, + runtime.ContentTypeJSON, codecs, storage.NewDefaultResourceEncodingConfig(scheme), resources, - // We always use an empty list of prefix overrides: no prefix override, contrary to - // vanilla code which has many overrides for backward compatibility against a given storage target - // This means hepto is not compatible with vanilla when using the same etcd backend, and we might - // want to be careful when upgrading to avoid unexpected prefix changes - make(map[schema.GroupResource]string), - ), + map[schema.GroupResource]string{}, + ) + } + return &RestOptionsFactory{ + StorageFactory: storageFactory, } } diff --git a/services/apiserver.go b/services/apiserver.go index 13ee71f..289ab5f 100644 --- a/services/apiserver.go +++ b/services/apiserver.go @@ -44,6 +44,7 @@ import ( controllersa "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/controlplane" "k8s.io/kubernetes/pkg/controlplane/controller/clusterauthenticationtrust" + "k8s.io/kubernetes/pkg/controlplane/controller/crdregistration" "k8s.io/kubernetes/pkg/controlplane/reconcilers" generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi" kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" @@ -99,6 +100,10 @@ var kubeApiserver = &Unit{ return fmt.Errorf("could not initialize aggregator client: %w", err) } registrationController := autoregister.NewAutoRegisterController(aggregatorServer.APIRegistrationInformers.Apiregistration().V1().APIServices(), apiRegistrationClient) + crdController := crdregistration.NewCRDRegistrationController( + extensionServer.Informers.Apiextensions().V1().CustomResourceDefinitions(), + registrationController, + ) for _, resourcePath := range apiServer.GenericAPIServer.ListedPaths() { match := pathRegex.FindStringSubmatch(resourcePath) if match == nil { @@ -115,6 +120,7 @@ var kubeApiserver = &Unit{ }) } go registrationController.Run(1, ctx.Done()) + go crdController.Run(1, ctx.Done()) // Finally start the apiserver server := aggregatorServer.GenericAPIServer.PrepareRun() @@ -249,8 +255,7 @@ func buildExtensionsConfig(config server.Config, clients *k8s.Clients) (*extensi SharedInformerFactory: clients.Informer, }, ExtraConfig: extensions.ExtraConfig{ - // TODO This might be an issue, since vanilla sets a special unstructured encoding for CRD - CRDRESTOptionsGetter: generic.RESTOptionsGetter, + CRDRESTOptionsGetter: k8s.PrepareStorage(nil, nil, nil), }, }, nil } -- GitLab