From f63ac1962cd6515f16fab4bfddbff09c3f5291a2 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Tue, 21 Jun 2016 18:09:31 -0700 Subject: [PATCH] GCE provider: Create TargetPool with 200 instances, then update with rest Tested with 2000 nodes, this actually meets the GCE API specifications (which is nutty). Previous PR (#25178) was based on a mistaken understanding of a poorly documented set of limitations, and even poorer testing, for which I am embarassed. --- pkg/cloudprovider/providers/gce/gce.go | 30 +++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 0ffcce4527927..92d09ce13be2e 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -69,6 +69,9 @@ const ( // are iterated through to prevent infinite loops if the API // were to continuously return a nextPageToken. maxPages = 25 + + // Target Pool creation is limited to 200 instances. + maxTargetPoolCreateInstances = 200 ) // GCECloud is an implementation of Interface, LoadBalancer and Instances for Google Compute Engine. @@ -537,7 +540,7 @@ func (gce *GCECloud) EnsureLoadBalancer(apiService *api.Service, hostNames []str affinityType := apiService.Spec.SessionAffinity serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name} - glog.V(2).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", loadBalancerName, gce.region, loadBalancerIP, portStr, hosts, serviceName, apiService.Annotations) + glog.V(2).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", loadBalancerName, gce.region, loadBalancerIP, portStr, hostNames, serviceName, apiService.Annotations) // Check if the forwarding rule exists, and if so, what its IP is. fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := gce.forwardingRuleNeedsUpdate(loadBalancerName, gce.region, loadBalancerIP, ports) @@ -706,10 +709,27 @@ func (gce *GCECloud) EnsureLoadBalancer(apiService *api.Service, hostNames []str // Once we've deleted the resources (if necessary), build them back up (or for // the first time if they're new). if tpNeedsUpdate { - if err := gce.createTargetPool(loadBalancerName, serviceName.String(), gce.region, hosts, affinityType); err != nil { + createInstances := hosts + if len(hosts) > maxTargetPoolCreateInstances { + createInstances = createInstances[:maxTargetPoolCreateInstances] + } + + if err := gce.createTargetPool(loadBalancerName, serviceName.String(), gce.region, createInstances, affinityType); err != nil { return nil, fmt.Errorf("failed to create target pool %s: %v", loadBalancerName, err) } - glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): created target pool", loadBalancerName, serviceName) + if len(hosts) <= maxTargetPoolCreateInstances { + glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): created target pool", loadBalancerName, serviceName) + } else { + glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): created initial target pool (now updating with %d hosts)", loadBalancerName, serviceName, len(hosts)-maxTargetPoolCreateInstances) + + created := sets.NewString() + for _, host := range createInstances { + created.Insert(host.makeComparableHostPath()) + } + if err := gce.updateTargetPool(loadBalancerName, created, hosts); err != nil { + return nil, fmt.Errorf("failed to update target pool %s: %v", loadBalancerName, err) + } + } } if tpNeedsUpdate || fwdRuleNeedsUpdate { if err := gce.createForwardingRule(loadBalancerName, serviceName.String(), gce.region, ipAddress, ports); err != nil { @@ -1155,6 +1175,10 @@ func (gce *GCECloud) UpdateLoadBalancer(service *api.Service, hostNames []string existing.Insert(hostURLToComparablePath(instance)) } + return gce.updateTargetPool(loadBalancerName, existing, hosts) +} + +func (gce *GCECloud) updateTargetPool(loadBalancerName string, existing sets.String, hosts []*gceInstance) error { var toAdd []*compute.InstanceReference var toRemove []*compute.InstanceReference for _, host := range hosts {