Skip to content

helm: the chart cannot deploy a replicated range, so nothing in Kubernetes exercises replication #284

Description

@allamiro

Update (2026-08-08): the first half of this landed in #286. The chart can now
render a replicated range — data.topology: replicated picks leader/follower/standalone,
the leader gets a followers list of per-pod headless FQDNs, and the followers get a
lease block. Option (1) below is DONE.

Two things remain, and they are different sizes, so they are split:

The original text follows unchanged.


The chart deploys three independent standalone ranges, not one replicated range. Three replicas are three separate logs, which is why --durability quorum is refused outright — "Quorum durability requires a configured replica set" — and why a pod nobody produced to stays empty. scripts/k8s-smoke.sh asserts both, so the behaviour is pinned rather than incidental.

That means the deployment shape which exercises replication, fencing, promotion, and the whole #240 epoch arc is not reachable from the chart at all. Everything that arc fixed is currently only exercised by the live-chaos harness.

The blocker the chart cited is gone

The template said:

Replicated ranges under co-location wait on follower-side epoch propagation upstream.

That landed in #239 (lease_watcher.rs — followers learn granted epochs without a restart), and the rest of the recovery arc landed as #240's stack. DataNodeConfig already supports role: leader with a followers list, role: follower, and a lease block that is explicitly valid on followers. The engine is no longer the constraint.

The constraint that is real

role is a static per-node config field, and a StatefulSet renders one config per ordinal. So a replicated range means:

  • ordinal 0 → role: leader, with a followers list naming the other ordinals' headless FQDNs
  • ordinals 1..n → role: follower, each with a lease block so it adopts granted epochs

That renders fine. What does not work is failover: when metadata grants the range to a different node, the new holder needs role: leader and the old one needs role: follower, and nothing re-renders a ConfigMap in response to a lease change. The live-chaos harness handles this by restarting the promoted node with a new config (scenario 09 does exactly that), which is a harness move, not an operator one.

Options, roughly in order of honesty

  1. Render the static shape and document the limitation. Leader is ordinal 0; failover requires an operator to re-render and restart. Useful for testing replication and for deployments that accept manual failover, and it makes the node: complete the failover recovery protocol — epoch-qualified truncation, pre-probe fencing, transition evidence #240 work reachable outside the chaos harness.
  2. Make the role dynamic in the binary — every node starts as a candidate and its role follows the lease, rather than being fixed at config time. This is the shape Kubernetes actually wants, and it would make the chart's job trivial. It is also the larger change, and it interacts with node: vtop-node ignores SIGTERM, so every orderly stop is a crash stop #280 (a departing leader releasing its lease).
  3. Leave it standalone and keep replication exercised only by live-chaos.

(2) is where this should end up. (1) is worth having in the meantime, because without it nothing in Kubernetes ever exercises the replication path.

Also worth testing while here

Cross-namespace. The chart parameterises the namespace and every peer FQDN includes it, so two releases in different namespaces should be independent by construction — but "should be" is what this whole exercise keeps disproving. A second release in another namespace, both streaming, neither seeing the other's records, belongs in the smoke test as a variant.


Update (2026-08-08): the first half is done and verified live

#293 landed it. scripts/k8s-smoke.sh now deploys the replicated topology as a third shape and asserts the things only that shape can prove:

[k8s-smoke] producing with QUORUM durability, which a standalone range refuses
[k8s-smoke] quorum produce accepted 60 records
[k8s-smoke] follower 1 has durably applied all 60 records
[k8s-smoke] follower 2 has durably applied all 60 records
[k8s-smoke] replication verified in Kubernetes: quorum durability works and both followers hold the data

The assertions are deliberately the INVERSE of the standalone ones — quorum succeeds where it is refused, and a follower nobody produced to holds everything instead of staying empty — because that is what proves the topology took effect rather than merely being accepted. Both followers are checked, since quorum only proves a majority acked (with three replicas, the leader plus one), and it reads local_committed_offset, what the follower has FSYNCED, not next_offset.

Getting there needed three bugs fixed, all in #293: the topology rendered invalid YAML and had never once worked; a replicated install needs meta create-topic and register-node per node, which nothing documented; and nothing followed a Raft leader redirect (#292), so two of three replicas failed closed permanently.

What remains under this number is option (2) alone: failover still needs an operator. role is fixed at render time, so when metadata grants the range elsewhere nothing re-renders the ConfigMap. That interacts with #280 (a departing leader releasing its lease) and the two probably belong in the same milestone.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions