Annotation for opting into backend sharing; Use hash suffix for sharing; Fix resource GC

This commit is contained in:
Nick Sardo 2017-06-13 13:22:12 -07:00
parent d97d80fbd7
commit 3ea26e7436
3 changed files with 106 additions and 76 deletions

View File

@ -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
}

View File

@ -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)
return nil, err if err = gce.DeleteRegionForwardingRule(loadBalancerName, gce.region); err != nil && !isNotFound(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)
return nil
}
if hcName == "" { func (gce *GCECloud) teardownInternalHealthCheckAndFirewall(hcName string) error {
return nil
}
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 {

View File

@ -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)
} }