Skip to content

Commit de05bd8

Browse files
committed
Lazy initialization of network urls for GCE provider
1 parent 72cdc8c commit de05bd8

File tree

2 files changed

+66
-34
lines changed

2 files changed

+66
-34
lines changed

staging/src/k8s.io/legacy-cloud-providers/gce/gce.go

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ type Cloud struct {
9999
// for the cloudprovider to start watching the configmap.
100100
ClusterID ClusterID
101101

102+
// initializer is used for lazy initialization of subnetworkURL
103+
// and isLegacyNetwork fields if they are not passed via the config.
104+
// The reason is to avoid GCE API calls to initialize them if they
105+
// will never be used. This is especially important when
106+
// it is run from Kubelets, as there can be thousands of them.
107+
subnetworkURLAndIsLegacyNetworkInitializer sync.Once
108+
102109
service *compute.Service
103110
serviceBeta *computebeta.Service
104111
serviceAlpha *computealpha.Service
@@ -115,10 +122,14 @@ type Cloud struct {
115122
// managedZones will be set to the 1 zone if running a single zone cluster
116123
// it will be set to ALL zones in region for any multi-zone cluster
117124
// Use GetAllCurrentZones to get only zones that contain nodes
118-
managedZones []string
119-
networkURL string
120-
isLegacyNetwork bool
121-
subnetworkURL string
125+
managedZones []string
126+
networkURL string
127+
// unsafeIsLegacyNetwork should be used only via IsLegacyNetwork() accessor,
128+
// to ensure it was properly initialized.
129+
unsafeIsLegacyNetwork bool
130+
// unsafeSubnetworkURL should be used only via SubnetworkURL() accessor,
131+
// to ensure it was properly initialized.
132+
unsafeSubnetworkURL string
122133
secondaryRangeName string
123134
networkProjectID string
124135
onXPN bool
@@ -465,32 +476,12 @@ func CreateGCECloud(config *CloudConfig) (*Cloud, error) {
465476
subnetURL = config.SubnetworkURL
466477
} else if config.SubnetworkName != "" {
467478
subnetURL = gceSubnetworkURL(config.APIEndpoint, netProjID, config.Region, config.SubnetworkName)
468-
} else {
469-
// Determine the type of network and attempt to discover the correct subnet for AUTO mode.
470-
// Gracefully fail because kubelet calls CreateGCECloud without any config, and minions
471-
// lack the proper credentials for API calls.
472-
if networkName := lastComponent(networkURL); networkName != "" {
473-
var n *compute.Network
474-
if n, err = getNetwork(service, netProjID, networkName); err != nil {
475-
klog.Warningf("Could not retrieve network %q; err: %v", networkName, err)
476-
} else {
477-
switch typeOfNetwork(n) {
478-
case netTypeLegacy:
479-
klog.Infof("Network %q is type legacy - no subnetwork", networkName)
480-
isLegacyNetwork = true
481-
case netTypeCustom:
482-
klog.Warningf("Network %q is type custom - cannot auto select a subnetwork", networkName)
483-
case netTypeAuto:
484-
subnetURL, err = determineSubnetURL(service, netProjID, networkName, config.Region)
485-
if err != nil {
486-
klog.Warningf("Could not determine subnetwork for network %q and region %v; err: %v", networkName, config.Region, err)
487-
} else {
488-
klog.Infof("Auto selecting subnetwork %q", subnetURL)
489-
}
490-
}
491-
}
492-
}
493479
}
480+
// If neither SubnetworkURL nor SubnetworkName are provided, defer to
481+
// lazy initialization. Determining subnetURL and isLegacyNetwork requires
482+
// GCE API call. Given that it's not used in many cases and the fact that
483+
// the provider is initialized also for Kubelets (and there can be thousands
484+
// of them) we defer to lazy initialization here.
494485

495486
if len(config.ManagedZones) == 0 {
496487
config.ManagedZones, err = getZonesForRegion(service, config.ProjectID, config.Region)
@@ -518,8 +509,8 @@ func CreateGCECloud(config *CloudConfig) (*Cloud, error) {
518509
localZone: config.Zone,
519510
managedZones: config.ManagedZones,
520511
networkURL: networkURL,
521-
isLegacyNetwork: isLegacyNetwork,
522-
subnetworkURL: subnetURL,
512+
unsafeIsLegacyNetwork: isLegacyNetwork,
513+
unsafeSubnetworkURL: subnetURL,
523514
secondaryRangeName: config.SecondaryRangeName,
524515
nodeTags: config.NodeTags,
525516
nodeInstancePrefix: config.NodeInstancePrefix,
@@ -542,6 +533,45 @@ func CreateGCECloud(config *CloudConfig) (*Cloud, error) {
542533
return gce, nil
543534
}
544535

536+
// initializeNetworkConfig() is supposed to be called under sync.Once()
537+
// for accessors to subnetworkURL and isLegacyNetwork fields.
538+
func (g *Cloud) initializeSubnetworkURLAndIsLegacyNetwork() {
539+
if g.unsafeSubnetworkURL != "" {
540+
// This has already been initialized via the config.
541+
return
542+
}
543+
544+
var subnetURL string
545+
var isLegacyNetwork bool
546+
547+
// Determine the type of network and attempt to discover the correct subnet for AUTO mode.
548+
// Gracefully fail because kubelet calls CreateGCECloud without any config, and minions
549+
// lack the proper credentials for API calls.
550+
if networkName := lastComponent(g.NetworkURL()); networkName != "" {
551+
if n, err := getNetwork(g.service, g.NetworkProjectID(), networkName); err != nil {
552+
klog.Warningf("Could not retrieve network %q; err: %v", networkName, err)
553+
} else {
554+
switch typeOfNetwork(n) {
555+
case netTypeLegacy:
556+
klog.Infof("Network %q is type legacy - no subnetwork", networkName)
557+
isLegacyNetwork = true
558+
case netTypeCustom:
559+
klog.Warningf("Network %q is type custom - cannot auto select a subnetwork", networkName)
560+
case netTypeAuto:
561+
subnetURL, err = determineSubnetURL(g.service, g.NetworkProjectID(), networkName, g.Region())
562+
if err != nil {
563+
klog.Warningf("Could not determine subnetwork for network %q and region %v; err: %v", networkName, g.Region(), err)
564+
} else {
565+
klog.Infof("Auto selecting subnetwork %q", subnetURL)
566+
}
567+
}
568+
}
569+
}
570+
571+
g.unsafeSubnetworkURL = subnetURL
572+
g.unsafeIsLegacyNetwork = isLegacyNetwork
573+
}
574+
545575
// SetRateLimiter adds a custom cloud.RateLimiter implementation.
546576
// WARNING: Calling this could have unexpected behavior if you have in-flight
547577
// requests. It is best to use this immediately after creating a Cloud.
@@ -672,12 +702,14 @@ func (g *Cloud) NetworkURL() string {
672702

673703
// SubnetworkURL returns the subnetwork url
674704
func (g *Cloud) SubnetworkURL() string {
675-
return g.subnetworkURL
705+
g.subnetworkURLAndIsLegacyNetworkInitializer.Do(g.initializeSubnetworkURLAndIsLegacyNetwork)
706+
return g.unsafeSubnetworkURL
676707
}
677708

678709
// IsLegacyNetwork returns true if the cluster is still running a legacy network configuration.
679710
func (g *Cloud) IsLegacyNetwork() bool {
680-
return g.isLegacyNetwork
711+
g.subnetworkURLAndIsLegacyNetworkInitializer.Do(g.initializeSubnetworkURLAndIsLegacyNetwork)
712+
return g.unsafeIsLegacyNetwork
681713
}
682714

683715
// SetInformers sets up the zone handlers we need watching for node changes.

staging/src/k8s.io/legacy-cloud-providers/gce/gce_loadbalancer_internal.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func (g *Cloud) ensureInternalLoadBalancer(clusterName, clusterID string, svc *v
7575
}
7676
scheme := cloud.SchemeInternal
7777
options := getILBOptions(svc)
78-
if g.isLegacyNetwork {
78+
if g.IsLegacyNetwork() {
7979
g.eventRecorder.Event(svc, v1.EventTypeWarning, "ILBOptionsIgnored", "Internal LoadBalancer options are not supported with Legacy Networks.")
8080
options = ILBOptions{}
8181
}

0 commit comments

Comments
 (0)