-
Notifications
You must be signed in to change notification settings - Fork 301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a controller for handling L4 Internal LoadBalancer services #991
Conversation
pkg/controller/service_controller.go
Outdated
} | ||
|
||
func (l4c *L4Controller) processServiceDeletion(key string, svc *v1.Service) error { | ||
nm, err := utils.ToNamespacedName(key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this as nm.Namespace and svc.Namespace are same?.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
method can be update to
func (l4c *L4Controller) processServiceDeletion(svc *v1.Service) error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had added this because svc could be nil. But then I modified the main sync() to handle nil services. I am keeping the 'key' parameter to lookup the L4Handler.
pkg/utils/utils_test.go
Outdated
{Desc: "Empty", Input: []int{}, Result: nil}, | ||
} { | ||
result := GetPortRanges(tc.Input) | ||
if !reflect.DeepEqual(result, tc.Result) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following implementation is much easier to debug test failures:
Refer: https://godoc.org/github.com/google/go-cmp/cmp#Diff
if diff := cmp.Diff(tc.Result, result); diff != "" {
t.Errorf("GetPortRanges(%s) mismatch (-want +got):\n%s", tc.Desc, diff)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice.. fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some drive-by comments. Will look more later:)
Will work on rebasign and ping back for review. Thanks for the comments so far! |
bc46338
to
44fdbb5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. small nits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some structural suggestions.
pkg/controller/service_controller.go
Outdated
@@ -0,0 +1,384 @@ | |||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe put this service controller
into a separate pkg/l4
package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/controller/service_controller.go
Outdated
} | ||
updated := current.DeepCopy() | ||
updated.Status.LoadBalancer = *newStatus | ||
if _, err := svcClient.UpdateStatus(updated); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a patch util in ingress-gce
https://github.com/kubernetes/ingress-gce/blob/master/pkg/utils/patch.go#L32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
// getForwardingRule with the given name | ||
// rule with the given name exists with the correct parameters and creates a forwarding rule if | ||
// it does not exist already. If shouldExist parameter is true, this function returns if forwarding rule is not found. | ||
func (l *L4) ensureForwardingRule(loadBalancerName, bsLink string, options gce.ILBOptions) (*composite.ForwardingRule, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably worth putting protocol in the forwarding rule name.
This is to leave future room to enable dual-protocol ILB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
/retest |
aaa50b1
to
734e3d5
Compare
cmd/glbc/main.go
Outdated
@@ -218,6 +219,12 @@ func runControllers(ctx *ingctx.ControllerContext) { | |||
|
|||
fwc := firewalls.NewFirewallController(ctx, flags.F.NodePortRanges.Values()) | |||
|
|||
if flags.F.RunL4Controller { | |||
l4Controller := l4controller.NewL4Controller(ctx, stopCh) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: l4controller.NewL4Controller seems a bit redundant.
I would recommend naming package to l4
. I would imagine this package to grow significantly over time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/l4controller/l4controller.go
Outdated
|
||
l4c.handlerMap = make(map[string]*loadbalancers.L4) | ||
l4c.svcQueue = utils.NewPeriodicTaskQueue("l4", "services", l4c.sync) | ||
ctx.ServiceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the event handling here may be problematic. Consider this case:
The controller is down. Service with ILB is added. Then controller starts back up. Then the event will come in as Update instead of Add. (Please verify!) Then Update will get ignored because it does not have the finalizer.
I think the most conservative handling is to have Add/Update to be handled consistently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed in person. The exact case mentioned here will actually show up as an Add instead of Update upon controller restart. However, the logic here does not handle cases where a non-ILB service was updated to use ILB, as Minhan pointed out. Fixed this logic and added a test. Thanks!
pkg/l4controller/l4controller.go
Outdated
} else { | ||
oldSvc := old.(*v1.Service) | ||
svcKey := utils.ServiceKeyFunc(curSvc.Namespace, curSvc.Name) | ||
if l4c.needsUpdate(curSvc, oldSvc) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if this is needed.
needsUpdate or not. It may be worth reasserting the LB config?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can filter service by if it has 1. finalizer V2 or 2. if it wants ILB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, reworked this logic.
I included needsUpdate so we can avoid processing an update every time a finalizer is added/neg annotation is added/ status field is updated.
pkg/l4controller/l4controller.go
Outdated
l4c.svcQueue.Shutdown() | ||
} | ||
|
||
func (l4c *L4Controller) getL4Handler(svcKey string, service *v1.Service) *loadbalancers.L4 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need to cache L4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No strong reason. Mainly to avoid creating it over and over for the same service. I thought I could store references to already created resources in it, in future. Removed now, we can add it id the need arises.
pkg/l4controller/l4controller.go
Outdated
needsILB, svcType := annotations.WantsL4ILB(svc) | ||
if !needsILB { | ||
klog.V(2).Infof("Service %s of type %s does not require L4 ILB, cleaning up resources", key, svcType) | ||
return l4c.processServiceDeletion(key, svc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
I recommend merging the deletion condition handling into one function needsDeletion
`
func needToDeleteILB(....) bool {
must have ILBFinalizerV2
AND (has deletion timestamp OR is not type ILB)
to return true
}
`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea, done.
pkg/l4controller/l4controller.go
Outdated
} | ||
// Use the same function for both create and updates. If controller crashes and restarts, | ||
// all existing services will show up as Service Adds. | ||
status, err := l4.EnsureInternalLoadBalancer(nodeNames, service) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i see a bunch of SyncLoadBalancerFailed
events. But no success event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
return composite.DeleteHealthCheck(cloud, key, meta.VersionGA) | ||
} | ||
|
||
func HealthCheckName(shared bool, clusteruid, lbName string) (string, string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add comment on the naming? For instance, why there is 2 firewall names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
return nil | ||
} | ||
err = deleteFunc(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this the correct name
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment why needs to delete 2 firewalls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
/assign @freehan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be a follow up. Remember to collect usage metrics for primary_VM_IP NEG. https://github.com/kubernetes/ingress-gce/blob/master/pkg/metrics/features.go#L78
/lgtm
/approve
@@ -178,6 +178,10 @@ func (s *backendSyncer) GC(svcPorts []utils.ServicePort) error { | |||
// gc deletes the provided backends | |||
func (s *backendSyncer) gc(backends []*composite.BackendService, knownPorts sets.String) error { | |||
for _, be := range backends { | |||
// Skip L4 LB backend services |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment:
backendSyncer currently only GC backend services for L7 XLB/ILB.
L4 LB is GC as part of the deletion follow as there is no shared backend services among L4 ILBs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
translator imports loadbalancer which imports firewalls, which again depends on translator. Removed the translator -> loadbalancer dependency.
Fixes including adding CustomSubnet support and self links for backend service, healthcheck. Removed the operation from queue key Added connectiondraining to backend service. Added a new flag to run L4 controller. Used namer.PrimaryIPNEG() instead of namer.NEG() Use a common description for all ILB resources. Added locking for shared healthchecks. Only process relevant updates in l4 controller Renamed files, used patch instead of update. unit tests for L4 ILB Most of the tests in l4_test.go are from gce_loadbalancer_internal_test.go
Good point, we need to add usage metrics for this L4 controller as well. Will cover PRIMARY_VM_IP NEG as part of that too. Thanks! |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: freehan, prameshj The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This change adds a controller that will create the GCE resources(Forwarding rule, firewall rules, healthcheck, backend services) for Internal LoadBalancer services. The NEG creation will be done in the NEG controller and those changes are in PR - #959
Most of the code is similar to the service controller code in k/k.
@skmatti
/assign @MrHohn @freehan