k8s.io/kubernetes@v1.29.3/pkg/controlplane/instance.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package controlplane 18 19 import ( 20 "fmt" 21 "net" 22 "net/http" 23 "os" 24 "reflect" 25 "strconv" 26 "time" 27 28 admissionregistrationv1 "k8s.io/api/admissionregistration/v1" 29 admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1" 30 admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" 31 apiserverinternalv1alpha1 "k8s.io/api/apiserverinternal/v1alpha1" 32 appsv1 "k8s.io/api/apps/v1" 33 authenticationv1 "k8s.io/api/authentication/v1" 34 authenticationv1alpha1 "k8s.io/api/authentication/v1alpha1" 35 authenticationv1beta1 "k8s.io/api/authentication/v1beta1" 36 authorizationapiv1 "k8s.io/api/authorization/v1" 37 autoscalingapiv1 "k8s.io/api/autoscaling/v1" 38 autoscalingapiv2 "k8s.io/api/autoscaling/v2" 39 batchapiv1 "k8s.io/api/batch/v1" 40 certificatesapiv1 "k8s.io/api/certificates/v1" 41 certificatesv1alpha1 "k8s.io/api/certificates/v1alpha1" 42 coordinationapiv1 "k8s.io/api/coordination/v1" 43 apiv1 "k8s.io/api/core/v1" 44 discoveryv1 "k8s.io/api/discovery/v1" 45 eventsv1 "k8s.io/api/events/v1" 46 networkingapiv1 "k8s.io/api/networking/v1" 47 networkingapiv1alpha1 "k8s.io/api/networking/v1alpha1" 48 nodev1 "k8s.io/api/node/v1" 49 policyapiv1 "k8s.io/api/policy/v1" 50 rbacv1 "k8s.io/api/rbac/v1" 51 resourcev1alpha2 "k8s.io/api/resource/v1alpha2" 52 schedulingapiv1 "k8s.io/api/scheduling/v1" 53 storageapiv1 "k8s.io/api/storage/v1" 54 storageapiv1alpha1 "k8s.io/api/storage/v1alpha1" 55 storageapiv1beta1 "k8s.io/api/storage/v1beta1" 56 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 57 "k8s.io/apimachinery/pkg/runtime/schema" 58 utilnet "k8s.io/apimachinery/pkg/util/net" 59 "k8s.io/apimachinery/pkg/util/runtime" 60 "k8s.io/apimachinery/pkg/util/uuid" 61 "k8s.io/apimachinery/pkg/util/wait" 62 "k8s.io/apiserver/pkg/endpoints/discovery" 63 apiserverfeatures "k8s.io/apiserver/pkg/features" 64 peerreconcilers "k8s.io/apiserver/pkg/reconcilers" 65 "k8s.io/apiserver/pkg/registry/generic" 66 genericapiserver "k8s.io/apiserver/pkg/server" 67 "k8s.io/apiserver/pkg/server/dynamiccertificates" 68 serverstorage "k8s.io/apiserver/pkg/server/storage" 69 utilfeature "k8s.io/apiserver/pkg/util/feature" 70 utilpeerproxy "k8s.io/apiserver/pkg/util/peerproxy" 71 "k8s.io/client-go/informers" 72 "k8s.io/client-go/kubernetes" 73 corev1client "k8s.io/client-go/kubernetes/typed/core/v1" 74 discoveryclient "k8s.io/client-go/kubernetes/typed/discovery/v1" 75 "k8s.io/component-helpers/apimachinery/lease" 76 "k8s.io/klog/v2" 77 api "k8s.io/kubernetes/pkg/apis/core" 78 flowcontrolv1 "k8s.io/kubernetes/pkg/apis/flowcontrol/v1" 79 flowcontrolv1beta1 "k8s.io/kubernetes/pkg/apis/flowcontrol/v1beta1" 80 flowcontrolv1beta2 "k8s.io/kubernetes/pkg/apis/flowcontrol/v1beta2" 81 flowcontrolv1beta3 "k8s.io/kubernetes/pkg/apis/flowcontrol/v1beta3" 82 "k8s.io/kubernetes/pkg/controlplane/apiserver/options" 83 "k8s.io/kubernetes/pkg/controlplane/controller/apiserverleasegc" 84 "k8s.io/kubernetes/pkg/controlplane/controller/clusterauthenticationtrust" 85 "k8s.io/kubernetes/pkg/controlplane/controller/defaultservicecidr" 86 "k8s.io/kubernetes/pkg/controlplane/controller/kubernetesservice" 87 "k8s.io/kubernetes/pkg/controlplane/controller/legacytokentracking" 88 "k8s.io/kubernetes/pkg/controlplane/controller/systemnamespaces" 89 "k8s.io/kubernetes/pkg/controlplane/reconcilers" 90 "k8s.io/kubernetes/pkg/features" 91 kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" 92 kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" 93 "k8s.io/kubernetes/pkg/routes" 94 "k8s.io/kubernetes/pkg/serviceaccount" 95 "k8s.io/utils/clock" 96 97 // RESTStorage installers 98 admissionregistrationrest "k8s.io/kubernetes/pkg/registry/admissionregistration/rest" 99 apiserverinternalrest "k8s.io/kubernetes/pkg/registry/apiserverinternal/rest" 100 appsrest "k8s.io/kubernetes/pkg/registry/apps/rest" 101 authenticationrest "k8s.io/kubernetes/pkg/registry/authentication/rest" 102 authorizationrest "k8s.io/kubernetes/pkg/registry/authorization/rest" 103 autoscalingrest "k8s.io/kubernetes/pkg/registry/autoscaling/rest" 104 batchrest "k8s.io/kubernetes/pkg/registry/batch/rest" 105 certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest" 106 coordinationrest "k8s.io/kubernetes/pkg/registry/coordination/rest" 107 corerest "k8s.io/kubernetes/pkg/registry/core/rest" 108 discoveryrest "k8s.io/kubernetes/pkg/registry/discovery/rest" 109 eventsrest "k8s.io/kubernetes/pkg/registry/events/rest" 110 flowcontrolrest "k8s.io/kubernetes/pkg/registry/flowcontrol/rest" 111 networkingrest "k8s.io/kubernetes/pkg/registry/networking/rest" 112 noderest "k8s.io/kubernetes/pkg/registry/node/rest" 113 policyrest "k8s.io/kubernetes/pkg/registry/policy/rest" 114 rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest" 115 resourcerest "k8s.io/kubernetes/pkg/registry/resource/rest" 116 schedulingrest "k8s.io/kubernetes/pkg/registry/scheduling/rest" 117 storagerest "k8s.io/kubernetes/pkg/registry/storage/rest" 118 ) 119 120 const ( 121 // DefaultEndpointReconcilerInterval is the default amount of time for how often the endpoints for 122 // the kubernetes Service are reconciled. 123 DefaultEndpointReconcilerInterval = 10 * time.Second 124 // DefaultEndpointReconcilerTTL is the default TTL timeout for the storage layer 125 DefaultEndpointReconcilerTTL = 15 * time.Second 126 // IdentityLeaseComponentLabelKey is used to apply a component label to identity lease objects, indicating: 127 // 1. the lease is an identity lease (different from leader election leases) 128 // 2. which component owns this lease 129 IdentityLeaseComponentLabelKey = "apiserver.kubernetes.io/identity" 130 // KubeAPIServer defines variable used internally when referring to kube-apiserver component 131 KubeAPIServer = "kube-apiserver" 132 // KubeAPIServerIdentityLeaseLabelSelector selects kube-apiserver identity leases 133 KubeAPIServerIdentityLeaseLabelSelector = IdentityLeaseComponentLabelKey + "=" + KubeAPIServer 134 // repairLoopInterval defines the interval used to run the Services ClusterIP and NodePort repair loops 135 repairLoopInterval = 3 * time.Minute 136 ) 137 138 var ( 139 // IdentityLeaseGCPeriod is the interval which the lease GC controller checks for expired leases 140 // IdentityLeaseGCPeriod is exposed so integration tests can tune this value. 141 IdentityLeaseGCPeriod = 3600 * time.Second 142 // IdentityLeaseDurationSeconds is the duration of kube-apiserver lease in seconds 143 // IdentityLeaseDurationSeconds is exposed so integration tests can tune this value. 144 IdentityLeaseDurationSeconds = 3600 145 // IdentityLeaseRenewIntervalSeconds is the interval of kube-apiserver renewing its lease in seconds 146 // IdentityLeaseRenewIntervalSeconds is exposed so integration tests can tune this value. 147 IdentityLeaseRenewIntervalPeriod = 10 * time.Second 148 ) 149 150 // ExtraConfig defines extra configuration for the master 151 type ExtraConfig struct { 152 ClusterAuthenticationInfo clusterauthenticationtrust.ClusterAuthenticationInfo 153 154 APIResourceConfigSource serverstorage.APIResourceConfigSource 155 StorageFactory serverstorage.StorageFactory 156 EndpointReconcilerConfig EndpointReconcilerConfig 157 EventTTL time.Duration 158 KubeletClientConfig kubeletclient.KubeletClientConfig 159 160 EnableLogsSupport bool 161 ProxyTransport *http.Transport 162 163 // PeerProxy, if not nil, sets proxy transport between kube-apiserver peers for requests 164 // that can not be served locally 165 PeerProxy utilpeerproxy.Interface 166 167 // PeerEndpointLeaseReconciler updates the peer endpoint leases 168 PeerEndpointLeaseReconciler peerreconcilers.PeerEndpointLeaseReconciler 169 170 // PeerCAFile is the ca bundle used by this kube-apiserver to verify peer apiservers' 171 // serving certs when routing a request to the peer in the case the request can not be served 172 // locally due to version skew. 173 PeerCAFile string 174 175 // PeerAdvertiseAddress is the IP for this kube-apiserver which is used by peer apiservers to route a request 176 // to this apiserver. This happens in cases where the peer is not able to serve the request due to 177 // version skew. If unset, AdvertiseAddress/BindAddress will be used. 178 PeerAdvertiseAddress peerreconcilers.PeerAdvertiseAddress 179 180 // Values to build the IP addresses used by discovery 181 // The range of IPs to be assigned to services with type=ClusterIP or greater 182 ServiceIPRange net.IPNet 183 // The IP address for the GenericAPIServer service (must be inside ServiceIPRange) 184 APIServerServiceIP net.IP 185 186 // dual stack services, the range represents an alternative IP range for service IP 187 // must be of different family than primary (ServiceIPRange) 188 SecondaryServiceIPRange net.IPNet 189 // the secondary IP address the GenericAPIServer service (must be inside SecondaryServiceIPRange) 190 SecondaryAPIServerServiceIP net.IP 191 192 // Port for the apiserver service. 193 APIServerServicePort int 194 195 // TODO, we can probably group service related items into a substruct to make it easier to configure 196 // the API server items and `Extra*` fields likely fit nicely together. 197 198 // The range of ports to be assigned to services with type=NodePort or greater 199 ServiceNodePortRange utilnet.PortRange 200 // If non-zero, the "kubernetes" services uses this port as NodePort. 201 KubernetesServiceNodePort int 202 203 // Number of masters running; all masters must be started with the 204 // same value for this field. (Numbers > 1 currently untested.) 205 MasterCount int 206 207 // MasterEndpointReconcileTTL sets the time to live in seconds of an 208 // endpoint record recorded by each master. The endpoints are checked at an 209 // interval that is 2/3 of this value and this value defaults to 15s if 210 // unset. In very large clusters, this value may be increased to reduce the 211 // possibility that the master endpoint record expires (due to other load 212 // on the etcd server) and causes masters to drop in and out of the 213 // kubernetes service record. It is not recommended to set this value below 214 // 15s. 215 MasterEndpointReconcileTTL time.Duration 216 217 // Selects which reconciler to use 218 EndpointReconcilerType reconcilers.Type 219 220 ServiceAccountIssuer serviceaccount.TokenGenerator 221 ServiceAccountMaxExpiration time.Duration 222 ExtendExpiration bool 223 224 // ServiceAccountIssuerDiscovery 225 ServiceAccountIssuerURL string 226 ServiceAccountJWKSURI string 227 ServiceAccountPublicKeys []interface{} 228 229 VersionedInformers informers.SharedInformerFactory 230 231 // RepairServicesInterval interval used by the repair loops for 232 // the Services NodePort and ClusterIP resources 233 RepairServicesInterval time.Duration 234 } 235 236 // Config defines configuration for the master 237 type Config struct { 238 GenericConfig *genericapiserver.Config 239 ExtraConfig ExtraConfig 240 } 241 242 type completedConfig struct { 243 GenericConfig genericapiserver.CompletedConfig 244 ExtraConfig *ExtraConfig 245 } 246 247 // CompletedConfig embeds a private pointer that cannot be instantiated outside of this package 248 type CompletedConfig struct { 249 *completedConfig 250 } 251 252 // EndpointReconcilerConfig holds the endpoint reconciler and endpoint reconciliation interval to be 253 // used by the master. 254 type EndpointReconcilerConfig struct { 255 Reconciler reconcilers.EndpointReconciler 256 Interval time.Duration 257 } 258 259 // Instance contains state for a Kubernetes cluster api server instance. 260 type Instance struct { 261 GenericAPIServer *genericapiserver.GenericAPIServer 262 263 ClusterAuthenticationInfo clusterauthenticationtrust.ClusterAuthenticationInfo 264 } 265 266 func (c *Config) createMasterCountReconciler() reconcilers.EndpointReconciler { 267 endpointClient := corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig) 268 endpointSliceClient := discoveryclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig) 269 endpointsAdapter := reconcilers.NewEndpointsAdapter(endpointClient, endpointSliceClient) 270 271 return reconcilers.NewMasterCountEndpointReconciler(c.ExtraConfig.MasterCount, endpointsAdapter) 272 } 273 274 func (c *Config) createNoneReconciler() reconcilers.EndpointReconciler { 275 return reconcilers.NewNoneEndpointReconciler() 276 } 277 278 func (c *Config) createLeaseReconciler() reconcilers.EndpointReconciler { 279 endpointClient := corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig) 280 endpointSliceClient := discoveryclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig) 281 endpointsAdapter := reconcilers.NewEndpointsAdapter(endpointClient, endpointSliceClient) 282 283 ttl := c.ExtraConfig.MasterEndpointReconcileTTL 284 config, err := c.ExtraConfig.StorageFactory.NewConfig(api.Resource("apiServerIPInfo")) 285 if err != nil { 286 klog.Fatalf("Error creating storage factory config: %v", err) 287 } 288 masterLeases, err := reconcilers.NewLeases(config, "/masterleases/", ttl) 289 if err != nil { 290 klog.Fatalf("Error creating leases: %v", err) 291 } 292 293 return reconcilers.NewLeaseEndpointReconciler(endpointsAdapter, masterLeases) 294 } 295 296 func (c *Config) createEndpointReconciler() reconcilers.EndpointReconciler { 297 klog.Infof("Using reconciler: %v", c.ExtraConfig.EndpointReconcilerType) 298 switch c.ExtraConfig.EndpointReconcilerType { 299 // there are numerous test dependencies that depend on a default controller 300 case reconcilers.MasterCountReconcilerType: 301 return c.createMasterCountReconciler() 302 case "", reconcilers.LeaseEndpointReconcilerType: 303 return c.createLeaseReconciler() 304 case reconcilers.NoneEndpointReconcilerType: 305 return c.createNoneReconciler() 306 default: 307 klog.Fatalf("Reconciler not implemented: %v", c.ExtraConfig.EndpointReconcilerType) 308 } 309 return nil 310 } 311 312 // Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. 313 func (c *Config) Complete() CompletedConfig { 314 cfg := completedConfig{ 315 c.GenericConfig.Complete(c.ExtraConfig.VersionedInformers), 316 &c.ExtraConfig, 317 } 318 319 serviceIPRange, apiServerServiceIP, err := options.ServiceIPRange(cfg.ExtraConfig.ServiceIPRange) 320 if err != nil { 321 klog.Fatalf("Error determining service IP ranges: %v", err) 322 } 323 if cfg.ExtraConfig.ServiceIPRange.IP == nil { 324 cfg.ExtraConfig.ServiceIPRange = serviceIPRange 325 } 326 if cfg.ExtraConfig.APIServerServiceIP == nil { 327 cfg.ExtraConfig.APIServerServiceIP = apiServerServiceIP 328 } 329 330 discoveryAddresses := discovery.DefaultAddresses{DefaultAddress: cfg.GenericConfig.ExternalAddress} 331 discoveryAddresses.CIDRRules = append(discoveryAddresses.CIDRRules, 332 discovery.CIDRRule{IPRange: cfg.ExtraConfig.ServiceIPRange, Address: net.JoinHostPort(cfg.ExtraConfig.APIServerServiceIP.String(), strconv.Itoa(cfg.ExtraConfig.APIServerServicePort))}) 333 cfg.GenericConfig.DiscoveryAddresses = discoveryAddresses 334 335 if cfg.ExtraConfig.ServiceNodePortRange.Size == 0 { 336 // TODO: Currently no way to specify an empty range (do we need to allow this?) 337 // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) 338 // but then that breaks the strict nestedness of ServiceType. 339 // Review post-v1 340 cfg.ExtraConfig.ServiceNodePortRange = kubeoptions.DefaultServiceNodePortRange 341 klog.Infof("Node port range unspecified. Defaulting to %v.", cfg.ExtraConfig.ServiceNodePortRange) 342 } 343 344 if cfg.ExtraConfig.EndpointReconcilerConfig.Interval == 0 { 345 cfg.ExtraConfig.EndpointReconcilerConfig.Interval = DefaultEndpointReconcilerInterval 346 } 347 348 if cfg.ExtraConfig.MasterEndpointReconcileTTL == 0 { 349 cfg.ExtraConfig.MasterEndpointReconcileTTL = DefaultEndpointReconcilerTTL 350 } 351 352 if cfg.ExtraConfig.EndpointReconcilerConfig.Reconciler == nil { 353 cfg.ExtraConfig.EndpointReconcilerConfig.Reconciler = c.createEndpointReconciler() 354 } 355 356 if cfg.ExtraConfig.RepairServicesInterval == 0 { 357 cfg.ExtraConfig.RepairServicesInterval = repairLoopInterval 358 } 359 360 return CompletedConfig{&cfg} 361 } 362 363 // New returns a new instance of Master from the given config. 364 // Certain config fields will be set to a default value if unset. 365 // Certain config fields must be specified, including: 366 // KubeletClientConfig 367 func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*Instance, error) { 368 if reflect.DeepEqual(c.ExtraConfig.KubeletClientConfig, kubeletclient.KubeletClientConfig{}) { 369 return nil, fmt.Errorf("Master.New() called with empty config.KubeletClientConfig") 370 } 371 372 s, err := c.GenericConfig.New("kube-apiserver", delegationTarget) 373 if err != nil { 374 return nil, err 375 } 376 377 if c.ExtraConfig.EnableLogsSupport { 378 routes.Logs{}.Install(s.Handler.GoRestfulContainer) 379 } 380 381 // Metadata and keys are expected to only change across restarts at present, 382 // so we just marshal immediately and serve the cached JSON bytes. 383 md, err := serviceaccount.NewOpenIDMetadata( 384 c.ExtraConfig.ServiceAccountIssuerURL, 385 c.ExtraConfig.ServiceAccountJWKSURI, 386 c.GenericConfig.ExternalAddress, 387 c.ExtraConfig.ServiceAccountPublicKeys, 388 ) 389 if err != nil { 390 // If there was an error, skip installing the endpoints and log the 391 // error, but continue on. We don't return the error because the 392 // metadata responses require additional, backwards incompatible 393 // validation of command-line options. 394 msg := fmt.Sprintf("Could not construct pre-rendered responses for"+ 395 " ServiceAccountIssuerDiscovery endpoints. Endpoints will not be"+ 396 " enabled. Error: %v", err) 397 if c.ExtraConfig.ServiceAccountIssuerURL != "" { 398 // The user likely expects this feature to be enabled if issuer URL is 399 // set and the feature gate is enabled. In the future, if there is no 400 // longer a feature gate and issuer URL is not set, the user may not 401 // expect this feature to be enabled. We log the former case as an Error 402 // and the latter case as an Info. 403 klog.Error(msg) 404 } else { 405 klog.Info(msg) 406 } 407 } else { 408 routes.NewOpenIDMetadataServer(md.ConfigJSON, md.PublicKeysetJSON). 409 Install(s.Handler.GoRestfulContainer) 410 } 411 412 m := &Instance{ 413 GenericAPIServer: s, 414 ClusterAuthenticationInfo: c.ExtraConfig.ClusterAuthenticationInfo, 415 } 416 417 clientset, err := kubernetes.NewForConfig(c.GenericConfig.LoopbackClientConfig) 418 if err != nil { 419 return nil, err 420 } 421 422 // TODO: update to a version that caches success but will recheck on failure, unlike memcache discovery 423 discoveryClientForAdmissionRegistration := clientset.Discovery() 424 425 legacyRESTStorageProvider, err := corerest.New(corerest.Config{ 426 GenericConfig: corerest.GenericConfig{ 427 StorageFactory: c.ExtraConfig.StorageFactory, 428 EventTTL: c.ExtraConfig.EventTTL, 429 LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig, 430 ServiceAccountIssuer: c.ExtraConfig.ServiceAccountIssuer, 431 ExtendExpiration: c.ExtraConfig.ExtendExpiration, 432 ServiceAccountMaxExpiration: c.ExtraConfig.ServiceAccountMaxExpiration, 433 APIAudiences: c.GenericConfig.Authentication.APIAudiences, 434 Informers: c.ExtraConfig.VersionedInformers, 435 }, 436 Proxy: corerest.ProxyConfig{ 437 Transport: c.ExtraConfig.ProxyTransport, 438 KubeletClientConfig: c.ExtraConfig.KubeletClientConfig, 439 }, 440 Services: corerest.ServicesConfig{ 441 ClusterIPRange: c.ExtraConfig.ServiceIPRange, 442 SecondaryClusterIPRange: c.ExtraConfig.SecondaryServiceIPRange, 443 NodePortRange: c.ExtraConfig.ServiceNodePortRange, 444 IPRepairInterval: c.ExtraConfig.RepairServicesInterval, 445 }, 446 }) 447 if err != nil { 448 return nil, err 449 } 450 451 // The order here is preserved in discovery. 452 // If resources with identical names exist in more than one of these groups (e.g. "deployments.apps"" and "deployments.extensions"), 453 // the order of this list determines which group an unqualified resource name (e.g. "deployments") should prefer. 454 // This priority order is used for local discovery, but it ends up aggregated in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go 455 // with specific priorities. 456 // TODO: describe the priority all the way down in the RESTStorageProviders and plumb it back through the various discovery 457 // handlers that we have. 458 restStorageProviders := []RESTStorageProvider{ 459 legacyRESTStorageProvider, 460 apiserverinternalrest.StorageProvider{}, 461 authenticationrest.RESTStorageProvider{Authenticator: c.GenericConfig.Authentication.Authenticator, APIAudiences: c.GenericConfig.Authentication.APIAudiences}, 462 authorizationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer, RuleResolver: c.GenericConfig.RuleResolver}, 463 autoscalingrest.RESTStorageProvider{}, 464 batchrest.RESTStorageProvider{}, 465 certificatesrest.RESTStorageProvider{}, 466 coordinationrest.RESTStorageProvider{}, 467 discoveryrest.StorageProvider{}, 468 networkingrest.RESTStorageProvider{}, 469 noderest.RESTStorageProvider{}, 470 policyrest.RESTStorageProvider{}, 471 rbacrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer}, 472 schedulingrest.RESTStorageProvider{}, 473 storagerest.RESTStorageProvider{}, 474 flowcontrolrest.RESTStorageProvider{InformerFactory: c.GenericConfig.SharedInformerFactory}, 475 // keep apps after extensions so legacy clients resolve the extensions versions of shared resource names. 476 // See https://github.com/kubernetes/kubernetes/issues/42392 477 appsrest.StorageProvider{}, 478 admissionregistrationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer, DiscoveryClient: discoveryClientForAdmissionRegistration}, 479 eventsrest.RESTStorageProvider{TTL: c.ExtraConfig.EventTTL}, 480 resourcerest.RESTStorageProvider{}, 481 } 482 if err := m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...); err != nil { 483 return nil, err 484 } 485 486 m.GenericAPIServer.AddPostStartHookOrDie("start-system-namespaces-controller", func(hookContext genericapiserver.PostStartHookContext) error { 487 go systemnamespaces.NewController(clientset, c.ExtraConfig.VersionedInformers.Core().V1().Namespaces()).Run(hookContext.StopCh) 488 return nil 489 }) 490 491 _, publicServicePort, err := c.GenericConfig.SecureServing.HostPort() 492 if err != nil { 493 return nil, fmt.Errorf("failed to get listener address: %w", err) 494 } 495 kubernetesServiceCtrl := kubernetesservice.New(kubernetesservice.Config{ 496 PublicIP: c.GenericConfig.PublicAddress, 497 498 EndpointReconciler: c.ExtraConfig.EndpointReconcilerConfig.Reconciler, 499 EndpointInterval: c.ExtraConfig.EndpointReconcilerConfig.Interval, 500 501 ServiceIP: c.ExtraConfig.APIServerServiceIP, 502 ServicePort: c.ExtraConfig.APIServerServicePort, 503 PublicServicePort: publicServicePort, 504 KubernetesServiceNodePort: c.ExtraConfig.KubernetesServiceNodePort, 505 }, clientset, c.ExtraConfig.VersionedInformers.Core().V1().Services()) 506 m.GenericAPIServer.AddPostStartHookOrDie("bootstrap-controller", func(hookContext genericapiserver.PostStartHookContext) error { 507 kubernetesServiceCtrl.Start(hookContext.StopCh) 508 return nil 509 }) 510 m.GenericAPIServer.AddPreShutdownHookOrDie("stop-kubernetes-service-controller", func() error { 511 kubernetesServiceCtrl.Stop() 512 return nil 513 }) 514 515 if utilfeature.DefaultFeatureGate.Enabled(features.MultiCIDRServiceAllocator) { 516 m.GenericAPIServer.AddPostStartHookOrDie("start-kubernetes-service-cidr-controller", func(hookContext genericapiserver.PostStartHookContext) error { 517 controller := defaultservicecidr.NewController( 518 c.ExtraConfig.ServiceIPRange, 519 c.ExtraConfig.SecondaryServiceIPRange, 520 clientset, 521 ) 522 // The default serviceCIDR must exist before the apiserver is healthy 523 // otherwise the allocators for Services will not work. 524 controller.Start(hookContext.StopCh) 525 return nil 526 }) 527 } 528 529 if utilfeature.DefaultFeatureGate.Enabled(features.UnknownVersionInteroperabilityProxy) { 530 peeraddress := getPeerAddress(c.ExtraConfig.PeerAdvertiseAddress, c.GenericConfig.PublicAddress, publicServicePort) 531 peerEndpointCtrl := peerreconcilers.New( 532 c.GenericConfig.APIServerID, 533 peeraddress, 534 c.ExtraConfig.PeerEndpointLeaseReconciler, 535 c.ExtraConfig.EndpointReconcilerConfig.Interval, 536 clientset) 537 if err != nil { 538 return nil, fmt.Errorf("failed to create peer endpoint lease controller: %w", err) 539 } 540 m.GenericAPIServer.AddPostStartHookOrDie("peer-endpoint-reconciler-controller", 541 func(hookContext genericapiserver.PostStartHookContext) error { 542 peerEndpointCtrl.Start(hookContext.StopCh) 543 return nil 544 }) 545 m.GenericAPIServer.AddPreShutdownHookOrDie("peer-endpoint-reconciler-controller", 546 func() error { 547 peerEndpointCtrl.Stop() 548 return nil 549 }) 550 // Add PostStartHooks for Unknown Version Proxy filter. 551 if c.ExtraConfig.PeerProxy != nil { 552 m.GenericAPIServer.AddPostStartHookOrDie("unknown-version-proxy-filter", func(context genericapiserver.PostStartHookContext) error { 553 err := c.ExtraConfig.PeerProxy.WaitForCacheSync(context.StopCh) 554 return err 555 }) 556 } 557 } 558 559 m.GenericAPIServer.AddPostStartHookOrDie("start-cluster-authentication-info-controller", func(hookContext genericapiserver.PostStartHookContext) error { 560 controller := clusterauthenticationtrust.NewClusterAuthenticationTrustController(m.ClusterAuthenticationInfo, clientset) 561 562 // generate a context from stopCh. This is to avoid modifying files which are relying on apiserver 563 // TODO: See if we can pass ctx to the current method 564 ctx := wait.ContextForChannel(hookContext.StopCh) 565 566 // prime values and start listeners 567 if m.ClusterAuthenticationInfo.ClientCA != nil { 568 m.ClusterAuthenticationInfo.ClientCA.AddListener(controller) 569 if controller, ok := m.ClusterAuthenticationInfo.ClientCA.(dynamiccertificates.ControllerRunner); ok { 570 // runonce to be sure that we have a value. 571 if err := controller.RunOnce(ctx); err != nil { 572 runtime.HandleError(err) 573 } 574 go controller.Run(ctx, 1) 575 } 576 } 577 if m.ClusterAuthenticationInfo.RequestHeaderCA != nil { 578 m.ClusterAuthenticationInfo.RequestHeaderCA.AddListener(controller) 579 if controller, ok := m.ClusterAuthenticationInfo.RequestHeaderCA.(dynamiccertificates.ControllerRunner); ok { 580 // runonce to be sure that we have a value. 581 if err := controller.RunOnce(ctx); err != nil { 582 runtime.HandleError(err) 583 } 584 go controller.Run(ctx, 1) 585 } 586 } 587 588 go controller.Run(ctx, 1) 589 return nil 590 }) 591 592 if utilfeature.DefaultFeatureGate.Enabled(apiserverfeatures.APIServerIdentity) { 593 m.GenericAPIServer.AddPostStartHookOrDie("start-kube-apiserver-identity-lease-controller", func(hookContext genericapiserver.PostStartHookContext) error { 594 // generate a context from stopCh. This is to avoid modifying files which are relying on apiserver 595 // TODO: See if we can pass ctx to the current method 596 ctx := wait.ContextForChannel(hookContext.StopCh) 597 598 leaseName := m.GenericAPIServer.APIServerID 599 holderIdentity := m.GenericAPIServer.APIServerID + "_" + string(uuid.NewUUID()) 600 601 peeraddress := getPeerAddress(c.ExtraConfig.PeerAdvertiseAddress, c.GenericConfig.PublicAddress, publicServicePort) 602 // must replace ':,[]' in [ip:port] to be able to store this as a valid label value 603 controller := lease.NewController( 604 clock.RealClock{}, 605 clientset, 606 holderIdentity, 607 int32(IdentityLeaseDurationSeconds), 608 nil, 609 IdentityLeaseRenewIntervalPeriod, 610 leaseName, 611 metav1.NamespaceSystem, 612 // TODO: receive identity label value as a parameter when post start hook is moved to generic apiserver. 613 labelAPIServerHeartbeatFunc(KubeAPIServer, peeraddress)) 614 go controller.Run(ctx) 615 return nil 616 }) 617 // TODO: move this into generic apiserver and make the lease identity value configurable 618 m.GenericAPIServer.AddPostStartHookOrDie("start-kube-apiserver-identity-lease-garbage-collector", func(hookContext genericapiserver.PostStartHookContext) error { 619 go apiserverleasegc.NewAPIServerLeaseGC( 620 clientset, 621 IdentityLeaseGCPeriod, 622 metav1.NamespaceSystem, 623 KubeAPIServerIdentityLeaseLabelSelector, 624 ).Run(hookContext.StopCh) 625 return nil 626 }) 627 } 628 629 m.GenericAPIServer.AddPostStartHookOrDie("start-legacy-token-tracking-controller", func(hookContext genericapiserver.PostStartHookContext) error { 630 go legacytokentracking.NewController(clientset).Run(hookContext.StopCh) 631 return nil 632 }) 633 634 return m, nil 635 } 636 637 func labelAPIServerHeartbeatFunc(identity string, peeraddress string) lease.ProcessLeaseFunc { 638 return func(lease *coordinationapiv1.Lease) error { 639 if lease.Labels == nil { 640 lease.Labels = map[string]string{} 641 } 642 643 if lease.Annotations == nil { 644 lease.Annotations = map[string]string{} 645 } 646 647 // This label indiciates the identity of the lease object. 648 lease.Labels[IdentityLeaseComponentLabelKey] = identity 649 650 hostname, err := os.Hostname() 651 if err != nil { 652 return err 653 } 654 655 // convenience label to easily map a lease object to a specific apiserver 656 lease.Labels[apiv1.LabelHostname] = hostname 657 658 // Include apiserver network location <ip_port> used by peers to proxy requests between kube-apiservers 659 if utilfeature.DefaultFeatureGate.Enabled(features.UnknownVersionInteroperabilityProxy) { 660 if peeraddress != "" { 661 lease.Annotations[apiv1.AnnotationPeerAdvertiseAddress] = peeraddress 662 } 663 } 664 return nil 665 } 666 } 667 668 // RESTStorageProvider is a factory type for REST storage. 669 type RESTStorageProvider interface { 670 GroupName() string 671 NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) 672 } 673 674 // InstallAPIs will install the APIs for the restStorageProviders if they are enabled. 675 func (m *Instance) InstallAPIs(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, restStorageProviders ...RESTStorageProvider) error { 676 nonLegacy := []*genericapiserver.APIGroupInfo{} 677 678 // used later in the loop to filter the served resource by those that have expired. 679 resourceExpirationEvaluator, err := genericapiserver.NewResourceExpirationEvaluator(*m.GenericAPIServer.Version) 680 if err != nil { 681 return err 682 } 683 684 for _, restStorageBuilder := range restStorageProviders { 685 groupName := restStorageBuilder.GroupName() 686 apiGroupInfo, err := restStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter) 687 if err != nil { 688 return fmt.Errorf("problem initializing API group %q : %v", groupName, err) 689 } 690 if len(apiGroupInfo.VersionedResourcesStorageMap) == 0 { 691 // If we have no storage for any resource configured, this API group is effectively disabled. 692 // This can happen when an entire API group, version, or development-stage (alpha, beta, GA) is disabled. 693 klog.Infof("API group %q is not enabled, skipping.", groupName) 694 continue 695 } 696 697 // Remove resources that serving kinds that are removed. 698 // We do this here so that we don't accidentally serve versions without resources or openapi information that for kinds we don't serve. 699 // This is a spot above the construction of individual storage handlers so that no sig accidentally forgets to check. 700 resourceExpirationEvaluator.RemoveDeletedKinds(groupName, apiGroupInfo.Scheme, apiGroupInfo.VersionedResourcesStorageMap) 701 if len(apiGroupInfo.VersionedResourcesStorageMap) == 0 { 702 klog.V(1).Infof("Removing API group %v because it is time to stop serving it because it has no versions per APILifecycle.", groupName) 703 continue 704 } 705 706 klog.V(1).Infof("Enabling API group %q.", groupName) 707 708 if postHookProvider, ok := restStorageBuilder.(genericapiserver.PostStartHookProvider); ok { 709 name, hook, err := postHookProvider.PostStartHook() 710 if err != nil { 711 klog.Fatalf("Error building PostStartHook: %v", err) 712 } 713 m.GenericAPIServer.AddPostStartHookOrDie(name, hook) 714 } 715 716 if len(groupName) == 0 { 717 // the legacy group for core APIs is special that it is installed into /api via this special install method. 718 if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil { 719 return fmt.Errorf("error in registering legacy API: %w", err) 720 } 721 } else { 722 // everything else goes to /apis 723 nonLegacy = append(nonLegacy, &apiGroupInfo) 724 } 725 } 726 727 if err := m.GenericAPIServer.InstallAPIGroups(nonLegacy...); err != nil { 728 return fmt.Errorf("error in registering group versions: %v", err) 729 } 730 return nil 731 } 732 733 var ( 734 // stableAPIGroupVersionsEnabledByDefault is a list of our stable versions. 735 stableAPIGroupVersionsEnabledByDefault = []schema.GroupVersion{ 736 admissionregistrationv1.SchemeGroupVersion, 737 apiv1.SchemeGroupVersion, 738 appsv1.SchemeGroupVersion, 739 authenticationv1.SchemeGroupVersion, 740 authorizationapiv1.SchemeGroupVersion, 741 autoscalingapiv1.SchemeGroupVersion, 742 autoscalingapiv2.SchemeGroupVersion, 743 batchapiv1.SchemeGroupVersion, 744 certificatesapiv1.SchemeGroupVersion, 745 coordinationapiv1.SchemeGroupVersion, 746 discoveryv1.SchemeGroupVersion, 747 eventsv1.SchemeGroupVersion, 748 networkingapiv1.SchemeGroupVersion, 749 nodev1.SchemeGroupVersion, 750 policyapiv1.SchemeGroupVersion, 751 rbacv1.SchemeGroupVersion, 752 storageapiv1.SchemeGroupVersion, 753 schedulingapiv1.SchemeGroupVersion, 754 flowcontrolv1.SchemeGroupVersion, 755 } 756 757 // legacyBetaEnabledByDefaultResources is the list of beta resources we enable. You may only add to this list 758 // if your resource is already enabled by default in a beta level we still serve AND there is no stable API for it. 759 // see https://github.com/kubernetes/enhancements/tree/master/keps/sig-architecture/3136-beta-apis-off-by-default 760 // for more details. 761 legacyBetaEnabledByDefaultResources = []schema.GroupVersionResource{ 762 flowcontrolv1beta3.SchemeGroupVersion.WithResource("flowschemas"), // deprecate in 1.29, remove in 1.32 763 flowcontrolv1beta3.SchemeGroupVersion.WithResource("prioritylevelconfigurations"), // deprecate in 1.29, remove in 1.32 764 } 765 // betaAPIGroupVersionsDisabledByDefault is for all future beta groupVersions. 766 betaAPIGroupVersionsDisabledByDefault = []schema.GroupVersion{ 767 admissionregistrationv1beta1.SchemeGroupVersion, 768 authenticationv1beta1.SchemeGroupVersion, 769 storageapiv1beta1.SchemeGroupVersion, 770 flowcontrolv1beta1.SchemeGroupVersion, 771 flowcontrolv1beta2.SchemeGroupVersion, 772 flowcontrolv1beta3.SchemeGroupVersion, 773 } 774 775 // alphaAPIGroupVersionsDisabledByDefault holds the alpha APIs we have. They are always disabled by default. 776 alphaAPIGroupVersionsDisabledByDefault = []schema.GroupVersion{ 777 admissionregistrationv1alpha1.SchemeGroupVersion, 778 apiserverinternalv1alpha1.SchemeGroupVersion, 779 authenticationv1alpha1.SchemeGroupVersion, 780 resourcev1alpha2.SchemeGroupVersion, 781 certificatesv1alpha1.SchemeGroupVersion, 782 networkingapiv1alpha1.SchemeGroupVersion, 783 storageapiv1alpha1.SchemeGroupVersion, 784 } 785 ) 786 787 // DefaultAPIResourceConfigSource returns default configuration for an APIResource. 788 func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { 789 ret := serverstorage.NewResourceConfig() 790 // NOTE: GroupVersions listed here will be enabled by default. Don't put alpha or beta versions in the list. 791 ret.EnableVersions(stableAPIGroupVersionsEnabledByDefault...) 792 793 // disable alpha and beta versions explicitly so we have a full list of what's possible to serve 794 ret.DisableVersions(betaAPIGroupVersionsDisabledByDefault...) 795 ret.DisableVersions(alphaAPIGroupVersionsDisabledByDefault...) 796 797 // enable the legacy beta resources that were present before stopped serving new beta APIs by default. 798 ret.EnableResources(legacyBetaEnabledByDefaultResources...) 799 800 return ret 801 } 802 803 // utility function to get the apiserver address that is used by peer apiservers to proxy 804 // requests to this apiserver in case the peer is incapable of serving the request 805 func getPeerAddress(peerAdvertiseAddress peerreconcilers.PeerAdvertiseAddress, publicAddress net.IP, publicServicePort int) string { 806 if peerAdvertiseAddress.PeerAdvertiseIP != "" && peerAdvertiseAddress.PeerAdvertisePort != "" { 807 return net.JoinHostPort(peerAdvertiseAddress.PeerAdvertiseIP, peerAdvertiseAddress.PeerAdvertisePort) 808 } else { 809 return net.JoinHostPort(publicAddress.String(), strconv.Itoa(publicServicePort)) 810 } 811 }