@@ -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.
521365func (g * Cloud ) updateExternalLoadBalancer (clusterName string , service * v1.Service , nodes []* v1.Node ) error {
0 commit comments