Skip to content
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

Support for multiple replicas with auto-tls #198

Merged
merged 16 commits into from
Dec 17, 2020

Conversation

tvoran
Copy link
Member

@tvoran tvoran commented Dec 15, 2020

Adds a use-leader-elector option to vault-k8s to enable use of a leader-elector sidecar, which lets multiple replicas of the injector determine a "leader" which is then in charge of generating the CA, Cert, and Key, distributing them to the followers, and patching the webhook caBundle. Defaults to false.

The leader-elector sidecar in use is described in detail here: https://kubernetes.io/blog/2016/01/simple-leader-election-with-kubernetes/
The leader-elector containers determine a leader by modifying an Endpoint object, and they expose this information to the injector pod with a local http service that returns the current leader's hostname.

The followers read the cert and key needed for the webhook listener from a k8s Secret, which is updated by the leader when a certificate is near expiration.

Uses a leader-elector sidecar to ensure only one injector replica
generates the CA and cert+key. The other replicas pick up the cert+key
from a k8s secret for use in their TLS listeners.

The leader-elector sidecars coordinate using the annotations of a k8s
Endpoint object, which is why those extra permissions were added to
the role in the deployment yaml.

Build a dev image: `make image VERSION=dev`
Deploy: `kubectl apply -k deploy/ -n vault`
Added command-line and env option to control leader-elector
usage. Using Secrets informer for followers to ensure retrieving
timely cert updates without overloading the k8s api.
Added ttl and health checks to leader-elector. Added
AGENT_INJECT_USE_LEADER_ELECTOR env option to deployment.
Slightly refactored the leader package so it's more testable
Copy link
Contributor

@tomhjp tomhjp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! LGTM

deploy/injector-rbac.yaml Show resolved Hide resolved
subcommand/injector/flags.go Outdated Show resolved Hide resolved
helper/cert/source_gen.go Show resolved Hide resolved
subcommand/injector/command.go Outdated Show resolved Hide resolved
tvoran and others added 7 commits December 15, 2020 11:49
Co-authored-by: Tom Proctor <tomhjp@users.noreply.github.com>
Using the community gcr registry (k8s.gcr.io), election arg to match
the endpoint deploy yaml, and updating the secret name to match the
code.
To ensure the behavior is unchanged for users not using the leader
elector logic.
Passing the CA around in the Secret seemed to prevent followers from
recreating a CA if they're promoted to leader. Since the followers
don't need the CA, removed it from the Secret.
// For followers, run different function here that reads bundle from Secret,
// and returns that in the result. That will flow through the existing
// notify channel structure, testing if it's the same cert as last, etc.
if !leaderCheck {
Copy link
Contributor

@jasonodonnell jasonodonnell Dec 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get a log saying whether this pod is the leader or follower? Also wondering if we should apply a label so we can query for the leader (not blocking, future enhancement probably).

Currently I can't tell which is which:

[~] kubectl logs vault-injector-57485f744-24jwd -c sidecar-injector
Using leader elector logic
2020-12-16T15:22:43.623Z [INFO]  handler: Starting handler..
Listening on ":8080"...
Updated certificate bundle received. Updating certs...

[~] kubectl logs vault-injector-57485f744-lts8w -c sidecar-injector
Using leader elector logic
2020-12-16T15:22:44.109Z [INFO]  handler: Starting handler..
Listening on ":8080"...
Updated certificate bundle received. Updating certs...

Copy link
Member Author

@tvoran tvoran Dec 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good point, added more logging in ac4b4f4. I set the leader and follower log lines to debug since they are logged pretty frequently. Looks something like this:

❯ kubectl logs -n vault vault-agent-injector-c6d5c7689-6q4w7 -c sidecar-injector 
Using leader elector logic
2020-12-17T02:36:22.710Z [INFO]  handler: Starting handler..
Listening on ":8080"...
2020-12-17T02:36:22.719Z [INFO]  handler.auto-tls: Currently the leader
2020-12-17T02:36:22.726Z [INFO]  handler.auto-tls: Generated CA
2020-12-17T02:36:22.734Z [INFO]  handler.certwatcher: Updated certificate bundle received. Updating certs...
2020-12-17T02:36:27.711Z [INFO]  handler.auto-tls: Currently the leader

❯ kubectl logs -n vault vault-agent-injector-c6d5c7689-lmrjb -c sidecar-injector 
Using leader elector logic
2020-12-17T02:36:26.307Z [INFO]  handler: Starting handler..
Listening on ":8080"...
2020-12-17T02:36:26.314Z [DEBUG] handler.auto-tls: Currently a follower
2020-12-17T02:36:26.314Z [INFO]  handler.certwatcher: Updated certificate bundle received. Updating certs...
2020-12-17T02:36:31.308Z [DEBUG] handler.auto-tls: Currently a follower
...

Copy link
Contributor

@jasonodonnell jasonodonnell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor feedback but LGTM and tested fine!

Added a named logger to GenSource (auto-tls), mostly debug-level for
telling which is the leader and which is the follower.
While the leader is waiting for the current certificate to expire, a
leadership change could occur, and then the former leader's
certificate would be out of sync with the new leader. Added a
goroutine that signals a channel on a leadership change.
@tvoran tvoran merged commit 2cc053e into master Dec 17, 2020
@tvoran tvoran deleted the VAULT-84/leader-elector-container branch December 17, 2020 07:32
NLRemco pushed a commit to NLRemco/vault-k8s that referenced this pull request Feb 22, 2022
Uses a leader-elector sidecar to ensure only one injector replica
generates the CA and cert+key. The other replicas pick up the cert+key
from a k8s secret for use in their TLS listeners.

The leader-elector sidecars coordinate using the annotations of a k8s
Endpoint object, which is why those extra permissions were added to
the role in the deployment yaml.

Added command-line and env option to control leader-elector
usage. Using Secrets informer for followers to ensure retrieving
timely cert updates without overloading the k8s api.

Co-authored-by: Tom Proctor <tomhjp@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants