@@ -35,6 +35,9 @@ const (
35
35
DefaultConnectionDrainingTimeoutSeconds = 30
36
36
defaultTrackingMode = "PER_CONNECTION"
37
37
PerSessionTrackingMode = "PER_SESSION" // the only one supported with strong session affinity
38
+ DefaultZonalAffinitySpillover = "ZONAL_AFFINITY_SPILL_CROSS_ZONE"
39
+ DefaultZonalAffinitySpilloverRatio = 0
40
+ ZonalAffinityDisabledSpillover = "ZONAL_AFFINITY_DISABLED"
38
41
)
39
42
40
43
// LocalityLBPolicyType is the type of locality lb policy the backend service should use.
@@ -90,6 +93,31 @@ type L4BackendServiceParams struct {
90
93
NetworkInfo * network.NetworkInfo
91
94
ConnectionTrackingPolicy * composite.BackendServiceConnectionTrackingPolicy
92
95
LocalityLbPolicy LocalityLBPolicyType
96
+ EnableZonalAffinity bool
97
+ }
98
+
99
+ var versionPrecedence = map [meta.Version ]int {
100
+ meta .VersionAlpha : 2 ,
101
+ meta .VersionBeta : 1 ,
102
+ meta .VersionGA : 0 ,
103
+ }
104
+
105
+ // maxVersion returns the higher version based on precedence.
106
+ func maxVersion (a , b meta.Version ) meta.Version {
107
+ precedenceA , okA := versionPrecedence [a ]
108
+ if ! okA {
109
+ precedenceA = 0 // Use VersionGA precedence if invalid.
110
+ }
111
+
112
+ precedenceB , okB := versionPrecedence [b ]
113
+ if ! okB {
114
+ precedenceB = 0 // Use VersionGA precedence if invalid.
115
+ }
116
+
117
+ if precedenceA > precedenceB {
118
+ return a
119
+ }
120
+ return b
93
121
}
94
122
95
123
// ensureDescription updates the BackendService Description with the expected value
@@ -327,6 +355,14 @@ func (p *Pool) DeleteSignedURLKey(be *composite.BackendService, keyName string,
327
355
return nil
328
356
}
329
357
358
+ // minRequiredVersion to create a backend service with the given params
359
+ func minRequiredVersion (params L4BackendServiceParams ) meta.Version {
360
+ if params .EnableZonalAffinity {
361
+ return meta .VersionAlpha
362
+ }
363
+ return meta .VersionGA
364
+ }
365
+
330
366
// EnsureL4BackendService creates or updates the backend service with the given name.
331
367
func (p * Pool ) EnsureL4BackendService (params L4BackendServiceParams , beLogger klog.Logger ) (* composite.BackendService , utils.ResourceSyncStatus , error ) {
332
368
start := time .Now ()
@@ -342,25 +378,34 @@ func (p *Pool) EnsureL4BackendService(params L4BackendServiceParams, beLogger kl
342
378
if err != nil {
343
379
return nil , utils .ResourceResync , err
344
380
}
381
+
345
382
currentBS , err := composite .GetBackendService (p .cloud , key , meta .VersionGA , beLogger )
346
383
if err != nil && ! utils .IsNotFoundError (err ) {
347
384
return nil , utils .ResourceResync , err
348
385
}
349
- desc , err := utils .MakeL4LBServiceDescription (params .NamespacedName .String (), "" , meta .VersionGA , false , utils .ILB )
386
+
387
+ expectedVersion := minRequiredVersion (params )
388
+ expectedDesc , err := utils .MakeL4LBServiceDescription (params .NamespacedName .String (), "" , expectedVersion , false , utils .ILB )
350
389
if err != nil {
351
390
beLogger .Info ("EnsureL4BackendService: Failed to generate description for BackendService" , "err" , err )
352
391
}
353
392
354
393
expectedBS := & composite.BackendService {
355
394
Name : params .Name ,
356
395
Protocol : params .Protocol ,
357
- Description : desc ,
396
+ Version : expectedVersion ,
397
+ Description : expectedDesc ,
358
398
HealthChecks : []string {params .HealthCheckLink },
359
399
SessionAffinity : utils .TranslateAffinityType (params .SessionAffinity , beLogger ),
360
400
LoadBalancingScheme : params .Scheme ,
361
401
LocalityLbPolicy : string (params .LocalityLbPolicy ),
362
402
}
363
403
404
+ if params .EnableZonalAffinity {
405
+ beLogger .V (2 ).Info ("EnsureL4BackendService: using Zonal Affinity" , "spillover" , DefaultZonalAffinitySpillover , "spilloverRatio" , DefaultZonalAffinitySpilloverRatio )
406
+ expectedBS .NetworkPassThroughLbTrafficPolicy = defaultZonalAffinityTrafficPolicy ()
407
+ }
408
+
364
409
// We need this configuration only for Strong Session Affinity feature
365
410
if p .useConnectionTrackingPolicy {
366
411
beLogger .V (2 ).Info (fmt .Sprintf ("EnsureL4BackendService: using connection tracking policy: %+v" , params .ConnectionTrackingPolicy ))
@@ -388,7 +433,7 @@ func (p *Pool) EnsureL4BackendService(params L4BackendServiceParams, beLogger kl
388
433
// We need to perform a GCE call to re-fetch the object we just created
389
434
// so that the "Fingerprint" field is filled in. This is needed to update the
390
435
// object without error. The lookup is also needed to populate the selfLink.
391
- createdBS , err := composite .GetBackendService (p .cloud , key , meta . VersionGA , beLogger )
436
+ createdBS , err := composite .GetBackendService (p .cloud , key , expectedBS . Version , beLogger )
392
437
return createdBS , utils .ResourceUpdate , err
393
438
} else {
394
439
// TODO(FelipeYepez) remove this check once LocalityLBPolicyMaglev does not require allow lisiting
@@ -398,6 +443,17 @@ func (p *Pool) EnsureL4BackendService(params L4BackendServiceParams, beLogger kl
398
443
399
444
expectedBS .LocalityLbPolicy = string (LocalityLBPolicyMaglev )
400
445
}
446
+
447
+ // Use the version with most priority if the BackendService was already using one
448
+ currentVersion := meta .VersionGA
449
+ var currentDesc utils.L4LBResourceDescription
450
+ err = currentDesc .Unmarshal (currentBS .Description )
451
+ if err != nil {
452
+ beLogger .V (0 ).Error (err , "EnsureL4BackendService: error unmarshaling backend service description" )
453
+ } else {
454
+ currentVersion = currentDesc .APIVersion
455
+ }
456
+ expectedBS .Version = maxVersion (currentVersion , expectedBS .Version )
401
457
}
402
458
403
459
if backendSvcEqual (expectedBS , currentBS , p .useConnectionTrackingPolicy ) {
@@ -418,7 +474,7 @@ func (p *Pool) EnsureL4BackendService(params L4BackendServiceParams, beLogger kl
418
474
}
419
475
beLogger .V (2 ).Info ("EnsureL4BackendService: updated backend service successfully" )
420
476
421
- updatedBS , err := composite .GetBackendService (p .cloud , key , meta . VersionGA , beLogger )
477
+ updatedBS , err := composite .GetBackendService (p .cloud , key , expectedBS . Version , beLogger )
422
478
return updatedBS , utils .ResourceUpdate , err
423
479
}
424
480
@@ -447,9 +503,34 @@ func backendSvcEqual(newBS, oldBS *composite.BackendService, compareConnectionTr
447
503
(newBS .LocalityLbPolicy == string (LocalityLBPolicyDefault ) && oldBS .LocalityLbPolicy == string (LocalityLBPolicyMaglev )) ||
448
504
(newBS .LocalityLbPolicy == string (LocalityLBPolicyMaglev ) && oldBS .LocalityLbPolicy == string (LocalityLBPolicyDefault )))
449
505
506
+ // If zonal affinity is set, needs to be equal
507
+ svcsEqual = svcsEqual && zonalAffinityEqual (newBS , oldBS )
450
508
return svcsEqual
451
509
}
452
510
511
+ func convertNetworkLbTrafficPolicyToZonalAffinity (trafficPolicy * composite.BackendServiceNetworkPassThroughLbTrafficPolicy ) composite.BackendServiceNetworkPassThroughLbTrafficPolicyZonalAffinity {
512
+ if trafficPolicy == nil || trafficPolicy .ZonalAffinity == nil {
513
+ return composite.BackendServiceNetworkPassThroughLbTrafficPolicyZonalAffinity {
514
+ Spillover : ZonalAffinityDisabledSpillover ,
515
+ SpilloverRatio : 0 ,
516
+ }
517
+ }
518
+
519
+ return * trafficPolicy .ZonalAffinity
520
+ }
521
+
522
+ func zonalAffinityEqual (a , b * composite.BackendService ) bool {
523
+ aZonalAffinity := convertNetworkLbTrafficPolicyToZonalAffinity (a .NetworkPassThroughLbTrafficPolicy )
524
+ bZonalAffinity := convertNetworkLbTrafficPolicyToZonalAffinity (b .NetworkPassThroughLbTrafficPolicy )
525
+
526
+ // Compare Spillover values
527
+ spilloverEqual := aZonalAffinity .Spillover == bZonalAffinity .Spillover
528
+ // Compare SpilloverRatio values
529
+ spilloverRatioEqual := aZonalAffinity .SpilloverRatio == bZonalAffinity .SpilloverRatio
530
+
531
+ return spilloverEqual && spilloverRatioEqual
532
+ }
533
+
453
534
// connectionTrackingPolicyEqual returns true if both elements are equal
454
535
// and return false if at least one parameter is different
455
536
func connectionTrackingPolicyEqual (a , b * composite.BackendServiceConnectionTrackingPolicy ) bool {
@@ -460,3 +541,12 @@ func connectionTrackingPolicyEqual(a, b *composite.BackendServiceConnectionTrack
460
541
a .EnableStrongAffinity == b .EnableStrongAffinity &&
461
542
a .IdleTimeoutSec == b .IdleTimeoutSec
462
543
}
544
+
545
+ func defaultZonalAffinityTrafficPolicy () * composite.BackendServiceNetworkPassThroughLbTrafficPolicy {
546
+ return & composite.BackendServiceNetworkPassThroughLbTrafficPolicy {
547
+ ZonalAffinity : & composite.BackendServiceNetworkPassThroughLbTrafficPolicyZonalAffinity {
548
+ Spillover : DefaultZonalAffinitySpillover ,
549
+ SpilloverRatio : DefaultZonalAffinitySpilloverRatio ,
550
+ },
551
+ }
552
+ }
0 commit comments