feat: implements svm controller

Signed-off-by: Nilekh Chaudhari <1626598+nilekhc@users.noreply.github.com>
This commit is contained in:
Nilekh Chaudhari
2024-01-04 19:34:05 +00:00
parent 91a7708cdc
commit 9161302e7f
17 changed files with 2337 additions and 65 deletions

View File

@@ -22,6 +22,7 @@ package app
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
"math/rand"
"net/http"
"os"
@@ -74,6 +75,7 @@ import (
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
"k8s.io/kubernetes/cmd/kube-controller-manager/names"
kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config"
garbagecollector "k8s.io/kubernetes/pkg/controller/garbagecollector"
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/serviceaccount"
)
@@ -227,7 +229,7 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
saTokenControllerDescriptor := newServiceAccountTokenControllerDescriptor(rootClientBuilder)
run := func(ctx context.Context, controllerDescriptors map[string]*ControllerDescriptor) {
controllerContext, err := CreateControllerContext(logger, c, rootClientBuilder, clientBuilder, ctx.Done())
controllerContext, err := CreateControllerContext(ctx, c, rootClientBuilder, clientBuilder)
if err != nil {
logger.Error(err, "Error building controller context")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
@@ -378,6 +380,9 @@ type ControllerContext struct {
// ControllerManagerMetrics provides a proxy to set controller manager specific metrics.
ControllerManagerMetrics *controllersmetrics.ControllerManagerMetrics
// GraphBuilder gives an access to dependencyGraphBuilder which keeps tracks of resources in the cluster
GraphBuilder *garbagecollector.GraphBuilder
}
// IsControllerEnabled checks if the context's controllers enabled or not
@@ -558,6 +563,7 @@ func NewControllerDescriptors() map[string]*ControllerDescriptor {
register(newValidatingAdmissionPolicyStatusControllerDescriptor())
register(newTaintEvictionControllerDescriptor())
register(newServiceCIDRsControllerDescriptor())
register(newStorageVersionMigratorControllerDescriptor())
for _, alias := range aliases.UnsortedList() {
if _, ok := controllers[alias]; ok {
@@ -571,7 +577,7 @@ func NewControllerDescriptors() map[string]*ControllerDescriptor {
// CreateControllerContext creates a context struct containing references to resources needed by the
// controllers such as the cloud provider and clientBuilder. rootClientBuilder is only used for
// the shared-informers client and token controller.
func CreateControllerContext(logger klog.Logger, s *config.CompletedConfig, rootClientBuilder, clientBuilder clientbuilder.ControllerClientBuilder, stop <-chan struct{}) (ControllerContext, error) {
func CreateControllerContext(ctx context.Context, s *config.CompletedConfig, rootClientBuilder, clientBuilder clientbuilder.ControllerClientBuilder) (ControllerContext, error) {
// Informer transform to trim ManagedFields for memory efficiency.
trim := func(obj interface{}) (interface{}, error) {
if accessor, err := meta.Accessor(obj); err == nil {
@@ -598,15 +604,15 @@ func CreateControllerContext(logger klog.Logger, s *config.CompletedConfig, root
restMapper := restmapper.NewDeferredDiscoveryRESTMapper(cachedClient)
go wait.Until(func() {
restMapper.Reset()
}, 30*time.Second, stop)
}, 30*time.Second, ctx.Done())
cloud, loopMode, err := createCloudProvider(logger, s.ComponentConfig.KubeCloudShared.CloudProvider.Name, s.ComponentConfig.KubeCloudShared.ExternalCloudVolumePlugin,
cloud, loopMode, err := createCloudProvider(klog.FromContext(ctx), s.ComponentConfig.KubeCloudShared.CloudProvider.Name, s.ComponentConfig.KubeCloudShared.ExternalCloudVolumePlugin,
s.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile, s.ComponentConfig.KubeCloudShared.AllowUntaggedCloud, sharedInformers)
if err != nil {
return ControllerContext{}, err
}
ctx := ControllerContext{
controllerContext := ControllerContext{
ClientBuilder: clientBuilder,
InformerFactory: sharedInformers,
ObjectOrMetadataInformerFactory: informerfactory.NewInformerFactory(sharedInformers, metadataInformers),
@@ -618,8 +624,26 @@ func CreateControllerContext(logger klog.Logger, s *config.CompletedConfig, root
ResyncPeriod: ResyncPeriod(s),
ControllerManagerMetrics: controllersmetrics.NewControllerManagerMetrics("kube-controller-manager"),
}
if controllerContext.ComponentConfig.GarbageCollectorController.EnableGarbageCollector &&
controllerContext.IsControllerEnabled(NewControllerDescriptors()[names.GarbageCollectorController]) {
ignoredResources := make(map[schema.GroupResource]struct{})
for _, r := range controllerContext.ComponentConfig.GarbageCollectorController.GCIgnoredResources {
ignoredResources[schema.GroupResource{Group: r.Group, Resource: r.Resource}] = struct{}{}
}
controllerContext.GraphBuilder = garbagecollector.NewDependencyGraphBuilder(
ctx,
metadataClient,
controllerContext.RESTMapper,
ignoredResources,
controllerContext.ObjectOrMetadataInformerFactory,
controllerContext.InformersStarted,
)
}
controllersmetrics.Register()
return ctx, nil
return controllerContext, nil
}
// StartControllers starts a set of controllers with a specified ControllerContext

View File

@@ -94,6 +94,7 @@ func TestControllerNamesDeclaration(t *testing.T) {
names.LegacyServiceAccountTokenCleanerController,
names.ValidatingAdmissionPolicyStatusController,
names.ServiceCIDRController,
names.StorageVersionMigratorController,
)
for _, name := range KnownControllers() {

View File

@@ -688,17 +688,16 @@ func startGarbageCollectorController(ctx context.Context, controllerContext Cont
for _, r := range controllerContext.ComponentConfig.GarbageCollectorController.GCIgnoredResources {
ignoredResources[schema.GroupResource{Group: r.Group, Resource: r.Resource}] = struct{}{}
}
garbageCollector, err := garbagecollector.NewGarbageCollector(
garbageCollector, err := garbagecollector.NewComposedGarbageCollector(
ctx,
gcClientset,
metadataClient,
controllerContext.RESTMapper,
ignoredResources,
controllerContext.ObjectOrMetadataInformerFactory,
controllerContext.InformersStarted,
controllerContext.GraphBuilder,
)
if err != nil {
return nil, true, fmt.Errorf("failed to start the generic garbage collector: %v", err)
return nil, true, fmt.Errorf("failed to start the generic garbage collector: %w", err)
}
// Start the garbage collector.

View File

@@ -0,0 +1,92 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package app
import (
"context"
"fmt"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/metadata"
"k8s.io/controller-manager/controller"
"k8s.io/kubernetes/cmd/kube-controller-manager/names"
"k8s.io/kubernetes/pkg/features"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientgofeaturegate "k8s.io/client-go/features"
svm "k8s.io/kubernetes/pkg/controller/storageversionmigrator"
)
func newStorageVersionMigratorControllerDescriptor() *ControllerDescriptor {
return &ControllerDescriptor{
name: names.StorageVersionMigratorController,
aliases: []string{"svm"},
initFunc: startSVMController,
}
}
func startSVMController(
ctx context.Context,
controllerContext ControllerContext,
controllerName string,
) (controller.Interface, bool, error) {
if !utilfeature.DefaultFeatureGate.Enabled(features.StorageVersionMigrator) ||
!clientgofeaturegate.FeatureGates().Enabled(clientgofeaturegate.InformerResourceVersion) {
return nil, false, nil
}
if !controllerContext.ComponentConfig.GarbageCollectorController.EnableGarbageCollector {
return nil, true, fmt.Errorf("storage version migrator requires garbage collector")
}
config := controllerContext.ClientBuilder.ConfigOrDie(controllerName)
client := controllerContext.ClientBuilder.ClientOrDie(controllerName)
informer := controllerContext.InformerFactory.Storagemigration().V1alpha1().StorageVersionMigrations()
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
return nil, false, err
}
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil {
return nil, false, err
}
go svm.NewResourceVersionController(
ctx,
client,
discoveryClient,
metadata.NewForConfigOrDie(config),
informer,
controllerContext.RESTMapper,
).Run(ctx)
svmController := svm.NewSVMController(
ctx,
client,
dynamicClient,
informer,
controllerName,
controllerContext.RESTMapper,
controllerContext.GraphBuilder,
)
go svmController.Run(ctx)
return svmController, true, nil
}

View File

@@ -83,4 +83,5 @@ const (
LegacyServiceAccountTokenCleanerController = "legacy-serviceaccount-token-cleaner-controller"
ValidatingAdmissionPolicyStatusController = "validatingadmissionpolicy-status-controller"
ServiceCIDRController = "service-cidr-controller"
StorageVersionMigratorController = "storage-version-migrator-controller"
)