博客 / 詳情

返回

docker-compose 部署單節點 kafka 4.0 測試環境

高版本kafka已經不再需要ZooKeeper當保姆才能啓動了,現在部署一個單機單節點測試環境比原來方便不少。

不過最常用的bitnami/kafka不再提供免費鏡像,導致我們只能用apache/kafka,新鏡像的配置會稍微麻煩一些,所以記錄一下。

部署內容:

  • 單節點kafka服務,版本4.0+
  • kafka UI,方便管理,版本用最新的
  • 開啓簡單的用户名密碼驗證

docker-compose文件:

version: '3'

networks:
  kafka-net:

services:
  kafka:
    image: apache/kafka:latest
    container_name: kafka
    networks:
      - kafka-net
    ports:
      - "9092:9092"
    volumes:
      - ./kafka_data:/var/lib/kafka/data
      - ./kafka_server_jaas.conf:/etc/kafka/kafka_server_jaas.conf # 配置用户名密碼
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: 'broker,controller'
      KAFKA_CONTROLLER_QUORUM_VOTERS: '1@localhost:9093'
      KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
      
      # 定義監聽器:EXTERNAL(9092) 走 SASL 認證,PLAINTEXT(29092) 給容器內用(這裏也改為 SASL 確保安全)
      KAFKA_LISTENERS: 'SASL_PLAINTEXT://0.0.0.0:29092,EXTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093'
      KAFKA_ADVERTISED_LISTENERS: 'SASL_PLAINTEXT://kafka:29092,EXTERNAL://localhost:9092'
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT,EXTERNAL:SASL_PLAINTEXT'
      KAFKA_INTER_BROKER_LISTENER_NAME: 'SASL_PLAINTEXT'
      
      # SASL/PLAIN 認證配置
      KAFKA_SASL_ENABLED_MECHANISMS: 'PLAIN'
      KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: 'PLAIN'
      # 告訴 Kafka 讀取我們的 JAAS 文件
      KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf"

      # 數據持久化
      KAFKA_LOG_DIRS: '/var/lib/kafka/data'

  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: kafka-ui
    depends_on:
      - kafka
    networks:
      - kafka-net
    ports:
      # 映射到8090,因為8080一般還得掛其他的服務做測試
      - "8090:8080"
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:29092
      # 配置 UI 使用用户名和密碼連接 Kafka
      KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: SASL_PLAINTEXT
      KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM: PLAIN
      KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: 'org.apache.kafka.common.security.plain.PlainLoginModule required username="你配置的用户名" password="你配置的密碼";'

配置文件裏輸入用户和密碼:

KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="節點在集羣內通信時的用户名"
    password="節點在集羣內通信時的密碼"
    # 下面這些才是用户配置
    # 格式user_<用户名>="密碼"
    user_apot="你配置的密碼";
};

創建好文件和目錄之後用docker-compose up -d就能啓動服務了。訪問localhost:8090可以看到kafka的web控制面板:

image

安裝好之後可以用下面的命令查看版本:

$ docker exec -it kafka /opt/kafka/bin/kafka-server-start.sh --version

[2025-12-29 11:08:34,595] INFO Registered kafka:type=kafka.Log4jController MBean (kafka.utils.Log4jControllerRegistration$)
4.0.0

可以看到已經配置好了kafka 4.0環境。

apache/kafka的鏡像裏內置了各種操作kafka的腳本,不過這些腳本沒被添加進$PATH,執行的時候需要指定路徑:

# 先配置登錄驗證信息
docker exec -it kafka bash -c "cat <<EOF > /tmp/client.conf
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username='客户端登錄用户名,就是我們之前用user_xxx配置的那些' \
  password='客户端登錄密碼';
EOF"

# 調用腳本創建一個topic,需要指定腳本路徑
docker exec -it kafka /opt/kafka/bin/kafka-topics.sh --command-config /tmp/client.conf \
  --bootstrap-server localhost:9092 \
  --create \
  --topic test.data \
  --partitions 1 \
  --replication-factor 1 \
  --config cleanup.policy=delete \
  --config retention.ms=86400000

所有腳本都存放在/opt/kafka/bin路徑下,調用前還需要提供登錄憑證信息,這些需要注意。打開localhost:8090上的web UI,就能找到我們剛剛創建的topic了:

image

過期處理策略和過期時間也已經被正確設置:

image

總體而言執行腳本還是有些繁瑣,我更願意通過代碼或者web界面來做這些操作。

最後我們寫一個go的測試代碼,向我們的測試用單節點kafka裏寫入一些數據:

package main

import (
	"context"
	"math/rand/v2"
	"strconv"
	"time"

	"github.com/segmentio/kafka-go"
	"github.com/segmentio/kafka-go/sasl/plain"
)

const (
	topic         = "lean.data1"
	kafkaEndpoint = "localhost:9092"
)

func main() {
	mechanism := plain.Mechanism{
		Username: "客户端登錄用户名",
		Password: "客户端登錄密碼",
	}

	dialer := &kafka.Dialer{
		Timeout:       10 * time.Second,
		DualStack:     true,
		SASLMechanism: mechanism,
	}

	w := kafka.NewWriter(kafka.WriterConfig{
		Brokers: []string{kafkaEndpoint},
		Dialer:  dialer, // 必須傳入帶 SASL 的 dialer
		Async:   false,
	})
	defer w.Close()

	msg := kafka.Message{
		Topic: topic,
		Key:   []byte("test"),
		Value: []byte(strconv.Itoa(rand.Int())), // 隨便寫入一些隨機數據
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	err := w.WriteMessages(ctx, msg)
	if err != nil {
		panic(err)
	}
}

image

可以看到我們的隨機數已經正常寫入topic了。

注意:這個配置只使用了最基本的驗證,且是單節點,不適合在測試和學習之外的任何用途使用,為了安全我也建議在測試完成之後就立刻用docker-compose down關閉服務。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.