-
Notifications
You must be signed in to change notification settings - Fork 389
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 leader election for kcp (core) controllers #2996
Conversation
Skipping CI for Draft Pull Request. |
/cc |
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.
Hey @embik 👋🏼
Finally getting around to reviewing this, apologies for the delay.
From an initial pass, I just have a couple of questions around leader state transitions and what happens when those occur.
For the sake of completeness, here is the document that we were working on to compare how controllers were "managed" by kcm and kcp: https://hackmd.io/bZhJ7dtoT4qfqf8q9u9hng?view
The way kcm handles OnStoppedLeading
answers my questions, but I'm not sure if we can do that since afaict, the kcp server is run in the foreground as a standalone binary, so we probably can't exit and rely on a daemon to bring it back.
pkg/server/server.go
Outdated
OnStartedLeading: func(ctx context.Context) { | ||
logger.Info("started leading") | ||
|
||
for controllerName, controller := range s.controllers { | ||
logger := logger.WithValues("controller", controllerName) | ||
go s.runController(ctx, controller, logger) | ||
} | ||
}, | ||
OnStoppedLeading: func() { | ||
logger.Info("stopped leading") | ||
}, |
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 trying to work through the scenario which looks like:
starts leading -> stops leading -> starts leading
If this were to happen, we end up re-spawning all registered controllers.
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.
My understanding - and it might be flawed - is that all controllers should terminate because the context passed to them is canceled upon losing a leader election. So the idea for me was that re-spawning all controllers is exactly what we want when winning a leader election.
However, I haven't gotten around to actually test this yet. So I could be wrong here.
pkg/server/server.go
Outdated
Name: "kcp-controllers", | ||
}) | ||
|
||
logger.Info("leader election has stopped") |
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.
RunOrDie
exits either when some error occurs (through a panic
), the ctx
is cancelled or if the lease couldn't be renewed. If lease couldn't be renewed, we exit this function entirely and don't re-enter it again.
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 a good point - any thoughts on what should happen in that case? We could let the kcp process crash so it gets restarted or put this in a loop, but I'm anxious to just let it keep crashing again and again if there is a bigger problem.
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 have chosen to implement a continuous loop around the leader election, so that if a kcp instance loses the leader role it will restart RunOrDie
(until the overarching context is canceled).
e76617e
to
19028c8
Compare
f5bcadc
to
30586d1
Compare
/retest I suspect it's a flake this time. |
/cc @xrstf |
/lgtm |
LGTM label has been added. Git tree hash: c22f0988f4562225a962b53a567a85aa04bc5f27
|
/cc @sttts |
Signed-off-by: Marvin Beckers <marvin@kubermatic.com>
30586d1
to
228535f
Compare
Signed-off-by: Marvin Beckers <marvin@kubermatic.com>
228535f
to
3c2f7b6
Compare
/retest |
1 similar comment
/retest |
/lgtm |
LGTM label has been added. Git tree hash: 6630e01b14399c334fdbf16fac5d3fd24af7674f
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: sttts 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 |
Summary
This PR adds leader elections for controllers started by kcp (core). As the leader election should be done by shard, the code uses the
system:admin
shard-local workspace. Namespace andLease
name within that namespace can be optionally configured via additional flags, but it defaults tokube-system/kcp-controllers
.This PR introduces some changes to how controllers are registered, mostly so they can start in a single post-start-hook and be wrapped by a leader election instead of all of them starting in their own hook.
My idea for leader election was: Since the
kcp
process is both serving the api and running the controllers, there is no need for it to crash when it loses a leader election. This is notkube-controller-manager
. Instead leader election runs in a continuous loop and even if the leader lock is lost, it is possible that the same kcp process wins leader election at a later point and restarts the controllers that were previously shut down after losing the leader election.While writing this code, I learned a lot about the kcp server code and ran into the following things that will not be addressed by this PR. It has been sitting in draft for several months now, and I believe that it cannot be all fixed at once:
Lease
object that some kube-apiserver code creates insystem:admin
. Both instances will continuously logthe object has been modified
for that. I haven't seen this affecting anything, but who knows.Still, two
kcp
instances pointing to the same etcd are functional with this PR. I tested e.g. new workspaces being initialised properly, then terminating one of the instances, and after leader election times out the other instance assumes leadership and starts controllers, also initialising workspaces created afterwards.Related issue(s)
Fixes #2216
Release Notes