@@ -29,7 +29,6 @@ import (
29
29
30
30
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud"
31
31
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
32
- "github.com/google/go-cmp/cmp"
33
32
compute "google.golang.org/api/compute/v1"
34
33
v1 "k8s.io/api/core/v1"
35
34
"k8s.io/apimachinery/pkg/types"
@@ -188,121 +187,109 @@ func (g *Cloud) ensureInternalLoadBalancer(clusterName, clusterID string, svc *v
188
187
189
188
// Get all existing forwarding rules for this service.
190
189
// A service can have a forwarding rule with the base name, or with a protocol suffix.
191
- existingFwdRules := make (map [string ]* compute.ForwardingRule )
192
- // The `existingFwdRule` is the one with the base name, passed into this function.
193
- if existingFwdRule != nil {
194
- existingFwdRules [existingFwdRule .Name ] = existingFwdRule
195
- }
190
+ // TODO: Remove existingFwdRules and use the one from the function.
196
191
// Check for forwarding rules with protocol suffixes.
197
- if len (groupedPorts ) > 1 {
198
- for protocol := range groupedPorts {
199
- frName := fmt .Sprintf ("%s-%s" , loadBalancerName , strings .ToLower (string (protocol )))
200
- if _ , ok := existingFwdRules [frName ]; ok {
201
- continue
202
- }
203
- fr , err := g .GetRegionForwardingRule (frName , g .region )
204
- if err != nil && ! isNotFound (err ) {
205
- return nil , err
206
- }
207
- if fr != nil {
208
- existingFwdRules [fr .Name ] = fr
209
- }
210
- }
211
- }
192
+ op := & ensureOperation {}
193
+ g .findActualBackendServiceInternal (backendServiceName , op )
212
194
213
- desiredFwdRuleNames := sets .NewString ()
214
- var desiredFwdRuleProtocols []v1.Protocol
215
- for protocol := range groupedPorts {
216
- desiredFwdRuleProtocols = append (desiredFwdRuleProtocols , protocol )
195
+ existingForwardingRules , err := g .getExistingForwardingRules (loadBalancerName )
196
+ if err != nil {
197
+ return nil , err
217
198
}
218
- // Sort protocols to have a stable order for naming and processing.
219
- sort .Slice (desiredFwdRuleProtocols , func (i , j int ) bool {
220
- return desiredFwdRuleProtocols [i ] < desiredFwdRuleProtocols [j ]
221
- })
199
+ op .forwardingRulesActual = existingForwardingRules
222
200
223
201
var createdFwdRules []* compute.ForwardingRule
224
- var desiredBackendServices = make (map [string ]bool )
225
-
226
- for _ , protocol := range desiredFwdRuleProtocols {
227
- portStruct := groupedPorts [protocol ]
228
- ports := portStruct .portRanges
229
-
230
- // Each protocol gets its own backend service.
231
- // The backend service name must be unique per protocol.
232
- // Pass a single-protocol map to makeBackendServiceName.
233
- singleProtocolGroupedPorts := map [v1.Protocol ]ProtocolPorts {protocol : portStruct }
234
- backendServiceName := makeBackendServiceName (loadBalancerName , clusterID , sharedBackend , scheme , singleProtocolGroupedPorts , svc .Spec .SessionAffinity )
235
- desiredBackendServices [backendServiceName ] = true
236
- backendServiceLink := g .getBackendServiceLink (backendServiceName )
237
-
238
- bsDescription := makeBackendServiceDescription (nm , sharedBackend )
239
- err = g .ensureInternalBackendService (backendServiceName , bsDescription , svc .Spec .SessionAffinity , scheme , protocol , igLinks , hc .SelfLink )
240
- if err != nil {
241
- return nil , err
242
- }
243
202
203
+ var desiredForwardingRules []* compute.ForwardingRule
204
+ for protocol , protocolPorts := range groupedPorts {
244
205
// Each protocol gets its own forwarding rule.
245
206
// If there's only one protocol, the forwarding rule name is the load balancer name.
246
207
// Otherwise, it's load-balancer-name-<protocol>.
247
208
frName := loadBalancerName
248
209
if len (groupedPorts ) > 1 {
249
210
frName = fmt .Sprintf ("%s-%s" , loadBalancerName , strings .ToLower (string (protocol )))
250
211
}
251
- desiredFwdRuleNames .Insert (frName )
252
212
253
- newFwdRule := & compute.ForwardingRule {
213
+ forwardingRule := & compute.ForwardingRule {
254
214
Name : frName ,
255
215
Description : fwdRuleDescriptionString ,
256
216
IPAddress : ipToUse ,
257
217
BackendService : backendServiceLink ,
258
- Ports : ports ,
259
218
IPProtocol : string (protocol ),
260
219
LoadBalancingScheme : string (scheme ),
261
220
Subnetwork : subnetworkURL ,
262
221
Network : g .networkURL ,
263
222
}
264
223
if options .AllowGlobalAccess {
265
- newFwdRule .AllowGlobalAccess = options .AllowGlobalAccess
224
+ forwardingRule .AllowGlobalAccess = options .AllowGlobalAccess
225
+ }
226
+ if len (protocolPorts .ports ) > maxL4ILBPorts {
227
+ forwardingRule .Ports = nil
228
+ forwardingRule .AllPorts = true
229
+ } else {
230
+ for _ , port := range protocolPorts .ports {
231
+ forwardingRule .Ports = append (forwardingRule .Ports , strconv .Itoa (port ))
232
+ }
266
233
}
267
- if len (ports ) > maxL4ILBPorts {
268
- newFwdRule .Ports = nil
269
- newFwdRule .AllPorts = true
234
+
235
+ // Check if a forwarding rule for this protocol already exists; reuse the same name if possible.
236
+ for _ , existingFwdRule := range existingForwardingRules {
237
+ if existingFwdRule .IPProtocol == forwardingRule .IPProtocol {
238
+ forwardingRule .Name = existingFwdRule .Name
239
+ break
240
+ }
270
241
}
271
242
272
- // Check if a forwarding rule for this protocol already exists.
243
+ desiredForwardingRules = append (desiredForwardingRules , forwardingRule )
244
+ }
245
+ op .forwardingRulesDesired = desiredForwardingRules
246
+
247
+ bsDescription := makeBackendServiceDescription (nm , sharedBackend )
248
+ backendServiceProtocol := "UNSPECIFIED"
249
+ if len (desiredForwardingRules ) == 1 {
250
+ backendServiceProtocol = desiredForwardingRules [0 ].IPProtocol
251
+ }
252
+ g .buildDesiredBackendServiceInternal (backendServiceName , bsDescription , svc .Spec .SessionAffinity , scheme , backendServiceProtocol , igLinks , hc .SelfLink , op )
253
+
254
+ if err := g .ensureInternalBackendService (backendServiceName , op ); err != nil {
255
+ return nil , err
256
+ }
257
+
258
+ for _ , desiredForwardingRule := range desiredForwardingRules {
273
259
var existingFwdRuleForProtocol * compute.ForwardingRule
274
- if fr , ok := existingFwdRules [frName ]; ok {
275
- existingFwdRuleForProtocol = fr
260
+ for _ , existingFwdRule := range existingForwardingRules {
261
+ if existingFwdRule .IPProtocol == desiredForwardingRule .IPProtocol {
262
+ existingFwdRuleForProtocol = existingFwdRule
263
+ break
264
+ }
276
265
}
277
266
278
- if err := g .ensureInternalForwardingRule (existingFwdRuleForProtocol , newFwdRule ); err != nil {
267
+ if err := g .ensureInternalForwardingRule (existingFwdRuleForProtocol , desiredForwardingRule ); err != nil {
279
268
return nil , err
280
269
}
281
- createdFwdRules = append (createdFwdRules , newFwdRule )
270
+ createdFwdRules = append (createdFwdRules , desiredForwardingRule )
282
271
}
283
272
284
273
// Delete any forwarding rules that are no longer needed.
285
- for frName , fr := range existingFwdRules {
286
- if desiredFwdRuleNames .Has (frName ) {
274
+ for frName , fr := range existingForwardingRules {
275
+ var matching * compute.ForwardingRule
276
+ for _ , desiredForwardingRule := range desiredForwardingRules {
277
+ if desiredForwardingRule .Name == fr .Name {
278
+ matching = desiredForwardingRule
279
+ continue
280
+ }
281
+ }
282
+ if matching != nil {
287
283
continue
288
284
}
285
+
289
286
klog .V (2 ).Infof ("ensureInternalLoadBalancer(%v): deleting stale forwarding rule %s" , loadBalancerName , frName )
290
287
if err := ignoreNotFound (g .DeleteRegionForwardingRule (frName , g .region )); err != nil {
291
288
return nil , err
292
289
}
293
- // Also delete the associated backend service if it's not used by other forwarding rules.
294
- if fr .BackendService != "" {
295
- bsName := getNameFromLink (fr .BackendService )
296
- if ! desiredBackendServices [bsName ] {
297
- klog .V (2 ).Infof ("ensureInternalLoadBalancer(%v): deleting stale backend service %s" , loadBalancerName , bsName )
298
- if err := g .teardownInternalBackendService (bsName ); err != nil {
299
- klog .Warningf ("ensureInternalLoadBalancer: could not delete old backend service %s: %v" , bsName , err )
300
- }
301
- }
302
- }
303
290
}
304
291
305
- if len (createdFwdRules ) == 0 {
292
+ if len (desiredForwardingRules ) == 0 {
306
293
klog .V (2 ).Infof ("ensureInternalLoadBalancer(%v): no forwarding rules needed, all deleted." , loadBalancerName )
307
294
return & v1.LoadBalancerStatus {}, nil
308
295
}
@@ -881,43 +868,72 @@ func (g *Cloud) ensureInternalInstanceGroupsDeleted(name string) error {
881
868
return nil
882
869
}
883
870
884
- func ( g * Cloud ) ensureInternalBackendService ( name , description string , affinityType v1. ServiceAffinity , scheme cloud. LbScheme , protocol v1. Protocol , igLinks [] string , hcLink string ) error {
885
- klog . V ( 2 ). Infof ( "ensureInternalBackendService(%v, %v, %v): checking existing backend service with %d groups" , name , scheme , protocol , len ( igLinks ))
886
- bs , err := g . GetRegionBackendService ( name , g . region )
887
- if err != nil && ! isNotFound ( err ) {
888
- return err
889
- }
871
+ type ensureOperation struct {
872
+ backendServiceDesired * compute. BackendService
873
+ backendServiceActual * compute. BackendService
874
+ forwardingRulesDesired [] * compute. ForwardingRule
875
+ forwardingRulesActual map [ string ] * compute. ForwardingRule
876
+ }
890
877
878
+ func (g * Cloud ) buildDesiredBackendServiceInternal (name , description string , affinityType v1.ServiceAffinity , scheme cloud.LbScheme , protocol string , igLinks []string , hcLink string , op * ensureOperation ) error {
891
879
backends := backendsFromGroupLinks (igLinks )
892
- expectedBS := & compute.BackendService {
880
+ bs := & compute.BackendService {
893
881
Name : name ,
894
- Protocol : string ( protocol ) ,
882
+ Protocol : protocol ,
895
883
Description : description ,
896
884
HealthChecks : []string {hcLink },
897
885
Backends : backends ,
898
886
SessionAffinity : translateAffinityType (affinityType ),
899
887
LoadBalancingScheme : string (scheme ),
900
888
}
901
889
890
+ op .backendServiceDesired = bs
891
+ return nil
892
+ }
893
+
894
+ func (g * Cloud ) findActualBackendServiceInternal (name string , op * ensureOperation ) error {
895
+ klog .V (2 ).Infof ("findActualBackendServiceInternal(%v): checking existing backend services" , name )
896
+
897
+ bs , err := g .GetRegionBackendService (name , g .region )
898
+ if err != nil && ! isNotFound (err ) {
899
+ return err
900
+ }
901
+
902
+ op .backendServiceActual = bs
903
+ return nil
904
+ }
905
+
906
+ func (g * Cloud ) ensureInternalBackendService (name string , op * ensureOperation ) error {
902
907
// Create backend service if none was found
903
- if bs == nil {
908
+ if op . backendServiceActual == nil {
904
909
klog .V (2 ).Infof ("ensureInternalBackendService: creating backend service %v" , name )
905
- err := g .CreateRegionBackendService (expectedBS , g .region )
910
+ err := g .CreateRegionBackendService (op . backendServiceDesired , g .region )
906
911
if err != nil {
907
912
return err
908
913
}
909
914
klog .V (2 ).Infof ("ensureInternalBackendService: created backend service %v successfully" , name )
910
915
return nil
911
916
}
912
917
913
- if backendSvcEqual (expectedBS , bs ) {
918
+ if backendSvcEqual (op . backendServiceActual , op . backendServiceDesired ) {
914
919
return nil
915
920
}
916
921
922
+ // Delete existing forwarding rule before making changes to the backend service. For example - changing protocol
923
+ // of backend service without first deleting forwarding rule will throw an error since the linked forwarding
924
+ // rule would show the old protocol.
925
+ for _ , fr := range op .forwardingRulesActual {
926
+ klog .V (2 ).Infof ("ensureInternalBackendService: deleting forwarding rule %v" , fr .Name )
927
+ if err := g .DeleteRegionForwardingRule (fr .Name , g .region ); ignoreNotFound (err ) != nil {
928
+ return err
929
+ }
930
+ }
931
+ op .forwardingRulesActual = nil
932
+
917
933
klog .V (2 ).Infof ("ensureInternalBackendService: updating backend service %v" , name )
918
934
// Set fingerprint for optimistic locking
919
- expectedBS . Fingerprint = bs .Fingerprint
920
- if err := g .UpdateRegionBackendService (expectedBS , g .region ); err != nil {
935
+ op . backendServiceDesired . Fingerprint = op . backendServiceActual .Fingerprint
936
+ if err := g .UpdateRegionBackendService (op . backendServiceDesired , g .region ); err != nil {
921
937
return err
922
938
}
923
939
klog .V (2 ).Infof ("ensureInternalBackendService: updated backend service %v successfully" , name )
0 commit comments