-
Notifications
You must be signed in to change notification settings - Fork 1k
Enable a frr-k8s based bgp backend #2162
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
Conversation
Those might be required also by the frrk8s implementation. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
d5dc257 to
8b6d342
Compare
internal/bgp/frrk8s/frrk8s.go
Outdated
| metallbNamespace string | ||
| currentNode 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.
nit: these could be just namespace, node
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'll change them to what they mean: targetNamespace and nodeToConfigure or something along that line
wdyt?
internal/bgp/frrk8s/frrk8s.go
Outdated
| toAdd := frrv1beta1.BFDProfile{ | ||
| Name: bfd.Name, | ||
| } | ||
| if bfd.ReceiveInterval != 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.
do the ifs here do something?
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.
they prevent the speaker from panicking if the value is 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.
maybe I'm missing something but how when both are pointers (toAdd.x and bfd.x)?
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.
ah dang you are right!
| newConfig.Spec.BGP.Routers = append(newConfig.Spec.BGP.Routers, toAdd) | ||
| } | ||
|
|
||
| for _, bfd := range sm.bfdProfiles { |
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: can you leave a short comment that sm.BfdProfiles is already sorted?
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'll move the sorting here, I think it makes more sense
internal/bgp/frrk8s/frrk8s.go
Outdated
| } | ||
| neighbor.ToAdvertise.PrefixesWithCommunity = toAdvertiseWithCommunity(prefixesForCommunity) | ||
| neighbor.ToAdvertise.PrefixesWithLocalPref = toAdvertiseWithLocalPref(prefixesForLocalPref) | ||
| sort.Slice(neighbor.ToAdvertise.Allowed.Prefixes, func(i, j int) bool { |
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: use sort.Strings
internal/bgp/frrk8s/frrk8s.go
Outdated
| res = append(res, frrv1beta1.CommunityPrefixes{Community: c, Prefixes: prefixes}) | ||
| } | ||
| sort.Slice(res, func(i, j int) bool { | ||
| return res[i].Community > res[j].Community |
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 < j for increasing order
internal/k8s/k8s.go
Outdated
| } | ||
| if err := frrk8sController.SetupWithManager(mgr); err != nil { | ||
| level.Error(c.logger).Log("error", err, "unable to create controller", "node") | ||
| fmt.Println("FEDE 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.
😄
internal/k8s/k8s.go
Outdated
| Reload: make(chan event.GenericEvent), | ||
| } | ||
| if err := frrk8sController.SetupWithManager(mgr); err != nil { | ||
| level.Error(c.logger).Log("error", err, "unable to create controller", "node") |
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: "node" -> "frr-k8s"
| apiVersion: kustomize.config.k8s.io/v1beta1 | ||
| kind: Kustomization | ||
| resources: | ||
| - https://github.com/metallb/frr-k8s/config/default/?timeout=120&ref=main |
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.
we should remember setting this to != main before merging this
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.
we'll have to do a tag first
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 necessary?
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, but adapted the type. We need it because the controller serves as webhook endpoint and it must know what needs to validate.
config/frr-k8s/frr-cm.yaml
Outdated
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.
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.
removed
657d8af to
166dd6c
Compare
internal/bgp/frrk8s/frrk8s.go
Outdated
| configChangedCallback func(interface{}) | ||
| } | ||
|
|
||
| func (sm *sessionManager) SetEventListener(callback func(interface{})) { |
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 saw in the next commit how the session manager is buried into the speaker abstraction and it's not easy to extract (unless we want to have a singleton variable as part of the module, which I am not sure I like).
yep let's keep it that way
Here we set a listener that listens to event. The name does not seem terrible to me, but I can switch to callback if you want.
I think it makes a bit more sense since we don't listen here, I guess SetEventCallback?
|
|
||
| func (sm *sessionManager) SyncExtraInfo(extraInfo string) error { | ||
| if extraInfo != "" { | ||
| return errors.New("extra info not supported in frr-k8s mode") |
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'm fine with that but we should remember to document it (more like "highlighting" since this mode unlocks more frr capabilities) when we get to it
internal/bgp/frrk8s/frrk8s.go
Outdated
| toAdd := frrv1beta1.BFDProfile{ | ||
| Name: bfd.Name, | ||
| } | ||
| if bfd.ReceiveInterval != 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.
maybe I'm missing something but how when both are pointers (toAdd.x and bfd.x)?
| toNotify := sm.desiredConfig.DeepCopy() | ||
| sm.configChangedCallback(*toNotify) |
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.
what I'm more worried about is us creating a ton of events that the controller will process (polluting the logs at a minimum) + it'd be nice to save a few api calls (since every speaker generates them).
| return ctrl.Result{}, nil | ||
| } | ||
|
|
||
| toApply := &frrv1beta1.FRRConfiguration{ObjectMeta: metav1.ObjectMeta{Name: r.desiredConfiguration.Name, Namespace: r.desiredConfiguration.Namespace}} |
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: can you indent this?
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
| g.Expect(err).ToNot(HaveOccurred()) | ||
| m, err := manager.New(cfg, manager.Options{Metrics: metricsserver.Options{BindAddress: "0"}}) | ||
| g.Expect(err).ToNot(HaveOccurred()) | ||
|
|
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 we start the test with a "stale" config and see that the controller first deletes it (since desired == 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.
done
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?
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.
removed
The real reason why we need this, is to be able to inject a listener that listens to generated frrk8s changes. It has to be a listener because it has to added AFTER the creation of the manager, that in turn is passed to the various controllers. In order to keep the event generic, we pass an empty interface to the callback, so the consumer can assert the type and handle the event accordingly to its type. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
Here we add another bgp session manager implementation where starting from the exposed interface we generate an FRR-K8s configuration tied to the running node. The consuming side is notified via a callback. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
We expose a method that gets short-circuited with the protocol implementation. This will allow us to set a listener to the frrk8s implementation. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
61c78f7 to
9b95287
Compare
The controller is driven in two ways: - it listens for changes on the frrconfig related to the metallb namespace and the node the controller is running on - it listen for changes in the UpdateConfig method Given calling UpdateConfig is asynchronous, the passed data is stored and an event is sent to a channel so it can be processed inside the reconciliation loop. The notification callback has empty interface as a field so this callback an be used as a bgp event listener. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
We need to: - pass the implementation to the controller, so services and config can be translated - expose a way for the controller to set an event listener, so the implementation can notify the contorller of a new event to process Given this circular dependency, the controller sets the listener after its creation, to the already existing frrk8s implementation. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
3251ca4 to
abd1b2b
Compare
Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
We don't have password support yet, but we want to see a basic smoke test working. Here we run a service connectivity test with ebgp-single-hop which is the container configured without password. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
Adding a new lane that just deploys the machinery and runs the smoke test we added. Signed-off-by: Federico Paolinelli <fpaoline@redhat.com>
abd1b2b to
f21f089
Compare
|
lgtm 😄 |
Following the frr splitting design proposal, here we add a new BGP implementation, whcih is based on FRR-K8s. What this implemetation does is to generate the corresponding frr-k8s configuration so that the FRR-k8s daemon can configure FRR.
This will allow external actors to add additional FRR knobs that are not related to MetalLB.