A Three-Node Quorum

A Three-Node Controller and Broker Quorum

Production clusters run in isolated mode, with three or five dedicated controllers, so that a busy broker cannot starve the quorum (combined mode is for development). The six-node cluster mounts properties files and a start script (Formatting Storage and Configuration Files) rather than setting dozens of variables, and a YAML anchor keeps it short.

compose/quorum.yaml: three controllers and three brokersYAML
# quorum.yaml: three KRaft controllers (nodes 1-3) and three brokers (nodes 4-6)
name: l3-kq
x-node: &node
  image: apache/kafka:4.3.1
  entrypoint: ["bash", "/mnt/quorum/start.sh"]
  volumes: ["./quorum:/mnt/quorum:ro"]          # properties files and start.sh
  environment: &env
    CLUSTER_ID: Wb96LW2BRGSHe9VjFRvWOA
    INITIAL_CONTROLLERS: "1@l3-c1:9093:5CUtmwF4QDiCN7NVutEiyQ,\
      2@l3-c2:9093:4W0Cc1gvRbK40QSwRSZurg,3@l3-c3:9093:sTd2qAh9RWq8WbRS7RDbcw"
    KAFKA_HEAP_OPTS: "-Xms256m -Xmx256m"
services:
  c1: {<<: *node, container_name: l3-c1, environment: {<<: *env, ROLE: controller, NODE_ID: 1}}
  c2: {<<: *node, container_name: l3-c2, environment: {<<: *env, ROLE: controller, NODE_ID: 2}}
  c3: {<<: *node, container_name: l3-c3, environment: {<<: *env, ROLE: controller, NODE_ID: 3}}
  b4: {<<: *node, container_name: l3-b4, environment: {<<: *env, ROLE: broker, NODE_ID: 4},
       ports: ["33194:9094"]}
  b5: {<<: *node, container_name: l3-b5, environment: {<<: *env, ROLE: broker, NODE_ID: 5},
       ports: ["33195:9094"]}
  b6: {<<: *node, container_name: l3-b6, environment: {<<: *env, ROLE: broker, NODE_ID: 6},
       ports: ["33196:9094"]}
networks: {default: {name: l3-booknest}}

Started with docker compose -f compose/quorum.yaml up -d, the six JVMs (256 MB heaps) used about 1.3 GiB: under 300 MiB per broker, 130-155 MiB per controller. Data lives in the image's anonymous volumes until down -v.