Upgrading a cluster
Moving a running cluster to the next minor release one node at a time — followers first, the store's leader last — and the three rules that keep every record.
A cluster running 0.23.0-beta or later moves to the next minor release
without stopping. Replace one node at a time: stop it, start the new release on the
same store directory, and wait for it to answer before the next. Each
replaced node opens the store the previous release wrote and catches up from its
leader, and the cluster takes writes throughout — a rolling upgrade.
The order
- Find the leaders.
INFO FOR NODEreportscluster.leaders— which node leads the store line and each placed range — and the console's cluster map draws it. - Replace the followers, one at a time. Stop the process, start the new release on the same store directory with the same flags, and wait until it answers and has caught up before the next.
- Replace the store line's leader last. While it is down, writes it would have taken are refused until another node is elected — about one lease and one election, as on any failover. A node leading a placed range pauses that range the same way; to avoid even that pause, move the placement to a node already upgraded first.
What is promised, and what is not
- One minor version at a time —
0.23to0.24. Two steps are two upgrades, each done in full before the next starts. - Back is a restart, until you finalize. From
0.31.0-beta, a newer release keeps the on-disk format the store already holds, so the release before can still open it — see taking an upgrade back. Take a snapshot before you start anyway. - New features after the last node. While both releases run, use only what
both understand. Turn on what the new release adds —
BALANCE LEADERSHIPS,LEADS … PREFERRED, giving a range back withLEADS NONE, a transaction across two leaders — once every node runs it. An older node does not know them, and a decision only half the cluster can read is not one it makes. - Replication changes shape on its own. From
0.31.2-betaa leader sends its followers each commit as it lands. That happens only between two nodes of that release or later; any other pair streams as before, so a cluster of mixed versions replicates throughout. It needs no switch. - Gathered reads fold more as leaders are replaced. From
0.32.0-betaa node holding part of a split table asks a shard's leader to foldmedian,collectand the counter folds only when that leader runs0.32.0-betaor later; an older leader sends its records, as before. The answer is the same either way; what travels shrinks once the last leader is replaced. - Approximate folds and expiry wait for the last node. From
0.33.0-betaa leader foldsapprox_distinctandapprox_quantileitself only when it runs0.33.0-betaor later; an older leader sends its records. Declaring that a table's records expire, or a rollup that keeps those folds, waits on an older store forALTER STORE FINALIZE FORMAT— run it only once every node runs0.33.0-betaand no rollback to an older build is planned.
Measured on three local processes going from 0.23.0-beta to 0.24.0-beta,
and again from 0.31.1-beta to 0.31.2-beta: each node replaced in turn,
writes landing after every step, and every node holding every record at the
end.
Taking an upgrade back
A store keeps the format it held when the newer release first opened it. The
newer release reads and writes it in that format, and refuses — with
FormatNotFinalized, writing nothing — the one statement that needs its own
format today: a containment index (DEFINE INDEX … CONTAINS). Going back is
stopping each node and starting the previous release on the same directory.
INFO FOR STORE shows where a store stands:
INFO FOR STORE;
{ format: 5, namespaces: ['shop'], writes: 6 }
format is what the store holds and writes is what this release writes; the
console shows both on This node. When they differ, the way back is open.
When no older release will open the store again, close it:
ALTER STORE FINALIZE FORMAT;
It raises the store to the format this release writes, on every replica, and
answers { format: 6 }. It is one-way: afterwards the previous release refuses
to open the store, naming the format it found, and the way back is the snapshot
taken before. On a cluster it is refused — FormatPeerTooOld, naming the
replica — until every declared replica has collected from this node running a
release that writes the format. Upgrade every node, let each collect once, then
finalize. It needs store-wide authority.
A store a release creates holds that release's format from the start, so a store
created by 0.28.0-beta or later already holds format 6 and sees no difference.
Measured on the store 0.27.1-beta wrote: 0.31.0-beta opened it at format 5
and refused a containment index, 0.27.2-beta opened it again and read back
every record including the ones 0.31.0-beta wrote; after the finalize,
0.27.2-beta refused it.
From an older release
The first step this covers is 0.23 to 0.24. A store written by an earlier
release is moved by taking a script backup
and restoring it into the new release as a fresh cluster.