+1

Triển khai Kafka KRaft mode và KafkaUI bằng docker compose có thể áp dụng cho môi trường production

🧠 Giới Thiệu Kafka KRaft + Docker Compose

✅ Yêu Cầu Trước Khi Bắt Đầu

  • Đã cài đặt DockerDocker Compose
  • Có kiến thức cơ bản về Docker và Docker Compose

1. Tổng Quan Về Kafka

Kafka là một distributed streaming platform được sử dụng để xây dựng các ứng dụng real-time data pipelinestream processing.

Kafka có thể xử lý khối lượng lớn dữ liệu nhờ:

  • Partitioning dữ liệu trên nhiều broker
  • Đảm bảo High Availability (HA)Fault Tolerance

🔍 Các Thành Phần Chính Trong Kiến Trúc Kafka

Thành phần Vai trò
Producer Gửi dữ liệu đến topic
Broker Lưu trữ và quản lý dữ liệu
Consumer Đọc dữ liệu từ topic
Topic Tập hợp các message theo danh mục

2. Zookeeper Là Gì và Tại Sao Kafka Cần Nó?

🧩 Zookeeper Là Gì?

Zookeeper là một distributed coordination service, giúp Kafka:

  • Quản lý metadata (topics, partitions, broker)
  • Điều phối election
  • Đồng bộ hóa dữ liệu giữa các node

📌 Vai Trò Của Zookeeper Trong Kafka

  1. Quản lý metadata:

    • Topic, partition, leader election, ACLs
  2. Theo dõi trạng thái broker

  3. Leader election cho partition

  4. Lưu trữ cấu hình & hạn ngạch (quotas)

❗Nhược Điểm Khi Sử Dụng Zookeeper

  • Cần vận hành một cụm riêng
  • Độ trễ và chi phí khi coordination
  • Khó mở rộng với high write-throughput

3. KRaft Mode – Kafka Không Cần Zookeeper

Từ Kafka 2.8+ (preview) và 3.3+ (production), Kafka hỗ trợ KRaft Mode:

  • Sử dụng Raft consensus algorithm để thay thế Zookeeper
  • Metadata lưu trong topic nội bộ: _cluster_metadata
  • Tự xử lý broker registration, controller election

🔥 Ưu điểm khi dùng KRaft

  • Không cần Zookeeper
  • Kiến trúc đơn giản hơn
  • Quản lý metadata hiệu quả và ổn định

4. Triển Khai Kafka KRaft Với Docker Compose

📦 Kiến Trúc Docker Compose

  • 3 Kafka brokers (KRaft mode)
  • 1 Kafka UI để theo dõi hệ thống

🌐 Các Port

Broker Host Port Container Port
kafka-1 19092 9092
kafka-2 29092 9092
kafka-3 39092 9092
Kafka UI 8080 8080

🧾 Cấu Hình docker-compose.yml

🔧 Kafka Broker - kafka-1

kafka-1:
  image: apache/kafka:latest
  hostname: kafka-1
  container_name: kafka-kraft-1
  ports:
    - "19092:9092"
  environment:
    KAFKA_NODE_ID: 1
    KAFKA_PROCESS_ROLES: broker,controller
    KAFKA_LISTENERS: PLAINTEXT://kafka-1:9092,CONTROLLER://kafka-1:9093,INTERNAL://kafka-1:9094
    KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-1:9092,INTERNAL://kafka-1:9094
    KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
    KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT
    KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka-1:9093
    KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
    KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
    KAFKA_NUM_PARTITIONS: 1
    KAFKA_LOG_RETENTION_HOURS: 24
  networks:
    - kafka-net
  volumes:
    - kafka-data-1:/var/lib/kafka/data

🔧 Kafka UI

kafka-ui:
  image: provectuslabs/kafka-ui
  ports:
    - "8080:8080"
  restart: always
  environment:
    KAFKA_CLUSTERS_0_NAME: "kraft-cluster"
    KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka-1:9094,kafka-2:9094,kafka-3:9094
  depends_on:
    - kafka-1
    - kafka-2
    - kafka-3
  networks:
    - kafka-net

📦 Các brokers kafka-2, kafka-3 có cấu hình tương tự kafka-1, chỉ khác KAFKA_NODE_ID, hostname, container_name, ports.

Sau khi hoàn thành mình sẽ được 1 file docker compose hoàn chỉnh sau

version: '3.5'

services:
  kafka-1:
    image: apache/kafka
    hostname: kafka-1
    container_name: kafka-kraft-1
    ports:
      - "19092:9092"
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: broker,controller
      KAFKA_LISTENERS: PLAINTEXT://kafka-1:9092,CONTROLLER://kafka-1:9093,INTERNAL://kafka-1:9094
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:19092,INTERNAL://kafka-1:9094
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka-1:9093,2@kafka-2:9093,3@kafka-3:9093
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_NUM_PARTITIONS: 1
      KAFKA_LOG_RETENTION_HOURS: 24
    networks:
      - kafka-net
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "./opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 > /dev/null 2>&1",
        ]
      interval: 10s
      timeout: 10s
      retries: 5
    volumes:
      - kafka-data-1:/var/lib/kafka/data

  kafka-2:
    image: apache/kafka
    hostname: kafka-2
    container_name: kafka-kraft-2
    ports:
      - "29092:9092"
    environment:
      KAFKA_NODE_ID: 2
      KAFKA_PROCESS_ROLES: broker,controller
      KAFKA_LISTENERS: PLAINTEXT://kafka-2:9092,CONTROLLER://kafka-2:9093,INTERNAL://kafka-2:9094
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:29092,INTERNAL://kafka-2:9094
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka-1:9093,2@kafka-2:9093,3@kafka-3:9093
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_NUM_PARTITIONS: 1
      KAFKA_LOG_RETENTION_HOURS: 24
    networks:
      - kafka-net
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "./opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 > /dev/null 2>&1",
        ]
      interval: 10s
      timeout: 10s
      retries: 5
    volumes:
      - kafka-data-2:/var/lib/kafka/data

  kafka-3:
    image: apache/kafka
    hostname: kafka-3
    container_name: kafka-kraft-3
    ports:
      - "39092:9092"
    environment:
      KAFKA_NODE_ID: 3
      KAFKA_PROCESS_ROLES: broker,controller
      KAFKA_LISTENERS: PLAINTEXT://kafka-3:9092,CONTROLLER://kafka-3:9093,INTERNAL://kafka-3:9094
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:39092,INTERNAL://kafka-3:9094
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka-1:9093,2@kafka-2:9093,3@kafka-3:9093
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_NUM_PARTITIONS: 1
      KAFKA_LOG_RETENTION_HOURS: 24
    networks:
      - kafka-net
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "./opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 > /dev/null 2>&1",
        ]
      interval: 10s
      timeout: 10s
      retries: 5
    volumes:
      - kafka-data-3:/var/lib/kafka/data

  kafka-ui:
    image: provectuslabs/kafka-ui
    ports:
      - "8080:8080"
    restart: always
    environment:
      KAFKA_CLUSTERS_0_NAME: "kraft-cluster"
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka-1:9094,kafka-2:9094,kafka-3:9094
    depends_on:
      - kafka-1
      - kafka-2
      - kafka-3
    networks:
      - kafka-net

volumes:
  kafka-data-1:
  kafka-data-2:
  kafka-data-3:

networks:
  kafka-net:
    driver: bridge

💾 Mount Volumes

volumes:
  kafka-data-1:
  kafka-data-2:
  kafka-data-3:

🌐 Mạng dùng chung

networks:
  kafka-net:
    driver: bridge

5. Khởi Chạy Hệ Thống

docker-compose up -d

✅ Sau khi chạy, bạn có thể truy cập Kafka UI tại: http://localhost:8080


6. Tạo Topic Mới Trong Kafka

Khi tạo topic, chú ý đến:

Thông số Mô tả
Topic name Tên topic
Number of partitions Phân vùng (nhiều partition giúp parallelism tốt hơn)
Replication factor Số bản sao cho mỗi partition
Min In Sync Replicas Số replicas tối thiểu đang online khi ghi
Cleanup policy Xóa (delete), ghi đè (compact), hoặc kết hợp
Retention.ms Kafka sẽ xóa dữ liệu sau thời gian này
Retention.bytes Dung lượng tối đa được giữ
Max message bytes Kích thước tối đa của message

🧪 Ví dụ:

Tạo topic payment.response.dev để nhận kết quả trả về từ event thanh toán.


7. Gửi Message Test

Bắn một message vào topic payment.response.dev sử dụng broker-1 (localhost:19092), sau đó kiểm tra trên Kafka UI.


📸 Hình Ảnh Minh Họa

Mô tả Hình ảnh
Container đã chạy containers
Kafka UI kafka-ui
Danh sách brokers brokers
Topic list topics
Tạo topic mới create-topic
Topic sau khi tạo topic-created
Message trong topic msg

🔗 Tham Khảo

Sau khi hoàn thành mình đã bỏ vào chatgpt để gen markdown cho đẹp, anh em xem thì vui vẻ nhé 😃))


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.