From 6a8faa6e403cbe779e348e4fc0c6dc3fed4eae82 Mon Sep 17 00:00:00 2001 From: yue9944882 <291271447@qq.com> Date: Wed, 8 Aug 2018 21:06:30 +0800 Subject: [PATCH] replace contrustor of ad controller with config.complete.new flow review: 1. import order 2. only set nil field on complete 3. replace hardcoded default namespace --- cmd/kube-apiserver/app/BUILD | 14 +--- cmd/kube-apiserver/app/server.go | 113 ++++++-------------------- pkg/kubeapiserver/admission/BUILD | 47 +++++++---- pkg/kubeapiserver/admission/config.go | 108 ++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 116 deletions(-) create mode 100644 pkg/kubeapiserver/admission/config.go diff --git a/cmd/kube-apiserver/app/BUILD b/cmd/kube-apiserver/app/BUILD index ef7a18ffd94..52444b38c23 100644 --- a/cmd/kube-apiserver/app/BUILD +++ b/cmd/kube-apiserver/app/BUILD @@ -1,9 +1,4 @@ -package(default_visibility = ["//visibility:public"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) +load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", @@ -13,6 +8,7 @@ go_library( "server.go", ], importpath = "k8s.io/kubernetes/cmd/kube-apiserver/app", + visibility = ["//visibility:public"], deps = [ "//cmd/kube-apiserver/app/options:go_default_library", "//pkg/api/legacyscheme:go_default_library", @@ -32,7 +28,6 @@ go_library( "//pkg/master/controller/crdregistration:go_default_library", "//pkg/master/reconcilers:go_default_library", "//pkg/master/tunneler:go_default_library", - "//pkg/quota/v1/install:go_default_library", "//pkg/registry/cachesize:go_default_library", "//pkg/registry/rbac/rest:go_default_library", "//pkg/serviceaccount:go_default_library", @@ -53,7 +48,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library", "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", @@ -67,11 +61,8 @@ go_library( "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library", - "//staging/src/k8s.io/client-go/discovery/cached: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/rest: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/util/cert:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library", @@ -105,4 +96,5 @@ filegroup( "//cmd/kube-apiserver/app/testing:all-srcs", ], tags = ["automanaged"], + visibility = ["//visibility:public"], ) diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 025abc07d3c..783b8fd090d 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -42,7 +42,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" utilwait "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/admission" - webhookinit "k8s.io/apiserver/pkg/admission/plugin/webhook/initializer" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authorization/authorizer" openapinamer "k8s.io/apiserver/pkg/endpoints/openapi" @@ -54,11 +53,8 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" apiserverflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/apiserver/pkg/util/webhook" - cacheddiscovery "k8s.io/client-go/discovery/cached" clientgoinformers "k8s.io/client-go/informers" clientgoclientset "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/restmapper" certutil "k8s.io/client-go/util/cert" cloudprovider "k8s.io/cloud-provider" aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver" @@ -81,7 +77,6 @@ import ( "k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/master/reconcilers" "k8s.io/kubernetes/pkg/master/tunneler" - quotainstall "k8s.io/kubernetes/pkg/quota/v1/install" "k8s.io/kubernetes/pkg/registry/cachesize" rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest" "k8s.io/kubernetes/pkg/serviceaccount" @@ -506,24 +501,6 @@ func buildGenericConfig( } versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute) - if s.EnableAggregatorRouting { - serviceResolver = aggregatorapiserver.NewEndpointServiceResolver( - versionedInformers.Core().V1().Services().Lister(), - versionedInformers.Core().V1().Endpoints().Lister(), - ) - } else { - serviceResolver = aggregatorapiserver.NewClusterIPServiceResolver( - versionedInformers.Core().V1().Services().Lister(), - ) - } - // resolve kubernetes.default.svc locally - localHost, err := url.Parse(genericConfig.LoopbackClientConfig.Host) - if err != nil { - lastErr = err - return - } - serviceResolver = aggregatorapiserver.NewLoopbackServiceResolver(serviceResolver, localHost) - genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, clientgoExternalClient, versionedInformers) if err != nil { lastErr = fmt.Errorf("invalid authentication config: %v", err) @@ -539,35 +516,14 @@ func buildGenericConfig( genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName) } - webhookAuthResolverWrapper := func(delegate webhook.AuthenticationInfoResolver) webhook.AuthenticationInfoResolver { - return &webhook.AuthenticationInfoResolverDelegator{ - ClientConfigForFunc: func(server string) (*rest.Config, error) { - if server == "kubernetes.default.svc" { - return genericConfig.LoopbackClientConfig, nil - } - return delegate.ClientConfigFor(server) - }, - ClientConfigForServiceFunc: func(serviceName, serviceNamespace string) (*rest.Config, error) { - if serviceName == "kubernetes" && serviceNamespace == "default" { - return genericConfig.LoopbackClientConfig, nil - } - ret, err := delegate.ClientConfigForService(serviceName, serviceNamespace) - if err != nil { - return nil, err - } - if proxyTransport != nil && proxyTransport.DialContext != nil { - ret.Dial = proxyTransport.DialContext - } - return ret, err - }, - } + admissionConfig := &kubeapiserveradmission.AdmissionConfig{ + ExternalInformers: versionedInformers, + LoopbackClientConfig: genericConfig.LoopbackClientConfig, + CloudConfigFile: s.CloudProvider.CloudConfigFile, } - pluginInitializers, admissionPostStartHook, err = BuildAdmissionPluginInitializers( - s, - client, - serviceResolver, - webhookAuthResolverWrapper, - ) + serviceResolver = buildServiceResolver(s.EnableAggregatorRouting, genericConfig.LoopbackClientConfig.Host, versionedInformers) + + pluginInitializers, admissionPostStartHook, err = admissionConfig.New(proxyTransport, serviceResolver) if err != nil { lastErr = fmt.Errorf("failed to create admission plugin initializer: %v", err) return @@ -586,42 +542,6 @@ func buildGenericConfig( return } -// BuildAdmissionPluginInitializers constructs the admission plugin initializer -func BuildAdmissionPluginInitializers( - s *options.ServerRunOptions, - client internalclientset.Interface, - serviceResolver aggregatorapiserver.ServiceResolver, - webhookAuthWrapper webhook.AuthenticationInfoResolverWrapper, -) ([]admission.PluginInitializer, genericapiserver.PostStartHookFunc, error) { - var cloudConfig []byte - - if s.CloudProvider.CloudConfigFile != "" { - var err error - cloudConfig, err = ioutil.ReadFile(s.CloudProvider.CloudConfigFile) - if err != nil { - glog.Fatalf("Error reading from cloud configuration file %s: %#v", s.CloudProvider.CloudConfigFile, err) - } - } - - // We have a functional client so we can use that to build our discovery backed REST mapper - // Use a discovery client capable of being refreshed. - discoveryClient := cacheddiscovery.NewMemCacheClient(client.Discovery()) - discoveryRESTMapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) - - admissionPostStartHook := func(context genericapiserver.PostStartHookContext) error { - discoveryRESTMapper.Reset() - go utilwait.Until(discoveryRESTMapper.Reset, 30*time.Second, context.StopCh) - return nil - } - - quotaConfiguration := quotainstall.NewQuotaConfigurationForAdmission() - - kubePluginInitializer := kubeapiserveradmission.NewPluginInitializer(cloudConfig, discoveryRESTMapper, quotaConfiguration) - webhookPluginInitializer := webhookinit.NewPluginInitializer(webhookAuthWrapper, serviceResolver) - - return []admission.PluginInitializer{webhookPluginInitializer, kubePluginInitializer}, admissionPostStartHook, nil -} - // BuildAuthenticator constructs the authenticator func BuildAuthenticator(s *options.ServerRunOptions, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) { authenticatorConfig := s.Authentication.ToAuthenticationConfig() @@ -728,6 +648,25 @@ func Complete(s *options.ServerRunOptions) (completedServerRunOptions, error) { return options, nil } +func buildServiceResolver(enabledAggregatorRouting bool, hostname string, informer clientgoinformers.SharedInformerFactory) webhook.ServiceResolver { + var serviceResolver webhook.ServiceResolver + if enabledAggregatorRouting { + serviceResolver = aggregatorapiserver.NewEndpointServiceResolver( + informer.Core().V1().Services().Lister(), + informer.Core().V1().Endpoints().Lister(), + ) + } else { + serviceResolver = aggregatorapiserver.NewClusterIPServiceResolver( + informer.Core().V1().Services().Lister(), + ) + } + // resolve kubernetes.default.svc locally + if localHost, err := url.Parse(hostname); err == nil { + serviceResolver = aggregatorapiserver.NewLoopbackServiceResolver(serviceResolver, localHost) + } + return serviceResolver +} + func readCAorNil(file string) ([]byte, error) { if len(file) == 0 { return nil, nil diff --git a/pkg/kubeapiserver/admission/BUILD b/pkg/kubeapiserver/admission/BUILD index 13ab3a1489d..e42fc3dae3a 100644 --- a/pkg/kubeapiserver/admission/BUILD +++ b/pkg/kubeapiserver/admission/BUILD @@ -1,9 +1,32 @@ -package(default_visibility = ["//visibility:public"]) +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", +go_library( + name = "go_default_library", + srcs = [ + "config.go", + "initializer.go", + ], + importpath = "k8s.io/kubernetes/pkg/kubeapiserver/admission", + visibility = ["//visibility:public"], + deps = [ + "//pkg/client/clientset_generated/internalclientset:go_default_library", + "//pkg/client/informers/informers_generated/internalversion:go_default_library", + "//pkg/quota/v1:go_default_library", + "//pkg/quota/v1/install:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/initializer:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/server:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library", + "//staging/src/k8s.io/client-go/discovery/cached:go_default_library", + "//staging/src/k8s.io/client-go/informers:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/restmapper:go_default_library", + "//vendor/github.com/golang/glog:go_default_library", + ], ) go_test( @@ -13,19 +36,6 @@ go_test( deps = ["//staging/src/k8s.io/apiserver/pkg/admission:go_default_library"], ) -go_library( - name = "go_default_library", - srcs = ["initializer.go"], - importpath = "k8s.io/kubernetes/pkg/kubeapiserver/admission", - deps = [ - "//pkg/quota/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/admission:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", - "//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library", - ], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), @@ -40,4 +50,5 @@ filegroup( "//pkg/kubeapiserver/admission/util:all-srcs", ], tags = ["automanaged"], + visibility = ["//visibility:public"], ) diff --git a/pkg/kubeapiserver/admission/config.go b/pkg/kubeapiserver/admission/config.go new file mode 100644 index 00000000000..440c64ec9d3 --- /dev/null +++ b/pkg/kubeapiserver/admission/config.go @@ -0,0 +1,108 @@ +/* +Copyright 2018 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 admission + +import ( + "io/ioutil" + "net/http" + "time" + + "github.com/golang/glog" + + "k8s.io/api/core/v1" + utilwait "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/admission" + webhookinit "k8s.io/apiserver/pkg/admission/plugin/webhook/initializer" + "k8s.io/apiserver/pkg/server" + genericapiserver "k8s.io/apiserver/pkg/server" + "k8s.io/apiserver/pkg/util/webhook" + cacheddiscovery "k8s.io/client-go/discovery/cached" + externalinformers "k8s.io/client-go/informers" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + internalinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" + quotainstall "k8s.io/kubernetes/pkg/quota/v1/install" +) + +type AdmissionConfig struct { + CloudConfigFile string + LoopbackClientConfig *rest.Config + ExternalInformers externalinformers.SharedInformerFactory + InternalInformers internalinformers.SharedInformerFactory +} + +func (c *AdmissionConfig) buildAuthnInfoResolver(proxyTransport *http.Transport) webhook.AuthenticationInfoResolverWrapper { + webhookAuthResolverWrapper := func(delegate webhook.AuthenticationInfoResolver) webhook.AuthenticationInfoResolver { + return &webhook.AuthenticationInfoResolverDelegator{ + ClientConfigForFunc: func(server string) (*rest.Config, error) { + if server == "kubernetes.default.svc" { + return c.LoopbackClientConfig, nil + } + return delegate.ClientConfigFor(server) + }, + ClientConfigForServiceFunc: func(serviceName, serviceNamespace string) (*rest.Config, error) { + if serviceName == "kubernetes" && serviceNamespace == v1.NamespaceDefault { + return c.LoopbackClientConfig, nil + } + ret, err := delegate.ClientConfigForService(serviceName, serviceNamespace) + if err != nil { + return nil, err + } + if proxyTransport != nil && proxyTransport.DialContext != nil { + ret.Dial = proxyTransport.DialContext + } + return ret, err + }, + } + } + return webhookAuthResolverWrapper +} + +func (c *AdmissionConfig) New(proxyTransport *http.Transport, serviceResolver webhook.ServiceResolver) ([]admission.PluginInitializer, server.PostStartHookFunc, error) { + webhookAuthResolverWrapper := c.buildAuthnInfoResolver(proxyTransport) + webhookPluginInitializer := webhookinit.NewPluginInitializer(webhookAuthResolverWrapper, serviceResolver) + + var cloudConfig []byte + if c.CloudConfigFile != "" { + var err error + cloudConfig, err = ioutil.ReadFile(c.CloudConfigFile) + if err != nil { + glog.Fatalf("Error reading from cloud configuration file %s: %#v", c.CloudConfigFile, err) + } + } + internalClient, err := internalclientset.NewForConfig(c.LoopbackClientConfig) + if err != nil { + return nil, nil, err + } + + discoveryClient := cacheddiscovery.NewMemCacheClient(internalClient.Discovery()) + discoveryRESTMapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + kubePluginInitializer := NewPluginInitializer( + cloudConfig, + discoveryRESTMapper, + quotainstall.NewQuotaConfigurationForAdmission(), + ) + + admissionPostStartHook := func(context genericapiserver.PostStartHookContext) error { + discoveryRESTMapper.Reset() + go utilwait.Until(discoveryRESTMapper.Reset, 30*time.Second, context.StopCh) + return nil + } + + return []admission.PluginInitializer{webhookPluginInitializer, kubePluginInitializer}, admissionPostStartHook, nil +}