@@ -36,6 +36,7 @@ import (
3636 "k8s.io/ingress-gce/pkg/backends"
3737 "k8s.io/ingress-gce/pkg/common/operator"
3838 "k8s.io/ingress-gce/pkg/context"
39+
3940 "k8s.io/ingress-gce/pkg/flags"
4041 "k8s.io/ingress-gce/pkg/forwardingrules"
4142 "k8s.io/ingress-gce/pkg/instancegroups"
@@ -58,6 +59,8 @@ const (
5859
5960 instanceGroupLink backendLinkType = 0
6061 negLink backendLinkType = 1
62+
63+ delayDurationForLegacyOwnershipPriority = 5 * time .Second // Configurable via flag if needed
6164)
6265
6366type backendLinkType int64
@@ -86,6 +89,7 @@ type L4NetLBController struct {
8689 serviceVersions * serviceVersionsTracker
8790 enableNEGSupport bool
8891 enableNEGAsDefault bool
92+ enableRBSDefault bool
8993
9094 hasSynced func () bool
9195
@@ -122,6 +126,7 @@ func NewL4NetLBController(
122126 serviceVersions : NewServiceVersionsTracker (),
123127 logger : logger ,
124128 hasSynced : ctx .HasSynced ,
129+ enableRBSDefault : ctx .EnableL4NetLBRBSByDefault ,
125130 }
126131 var networkLister cache.Indexer
127132 if ctx .NetworkInformer != nil {
@@ -359,6 +364,7 @@ func (lc *L4NetLBController) shouldProcessService(newSvc, oldSvc *v1.Service, sv
359364 warnL4FinalizerRemoved (lc .ctx , oldSvc , newSvc )
360365
361366 if ! lc .isRBSBasedService (newSvc , svcLogger ) && ! lc .isRBSBasedService (oldSvc , svcLogger ) {
367+ svcLogger .V (4 ).Info ("Ignoring non RBS based NetLB service" )
362368 return false , false
363369 }
364370 if lc .needsAddition (newSvc , oldSvc ) || lc .needsUpdate (newSvc , oldSvc ) || lc .needsDeletion (newSvc , svcLogger ) {
@@ -384,34 +390,95 @@ func (lc *L4NetLBController) isRBSBasedService(svc *v1.Service, svcLogger klog.L
384390 // Check if the type=LoadBalancer, so we don't execute API calls o non-LB services
385391 // this call is nil-safe
386392 if ! utils .IsLoadBalancerServiceType (svc ) {
393+ svcLogger .V (4 ).Info ("Service is not of type LoadBalancer" )
387394 return false
388395 }
389396 if svc .Spec .LoadBalancerClass != nil {
397+ svcLogger .V (4 ).Info ("Service has LoadBalancerClass annotation" , "loadBalancerClass" , * svc .Spec .LoadBalancerClass )
390398 return annotations .HasLoadBalancerClass (svc , annotations .RegionalExternalLoadBalancerClass )
391399 }
392- return annotations .HasRBSAnnotation (svc ) || utils .HasL4NetLBFinalizerV2 (svc ) || utils .HasL4NetLBFinalizerV3 (svc ) || lc .hasRBSForwardingRule (svc , svcLogger )
400+ if lc .enableRBSDefault {
401+ svcLogger .V (4 ).Info ("RBS is enabled by default, treating service as RBS based" )
402+ return true
403+ }
404+ if utils .HasL4NetLBFinalizerV2 (svc ) || utils .HasL4NetLBFinalizerV3 (svc ) {
405+ svcLogger .V (4 ).Info ("Service has L4 NetLB RBS finalizer" )
406+ return true
407+ }
408+ if annotations .HasRBSAnnotation (svc ) {
409+ svcLogger .V (4 ).Info ("Service has RBS annotation" )
410+ return true
411+ }
412+ if utils .HasL4NetLBFinalizerV1 (svc ) {
413+ svcLogger .V (4 ).Info ("Service has Legacy L4 NetLB finalizer" )
414+ return false
415+ }
416+ if lc .hasRBSForwardingRule (svc , svcLogger ) {
417+ svcLogger .V (4 ).Info ("Service has RBS forwarding rule" )
418+ return true
419+ }
420+ return false
421+ }
422+
423+ func (lc * L4NetLBController ) hasLegacyControllerOwnership (svc * v1.Service , svcLogger klog.Logger ) bool {
424+ // Check for legacy finalizer
425+ if utils .HasL4NetLBFinalizerV1 (svc ) {
426+ return true
427+ }
428+
429+ // Check if forwarding rule points to a target pool
430+ return lc .hasTargetPoolForwardingRule (svc , svcLogger )
431+ }
432+
433+ // refreshServiceFromK8s fetches the latest version of the service from Kubernetes
434+ // This is needed after adding a delay to ensure we have the most up-to-date version
435+ // which may include finalizers added by other controllers
436+ func (lc * L4NetLBController ) refreshServiceFromK8s (service * v1.Service , svcLogger klog.Logger ) * v1.Service {
437+ svcLogger .V (3 ).Info ("Refreshing service from Kubernetes" ,
438+ "currentResourceVersion" , service .ResourceVersion )
439+
440+ // Get the latest service from Kubernetes
441+ svcKey := utils .ServiceKeyFunc (service .Namespace , service .Name )
442+ refreshedService , exists , err := lc .ctx .Services ().GetByKey (svcKey )
443+ if err != nil {
444+ svcLogger .Info ("Could not get service from store, using existing one, error: " , err )
445+ } else if exists {
446+ service = refreshedService
447+ svcLogger .Info ("finalizer Found service in informer store after wait, using it." )
448+ } else {
449+ // Service might have been deleted during the wait, return to avoid processing a non-existing service.
450+ service = nil
451+ svcLogger .Info ("Service not found in informer store after wait, ignoring processing." )
452+ }
453+ return service
393454}
394455
395456func (lc * L4NetLBController ) preventLegacyServiceHandling (service * v1.Service , key string , svcLogger klog.Logger ) (bool , error ) {
396- if (annotations .HasRBSAnnotation (service ) || annotations .HasLoadBalancerClass (service , annotations .RegionalExternalLoadBalancerClass )) && lc .hasTargetPoolForwardingRule (service , svcLogger ) {
397- if utils .HasL4NetLBFinalizerV2 (service ) || utils .HasL4NetLBFinalizerV3 (service ) {
457+ svcLogger .Info ("Checking for legacy target pool service with RBS annotation or finalizers" , "finalizers" , service .ObjectMeta .Finalizers )
458+ if lc .hasLegacyControllerOwnership (service , svcLogger ) {
459+ if utils .HasL4NetLBRBSFinalizers (service ) {
398460 // If we found that RBS finalizer was attached to service, it means that RBS controller
399461 // had a race condition on Service creation with Legacy Controller.
400462 // It should only happen during service creation, and we should clean up RBS resources
463+ svcLogger .Info ("Detected Target Pool on RBS service with RBS finalizer. Cleaning up RBS resources to prevent race condition." , "finalizers" , service .ObjectMeta .Finalizers )
401464 return true , lc .preventTargetPoolRaceWithRBSOnCreation (service , key , svcLogger )
402- } else {
465+ } else if annotations . HasRBSAnnotation ( service ) {
403466 // Target Pool to RBS migration is NOT yet supported and causes service to break (for now).
404467 // If we detect RBS annotation on legacy service, we remove RBS annotation,
405468 // so service stays with Legacy Target Pool implementation
469+ svcLogger .Info ("Detected Target Pool on service with RBS annotation. Removing RBS annotation to prevent unsupported migration." , "finalizers" , service .ObjectMeta .Finalizers )
406470 return true , lc .preventExistingTargetPoolToRBSMigration (service , svcLogger )
407471 }
472+ svcLogger .Info ("Service is legacy Target Pool based service. No action needed." , "finalizers" , service .ObjectMeta .Finalizers )
473+ return true , nil
408474 }
409475 return false , nil
410476}
411477
412478func (lc * L4NetLBController ) hasTargetPoolForwardingRule (service * v1.Service , svcLogger klog.Logger ) bool {
413479 frName := utils .LegacyForwardingRuleName (service )
414480 if lc .hasForwardingRuleAnnotation (service , frName ) {
481+ svcLogger .V (4 ).Info ("Service does not have Target Pool forwarding rule annotation" , "forwardingRule" , frName )
415482 return false
416483 }
417484
@@ -421,8 +488,10 @@ func (lc *L4NetLBController) hasTargetPoolForwardingRule(service *v1.Service, sv
421488 return false
422489 }
423490 if existingFR != nil && existingFR .Target != "" {
491+ svcLogger .V (4 ).Info ("Service has Target Pool forwarding rule" , "forwardingRule" , frName , "targetPool" , strings .Split (existingFR .Target , "/" )[len (strings .Split (existingFR .Target , "/" ))- 1 ])
424492 return true
425493 }
494+ svcLogger .V (4 ).Info ("Service does not have Target Pool forwarding rule" , "forwardingRule" , frName )
426495 return false
427496}
428497
@@ -611,6 +680,12 @@ func (lc *L4NetLBController) syncInternal(service *v1.Service, svcLogger klog.Lo
611680 svcLogger .Info ("Finished syncing L4 NetLB RBS service" , "timeTaken" , time .Since (startTime ))
612681 }()
613682
683+ // Prevent race condition with legacy controller
684+ service = lc .handleCreationRace (service , svcLogger )
685+ if service == nil {
686+ return nil
687+ }
688+
614689 usesNegBackends := lc .shouldUseNEGBackends (service , svcLogger )
615690
616691 l4NetLBParams := & l4resources.L4NetLBParams {
@@ -976,3 +1051,36 @@ func (lc *L4NetLBController) publishSyncMetrics(result *l4resources.L4NetLBSyncR
9761051
9771052 metrics .PublishNetLBSyncMetrics (result .Error == nil , result .SyncType , result .GCEResourceInError , utils .GetErrorType (result .Error ), result .StartTime , isResync , isWeightedLB , result .MetricsState .Protocol , backendType )
9781053}
1054+
1055+ // handleCreationRace prevents a race condition between the legacy and new L4 NetLB controllers
1056+ // when a service is created, ensuring the L4 controller processes the most recent service
1057+ // state and avoids conflicting operations..
1058+ func (lc * L4NetLBController ) handleCreationRace (service * v1.Service , svcLogger klog.Logger ) * v1.Service {
1059+ l4NetLBLegacyHeadStartTime := flags .F .L4NetLBLegacyHeadStartTime
1060+ hasL4NetLBRBSFinalizers := utils .HasL4NetLBRBSFinalizers (service )
1061+ hasLegacyL4NetLBFinalizerV1 := utils .HasL4NetLBFinalizerV1 (service )
1062+
1063+ if ! hasLegacyL4NetLBFinalizerV1 && ! hasL4NetLBRBSFinalizers && l4NetLBLegacyHeadStartTime > 0 * time .Second {
1064+ // Add a delay to allow legacy controller to potentially claim the service first
1065+ svcLogger .Info ("Service does not have RBS finalizer yet and RBS is default. Adding delay to allow legacy controller to act first" ,
1066+ "delay" , delayDurationForLegacyOwnershipPriority )
1067+ time .Sleep (delayDurationForLegacyOwnershipPriority )
1068+
1069+ // Refresh the service from Kubernetes to get the latest version
1070+ // This is critical because the legacy controller may have added its finalizer (NetLBFinalizerV1)
1071+ // during the delay period
1072+ refreshedService := lc .refreshServiceFromK8s (service , svcLogger )
1073+
1074+ // Use the refreshed service for the rest of the sync
1075+ service = refreshedService
1076+
1077+ // Also check explicitly for legacy ownership to be extra safe
1078+ if lc .hasLegacyControllerOwnership (service , svcLogger ) {
1079+ svcLogger .Info ("After delay and refresh, detected legacy controller ownership. Skipping RBS sync." )
1080+ return nil
1081+ }
1082+
1083+ svcLogger .Info ("After delay and refresh, proceeding with RBS sync" , "resourceVersion" , service .ResourceVersion )
1084+ }
1085+ return service
1086+ }
0 commit comments