TL;DR Link to heading
A Redis ACL user can hold two passwords at once, so a rotation needs no moment where
anyone is locked out. Add the new password to every Redis and Sentinel process, publish
it, restart the clients, then restart the Redis pods one by one. The restarts remove the
old password; you can’t do it at runtime on the Bitnami chart, because the health probes
still log in with it. Before restarting, move sentinel-pass to the new password as
well, or the Sentinels lock each other out.
Two passwords at once Link to heading
ACL SETUSER default >new-password
> adds a password and leaves the existing one alone. From then on AUTH accepts
either, so the rotation becomes: servers accept both, clients switch, servers drop the
old one. Nothing is rejected at any step, as long as the servers accept the new password
before any client can read it.
ACL changes don’t replicate, so run it on every node. redis-cli -x reads the last
argument from stdin, which keeps the password out of your shell history and ps:
{ printf '>'; cat new-password-file; } \
| kubectl exec -i redis-node-0 -c redis -- \
sh -c 'REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli --no-auth-warning -x ACL SETUSER default'
Then try AUTH on each node three times: old password, new password, wrong password.
The wrong one should return WRONGPASS and add one to acl_access_denied_auth in
INFO stats. If it doesn’t, your check can’t fail. Once it does, that counter is your
alarm for the rest of the rotation.
Sentinel is a server too Link to heading
The chart gives Sentinel the same requirepass as Redis, and anything that asks Sentinel
for the master logs in to it. If haproxy sits in front of Redis, its health checks do
exactly that every few seconds. Add the new password only on port 6379 and the first
haproxy pod restarted onto it marks every Sentinel down and stops routing. Run the
ACL SETUSER on port 26379 as well: six processes for a three-node cluster.
The probes stop you removing the old password Link to heading
ACL SETUSER default <old-password looks like the obvious last step. On the Bitnami
chart it takes the cluster down. The liveness and readiness probes, and the metrics
exporter, log in using the container’s environment variable, which still holds the old
password until the container restarts. Remove it and every probe fails; with liveness
every 5 seconds and a failure threshold of 5, each pod is killed about 25 seconds later.
A restart does the removal instead. On startup the chart builds requirepass,
masterauth and sentinel.conf from the environment, which now holds the new password
only. Roll the pods one at a time, replicas first, master last, and check each before
the next.
Move the internal logins first Link to heading
Mid-roll, restarted pods accept only the new password, while the rest accept both but still send the old one when they talk to each other. So before the first restart, switch every internal login:
| From | To | Command |
|---|---|---|
| Replica | Master | CONFIG SET masterauth |
| Sentinel | Redis | SENTINEL SET <master> auth-pass |
| Sentinel | Sentinel | SENTINEL CONFIG SET sentinel-pass (6.2+) |
The third one is easy to miss. Without sentinel-pass, a Sentinel logs in to its peers
with its own requirepass, and the chart never sets sentinel-pass. Restart one pod
without it and the other two Sentinels mark the new one down:
SENTINEL SENTINELS mymaster
ip=redis-node-2... flags=s_down,sentinel last-ok-ping-reply=289193
Clients carry on, since two Sentinels still make quorum. Restart the master in that
state, though, and a split Sentinel group has to run the failover. Setting
sentinel-pass on the other two clears it within a ping interval.
All three settings live only in memory and vanish on restart, which is fine: the restarted pod’s config already uses the new password.
Proving nobody is on the old password Link to heading
Behind a proxy, CLIENT LIST shows every application connection coming from the proxy’s
pod IPs, so it can’t tell you which app still holds the old password. Prove it from the
other side instead:
- every client pod started after the new secret synced (run the same check on the Redis pods as a control; they’re older, so it should fail);
- every mounted secret file and synced Kubernetes Secret has the new password’s SHA-256 digest;
- every client connection on the master is younger than the proxy restart.
Restart every client rather than working out which ones reread the file. Most cache the password in a connection pool, and a uniform restart gives you a uniform proof. Cronjobs need nothing: each run is a fresh pod, which also makes them your earliest warning.
One trap while watching: ACL LOG merges repeated failures into one entry and keeps only
the latest client’s details. Two Sentinel failures followed by your own wrong-password
test show up as count=3 from 127.0.0.1. Trust the counter, not the address.
Checklist Link to heading
- Generate the password. Keep the character set if something templates it into config; length is free.
ACL SETUSER default >newon every Redis and Sentinel. Test old, new and wrong.- Publish to the secret store and wait for the synced Secret to show the new digest.
masterauth,auth-passandsentinel-passto the new password on every node. Check replication and that no Sentinel iss_down.- Restart the proxy, then every client. Check start times, digests and connection ages.
- Delete Redis pods one at a time, master last. After each: old rejected, new accepted,
links up, Sentinels whole. To roll back,
ACL SETUSER default >oldon the restarted pods restores access instantly. - Watch the counters and client logs, then disable the old secret version.
Clients see graceful restarts and one failover, and not a single WRONGPASS.