Skip to main content

Scale a cluster

Move replicas before removing capacity. A registered broker is not useful capacity until partitions are assigned to it, and stopping a broker does not move its replicas elsewhere.

Add brokers

Format each new log directory as a KIP-853 joiner, then start the broker with an existing controller DNS name. Keep the cluster id from the existing fleet.

krabka-format --log-dir /var/lib/krabka --node-id 4 \
  --cluster-id "$CLUSTER_ID" --no-initial-controllers
krabka-broker --log-dir /var/lib/krabka --broker-id 4 \
  --controller-bootstrap-servers controllers.example:9093 \
  --controller-auto-join

Wait for broker 4 to appear unfenced in kafka-cluster list-endpoints. Then generate a plan over every usable broker. Save the second JSON document printed by --generate as proposed.json and review it before execution.

printf '{"topics":[{"topic":"orders"}],"version":1}\n' > topics.json
kafka-reassign-partitions --bootstrap-server "$BOOTSTRAP" --generate \
  --broker-list 1,2,3,4 --topics-to-move-json-file topics.json
kafka-reassign-partitions --bootstrap-server "$BOOTSTRAP" --execute \
  --reassignment-json-file proposed.json --throttle 52428800
kafka-reassign-partitions --bootstrap-server "$BOOTSTRAP" --verify \
  --reassignment-json-file proposed.json

During the move, krabka_broker_reassigning_partitions must fall to zero and rate(krabka_broker_replication_throttled_bytes_{in,out}_total[5m]) should sit near the configured rate. --verify reports completion and clears the KIP-73 throttle. If the gauge stays flat while both byte rates are zero, use the stalled reassignment runbook.

The Kubernetes operator already owns joiner formatting and controller discovery. Increase KafkaNodePool.spec.replicas, wait for its Ready condition, then create and approve a KafkaRebalance; do not reproduce the commands above inside the pod template.

Remove a broker

Generate a plan whose --broker-list omits the broker, execute it, and verify it exactly as above. Do not continue until kafka-topics --describe names the broker in neither Replicas nor Isr for any partition.

When [break_glass] is configured, unregistering needs a proposal approved by a second principal. The proposal target is the decimal broker id.

krabka-guard -b "$BOOTSTRAP" break-glass propose \
  --action unregister-broker --target 4 --reason "capacity removal" --ttl 30m
krabka-guard -b "$BOOTSTRAP" break-glass approve \
  --proposal "$PROPOSAL_ID" --sign-with bob.pk8 --key-id bob
kafka-cluster unregister --bootstrap-server "$BOOTSTRAP" --id 4

The unregister consumes the matching approved proposal atomically. A missing approval returns POLICY_VIOLATION (44). Stop the broker and release its disk only after kafka-cluster list-endpoints no longer lists it. For an operator-managed pool, reduce spec.replicas only after the explicit reassignment omitting that broker verifies complete; the operator owns the StatefulSet and retained PVC lifecycle.