func Run(serverOptions *genericoptions.ServerRunOptions, stopCh <-chan struct{}) error { // Set ServiceClusterIPRange _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serverOptions.ServiceClusterIPRange = *serviceClusterIPRange serverOptions.StorageConfig.ServerList = []string{"http://127.0.0.1:2379"} genericvalidation.ValidateRunOptions(serverOptions) genericvalidation.VerifyEtcdServersList(serverOptions) config := genericapiserver.NewConfig().ApplyOptions(serverOptions).Complete() if err := config.MaybeGenerateServingCerts(); err != nil { // this wasn't treated as fatal for this process before fmt.Printf("Error creating cert: %v", err) } config.Authorizer = authorizer.NewAlwaysAllowAuthorizer() config.SwaggerConfig = genericapiserver.DefaultSwaggerConfig() s, err := config.New() if err != nil { return fmt.Errorf("Error in bringing up the server: %v", err) } groupVersion := v1.SchemeGroupVersion groupName := groupVersion.Group groupMeta, err := registered.Group(groupName) if err != nil { return fmt.Errorf("%v", err) } storageFactory := newStorageFactory() storageConfig, err := storageFactory.NewConfig(unversioned.GroupResource{Group: groupName, Resource: "testtype"}) if err != nil { return fmt.Errorf("Unable to get storage config: %v", err) } restStorageMap := map[string]rest.Storage{ "testtypes": testgroupetcd.NewREST(storageConfig, generic.UndecoratedStorage), } apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *groupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ groupVersion.Version: restStorageMap, }, Scheme: api.Scheme, NegotiatedSerializer: api.Codecs, } if err := s.InstallAPIGroup(&apiGroupInfo); err != nil { return fmt.Errorf("Error in installing API: %v", err) } s.PrepareRun().Run(stopCh) return nil }
func Run(serverOptions *genericoptions.ServerRunOptions) error { // Set ServiceClusterIPRange _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serverOptions.ServiceClusterIPRange = *serviceClusterIPRange serverOptions.StorageConfig.ServerList = []string{"http://127.0.0.1:2379"} genericvalidation.ValidateRunOptions(serverOptions) genericvalidation.VerifyEtcdServersList(serverOptions) config := genericapiserver.NewConfig(serverOptions) config.Authorizer = authorizer.NewAlwaysAllowAuthorizer() config.Serializer = api.Codecs s, err := config.New() if err != nil { return fmt.Errorf("Error in bringing up the server: %v", err) } groupVersion := v1.SchemeGroupVersion groupName := groupVersion.Group groupMeta, err := registered.Group(groupName) if err != nil { return fmt.Errorf("%v", err) } storageFactory := newStorageFactory() storageConfig, err := storageFactory.NewConfig(unversioned.GroupResource{Group: groupName, Resource: "testtype"}) if err != nil { return fmt.Errorf("Unable to get storage config: %v", err) } restStorageMap := map[string]rest.Storage{ "testtypes": testgroupetcd.NewREST(storageConfig, generic.UndecoratedStorage), } apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *groupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ groupVersion.Version: restStorageMap, }, Scheme: api.Scheme, NegotiatedSerializer: api.Codecs, } if err := s.InstallAPIGroup(&apiGroupInfo); err != nil { return fmt.Errorf("Error in installing API: %v", err) } s.Run(serverOptions) return nil }
func buildAuthz(client authorizationclient.SubjectAccessReviewInterface, authz componentconfig.KubeletAuthorization) (authorizer.Authorizer, error) { switch authz.Mode { case componentconfig.KubeletAuthorizationModeAlwaysAllow: return alwaysallowauthorizer.NewAlwaysAllowAuthorizer(), nil case componentconfig.KubeletAuthorizationModeWebhook: if client == nil { return nil, errors.New("no client provided, cannot use webhook authorization") } return webhooksar.NewFromInterface( client, authz.Webhook.CacheAuthorizedTTL.Duration, authz.Webhook.CacheUnauthorizedTTL.Duration, ) case "": return nil, fmt.Errorf("No authorization mode specified") default: return nil, fmt.Errorf("Unknown authorization mode %s", authz.Mode) } }
// Returns a basic master config. func NewMasterConfig() *master.Config { config := storagebackend.Config{ ServerList: []string{GetEtcdURLFromEnv()}, // This causes the integration tests to exercise the etcd // prefix code, so please don't change without ensuring // sufficient coverage in other ways. Prefix: uuid.New(), } negotiatedSerializer := NewSingleContentTypeSerializer(api.Scheme, testapi.Default.Codec(), runtime.ContentTypeJSON) storageFactory := genericapiserver.NewDefaultStorageFactory(config, runtime.ContentTypeJSON, negotiatedSerializer, genericapiserver.NewDefaultResourceEncodingConfig(), master.DefaultAPIResourceConfigSource()) storageFactory.SetSerializer( unversioned.GroupResource{Group: api.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Default.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: autoscaling.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Autoscaling.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: batch.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Batch.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: apps.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Apps.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: extensions.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Extensions.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: policy.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Policy.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: rbac.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Rbac.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: certificates.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Certificates.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: storage.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Storage.Codec(), runtime.ContentTypeJSON)) genericConfig := genericapiserver.NewConfig() genericConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource() genericConfig.Authorizer = authorizer.NewAlwaysAllowAuthorizer() genericConfig.AdmissionControl = admit.NewAlwaysAdmit() genericConfig.EnableOpenAPISupport = true return &master.Config{ GenericConfig: genericConfig, StorageFactory: storageFactory, EnableCoreControllers: true, EnableWatchCache: true, KubeletClient: kubeletclient.FakeKubeletClient{}, } }
// New returns the right sort of union of multiple authorizer.Authorizer objects // based on the authorizationMode or an error. func (config AuthorizationConfig) New() (authorizer.Authorizer, error) { if len(config.AuthorizationModes) == 0 { return nil, errors.New("At least one authorization mode should be passed") } var authorizers []authorizer.Authorizer authorizerMap := make(map[string]bool) for _, authorizationMode := range config.AuthorizationModes { if authorizerMap[authorizationMode] { return nil, fmt.Errorf("Authorization mode %s specified more than once", authorizationMode) } // Keep cases in sync with constant list above. switch authorizationMode { case ModeAlwaysAllow: authorizers = append(authorizers, genericauthorizer.NewAlwaysAllowAuthorizer()) case ModeAlwaysDeny: authorizers = append(authorizers, genericauthorizer.NewAlwaysDenyAuthorizer()) case ModeABAC: if config.PolicyFile == "" { return nil, errors.New("ABAC's authorization policy file not passed") } abacAuthorizer, err := abac.NewFromFile(config.PolicyFile) if err != nil { return nil, err } authorizers = append(authorizers, abacAuthorizer) case ModeWebhook: if config.WebhookConfigFile == "" { return nil, errors.New("Webhook's configuration file not passed") } webhookAuthorizer, err := webhook.New(config.WebhookConfigFile, config.WebhookCacheAuthorizedTTL, config.WebhookCacheUnauthorizedTTL) if err != nil { return nil, err } authorizers = append(authorizers, webhookAuthorizer) case ModeRBAC: rbacAuthorizer := rbac.New( config.InformerFactory.Roles().Lister(), config.InformerFactory.RoleBindings().Lister(), config.InformerFactory.ClusterRoles().Lister(), config.InformerFactory.ClusterRoleBindings().Lister(), ) authorizers = append(authorizers, rbacAuthorizer) default: return nil, fmt.Errorf("Unknown authorization mode %s specified", authorizationMode) } authorizerMap[authorizationMode] = true } if !authorizerMap[ModeABAC] && config.PolicyFile != "" { return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC") } if !authorizerMap[ModeWebhook] && config.WebhookConfigFile != "" { return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook") } if !authorizerMap[ModeRBAC] && config.RBACSuperUser != "" { return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC") } return union.New(authorizers...), nil }
func (serverOptions *ServerRunOptions) Run(stopCh <-chan struct{}) error { // Set ServiceClusterIPRange _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serverOptions.GenericServerRunOptions.ServiceClusterIPRange = *serviceClusterIPRange serverOptions.Etcd.StorageConfig.ServerList = []string{"http://127.0.0.1:2379"} genericvalidation.ValidateRunOptions(serverOptions.GenericServerRunOptions) if errs := serverOptions.Etcd.Validate(); len(errs) > 0 { return utilerrors.NewAggregate(errs) } if errs := serverOptions.SecureServing.Validate(); len(errs) > 0 { return utilerrors.NewAggregate(errs) } if errs := serverOptions.InsecureServing.Validate("insecure-port"); len(errs) > 0 { return utilerrors.NewAggregate(errs) } if err := serverOptions.SecureServing.MaybeDefaultWithSelfSignedCerts(serverOptions.GenericServerRunOptions.AdvertiseAddress.String()); err != nil { glog.Fatalf("Error creating self-signed certificates: %v", err) } config := genericapiserver.NewConfig(). ApplyOptions(serverOptions.GenericServerRunOptions). ApplyInsecureServingOptions(serverOptions.InsecureServing) if _, err := config.ApplySecureServingOptions(serverOptions.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } if _, err := config.ApplyAuthenticationOptions(serverOptions.Authentication); err != nil { return fmt.Errorf("failed to configure authentication: %s", err) } config.Authorizer = authorizer.NewAlwaysAllowAuthorizer() s, err := config.Complete().New() if err != nil { return fmt.Errorf("Error in bringing up the server: %v", err) } groupVersion := v1.SchemeGroupVersion groupName := groupVersion.Group groupMeta, err := registered.Group(groupName) if err != nil { return fmt.Errorf("%v", err) } storageFactory := newStorageFactory() storageConfig, err := storageFactory.NewConfig(schema.GroupResource{Group: groupName, Resource: "testtype"}) if err != nil { return fmt.Errorf("Unable to get storage config: %v", err) } testTypeOpts := generic.RESTOptions{ StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: "testtypes", DeleteCollectionWorkers: 1, } restStorageMap := map[string]rest.Storage{ "testtypes": testgroupetcd.NewREST(testTypeOpts), } apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *groupMeta, VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ groupVersion.Version: restStorageMap, }, Scheme: api.Scheme, NegotiatedSerializer: api.Codecs, } if err := s.InstallAPIGroup(&apiGroupInfo); err != nil { return fmt.Errorf("Error in installing API: %v", err) } s.PrepareRun().Run(stopCh) return nil }
// Returns a basic master config. func NewMasterConfig() *master.Config { config := storagebackend.Config{ ServerList: []string{GetEtcdURLFromEnv()}, // This causes the integration tests to exercise the etcd // prefix code, so please don't change without ensuring // sufficient coverage in other ways. Prefix: uuid.New(), } info, _ := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) ns := NewSingleContentTypeSerializer(api.Scheme, info) storageFactory := genericapiserver.NewDefaultStorageFactory(config, runtime.ContentTypeJSON, ns, genericapiserver.NewDefaultResourceEncodingConfig(), master.DefaultAPIResourceConfigSource()) storageFactory.SetSerializer( unversioned.GroupResource{Group: api.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: autoscaling.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: batch.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: apps.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: extensions.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: policy.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: rbac.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: certificates.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: storage.GroupName, Resource: genericapiserver.AllResources}, "", ns) genericConfig := genericapiserver.NewConfig() kubeVersion := version.Get() genericConfig.Version = &kubeVersion genericConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource() genericConfig.Authorizer = authorizer.NewAlwaysAllowAuthorizer() genericConfig.AdmissionControl = admit.NewAlwaysAdmit() genericConfig.EnableMetrics = true return &master.Config{ GenericConfig: genericConfig, StorageFactory: storageFactory, EnableCoreControllers: true, EnableWatchCache: true, KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250}, APIServerServicePort: 443, MasterCount: 1, } }
// Returns a basic master config. func NewMasterConfig() *master.Config { config := storagebackend.Config{ ServerList: []string{GetEtcdURLFromEnv()}, // This causes the integration tests to exercise the etcd // prefix code, so please don't change without ensuring // sufficient coverage in other ways. Prefix: uuid.New(), } negotiatedSerializer := NewSingleContentTypeSerializer(api.Scheme, testapi.Default.Codec(), runtime.ContentTypeJSON) storageFactory := genericapiserver.NewDefaultStorageFactory(config, runtime.ContentTypeJSON, negotiatedSerializer, genericapiserver.NewDefaultResourceEncodingConfig(), master.DefaultAPIResourceConfigSource()) storageFactory.SetSerializer( unversioned.GroupResource{Group: api.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Default.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: autoscaling.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Autoscaling.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: batch.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Batch.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: apps.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Apps.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: extensions.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Extensions.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: policy.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Policy.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: rbac.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Rbac.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: certificates.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Certificates.Codec(), runtime.ContentTypeJSON)) storageFactory.SetSerializer( unversioned.GroupResource{Group: storage.GroupName, Resource: genericapiserver.AllResources}, "", NewSingleContentTypeSerializer(api.Scheme, testapi.Storage.Codec(), runtime.ContentTypeJSON)) return &master.Config{ GenericConfig: &genericapiserver.Config{ APIResourceConfigSource: master.DefaultAPIResourceConfigSource(), APIPrefix: "/api", APIGroupPrefix: "/apis", Authorizer: authorizer.NewAlwaysAllowAuthorizer(), AdmissionControl: admit.NewAlwaysAdmit(), Serializer: api.Codecs, // Set those values to avoid annoying warnings in logs. ServiceClusterIPRange: parseCIDROrDie("10.0.0.0/24"), ServiceNodePortRange: utilnet.PortRange{Base: 30000, Size: 2768}, EnableVersion: true, OpenAPIDefinitions: openapi.OpenAPIDefinitions, EnableOpenAPISupport: true, }, StorageFactory: storageFactory, EnableWatchCache: true, KubeletClient: kubeletclient.FakeKubeletClient{}, } }
func BuildKubernetesMasterConfig(options configapi.MasterConfig, requestContextMapper kapi.RequestContextMapper, kubeClient *kclient.Client, informers shared.InformerFactory, admissionControl admission.Interface, originAuthenticator authenticator.Request) (*MasterConfig, error) { if options.KubernetesMasterConfig == nil { return nil, errors.New("insufficient information to build KubernetesMasterConfig") } kubeletClientConfig := configapi.GetKubeletClientConfig(options) kubeletClient, err := kubeletclient.NewStaticKubeletClient(kubeletClientConfig) if err != nil { return nil, fmt.Errorf("unable to configure Kubelet client: %v", err) } // in-order list of plug-ins that should intercept admission decisions // TODO: Push node environment support to upstream in future podEvictionTimeout, err := time.ParseDuration(options.KubernetesMasterConfig.PodEvictionTimeout) if err != nil { return nil, fmt.Errorf("unable to parse PodEvictionTimeout: %v", err) } // Defaults are tested in TestCMServerDefaults cmserver := cmapp.NewCMServer() // Adjust defaults cmserver.Address = "" // no healthz endpoint cmserver.Port = 0 // no healthz endpoint cmserver.EnableGarbageCollector = false // disabled until we add the controller cmserver.PodEvictionTimeout = unversioned.Duration{Duration: podEvictionTimeout} cmserver.VolumeConfiguration.EnableDynamicProvisioning = options.VolumeConfig.DynamicProvisioningEnabled // resolve extended arguments // TODO: this should be done in config validation (along with the above) so we can provide // proper errors if err := cmdflags.Resolve(options.KubernetesMasterConfig.ControllerArguments, cmserver.AddFlags); len(err) > 0 { return nil, kerrors.NewAggregate(err) } // resolve extended arguments // TODO: this should be done in config validation (along with the above) so we can provide // proper errors schedulerserver := scheduleroptions.NewSchedulerServer() schedulerserver.PolicyConfigFile = options.KubernetesMasterConfig.SchedulerConfigFile if err := cmdflags.Resolve(options.KubernetesMasterConfig.SchedulerArguments, schedulerserver.AddFlags); len(err) > 0 { return nil, kerrors.NewAggregate(err) } cloud, err := cloudprovider.InitCloudProvider(cmserver.CloudProvider, cmserver.CloudConfigFile) if err != nil { return nil, err } if cloud != nil { glog.V(2).Infof("Successfully initialized cloud provider: %q from the config file: %q\n", cmserver.CloudProvider, cmserver.CloudConfigFile) } var proxyClientCerts []tls.Certificate if len(options.KubernetesMasterConfig.ProxyClientInfo.CertFile) > 0 { clientCert, err := tls.LoadX509KeyPair( options.KubernetesMasterConfig.ProxyClientInfo.CertFile, options.KubernetesMasterConfig.ProxyClientInfo.KeyFile, ) if err != nil { return nil, err } proxyClientCerts = append(proxyClientCerts, clientCert) } server, storageFactory, err := BuildDefaultAPIServer(options) if err != nil { return nil, err } // Preserve previous behavior of using the first non-loopback address // TODO: Deprecate this behavior and just require a valid value to be passed in publicAddress := net.ParseIP(options.KubernetesMasterConfig.MasterIP) if publicAddress == nil || publicAddress.IsUnspecified() || publicAddress.IsLoopback() { hostIP, err := knet.ChooseHostInterface() if err != nil { glog.Fatalf("Unable to find suitable network address.error='%v'. Set the masterIP directly to avoid this error.", err) } publicAddress = hostIP glog.Infof("Will report %v as public IP address.", publicAddress) } m := &master.Config{ Config: &genericapiserver.Config{ PublicAddress: publicAddress, ReadWritePort: server.SecurePort, Authenticator: originAuthenticator, // this is used to fulfill the tokenreviews endpoint which is used by node authentication Authorizer: authorizer.NewAlwaysAllowAuthorizer(), AdmissionControl: admissionControl, StorageFactory: storageFactory, ServiceClusterIPRange: (*net.IPNet)(&server.ServiceClusterIPRange), ServiceNodePortRange: server.ServiceNodePortRange, RequestContextMapper: requestContextMapper, APIResourceConfigSource: getAPIResourceConfig(options), APIPrefix: server.APIPrefix, APIGroupPrefix: server.APIGroupPrefix, MasterCount: server.MasterCount, // Set the TLS options for proxying to pods and services // Proxying to nodes uses the kubeletClient TLS config (so can provide a different cert, and verify the node hostname) ProxyTLSClientConfig: &tls.Config{ // Proxying to pods and services cannot verify hostnames, since they are contacted on randomly allocated IPs InsecureSkipVerify: true, Certificates: proxyClientCerts, }, Serializer: kapi.Codecs, EnableLogsSupport: server.EnableLogsSupport, EnableProfiling: server.EnableProfiling, EnableWatchCache: server.EnableWatchCache, MasterServiceNamespace: server.MasterServiceNamespace, ExternalHost: server.ExternalHost, MinRequestTimeout: server.MinRequestTimeout, KubernetesServiceNodePort: server.KubernetesServiceNodePort, }, EventTTL: server.EventTTL, KubeletClient: kubeletClient, EnableCoreControllers: true, DeleteCollectionWorkers: server.DeleteCollectionWorkers, } if server.EnableWatchCache { cachesize.SetWatchCacheSizes(server.WatchCacheSizes) } if options.DNSConfig != nil { _, dnsPortStr, err := net.SplitHostPort(options.DNSConfig.BindAddress) if err != nil { return nil, fmt.Errorf("unable to parse DNS bind address %s: %v", options.DNSConfig.BindAddress, err) } dnsPort, err := strconv.Atoi(dnsPortStr) if err != nil { return nil, fmt.Errorf("invalid DNS port: %v", err) } m.ExtraServicePorts = append(m.ExtraServicePorts, kapi.ServicePort{Name: "dns", Port: 53, Protocol: kapi.ProtocolUDP, TargetPort: intstr.FromInt(dnsPort)}, kapi.ServicePort{Name: "dns-tcp", Port: 53, Protocol: kapi.ProtocolTCP, TargetPort: intstr.FromInt(dnsPort)}, ) m.ExtraEndpointPorts = append(m.ExtraEndpointPorts, kapi.EndpointPort{Name: "dns", Port: int32(dnsPort), Protocol: kapi.ProtocolUDP}, kapi.EndpointPort{Name: "dns-tcp", Port: int32(dnsPort), Protocol: kapi.ProtocolTCP}, ) } kmaster := &MasterConfig{ Options: *options.KubernetesMasterConfig, KubeClient: kubeClient, Master: m, ControllerManager: cmserver, CloudProvider: cloud, SchedulerServer: schedulerserver, Informers: informers, } return kmaster, nil }