Skip to content

Commit 3cda00c

Browse files
committed
refactor into one flow
1 parent 55ca64d commit 3cda00c

File tree

1 file changed

+40
-196
lines changed

1 file changed

+40
-196
lines changed

providers/gce/gce_loadbalancer_external.go

Lines changed: 40 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -112,123 +112,16 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
112112
g.deleteWrongNetworkTieredResources(loadBalancerName, lbRefStr, netTier)
113113
}
114114

115-
// If the feature gate is not enabled, we check for multiple protocols and error out.
116-
if !g.AlphaFeatureGate.Enabled(AlphaFeatureMultiProtocolLB) {
117-
fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := g.forwardingRuleNeedsUpdate(loadBalancerName, g.region, requestedIP, ports)
118-
if err != nil {
119-
return nil, err
120-
}
121-
if !fwdRuleExists {
122-
klog.V(2).Infof("ensureExternalLoadBalancer(%s): Forwarding rule %v doesn't exist.", lbRefStr, loadBalancerName)
123-
}
124-
// Single-protocol logic
125-
ipAddressToUse, isSafeToReleaseIP, err := g.ensureIPAddress(loadBalancerName, lbRefStr, apiService.Spec.LoadBalancerIP, fwdRuleIP, netTier)
126-
if err != nil {
127-
return nil, err
128-
}
129-
defer func() {
130-
if isSafeToReleaseIP {
131-
if err := g.DeleteRegionAddress(loadBalancerName, g.region); err != nil && !isNotFound(err) {
132-
klog.Errorf("ensureExternalLoadBalancer(%s): Failed to release static IP %s in region %v: %v.", lbRefStr, ipAddressToUse, g.region, err)
133-
} else if isNotFound(err) {
134-
klog.V(2).Infof("ensureExternalLoadBalancer(%s): IP address %s is not reserved.", lbRefStr, ipAddressToUse)
135-
} else {
136-
klog.Infof("ensureExternalLoadBalancer(%s): Released static IP %s.", lbRefStr, ipAddressToUse)
137-
}
138-
} else {
139-
klog.Warningf("ensureExternalLoadBalancer(%s): Orphaning static IP %s in region %v: %v.", lbRefStr, ipAddressToUse, g.region, err)
140-
}
141-
}()
142-
143-
sourceRanges, err := servicehelpers.GetLoadBalancerSourceRanges(apiService)
144-
if err != nil {
145-
return nil, err
146-
}
147-
148-
firewallExists, firewallNeedsUpdate, err := g.firewallNeedsUpdate(loadBalancerName, serviceName.String(), ipAddressToUse, ports, sourceRanges)
149-
if err != nil {
150-
return nil, err
151-
}
152-
153-
if firewallNeedsUpdate {
154-
desc := makeFirewallDescription(serviceName.String(), ipAddressToUse)
155-
if firewallExists {
156-
klog.Infof("ensureExternalLoadBalancer(%s): Updating firewall.", lbRefStr)
157-
if err := g.updateFirewall(apiService, MakeFirewallName(loadBalancerName), desc, ipAddressToUse, sourceRanges, ports, hosts); err != nil {
158-
return nil, err
159-
}
160-
klog.Infof("ensureExternalLoadBalancer(%s): Updated firewall.", lbRefStr)
161-
} else {
162-
klog.Infof("ensureExternalLoadBalancer(%s): Creating firewall.", lbRefStr)
163-
if err := g.createFirewall(apiService, MakeFirewallName(loadBalancerName), desc, ipAddressToUse, sourceRanges, ports, hosts); err != nil {
164-
return nil, err
165-
}
166-
klog.Infof("ensureExternalLoadBalancer(%s): Created firewall.", lbRefStr)
167-
}
168-
}
169-
170-
tpExists, tpNeedsRecreation, err := g.targetPoolNeedsRecreation(loadBalancerName, g.region, apiService.Spec.SessionAffinity)
171-
if err != nil {
172-
return nil, err
173-
}
174-
if !tpExists {
175-
klog.Infof("ensureExternalLoadBalancer(%s): Target pool for service doesn't exist.", lbRefStr)
176-
}
177-
178-
var hcToCreate, hcToDelete *compute.HttpHealthCheck
179-
hcLocalTrafficExisting, err := g.GetHTTPHealthCheck(loadBalancerName)
180-
if err != nil && !isHTTPErrorCode(err, http.StatusNotFound) {
181-
return nil, fmt.Errorf("error checking HTTP health check for load balancer (%s): %v", lbRefStr, err)
182-
}
183-
if path, healthCheckNodePort := servicehelpers.GetServiceHealthCheckPathPort(apiService); path != "" {
184-
klog.V(4).Infof("ensureExternalLoadBalancer(%s): Service needs local traffic health checks on: %d%s.", lbRefStr, healthCheckNodePort, path)
185-
if hcLocalTrafficExisting == nil {
186-
klog.V(2).Infof("ensureExternalLoadBalancer(%s): Updating from nodes health checks to local traffic health checks.", lbRefStr)
187-
hcToDelete = makeHTTPHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort())
188-
tpNeedsRecreation = true
189-
}
190-
hcToCreate = makeHTTPHealthCheck(loadBalancerName, path, healthCheckNodePort)
191-
} else {
192-
klog.V(4).Infof("ensureExternalLoadBalancer(%s): Service needs nodes health checks.", lbRefStr)
193-
if hcLocalTrafficExisting != nil {
194-
klog.V(2).Infof("ensureExternalLoadBalancer(%s): Updating from local traffic health checks to nodes health checks.", lbRefStr)
195-
hcToDelete = hcLocalTrafficExisting
196-
tpNeedsRecreation = true
197-
}
198-
hcToCreate = makeHTTPHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort())
199-
}
200-
201-
if fwdRuleExists && (fwdRuleNeedsUpdate || tpNeedsRecreation) {
202-
isSafeToReleaseIP = false
203-
if err := g.DeleteRegionForwardingRule(loadBalancerName, g.region); err != nil && !isNotFound(err) {
204-
return nil, fmt.Errorf("failed to delete existing forwarding rule for load balancer (%s) update: %v", lbRefStr, err)
205-
}
206-
klog.Infof("ensureExternalLoadBalancer(%s): Deleted forwarding rule.", lbRefStr)
207-
}
208-
209-
if err := g.ensureTargetPoolAndHealthCheck(tpExists, tpNeedsRecreation, apiService, loadBalancerName, clusterID, ipAddressToUse, hosts, hcToCreate, hcToDelete); err != nil {
210-
return nil, err
211-
}
212-
213-
if tpNeedsRecreation || fwdRuleNeedsUpdate {
214-
klog.Infof("ensureExternalLoadBalancer(%s): Creating forwarding rule, IP %s (tier: %s).", lbRefStr, ipAddressToUse, netTier)
215-
if err := createForwardingRule(g, loadBalancerName, serviceName.String(), g.region, ipAddressToUse, g.targetPoolURL(loadBalancerName), ports, netTier, g.enableDiscretePortForwarding); err != nil {
216-
return nil, fmt.Errorf("failed to create forwarding rule for load balancer (%s): %v", lbRefStr, err)
217-
}
218-
isSafeToReleaseIP = true
219-
klog.Infof("ensureExternalLoadBalancer(%s): Created forwarding rule, IP %s.", lbRefStr, ipAddressToUse)
115+
groupedPorts := groupPortsByProtocol(ports)
116+
if !g.AlphaFeatureGate.Enabled(AlphaFeatureMultiProtocolLB) && len(groupedPorts) > 1 {
117+
var protocols []string
118+
for p := range groupedPorts {
119+
protocols = append(protocols, string(p))
220120
}
221-
222-
status := &v1.LoadBalancerStatus{}
223-
status.Ingress = []v1.LoadBalancerIngress{{IP: ipAddressToUse}}
224-
225-
return status, nil
121+
return nil, fmt.Errorf("load balancer with multiple protocols (%s) is not supported when AlphaFeatureMultiProtocolLB is disabled", strings.Join(protocols, ","))
226122
}
227123

228-
// Multi-protocol logic starts here
229-
groupedPorts := groupPortsByProtocol(ports)
230124
var fwdRuleIP string
231-
232125
// We need to determine the IP address for all forwarding rules.
233126
// We check if any of the forwarding rules already exist and use their IP.
234127
for protocol := range groupedPorts {
@@ -255,29 +148,8 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
255148

256149
// Make sure we know which IP address will be used and have properly reserved
257150
// it as static before moving forward with the rest of our operations.
258-
//
259-
// We use static IP addresses when updating a load balancer to ensure that we
260-
// can replace the load balancer's other components without changing the
261-
// address its service is reachable on. We do it this way rather than always
262-
// keeping the static IP around even though this is more complicated because
263-
// it makes it less likely that we'll run into quota issues. Only 7 static
264-
// IP addresses are allowed per region by default.
265-
//
266-
// We could let an IP be allocated for us when the forwarding rule is created,
267-
// but we need the IP to set up the firewall rule, and we want to keep the
268-
// forwarding rule creation as the last thing that needs to be done in this
269-
// function in order to maintain the invariant that "if the forwarding rule
270-
// exists, the LB has been fully created".
271151
ipAddressToUse := ""
272-
273-
// Through this process we try to keep track of whether it is safe to
274-
// release the IP that was allocated. If the user specifically asked for
275-
// an IP, we assume they are managing it themselves. Otherwise, we will
276-
// release the IP in case of early-terminating failure or upon successful
277-
// creating of the LB.
278-
// TODO(#36535): boil this logic down into a set of component functions
279-
// and key the flag values off of errors returned.
280-
isUserOwnedIP := false // if this is set, we never release the IP
152+
isUserOwnedIP := false
281153
isSafeToReleaseIP := false
282154

283155
defer func() {
@@ -419,9 +291,14 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
419291

420292
// Then, iterate over the protocols and create/update forwarding rules.
421293
for protocol, protocolPorts := range groupedPorts {
422-
frName := g.getProtocolForwardingRuleName(loadBalancerName, protocol)
423-
// If the old forwarding rule matches this protocol, use its name.
424-
if fwd != nil && fwd.IPProtocol == string(protocol) {
294+
var frName string
295+
if g.AlphaFeatureGate.Enabled(AlphaFeatureMultiProtocolLB) {
296+
frName = g.getProtocolForwardingRuleName(loadBalancerName, protocol)
297+
// If the old forwarding rule matches this protocol, use its name.
298+
if fwd != nil && fwd.IPProtocol == string(protocol) {
299+
frName = loadBalancerName
300+
}
301+
} else {
425302
frName = loadBalancerName
426303
}
427304

@@ -430,7 +307,7 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
430307
return nil, err
431308
}
432309

433-
if needsUpdate {
310+
if needsUpdate || tpNeedsRecreation {
434311
if exists {
435312
if err := g.DeleteRegionForwardingRule(frName, g.region); err != nil && !isNotFound(err) {
436313
return nil, err
@@ -445,31 +322,33 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
445322
}
446323

447324
// Garbage collect old forwarding rules.
448-
activeFRNames := sets.NewString()
449-
for protocol := range groupedPorts {
450-
activeFRNames.Insert(g.getProtocolForwardingRuleName(loadBalancerName, protocol))
451-
}
452-
// Check for the old forwarding rule name.
453-
if fwd != nil {
454-
protocol, err := getProtocol(fwd.IPProtocol)
455-
if err != nil {
456-
return nil, err
325+
if g.AlphaFeatureGate.Enabled(AlphaFeatureMultiProtocolLB) {
326+
activeFRNames := sets.NewString()
327+
for protocol := range groupedPorts {
328+
activeFRNames.Insert(g.getProtocolForwardingRuleName(loadBalancerName, protocol))
457329
}
458-
if _, ok := groupedPorts[protocol]; ok {
459-
activeFRNames.Insert(loadBalancerName)
330+
// Check for the old forwarding rule name.
331+
if fwd != nil {
332+
protocol, err := getProtocol(fwd.IPProtocol)
333+
if err != nil {
334+
return nil, err
335+
}
336+
if _, ok := groupedPorts[protocol]; ok {
337+
activeFRNames.Insert(loadBalancerName)
338+
}
460339
}
461-
}
462340

463-
// List all forwarding rules for this service and delete the ones that are not active.
464-
frs, err := g.ListRegionForwardingRules(g.region)
465-
if err != nil {
466-
return nil, err
467-
}
468-
for _, fr := range frs {
469-
if strings.HasPrefix(fr.Name, loadBalancerName) && !activeFRNames.Has(fr.Name) {
470-
klog.Infof("ensureExternalLoadBalancer(%s): Deleting orphaned forwarding rule %s.", lbRefStr, fr.Name)
471-
if err := g.DeleteRegionForwardingRule(fr.Name, g.region); err != nil && !isNotFound(err) {
472-
return nil, err
341+
// List all forwarding rules for this service and delete the ones that are not active.
342+
frs, err := g.ListRegionForwardingRules(g.region)
343+
if err != nil {
344+
return nil, err
345+
}
346+
for _, fr := range frs {
347+
if strings.HasPrefix(fr.Name, loadBalancerName) && !activeFRNames.Has(fr.Name) {
348+
klog.Infof("ensureExternalLoadBalancer(%s): Deleting orphaned forwarding rule %s.", lbRefStr, fr.Name)
349+
if err := g.DeleteRegionForwardingRule(fr.Name, g.region); err != nil && !isNotFound(err) {
350+
return nil, err
351+
}
473352
}
474353
}
475354
}
@@ -481,41 +360,6 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
481360
return status, nil
482361
}
483362

484-
func (g *Cloud) ensureIPAddress(loadBalancerName, lbRefStr, requestedIP, fwdRuleIP string, netTier cloud.NetworkTier) (ipAddress string, isSafeToReleaseIP bool, err error) {
485-
// Make sure we know which IP address will be used and have properly reserved
486-
// it as static before moving forward with the rest of our operations.
487-
ipAddressToUse := ""
488-
isUserOwnedIP := false
489-
490-
if requestedIP != "" {
491-
// If user requests a specific IP address, verify first. No mutation to
492-
// the GCE resources will be performed in the verification process.
493-
isUserOwnedIP, err = verifyUserRequestedIP(g, g.region, requestedIP, fwdRuleIP, lbRefStr, netTier)
494-
if err != nil {
495-
return "", false, err
496-
}
497-
ipAddressToUse = requestedIP
498-
}
499-
500-
if !isUserOwnedIP {
501-
// If we are not using the user-owned IP, either promote the
502-
// emphemeral IP used by the fwd rule, or create a new static IP.
503-
ipAddr, existed, err := ensureStaticIP(g, loadBalancerName, lbRefStr, g.region, fwdRuleIP, netTier)
504-
if err != nil {
505-
return "", false, fmt.Errorf("failed to ensure a static IP for load balancer (%s): %v", lbRefStr, err)
506-
}
507-
klog.Infof("ensureExternalLoadBalancer(%s): Ensured IP address %s (tier: %s).", lbRefStr, ipAddr, netTier)
508-
// If the IP was not owned by the user, but it already existed, it
509-
// could indicate that the previous update cycle failed. We can use
510-
// this IP and try to run through the process again, but we should
511-
// not release the IP unless it is explicitly flagged as OK.
512-
isSafeToReleaseIP = !existed
513-
ipAddressToUse = ipAddr
514-
}
515-
516-
return ipAddressToUse, isSafeToReleaseIP, nil
517-
}
518-
519363

520364
// updateExternalLoadBalancer is the external implementation of LoadBalancer.UpdateLoadBalancer.
521365
func (g *Cloud) updateExternalLoadBalancer(clusterName string, service *v1.Service, nodes []*v1.Node) error {

0 commit comments

Comments
 (0)