Skip to content

Scaling the Cluster

This guide explains how Danube brokers join and leave a cluster, and how to scale on bare metal, Docker Compose, or Kubernetes.

Every broker embeds a Raft consensus node. On startup, the broker inspects its local state and the cluster to decide how to proceed:

ScenarioHow it’s detectedWhat happens
Single-node, first bootNo node_id file, empty seed_nodesAuto-initializes a 1-voter cluster
Multi-node, first bootNo node_id file, seed peers have no leader yetPeers discover each other; lowest node_id bootstraps the cluster
New node, existing clusterNo node_id file, a seed peer reports has_leader = trueEnters join mode automatically — starts in “drained” state
Restartnode_id file exists on diskWaits for Raft leader election then resumes

Once a broker joins a cluster, it transitions through these states:

drained ──► active ──► drained (unload) ──► removed
  • Drained: the broker is a Raft member but the Load Manager will not assign topics to it. New nodes start here
  • Active: eligible for topic assignments. Activated via danube-admin brokers activate
  • Removed: the node has been removed from Raft membership and can be safely stopped

Auto-detection determines what the node should do, not whether it joins the cluster. When a fresh node sees has_leader = true, it enters a waiting state instead of bootstrapping a new cluster (preventing accidental split-brain).

Actually adding the node to the Raft voter set still requires explicit admin commands. This is intentional:

  • Safety: arbitrary nodes should not auto-join a Raft quorum
  • Staged rollout: the learner → voter → active progression lets operators verify each step
  • Operational control: the operator decides when a new broker starts receiving traffic

  • danube-admin CLI installed (releases)
  • DANUBE_ADMIN_ENDPOINT pointing to any active broker’s admin port
Terminal window
export DANUBE_ADMIN_ENDPOINT=http://broker-1:50051
Check current state
# Raft cluster membership (voters, learners, leader, term)
danube-admin cluster status
# Active brokers with status, addresses, and roles
danube-admin brokers list
# Load distribution and balance metrics
danube-admin brokers balance

Adding a new node is a 4-step process: start → add → promote → activate.

  1. Start the new broker in join mode

    Start new broker
    danube-broker --config-file danube_broker.yml \
    --broker-addr 0.0.0.0:6653 --admin-addr 0.0.0.0:50054 \
    --raft-addr 0.0.0.0:7653 --data-dir ./danube-data/raft-4 \
    --prom-exporter 0.0.0.0:9043 \
    --join

    The broker starts its admin server and waits for a Raft leader. It is not yet part of the cluster.

  2. Add as learner (non-voting)

    Terminal window
    danube-admin cluster add-node --node-addr http://broker-4:50054

    The node receives Raft log replication but does not vote. Safe to remove without impact if something goes wrong.

  3. Promote to voter

    Terminal window
    danube-admin cluster promote-node --node-id <ID>

    The broker registers in drained state, the Load Manager won’t assign topics yet.

  4. Activate the broker

    Terminal window
    danube-admin brokers activate --broker-id <ID> --reason "Scale-up"
  5. Rebalance existing topics (optional)

    Activation only affects new topic assignments. To redistribute existing topics:

    Terminal window
    # Preview what would happen
    danube-admin brokers rebalance --dry-run
    # Execute rebalancing
    danube-admin brokers rebalance

Scaling Down (Bare Metal / Docker Compose)

Section titled “Scaling Down (Bare Metal / Docker Compose)”

Removing a node is the reverse: unload → remove → stop.

Cluster SizeQuorumCan Lose
321 node
431 node
532 nodes
  1. Unload all topics

    Terminal window
    # Preview
    danube-admin brokers unload --broker-id <ID> --dry-run
    # Execute
    danube-admin brokers unload --broker-id <ID>
  2. Remove from Raft membership

    Terminal window
    danube-admin cluster remove-node --node-id <ID>
  3. Stop the broker process

    Terminal window
    kill $(cat broker.pid)

Clean the old data directory (the node was removed from Raft, so its persisted state is stale), then rejoin using the same workflow as scale-up:

Terminal window
rm -rf ./danube-data/raft-3
danube-broker --config-file danube_broker.yml \
--broker-addr 0.0.0.0:6652 --admin-addr 0.0.0.0:50053 \
--raft-addr 0.0.0.0:7652 --data-dir ./danube-data/raft-3 \
--join
# Then: add-node → promote → activate → rebalance

When using the danube-core Helm chart, brokers run as a StatefulSet with podManagementPolicy: Parallel. All pods start simultaneously and discover each other via headless DNS.

  1. Increase replica count

    Terminal window
    helm upgrade danube-core ./charts/danube-core -n danube \
    --set broker.replicaCount=5

    New pods detect has_leader = true during discovery and enter join mode automatically.

  2. Add, promote, and activate each new broker

    Port-forward and add brokers
    kubectl port-forward danube-core-broker-0 50051:50051 -n danube
    # For each new pod (e.g., broker-3, broker-4):
    danube-admin cluster add-node \
    --node-addr http://danube-core-broker-3.danube-core-broker-headless.danube.svc.cluster.local:50051
    danube-admin cluster promote-node --node-id <ID>
    danube-admin brokers activate --broker-id <ID>
  3. Rebalance (optional)

    Terminal window
    danube-admin brokers rebalance
  1. Unload topics and remove from Raft (same commands as bare metal, via port-forward)

  2. Reduce replica count

    Terminal window
    helm upgrade danube-core ./charts/danube-core -n danube \
    --set broker.replicaCount=3
  3. Delete orphaned PVCs

    Terminal window
    kubectl delete pvc data-danube-core-broker-3 -n danube
    kubectl delete pvc data-danube-core-broker-4 -n danube

Pod restarts (crashes, rolling upgrades, node evictions) are handled automatically. Each pod’s node_id is persisted in the PVC, so the broker detects a restart and resumes with its existing membership. No admin intervention is required.


CommandPurpose
cluster statusShow Raft membership (voters, learners, leader, term)
cluster add-node --node-addr URLAdd a new broker as a non-voting learner
cluster promote-node --node-id IDPromote learner to voting member
cluster remove-node --node-id IDRemove a node from Raft cluster
brokers listList all registered brokers with status
brokers activate --broker-id IDSet broker state to active (eligible for topics)
brokers unload --broker-id IDMigrate all topics off a broker
brokers unload --broker-id ID --dry-runPreview unload without executing
brokers balanceShow load distribution and CV metric
brokers rebalanceTrigger manual topic redistribution
brokers rebalance --dry-runPreview rebalance moves