Use metadata informers instead of dynamic informers in controller manager

All controllers in controller-manager that deal with objects generically
work with those objects without needing the full object. Update the GC
and quota controller to use PartialObjectMetadata input objects which
is faster and more efficient.
This commit is contained in:
Clayton Coleman 2019-07-10 18:37:24 -04:00
parent 98d87a4f03
commit d631f9b7e9
No known key found for this signature in database
GPG Key ID: 3D16906B4F1C5CB3
9 changed files with 43 additions and 44 deletions

View File

@ -121,10 +121,10 @@ go_library(
"//staging/src/k8s.io/client-go/discovery/cached:go_default_library", "//staging/src/k8s.io/client-go/discovery/cached:go_default_library",
"//staging/src/k8s.io/client-go/discovery/cached/memory:go_default_library", "//staging/src/k8s.io/client-go/discovery/cached/memory:go_default_library",
"//staging/src/k8s.io/client-go/dynamic:go_default_library", "//staging/src/k8s.io/client-go/dynamic:go_default_library",
"//staging/src/k8s.io/client-go/dynamic/dynamicinformer:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/metadata:go_default_library", "//staging/src/k8s.io/client-go/metadata:go_default_library",
"//staging/src/k8s.io/client-go/metadata/metadatainformer:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/restmapper:go_default_library", "//staging/src/k8s.io/client-go/restmapper:go_default_library",
"//staging/src/k8s.io/client-go/scale:go_default_library", "//staging/src/k8s.io/client-go/scale:go_default_library",

View File

@ -31,7 +31,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
@ -43,10 +43,10 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/apiserver/pkg/util/term" "k8s.io/apiserver/pkg/util/term"
cacheddiscovery "k8s.io/client-go/discovery/cached" cacheddiscovery "k8s.io/client-go/discovery/cached"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/dynamic/dynamicinformer"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/metadata"
"k8s.io/client-go/metadata/metadatainformer"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/restmapper" "k8s.io/client-go/restmapper"
"k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection"
@ -239,7 +239,7 @@ func Run(c *config.CompletedConfig, stopCh <-chan struct{}) error {
} }
controllerContext.InformerFactory.Start(controllerContext.Stop) controllerContext.InformerFactory.Start(controllerContext.Stop)
controllerContext.GenericInformerFactory.Start(controllerContext.Stop) controllerContext.ObjectOrMetadataInformerFactory.Start(controllerContext.Stop)
close(controllerContext.InformersStarted) close(controllerContext.InformersStarted)
select {} select {}
@ -295,9 +295,11 @@ type ControllerContext struct {
// InformerFactory gives access to informers for the controller. // InformerFactory gives access to informers for the controller.
InformerFactory informers.SharedInformerFactory InformerFactory informers.SharedInformerFactory
// GenericInformerFactory gives access to informers for typed resources // ObjectOrMetadataInformerFactory gives access to informers for typed resources
// and dynamic resources. // and dynamic resources by their metadata. All generic controllers currently use
GenericInformerFactory controller.InformerFactory // object metadata - if a future controller needs access to the full object this
// would become GenericInformerFactory and take a dynamic client.
ObjectOrMetadataInformerFactory controller.InformerFactory
// ComponentConfig provides access to init options for a given controller // ComponentConfig provides access to init options for a given controller
ComponentConfig kubectrlmgrconfig.KubeControllerManagerConfiguration ComponentConfig kubectrlmgrconfig.KubeControllerManagerConfiguration
@ -448,8 +450,8 @@ func CreateControllerContext(s *config.CompletedConfig, rootClientBuilder, clien
versionedClient := rootClientBuilder.ClientOrDie("shared-informers") versionedClient := rootClientBuilder.ClientOrDie("shared-informers")
sharedInformers := informers.NewSharedInformerFactory(versionedClient, ResyncPeriod(s)()) sharedInformers := informers.NewSharedInformerFactory(versionedClient, ResyncPeriod(s)())
dynamicClient := dynamic.NewForConfigOrDie(rootClientBuilder.ConfigOrDie("dynamic-informers")) metadataClient := metadata.NewForConfigOrDie(rootClientBuilder.ConfigOrDie("metadata-informers"))
dynamicInformers := dynamicinformer.NewDynamicSharedInformerFactory(dynamicClient, ResyncPeriod(s)()) metadataInformers := metadatainformer.NewSharedInformerFactory(metadataClient, ResyncPeriod(s)())
// If apiserver is not running we should wait for some time and fail only then. This is particularly // If apiserver is not running we should wait for some time and fail only then. This is particularly
// important when we start apiserver and controller manager at the same time. // important when we start apiserver and controller manager at the same time.
@ -477,17 +479,17 @@ func CreateControllerContext(s *config.CompletedConfig, rootClientBuilder, clien
} }
ctx := ControllerContext{ ctx := ControllerContext{
ClientBuilder: clientBuilder, ClientBuilder: clientBuilder,
InformerFactory: sharedInformers, InformerFactory: sharedInformers,
GenericInformerFactory: controller.NewInformerFactory(sharedInformers, dynamicInformers), ObjectOrMetadataInformerFactory: controller.NewInformerFactory(sharedInformers, metadataInformers),
ComponentConfig: s.ComponentConfig, ComponentConfig: s.ComponentConfig,
RESTMapper: restMapper, RESTMapper: restMapper,
AvailableResources: availableResources, AvailableResources: availableResources,
Cloud: cloud, Cloud: cloud,
LoopMode: loopMode, LoopMode: loopMode,
Stop: stop, Stop: stop,
InformersStarted: make(chan struct{}), InformersStarted: make(chan struct{}),
ResyncPeriod: ResyncPeriod(s), ResyncPeriod: ResyncPeriod(s),
} }
return ctx, nil return ctx, nil
} }

View File

@ -33,7 +33,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
cacheddiscovery "k8s.io/client-go/discovery/cached/memory" cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
"k8s.io/client-go/dynamic"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/metadata" "k8s.io/client-go/metadata"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
@ -334,7 +333,7 @@ func startResourceQuotaController(ctx ControllerContext) (http.Handler, bool, er
QuotaClient: resourceQuotaControllerClient.CoreV1(), QuotaClient: resourceQuotaControllerClient.CoreV1(),
ResourceQuotaInformer: ctx.InformerFactory.Core().V1().ResourceQuotas(), ResourceQuotaInformer: ctx.InformerFactory.Core().V1().ResourceQuotas(),
ResyncPeriod: controller.StaticResyncPeriodFunc(ctx.ComponentConfig.ResourceQuotaController.ResourceQuotaSyncPeriod.Duration), ResyncPeriod: controller.StaticResyncPeriodFunc(ctx.ComponentConfig.ResourceQuotaController.ResourceQuotaSyncPeriod.Duration),
InformerFactory: ctx.GenericInformerFactory, InformerFactory: ctx.ObjectOrMetadataInformerFactory,
ReplenishmentResyncPeriod: ctx.ResyncPeriod, ReplenishmentResyncPeriod: ctx.ResyncPeriod,
DiscoveryFunc: discoveryFunc, DiscoveryFunc: discoveryFunc,
IgnoredResourcesFunc: quotaConfiguration.IgnoredResources, IgnoredResourcesFunc: quotaConfiguration.IgnoredResources,
@ -439,7 +438,7 @@ func startGarbageCollectorController(ctx ControllerContext) (http.Handler, bool,
ctx.RESTMapper, ctx.RESTMapper,
deletableResources, deletableResources,
ignoredResources, ignoredResources,
ctx.GenericInformerFactory, ctx.ObjectOrMetadataInformerFactory,
ctx.InformersStarted, ctx.InformersStarted,
) )
if err != nil { if err != nil {

View File

@ -123,10 +123,10 @@ func TestController_DiscoveryError(t *testing.T) {
testClientBuilder := TestClientBuilder{clientset: testClientset} testClientBuilder := TestClientBuilder{clientset: testClientset}
testInformerFactory := informers.NewSharedInformerFactoryWithOptions(testClientset, time.Duration(1)) testInformerFactory := informers.NewSharedInformerFactoryWithOptions(testClientset, time.Duration(1))
ctx := ControllerContext{ ctx := ControllerContext{
ClientBuilder: testClientBuilder, ClientBuilder: testClientBuilder,
InformerFactory: testInformerFactory, InformerFactory: testInformerFactory,
GenericInformerFactory: testInformerFactory, ObjectOrMetadataInformerFactory: testInformerFactory,
InformersStarted: make(chan struct{}), InformersStarted: make(chan struct{}),
} }
for funcName, controllerInit := range controllerInitFuncMap { for funcName, controllerInit := range controllerInitFuncMap {
_, _, err := controllerInit(ctx) _, _, err := controllerInit(ctx)

View File

@ -80,11 +80,11 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
"//staging/src/k8s.io/client-go/dynamic/dynamicinformer:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/metadata/metadatainformer:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",

View File

@ -18,8 +18,8 @@ package controller
import ( import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic/dynamicinformer"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/metadata/metadatainformer"
) )
// InformerFactory creates informers for each group version resource. // InformerFactory creates informers for each group version resource.
@ -29,28 +29,28 @@ type InformerFactory interface {
} }
type informerFactory struct { type informerFactory struct {
typedInformerFactory informers.SharedInformerFactory typedInformerFactory informers.SharedInformerFactory
dynamicInformerFactory dynamicinformer.DynamicSharedInformerFactory metadataInformerFactory metadatainformer.SharedInformerFactory
} }
func (i *informerFactory) ForResource(resource schema.GroupVersionResource) (informers.GenericInformer, error) { func (i *informerFactory) ForResource(resource schema.GroupVersionResource) (informers.GenericInformer, error) {
informer, err := i.typedInformerFactory.ForResource(resource) informer, err := i.typedInformerFactory.ForResource(resource)
if err != nil { if err != nil {
return i.dynamicInformerFactory.ForResource(resource), nil return i.metadataInformerFactory.ForResource(resource), nil
} }
return informer, nil return informer, nil
} }
func (i *informerFactory) Start(stopCh <-chan struct{}) { func (i *informerFactory) Start(stopCh <-chan struct{}) {
i.typedInformerFactory.Start(stopCh) i.typedInformerFactory.Start(stopCh)
i.dynamicInformerFactory.Start(stopCh) i.metadataInformerFactory.Start(stopCh)
} }
// NewInformerFactory creates a new InformerFactory which works with both typed // NewInformerFactory creates a new InformerFactory which works with both typed
// resources and dynamic resources // resources and metadata-only resources
func NewInformerFactory(typedInformerFactory informers.SharedInformerFactory, dynamicInformerFactory dynamicinformer.DynamicSharedInformerFactory) InformerFactory { func NewInformerFactory(typedInformerFactory informers.SharedInformerFactory, metadataInformerFactory metadatainformer.SharedInformerFactory) InformerFactory {
return &informerFactory{ return &informerFactory{
typedInformerFactory: typedInformerFactory, typedInformerFactory: typedInformerFactory,
dynamicInformerFactory: dynamicInformerFactory, metadataInformerFactory: metadataInformerFactory,
} }
} }

View File

@ -29,10 +29,10 @@ go_test(
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/client-go/discovery/cached/memory:go_default_library", "//staging/src/k8s.io/client-go/discovery/cached/memory:go_default_library",
"//staging/src/k8s.io/client-go/dynamic:go_default_library", "//staging/src/k8s.io/client-go/dynamic:go_default_library",
"//staging/src/k8s.io/client-go/dynamic/dynamicinformer:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/metadata:go_default_library", "//staging/src/k8s.io/client-go/metadata:go_default_library",
"//staging/src/k8s.io/client-go/metadata/metadatainformer:go_default_library",
"//staging/src/k8s.io/client-go/restmapper:go_default_library", "//staging/src/k8s.io/client-go/restmapper:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//test/integration:go_default_library", "//test/integration:go_default_library",

View File

@ -38,10 +38,10 @@ import (
"k8s.io/apiserver/pkg/storage/names" "k8s.io/apiserver/pkg/storage/names"
cacheddiscovery "k8s.io/client-go/discovery/cached/memory" cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/client-go/dynamic/dynamicinformer"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/metadata" "k8s.io/client-go/metadata"
"k8s.io/client-go/metadata/metadatainformer"
"k8s.io/client-go/restmapper" "k8s.io/client-go/restmapper"
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
@ -242,7 +242,7 @@ func setupWithServer(t *testing.T, result *kubeapiservertesting.TestServer, work
t.Fatalf("failed to create dynamicClient: %v", err) t.Fatalf("failed to create dynamicClient: %v", err)
} }
sharedInformers := informers.NewSharedInformerFactory(clientSet, 0) sharedInformers := informers.NewSharedInformerFactory(clientSet, 0)
dynamicInformers := dynamicinformer.NewDynamicSharedInformerFactory(dynamicClient, 0) metadataInformers := metadatainformer.NewSharedInformerFactory(metadataClient, 0)
alwaysStarted := make(chan struct{}) alwaysStarted := make(chan struct{})
close(alwaysStarted) close(alwaysStarted)
gc, err := garbagecollector.NewGarbageCollector( gc, err := garbagecollector.NewGarbageCollector(
@ -250,7 +250,7 @@ func setupWithServer(t *testing.T, result *kubeapiservertesting.TestServer, work
restMapper, restMapper,
deletableResources, deletableResources,
garbagecollector.DefaultIgnoredResources(), garbagecollector.DefaultIgnoredResources(),
controller.NewInformerFactory(sharedInformers, dynamicInformers), controller.NewInformerFactory(sharedInformers, metadataInformers),
alwaysStarted, alwaysStarted,
) )
if err != nil { if err != nil {

2
vendor/modules.txt vendored
View File

@ -1315,8 +1315,6 @@ k8s.io/client-go/discovery/cached/disk
k8s.io/client-go/discovery/cached/memory k8s.io/client-go/discovery/cached/memory
k8s.io/client-go/discovery/fake k8s.io/client-go/discovery/fake
k8s.io/client-go/dynamic k8s.io/client-go/dynamic
k8s.io/client-go/dynamic/dynamicinformer
k8s.io/client-go/dynamic/dynamiclister
k8s.io/client-go/dynamic/fake k8s.io/client-go/dynamic/fake
k8s.io/client-go/informers k8s.io/client-go/informers
k8s.io/client-go/informers/admissionregistration k8s.io/client-go/informers/admissionregistration