-
Notifications
You must be signed in to change notification settings - Fork 373
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
CPLB userspace reverse proxy load balancer #5279
base: main
Are you sure you want to change the base?
Conversation
c7886ee
to
3682cf7
Compare
ac4e148
to
0910d28
Compare
0910d28
to
a651dbd
Compare
Got some feedback on the docs from Daniel, so I'm making it a draft temporarily |
This pull request has merge conflicts that need to be resolved. |
a651dbd
to
dfaf7d8
Compare
This pull request has merge conflicts that need to be resolved. |
dfaf7d8
to
cf158fb
Compare
tcpproxy is a subset of github.com/inetaf/tcpproxy with some modifications: 1- Implement the method SetRoutes to allow to set routes in bulk. Also allows deletion of routes which otherwise would be impossible. 2- Implement round robin load balancing (there was no load balancing at all). 3- Remove unused code. 4- Append Mirantis copyright for the modifications. Additionaly this PR had to do some modifications in the copyright linter script and `.golangci.yaml` because this is a file copied and modified. This is required to Apache 2.0 retribution right. Signed-off-by: Juan-Luis de Sousa-Valadas Castaño <jvaladas@mirantis.com>
cf158fb
to
8220614
Compare
b0a4984
to
5c2c026
Compare
// The order that routes are added in matters; each is matched in the order | ||
// registered. | ||
type Proxy struct { | ||
configs map[string]*config // ip:port => 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.
NB: There's the special type netip.AddrPort
for IP plus port number in the standard library, so this could be typed accordingly:
configs map[string]*config // ip:port => config | |
configs map[netip.AddrPort]*config |
I guess this would make the public Proxy API clearer as well.
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.
Since it's a private field, how about we leave the map as it is (a string is more convinient than a struct for the map) and we use netip.AddrPort in the public functions?
|
||
// ListenFunc optionally specifies an alternate listen | ||
// function. If nil, net.Dial is used. | ||
// The provided net is always "tcp". |
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.
If net is always "tcp"
, wouldn't it make sense to remove that parameter?
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 is the interface for net.Listen
, we could remove the field but we need for the tests. I'd rather leave this as it is.
for _, c := range p.lns { | ||
c.Close() | ||
} | ||
return 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.
The errors are completely ignored here. Let's either remove the error return completely, or collect them instead.
for _, c := range p.lns { | |
c.Close() | |
} | |
return nil | |
var errs []error | |
for _, c := range p.lns { | |
if err := c.Close(); err != nil { | |
errs = append(errs, err) | |
} | |
} | |
return errors.Join(errs...) |
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 there a way to merge this with the other inttest, and call this multiple times, as we're doing it e.g. for the dualstack tests.
cmd/controller/controller.go
Outdated
if cplbCfg := nodeConfig.Spec.Network.ControlPlaneLoadBalancing; cplbCfg != nil && cplbCfg.Enabled { | ||
if c.SingleNode { | ||
return errors.New("control plane load balancing cannot be used in a single-node cluster") | ||
} | ||
|
||
if enableK0sEndpointReconciler { | ||
return errors.New("control plane load balancing requires the component 'endpoint-reconciler' to be disabled") |
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 wonder if there's some way of making this error message a bit more comprehensive 🤔
The message is technically correct, but might not be too helpful for folks to understand the connection between externalAddress and k0s's understanding of endpoint reconciliation...
aed0b18
to
5155c18
Compare
IPVS is problematic for many reasons, implement a userspace load balancer which should get the job done and should be far less problematic. Signed-off-by: Juan-Luis de Sousa-Valadas Castaño <jvaladas@mirantis.com>
The only reason why we block externalAddres is that we need a disabled endpoint-reconciler. It doesn't make sense to move all this logic and these parameters to the config validation, instead do it all in cmd. Signed-off-by: Juan-Luis de Sousa-Valadas Castaño <jvaladas@mirantis.com>
1- Included userspace reverse proxy and made it the default option. 2- Explained better the difference between virtual IP and a load balancer, it was confusing for many users. 3- Added a whole troubleshooting section. Signed-off-by: Juan-Luis de Sousa-Valadas Castaño <jvaladas@mirantis.com>
1- Simplify tcpproxy by reomivng useless interfaces: The original tcpproxy allowed different types of routes and needed to do a bunch of interfacing for it to work. Since we only implement one kind of route and one kind of target, we remove all the interfaces and merge both structs into a unique struct. 2- Remove proxy.AddRoute: We only used it once and setRoutes can cover that use case 3- Lock tcpproxy.Proxy when modifying routes to make it thread safe. Prior to this we relied on the proxy being called only from one goroutine. Now it can be called concurrently, not that we expect to do that but a lock gives us extra safety. 4- Panic if tcpproxy.SetRoutes gets and empty route list. We now check this in cplb_unix.go. 5- Remove the route feeding goroutine for round robin, since we added a lock to make proxy.SetRoutes threadsafe we don't need that anymore and it can be made much simpler by adding a lock. Signed-off-by: Juan-Luis de Sousa-Valadas Castaño <jvaladas@mirantis.com>
5155c18
to
ba2de2c
Compare
I addressed most of the comments. As for the comments: 1-Add tcpproxy remains unchanged for easier reviews There are a few things unchanged: |
Description
Implement userspace CPLB reverse proxy load balancer.
Due to the keepalived virtualservers using IPVS for the load balancing, we simply couldn't make it work on some environments and needed to implement a userspace reverse proxy.
Fixes #4700
Type of change
How Has This Been Tested?
Checklist: