Annotation for opting into backend sharing; Use hash suffix for sharing; Fix resource GC
This commit is contained in:
		@@ -21,12 +21,17 @@ import "k8s.io/kubernetes/pkg/api/v1"
 | 
				
			|||||||
type LoadBalancerType string
 | 
					type LoadBalancerType string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// ServiceAnnotationLoadBalancerType is the annotation used on a service with type LoadBalancer
 | 
						// ServiceAnnotationLoadBalancerType is annotated on a service with type LoadBalancer
 | 
				
			||||||
	// dictates what specific kind of GCP LB should be assembled.
 | 
						// dictates what specific kind of GCP LB should be assembled.
 | 
				
			||||||
	// Currently, only "internal" is supported.
 | 
						// Currently, only "internal" is supported.
 | 
				
			||||||
	ServiceAnnotationLoadBalancerType = "cloud.google.com/load-balancer-type"
 | 
						ServiceAnnotationLoadBalancerType = "cloud.google.com/load-balancer-type"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LBTypeInternal LoadBalancerType = "internal"
 | 
						LBTypeInternal LoadBalancerType = "internal"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ServiceAnnotationInternalBackendShare is annotated on a service with "true" when users
 | 
				
			||||||
 | 
						// want to share GCP Backend Services for a set of internal load balancers.
 | 
				
			||||||
 | 
						// ALPHA feature - this may be removed in a future release.
 | 
				
			||||||
 | 
						ServiceAnnotationILBBackendShare = "cloud.google.com/load-balancer-backend-share"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLoadBalancerAnnotationType returns the type of GCP load balancer which should be assembled.
 | 
					// GetLoadBalancerAnnotationType returns the type of GCP load balancer which should be assembled.
 | 
				
			||||||
@@ -49,3 +54,12 @@ func GetLoadBalancerAnnotationType(service *v1.Service) (LoadBalancerType, bool)
 | 
				
			|||||||
		return v, false
 | 
							return v, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetLoadBalancerAnnotationBackendShare(service *v1.Service) bool {
 | 
				
			||||||
 | 
						l, exists := service.Annotations[ServiceAnnotationILBBackendShare]
 | 
				
			||||||
 | 
						if exists && l == "true" {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,8 +41,8 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
	ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
						ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
				
			||||||
	scheme := schemeInternal
 | 
						scheme := schemeInternal
 | 
				
			||||||
	loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
 | 
						loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
 | 
				
			||||||
	shared := !v1_service.RequestsOnlyLocalTraffic(svc)
 | 
						sharedBackend := serviceIsShared(svc)
 | 
				
			||||||
	backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, shared, scheme, protocol, svc.Spec.SessionAffinity)
 | 
						backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, sharedBackend, scheme, protocol, svc.Spec.SessionAffinity)
 | 
				
			||||||
	backendServiceLink := gce.getBackendServiceLink(backendServiceName)
 | 
						backendServiceLink := gce.getBackendServiceLink(backendServiceName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ensure instance groups exist and nodes are assigned to groups
 | 
						// Ensure instance groups exist and nodes are assigned to groups
 | 
				
			||||||
@@ -52,19 +52,26 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						existingBSName := getNameFromLink(existingFwdRule.BackendService)
 | 
				
			||||||
 | 
						existingBackendService, err := gce.GetRegionBackendService(existingBSName, gce.region)
 | 
				
			||||||
 | 
						if err != nil && !isNotFound(err) {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Lock the sharedResourceLock to prevent any deletions of shared resources while assembling shared resources here
 | 
						// Lock the sharedResourceLock to prevent any deletions of shared resources while assembling shared resources here
 | 
				
			||||||
	gce.sharedResourceLock.Lock()
 | 
						gce.sharedResourceLock.Lock()
 | 
				
			||||||
	defer gce.sharedResourceLock.Unlock()
 | 
						defer gce.sharedResourceLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ensure health check for backend service is created
 | 
						// Ensure health check for backend service is created
 | 
				
			||||||
	// By default, use the node health check endpoint
 | 
						// The health check is shared unless
 | 
				
			||||||
	hcName := makeHealthCheckName(loadBalancerName, clusterID, shared)
 | 
						sharedHealthCheck := !v1_service.RequestsOnlyLocalTraffic(svc)
 | 
				
			||||||
 | 
						hcName := makeHealthCheckName(loadBalancerName, clusterID, sharedHealthCheck)
 | 
				
			||||||
	hcPath, hcPort := GetNodesHealthCheckPath(), GetNodesHealthCheckPort()
 | 
						hcPath, hcPort := GetNodesHealthCheckPath(), GetNodesHealthCheckPort()
 | 
				
			||||||
	if !shared {
 | 
						if !sharedHealthCheck {
 | 
				
			||||||
		// Service requires a special health check, retrieve the OnlyLocal port & path
 | 
							// Service requires a special health check, retrieve the OnlyLocal port & path
 | 
				
			||||||
		hcPath, hcPort = v1_service.GetServiceHealthCheckPathPort(svc)
 | 
							hcPath, hcPort = v1_service.GetServiceHealthCheckPathPort(svc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	hc, err := gce.ensureInternalHealthCheck(hcName, nm, shared, hcPath, hcPort)
 | 
						hc, err := gce.ensureInternalHealthCheck(hcName, nm, sharedHealthCheck, hcPath, hcPort)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -73,7 +80,7 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
	if gce.OnXPN() {
 | 
						if gce.OnXPN() {
 | 
				
			||||||
		glog.V(2).Infof("ensureInternalLoadBalancer: cluster is on a cross-project network (XPN) network project %v, compute project %v - skipping firewall creation", gce.networkProjectID, gce.projectID)
 | 
							glog.V(2).Infof("ensureInternalLoadBalancer: cluster is on a cross-project network (XPN) network project %v, compute project %v - skipping firewall creation", gce.networkProjectID, gce.projectID)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if err = gce.ensureInternalFirewalls(loadBalancerName, clusterID, nm, svc, strconv.Itoa(int(hcPort)), shared, nodes); err != nil {
 | 
							if err = gce.ensureInternalFirewalls(loadBalancerName, clusterID, nm, svc, strconv.Itoa(int(hcPort)), sharedHealthCheck, nodes); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -95,13 +102,16 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
		expectedFwdRule.Network = gce.networkURL
 | 
							expectedFwdRule.Network = gce.networkURL
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete the previous internal load balancer if necessary
 | 
						fwdRuleDeleted := false
 | 
				
			||||||
	fwdRuleDeleted, err := gce.clearExistingInternalLB(loadBalancerName, existingFwdRule, expectedFwdRule, backendServiceName)
 | 
						if !fwdRuleEqual(existingFwdRule, expectedFwdRule) {
 | 
				
			||||||
	if err != nil {
 | 
							glog.V(2).Infof("ensureInternalLoadBalancer(%v: deleting existing forwarding rule with IP address %v", loadBalancerName, existingFwdRule.IPAddress)
 | 
				
			||||||
 | 
							if err = gce.DeleteRegionForwardingRule(loadBalancerName, gce.region); err != nil && !isNotFound(err) {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							fwdRuleDeleted = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bsDescription := makeBackendServiceDescription(nm, shared)
 | 
						bsDescription := makeBackendServiceDescription(nm, sharedBackend)
 | 
				
			||||||
	err = gce.ensureInternalBackendService(backendServiceName, bsDescription, svc.Spec.SessionAffinity, scheme, protocol, igLinks, hc.SelfLink)
 | 
						err = gce.ensureInternalBackendService(backendServiceName, bsDescription, svc.Spec.SessionAffinity, scheme, protocol, igLinks, hc.SelfLink)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -115,6 +125,11 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete the previous internal load balancer if necessary
 | 
				
			||||||
 | 
						if err = gce.clearPreviousInternalResources(loadBalancerName, existingBackendService, backendServiceName, hcName); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get the most recent forwarding rule for the new address.
 | 
						// Get the most recent forwarding rule for the new address.
 | 
				
			||||||
	existingFwdRule, err = gce.GetRegionForwardingRule(loadBalancerName, gce.region)
 | 
						existingFwdRule, err = gce.GetRegionForwardingRule(loadBalancerName, gce.region)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -126,39 +141,25 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
	return status, nil
 | 
						return status, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (gce *GCECloud) clearExistingInternalLB(loadBalancerName string, existingFwdRule, expectedFwdRule *compute.ForwardingRule, expectedBSName string) (fwdRuleDeleted bool, err error) {
 | 
					func (gce *GCECloud) clearPreviousInternalResources(loadBalancerName string, existingBackendService *compute.BackendService, expectedBSName, expectedHCName string) error {
 | 
				
			||||||
	if existingFwdRule == nil {
 | 
						if existingBackendService.Name != expectedBSName {
 | 
				
			||||||
		return false, nil
 | 
							glog.V(2).Infof("clearPreviousInternalResources(%v): expected backend service %q does not match previous %q - deleting backend service", loadBalancerName, expectedBSName, existingBackendService.Name)
 | 
				
			||||||
 | 
							if err := gce.teardownInternalBackendService(existingBackendService.Name); err != nil && !isNotFound(err) {
 | 
				
			||||||
 | 
								glog.Warningf("clearPreviousInternalResources: could not delete old backend service: %v, err: %v", existingBackendService.Name, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !fwdRuleEqual(existingFwdRule, expectedFwdRule) {
 | 
						if len(existingBackendService.HealthChecks) == 1 {
 | 
				
			||||||
		glog.V(2).Infof("clearExistingInternalLB(%v: deleting existing forwarding rule with IP address %v", loadBalancerName, existingFwdRule.IPAddress)
 | 
							existingHCName := getNameFromLink(existingBackendService.HealthChecks[0])
 | 
				
			||||||
		if err = gce.DeleteRegionForwardingRule(loadBalancerName, gce.region); err != nil && !isNotFound(err) {
 | 
							if existingHCName != expectedHCName {
 | 
				
			||||||
			return false, err
 | 
								glog.V(2).Infof("clearPreviousInternalResources(%v): expected health check %q does not match previous %q - deleting health check", loadBalancerName, expectedHCName, existingHCName)
 | 
				
			||||||
 | 
								if err := gce.teardownInternalHealthCheckAndFirewall(existingHCName); err != nil {
 | 
				
			||||||
 | 
									glog.Warningf("clearPreviousInternalResources: could not delete existing healthcheck: %v, err: %v", existingHCName, err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fwdRuleDeleted = true
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	existingBSName := getNameFromLink(existingFwdRule.BackendService)
 | 
						return nil
 | 
				
			||||||
	bs, err := gce.GetRegionBackendService(existingBSName, gce.region)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		if bs.Name != expectedBSName {
 | 
					 | 
				
			||||||
			glog.V(2).Infof("clearExistingInternalLB(%v): expected backend service %q does not match actual %q - deleting backend service & healthcheck & firewall", loadBalancerName, expectedBSName, bs.Name)
 | 
					 | 
				
			||||||
			// Delete the backend service as well in case it's switching between shared, nonshared, tcp, udp.
 | 
					 | 
				
			||||||
			var existingHCName string
 | 
					 | 
				
			||||||
			if len(bs.HealthChecks) == 1 {
 | 
					 | 
				
			||||||
				existingHCName = getNameFromLink(bs.HealthChecks[0])
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if err = gce.teardownInternalBackendResources(existingBSName, existingHCName); err != nil {
 | 
					 | 
				
			||||||
				glog.Warningf("clearExistingInternalLB: could not delete old resources: %v", err)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				glog.V(2).Infof("clearExistingInternalLB: done deleting old resources")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		glog.Warningf("clearExistingInternalLB(%v): failed to retrieve existing backend service %v", loadBalancerName, existingBSName)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fwdRuleDeleted, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (gce *GCECloud) updateInternalLoadBalancer(clusterName, clusterID string, svc *v1.Service, nodes []*v1.Node) error {
 | 
					func (gce *GCECloud) updateInternalLoadBalancer(clusterName, clusterID string, svc *v1.Service, nodes []*v1.Node) error {
 | 
				
			||||||
@@ -175,8 +176,8 @@ func (gce *GCECloud) updateInternalLoadBalancer(clusterName, clusterID string, s
 | 
				
			|||||||
	_, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
						_, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
				
			||||||
	scheme := schemeInternal
 | 
						scheme := schemeInternal
 | 
				
			||||||
	loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
 | 
						loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
 | 
				
			||||||
	shared := !v1_service.RequestsOnlyLocalTraffic(svc)
 | 
						sharedBackend := serviceIsShared(svc)
 | 
				
			||||||
	backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, shared, scheme, protocol, svc.Spec.SessionAffinity)
 | 
						backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, sharedBackend, scheme, protocol, svc.Spec.SessionAffinity)
 | 
				
			||||||
	// Ensure the backend service has the proper backend instance-group links
 | 
						// Ensure the backend service has the proper backend instance-group links
 | 
				
			||||||
	return gce.ensureInternalBackendServiceGroups(backendServiceName, igLinks)
 | 
						return gce.ensureInternalBackendServiceGroups(backendServiceName, igLinks)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -185,29 +186,28 @@ func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID st
 | 
				
			|||||||
	loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
 | 
						loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
 | 
				
			||||||
	_, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
						_, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
				
			||||||
	scheme := schemeInternal
 | 
						scheme := schemeInternal
 | 
				
			||||||
	shared := !v1_service.RequestsOnlyLocalTraffic(svc)
 | 
						sharedBackend := serviceIsShared(svc)
 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gce.sharedResourceLock.Lock()
 | 
						gce.sharedResourceLock.Lock()
 | 
				
			||||||
	defer gce.sharedResourceLock.Unlock()
 | 
						defer gce.sharedResourceLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting region internal forwarding rule", loadBalancerName)
 | 
						glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting region internal forwarding rule", loadBalancerName)
 | 
				
			||||||
	if err = gce.DeleteRegionForwardingRule(loadBalancerName, gce.region); err != nil && !isNotFound(err) {
 | 
						if err := gce.DeleteRegionForwardingRule(loadBalancerName, gce.region); err != nil && !isNotFound(err) {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, shared, scheme, protocol, svc.Spec.SessionAffinity)
 | 
						backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, sharedBackend, scheme, protocol, svc.Spec.SessionAffinity)
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting region backend service %v", loadBalancerName, backendServiceName)
 | 
						glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting region backend service %v", loadBalancerName, backendServiceName)
 | 
				
			||||||
	if err = gce.DeleteRegionBackendService(backendServiceName, gce.region); err != nil && !isNotFoundOrInUse(err) {
 | 
						if err := gce.DeleteRegionBackendService(backendServiceName, gce.region); err != nil && !isNotFoundOrInUse(err) {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Only delete the health check & health check firewall if they aren't being used by another LB.  If we get
 | 
						// Only delete the health check & health check firewall if they aren't being used by another LB.  If we get
 | 
				
			||||||
	// an ResourceInuseBy error, then we can skip deleting the firewall.
 | 
						// an ResourceInuseBy error, then we can skip deleting the firewall.
 | 
				
			||||||
	hcInUse := false
 | 
						hcInUse := false
 | 
				
			||||||
	hcName := makeHealthCheckName(loadBalancerName, clusterID, shared)
 | 
						hcName := makeHealthCheckName(loadBalancerName, clusterID, sharedBackend)
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting health check %v", loadBalancerName, hcName)
 | 
						glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting health check %v", loadBalancerName, hcName)
 | 
				
			||||||
	if err = gce.DeleteHealthCheck(hcName); err != nil && !isNotFoundOrInUse(err) {
 | 
						if err := gce.DeleteHealthCheck(hcName); err != nil && !isNotFoundOrInUse(err) {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	} else if isInUsedByError(err) {
 | 
						} else if isInUsedByError(err) {
 | 
				
			||||||
		glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): healthcheck %v still in use", loadBalancerName, hcName)
 | 
							glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): healthcheck %v still in use", loadBalancerName, hcName)
 | 
				
			||||||
@@ -215,7 +215,7 @@ func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID st
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting firewall for traffic", loadBalancerName)
 | 
						glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting firewall for traffic", loadBalancerName)
 | 
				
			||||||
	if err = gce.DeleteFirewall(loadBalancerName); err != nil {
 | 
						if err := gce.DeleteFirewall(loadBalancerName); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -223,48 +223,54 @@ func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID st
 | 
				
			|||||||
		glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): skipping firewall for healthcheck", loadBalancerName)
 | 
							glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): skipping firewall for healthcheck", loadBalancerName)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting firewall for healthcheck", loadBalancerName)
 | 
							glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting firewall for healthcheck", loadBalancerName)
 | 
				
			||||||
		fwHCName := makeHealthCheckFirewallkName(loadBalancerName, clusterID, shared)
 | 
							fwHCName := makeHealthCheckFirewallName(loadBalancerName, clusterID, sharedBackend)
 | 
				
			||||||
		if err = gce.DeleteFirewall(fwHCName); err != nil && !isInUsedByError(err) {
 | 
							if err := gce.DeleteFirewall(fwHCName); err != nil && !isInUsedByError(err) {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Try deleting instance groups - expect ResourceInuse error if needed by other LBs
 | 
						// Try deleting instance groups - expect ResourceInuse error if needed by other LBs
 | 
				
			||||||
	igName := makeInstanceGroupName(clusterID)
 | 
						igName := makeInstanceGroupName(clusterID)
 | 
				
			||||||
	if err = gce.ensureInternalInstanceGroupsDeleted(igName); err != nil && !isInUsedByError(err) {
 | 
						if err := gce.ensureInternalInstanceGroupsDeleted(igName); err != nil && !isInUsedByError(err) {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (gce *GCECloud) teardownInternalBackendResources(bsName, hcName string) error {
 | 
					func (gce *GCECloud) teardownInternalBackendService(bsName string) error {
 | 
				
			||||||
	if err := gce.DeleteRegionBackendService(bsName, gce.region); err != nil {
 | 
						if err := gce.DeleteRegionBackendService(bsName, gce.region); err != nil {
 | 
				
			||||||
		if isNotFound(err) {
 | 
							if isNotFound(err) {
 | 
				
			||||||
			glog.V(2).Infof("backend service already deleted: %v, err: %v", bsName, err)
 | 
								glog.V(2).Infof("teardownInternalBackendService(%v): backend service already deleted. err: %v", bsName, err)
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
		} else if err != nil && isInUsedByError(err) {
 | 
							} else if err != nil && isInUsedByError(err) {
 | 
				
			||||||
			glog.V(2).Infof("backend service in use: %v, err: %v", bsName, err)
 | 
								glog.V(2).Infof("teardownInternalBackendService(%v): backend service in use.", bsName)
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return fmt.Errorf("failed to delete backend service: %v, err: %v", bsName, err)
 | 
								return fmt.Errorf("failed to delete backend service: %v, err: %v", bsName, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("teardownInternalBackendService(%v): backend service deleted", bsName)
 | 
				
			||||||
	if hcName == "" {
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (gce *GCECloud) teardownInternalHealthCheckAndFirewall(hcName string) error {
 | 
				
			||||||
	hcInUse := false
 | 
						hcInUse := false
 | 
				
			||||||
	if err := gce.DeleteHealthCheck(hcName); err != nil {
 | 
						if err := gce.DeleteHealthCheck(hcName); err != nil {
 | 
				
			||||||
		if isNotFound(err) {
 | 
							if isNotFound(err) {
 | 
				
			||||||
			glog.V(2).Infof("health check already deleted: %v, err: %v", hcName, err)
 | 
								glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): health check does not exist.", hcName)
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
		} else if err != nil && isInUsedByError(err) {
 | 
							} else if err != nil && isInUsedByError(err) {
 | 
				
			||||||
			hcInUse = true
 | 
								hcInUse = true
 | 
				
			||||||
			glog.V(2).Infof("health check in use: %v, err: %v", hcName, err)
 | 
								glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): health check in use.", hcName)
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return fmt.Errorf("failed to delete health check: %v, err: %v", hcName, err)
 | 
								return fmt.Errorf("failed to delete health check: %v, err: %v", hcName, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): health check deleted", hcName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hcFirewallName := makeHealthCheckFirewallkNameFromHC(hcName)
 | 
						hcFirewallName := makeHealthCheckFirewallNameFromHC(hcName)
 | 
				
			||||||
	if hcInUse {
 | 
						if hcInUse {
 | 
				
			||||||
		glog.V(2).Infof("skipping deletion of health check firewall: %v", hcFirewallName)
 | 
							glog.V(2).Infof("skipping deletion of health check firewall: %v", hcFirewallName)
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -273,6 +279,7 @@ func (gce *GCECloud) teardownInternalBackendResources(bsName, hcName string) err
 | 
				
			|||||||
	if err := gce.DeleteFirewall(hcFirewallName); err != nil && !isNotFound(err) {
 | 
						if err := gce.DeleteFirewall(hcFirewallName); err != nil && !isNotFound(err) {
 | 
				
			||||||
		return fmt.Errorf("failed to delete health check firewall: %v, err: %v", hcFirewallName, err)
 | 
							return fmt.Errorf("failed to delete health check firewall: %v, err: %v", hcFirewallName, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): health check firewall deleted", hcFirewallName)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -315,7 +322,7 @@ func (gce *GCECloud) ensureInternalFirewall(fwName, fwDesc string, sourceRanges
 | 
				
			|||||||
	return gce.UpdateFirewall(expectedFirewall)
 | 
						return gce.UpdateFirewall(expectedFirewall)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (gce *GCECloud) ensureInternalFirewalls(loadBalancerName, clusterID string, nm types.NamespacedName, svc *v1.Service, healthCheckPort string, shared bool, nodes []*v1.Node) error {
 | 
					func (gce *GCECloud) ensureInternalFirewalls(loadBalancerName, clusterID string, nm types.NamespacedName, svc *v1.Service, healthCheckPort string, sharedHealthCheck bool, nodes []*v1.Node) error {
 | 
				
			||||||
	// First firewall is for ingress traffic
 | 
						// First firewall is for ingress traffic
 | 
				
			||||||
	fwDesc := makeFirewallDescription(nm.String(), svc.Spec.LoadBalancerIP)
 | 
						fwDesc := makeFirewallDescription(nm.String(), svc.Spec.LoadBalancerIP)
 | 
				
			||||||
	ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
						ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
 | 
				
			||||||
@@ -329,7 +336,7 @@ func (gce *GCECloud) ensureInternalFirewalls(loadBalancerName, clusterID string,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Second firewall is for health checking nodes / services
 | 
						// Second firewall is for health checking nodes / services
 | 
				
			||||||
	fwHCName := makeHealthCheckFirewallkName(loadBalancerName, clusterID, shared)
 | 
						fwHCName := makeHealthCheckFirewallName(loadBalancerName, clusterID, sharedHealthCheck)
 | 
				
			||||||
	hcSrcRanges := LoadBalancerSrcRanges()
 | 
						hcSrcRanges := LoadBalancerSrcRanges()
 | 
				
			||||||
	return gce.ensureInternalFirewall(fwHCName, "", hcSrcRanges, []string{healthCheckPort}, v1.ProtocolTCP, nodes)
 | 
						return gce.ensureInternalFirewall(fwHCName, "", hcSrcRanges, []string{healthCheckPort}, v1.ProtocolTCP, nodes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -496,6 +503,8 @@ func (gce *GCECloud) ensureInternalBackendService(name, description string, affi
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalBackendService: updating backend service %v", name)
 | 
						glog.V(2).Infof("ensureInternalBackendService: updating backend service %v", name)
 | 
				
			||||||
 | 
						// Set fingerprint for optimistic locking
 | 
				
			||||||
 | 
						expectedBS.Fingerprint = bs.Fingerprint
 | 
				
			||||||
	if err := gce.UpdateRegionBackendService(expectedBS, gce.region); err != nil {
 | 
						if err := gce.UpdateRegionBackendService(expectedBS, gce.region); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -503,6 +512,7 @@ func (gce *GCECloud) ensureInternalBackendService(name, description string, affi
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ensureInternalBackendServiceGroups updates backend services if their list of backend instance groups is incorrect.
 | 
				
			||||||
func (gce *GCECloud) ensureInternalBackendServiceGroups(name string, igLinks []string) error {
 | 
					func (gce *GCECloud) ensureInternalBackendServiceGroups(name string, igLinks []string) error {
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalBackendServiceGroups(%v): checking existing backend service's groups", name)
 | 
						glog.V(2).Infof("ensureInternalBackendServiceGroups(%v): checking existing backend service's groups", name)
 | 
				
			||||||
	bs, err := gce.GetRegionBackendService(name, gce.region)
 | 
						bs, err := gce.GetRegionBackendService(name, gce.region)
 | 
				
			||||||
@@ -516,7 +526,6 @@ func (gce *GCECloud) ensureInternalBackendServiceGroups(name string, igLinks []s
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glog.V(2).Infof("ensureInternalBackendServiceGroups: updating backend service %v", name)
 | 
						glog.V(2).Infof("ensureInternalBackendServiceGroups: updating backend service %v", name)
 | 
				
			||||||
	bs.Backends = backends
 | 
					 | 
				
			||||||
	if err := gce.UpdateRegionBackendService(bs, gce.region); err != nil {
 | 
						if err := gce.UpdateRegionBackendService(bs, gce.region); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -524,6 +533,10 @@ func (gce *GCECloud) ensureInternalBackendServiceGroups(name string, igLinks []s
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func serviceIsShared(svc *v1.Service) bool {
 | 
				
			||||||
 | 
						return GetLoadBalancerAnnotationBackendShare(svc) && !v1_service.RequestsOnlyLocalTraffic(svc)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func backendsFromGroupLinks(igLinks []string) []*compute.Backend {
 | 
					func backendsFromGroupLinks(igLinks []string) []*compute.Backend {
 | 
				
			||||||
	var backends []*compute.Backend
 | 
						var backends []*compute.Backend
 | 
				
			||||||
	for _, igLink := range igLinks {
 | 
						for _, igLink := range igLinks {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,8 @@ limitations under the License.
 | 
				
			|||||||
package gce
 | 
					package gce
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/sha1"
 | 
				
			||||||
 | 
						"encoding/hex"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,15 +35,16 @@ func makeInstanceGroupName(clusterID string) string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func makeBackendServiceName(loadBalancerName, clusterID string, shared bool, scheme lbScheme, protocol v1.Protocol, svcAffinity v1.ServiceAffinity) string {
 | 
					func makeBackendServiceName(loadBalancerName, clusterID string, shared bool, scheme lbScheme, protocol v1.Protocol, svcAffinity v1.ServiceAffinity) string {
 | 
				
			||||||
	if shared {
 | 
						if shared {
 | 
				
			||||||
		affinity := ""
 | 
							hash := sha1.New()
 | 
				
			||||||
		switch svcAffinity {
 | 
					 | 
				
			||||||
		case v1.ServiceAffinityClientIP:
 | 
					 | 
				
			||||||
			affinity = "clientip"
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			affinity = "noaffinity"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return fmt.Sprintf("k8s-%s-%s-%s-%s", clusterID, strings.ToLower(string(scheme)), strings.ToLower(string(protocol)), affinity)
 | 
							// For every non-nil option, hash its value. Currently, only service affinity is relevant.
 | 
				
			||||||
 | 
							hash.Write([]byte(string(svcAffinity)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							hashed := hex.EncodeToString(hash.Sum(nil))
 | 
				
			||||||
 | 
							hashed = hashed[:16]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 3 + 1 + 16 + 1 + 8 + 1 + 3 + 16
 | 
				
			||||||
 | 
							return fmt.Sprintf("k8s-%s-%s-%s-nmv1-%s", clusterID, strings.ToLower(string(scheme)), strings.ToLower(string(protocol)), hashed)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return loadBalancerName
 | 
						return loadBalancerName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -54,11 +57,11 @@ func makeHealthCheckName(loadBalancerName, clusterID string, shared bool) string
 | 
				
			|||||||
	return loadBalancerName
 | 
						return loadBalancerName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func makeHealthCheckFirewallkNameFromHC(healthCheckName string) string {
 | 
					func makeHealthCheckFirewallNameFromHC(healthCheckName string) string {
 | 
				
			||||||
	return healthCheckName + "-hc"
 | 
						return healthCheckName + "-hc"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func makeHealthCheckFirewallkName(loadBalancerName, clusterID string, shared bool) string {
 | 
					func makeHealthCheckFirewallName(loadBalancerName, clusterID string, shared bool) string {
 | 
				
			||||||
	if shared {
 | 
						if shared {
 | 
				
			||||||
		return fmt.Sprintf("k8s-%s-node-hc", clusterID)
 | 
							return fmt.Sprintf("k8s-%s-node-hc", clusterID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user