-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Experimental load-balancing control-plane with StateDB #32185
base: main
Are you sure you want to change the base?
Conversation
55b99f9
to
f2ce936
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.
Thanks for all the work on this @joamaki! This looks really promising, mostly just have a bunch of questions to make sure I'm understanding things correctly.
f2ce936
to
1892771
Compare
I believe
And here probably these should be |
1892771
to
ea09ba4
Compare
ea09ba4
to
d8a8d06
Compare
This comment was marked as outdated.
This comment was marked as outdated.
2703ef2
to
15b73d7
Compare
15b73d7
to
851b86f
Compare
/test |
5011331
to
d6a36d8
Compare
/test |
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.
Not very material this time: one question and the rest are just typos or rewording suggestions.
35b7a08
to
79d2d74
Compare
Implement JSON marshalling for AddrCluster type so it can be used in StateDB objects and dumped with cilium-dbg. Signed-off-by: Jussi Maki <jussi@isovalent.com>
For dumping StateDB objects with ImmSet[T] fields, add support for JSON marshallign and unmarshalling. The default implementation does not work as ImmSet[T] has private fields only. Signed-off-by: Jussi Maki <jussi@isovalent.com>
8ad9365
to
a25882c
Compare
Add experimental Services API for managing load-balancing frontends and backends. This is added as a new experimental package to avoid confusing it with the production implementation. When the hidden "--enable-experimental-services" flag is set: * K8s Service and Endpoints are reflected to service, frontend and backend tables * A mock reconciler is started that logs mock operations to reconcile the frontends. The tables can be inspected with "cilium-dbg statedb experimental" commands, e.g. "cilium-dbg statedb experimental frontends". Signed-off-by: Jussi Maki <jussi@isovalent.com>
The "cilium-dbg statedb" commands require the objects to be JSON serializable, which is easy to break accidentally. Add a fuzz test to generate arbitrary Service, Frontend and Backend objects and validate that the TableRow() output is the same across JSON serialization. Signed-off-by: Jussi Maki <jussi@isovalent.com>
a25882c
to
86118e4
Compare
/test |
/ci-runtime |
This is the beginnings of a new load-balancing control-plane implementation that aims to unify service load-balancing information under a single representation and to allow agent components to observe and update service-related information easily.
I'm approaching this first with experimental code rather than with a CFP as IMO it's too early to bring up a CFP with wider distribution before there's answers to how to approach the many use-cases. Since there are multiple parties involved in this experiment and it will span a long period of time, I'm proposing to already merge this skeleton implementation to avoid the pain of feature branches. This code is in a separate package, disabled by default and has no production impact other than slightly larger cilium-agent binary.
The rough structure this experiment is working towards is:
Instead of service load-balancing related data being spread over cache.Store, ServiceCache, ServiceManager, etc. we would unify it to 3 sets of tables that would serve the internal information needs and would be used towards BPF map reconciliation. This would solve many of the problems we have with merging service-related data coming from multiple data sources, reduce memory usage and speed up reconciliation throughput as less layers and context switching is involved. See also the current structure for contrast.
Since we want to mature this implementation gradually and to answer the still many small questions
related to this (topo-aware services, clustermesh, NodePort frontend IP expansion etc.), this PR is
introducing the support via a feature flag (
enable-experimental-services
) so this can be tested and developedgradually. This hidden feature flag starts a reflector that populates the load-balancing tables and a reconciler
that mocks the reconciliation operations.
Nothing yet uses the new API and the flag is disabled by default, so this code has no impact
to normal operation, but it allows further collaborative development on the API.
The implementation is structured as follows:
pkg/loadbalancer/experimental
is chosen as the package for these. This clearly separatesthe new code from the production code. Eventually it will make sense to move the code into the
loadbalancer
package that already defines the data structures related to load-balancing.pkg/loadbalancer/experimental/{service,frontend,backend}.go
:These are the load-balancing StateDB tables. To minimize data duplication we're dividing
these into Service (the metadata about the service), Frontend and Backend. To keep things simple
to start with many of fields in Service have been omitted. The Frontend is the object we're reconciling
as that defines a useful unit of work for the BPF map reconciliation as backends need to be updated before frontends and frontends (the services BPF map) directly references them.
pkg/loadbalancer/experimental/services.go
:Implements the "writer" to the load-balancing tables. We don't want to give write access to the tables directly as we want to validate changes and we need to mark frontend status as pending to ask the reconciler to process it.
pkg/loadbalancer/experimental/reflector.go
:Observes the Kubernetes Service and EndpointSlice objects and writes to the tables via the
Services
API. Eventually this could be implemented directly with a client-goReflector
and skip having acache.Store
that holds an unnecessary copy.pkg/loadbalancer/experimental/reconciler.go
:A simulation of what the proper reconciler towards the BPF maps would look like. Just logs the operations we'd need to perform.
The feature flag can be enabled and tested with:
Next steps following this is to start implementing a test-suite to validate how this API works with all the different use-cases we have for it, and to implement the proper BPF map reconciler so we can test using the FakeLBMap implementation for proper integration testing and to start doing e2e testing.