docker-compose方式部署kafka集群
Kafka 4.0 引入了 KRaft 模式(Kafka Raft Metadata Mode),它使 Kafka 集群不再依賴 ZooKeeper 進行元數據管理。KRaft 模式簡化了 Kafka 部署和管理,不需要額外配置 ZooKeeper 服務,使得集群的配置和運維更加高效。
本文將介紹如何配置一個基于 KRaft 模式的 Kafka 集群,步驟簡單明了。我們將從零開始,介紹如何配置 Kafka 集群并進行測試,包括遇到的權限問題以及如何通過自定義工具簡化測試命令。
一、KRaft 模式簡介
KRaft(Kafka Raft Metadata Mode)是 Kafka 在 4.0 版本引入的一個新特性,旨在替代傳統的依賴 ZooKeeper 的架構。在 KRaft 模式下,Kafka 使用內建的 Raft 協議來管理元數據和集群協調,而不需要外部的 ZooKeeper 服務。
主要特點:
不再依賴 ZooKeeper。
使用 Kafka 自帶的 Raft 協議處理元數據和控制器選舉。
簡化了集群配置,降低了維護成本。
二、集群配置
1. 配置主機
在本例中,我們使用了 3 臺主機,每臺主機上啟動一個 Kafka 容器,形成一個簡單的 KRaft 模式集群。
主機 1 (IP: 172.16.0.106):配置為 Kafka 節點 0。
主機 2 (IP: 172.16.0.107):配置為 Kafka 節點 1。
主機 3 (IP: 172.16.0.108):配置為 Kafka 節點 2。
2. Kafka 配置
在
docker-compose.yml
中,我們配置了 3 個 Kafka 節點的容器,采用 KRaft 模式,并設置了必要的環境變量來啟動集群。
這是第一個節點:0
services:kafka-0:image: bitnami/kafka:4.0.0container_name: kafka-0ports:- "9092:9092"- "9093:9093"environment:- KAFKA_CFG_NODE_ID=0- KAFKA_CFG_PROCESS_ROLES=controller,broker- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@172.16.0.106:9093,1@172.16.0.107:9093,2@172.16.0.108:9093- KAFKA_KRAFT_CLUSTER_ID=abcdefghijklmnopqrstuv- KAFKA_CFG_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://172.16.0.106:9092- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2volumes:- /data/kafka/kafka-0:/bitnami/kafka
?這是第一個節點::1
services:kafka-1:image: bitnami/kafka:4.0.0container_name: kafka-1ports:- "9092:9092"- "9093:9093"environment:- KAFKA_CFG_NODE_ID=1- KAFKA_CFG_PROCESS_ROLES=controller,broker- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@172.16.0.106:9093,1@172.16.0.107:9093,2@172.16.0.108:9093- KAFKA_KRAFT_CLUSTER_ID=abcdefghijklmnopqrstuv- KAFKA_CFG_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://172.16.0.107:9092- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2volumes:- /data/kafka/kafka-0:/bitnami/kafka
?這是第三個節點:2
services:kafka-2:image: bitnami/kafka:4.0.0container_name: kafka-2ports:- "9092:9092"- "9093:9093"environment:- KAFKA_CFG_NODE_ID=0- KAFKA_CFG_PROCESS_ROLES=controller,broker- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@172.16.0.106:9093,1@172.16.0.107:9093,2@172.16.0.108:9093- KAFKA_KRAFT_CLUSTER_ID=abcdefghijklmnopqrstuv- KAFKA_CFG_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://172.16.0.108:9092- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2volumes:- /data/kafka/kafka-0:/bitnami/kafka
?
每個 Kafka 節點的配置都類似,只是 KAFKA_CFG_NODE_ID
和 KAFKA_CFG_ADVERTISED_LISTENERS
不同。
3. 數據持久化
通過 Docker 的 volumes
配置,我們將每個容器的數據目錄掛載到宿主機上,從而實現數據持久化。如下所示:
volumes:- /data/kafka/kafka-0:/bitnami/kafka
這意味著 Kafka 容器中的數據會存儲在宿主機的 /data/kafka/kafka-0
目錄中,即使容器停止或刪除,數據也不會丟失。
三、遇到的權限問題及解決方法
在配置過程中,我遇到了一個權限問題:容器內的腳本無法刪除臨時文件或執行一些操作。
解決方法:
-
容器內操作權限問題:由于容器內沒有
sudo
權限,導致無法執行一些文件刪除操作。解決方案是在宿主機上執行相關操作,使用docker exec
執行命令時確保使用正確的權限。 -
文件系統權限:掛載到容器的宿主機目錄
/data/kafka/kafka-0
必須確保有正確的讀寫權限,否則 Kafka 容器無法正常寫入數據。確保宿主機上的目錄擁有正確的權限,例如使用chmod
命令修改目錄權限。
四、集群測試
測試 Kafka 集群是否成功部署,我們使用了以下步驟:
-
啟動 Kafka 容器:使用
docker-compose up
?分別啟動集群。 -
這個問題!Kafka 在 Docker 容器中運行時,通常會以
1001
這個用戶 ID(UID)來啟動,而宿主機上的目錄默認可能是root
用戶所有。這就導致了 Kafka 在容器內無法對掛載的目錄進行寫入或修改,因為容器用戶與宿主機目錄的所有者不同。解決方法:
你可以通過更改宿主機目錄的所有者為容器內的 Kafka 用戶(即 UID
1001
),這樣容器就能夠正確地訪問和修改該目錄。執行以下命令:
sudo chown -R 1001:1001 ./kafka_data
這將會把宿主機上的 ./kafka_data
目錄的所有者更改為 UID 1001
,即容器內的 Kafka 用戶。這樣,容器就可以在該目錄下創建所需的文件了。
為什么要這么做?
Kafka 容器默認使用
1001
用戶運行,而宿主機的目錄默認是root
用戶擁有。Docker 容器內的進程沒有
root
權限,因此無法修改宿主機上的目錄(除非你將宿主機目錄的權限改為所有人都能寫入)。使用
chown -R 1001:1001
將目錄所有者改為容器內 Kafka 用戶,使容器能夠訪問和操作該目錄。
?
-
檢查 Kafka 主題:使用
kafka-topics.sh --list --bootstrap-server localhost:9092
命令查看集群中的所有主題。
-
創建測試主題:通過
kafka-topics.sh --create --topic test --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1
創建一個名為
test
的測試主題。
docker exec -it kafka-0 bash
kafka-topics.sh --create --topic test --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1
kafka-topics.sh --list --bootstrap-server localhost:9092
五、自定義工具簡化命令
為了方便測試,我編寫了一個自定義工具腳本 kafka-tools.sh
,通過簡單的命令執行 Kafka 常用操作:
1.宿主機(容器外部)執行:
vim?kafka-tools.sh
#!/bin/bash# Kafka操作函數# 列出所有主題
kt() {kafka-topics.sh --list --bootstrap-server localhost:9092
}# 生產消息到指定主題
kp() {if [ -z "$1" ]; thenecho "請指定主題名稱!"return 1fikafka-console-producer.sh --broker-list localhost:9092 --topic "$1"
}# 消費指定主題的消息
kc() {if [ -z "$1" ]; thenecho "請指定主題名稱!"return 1fikafka-console-consumer.sh --bootstrap-server localhost:9092 --topic "$1" --from-beginning
}# 刪除指定主題
kd() {if [ -z "$1" ]; thenecho "請指定主題名稱!"return 1fikafka-topics.sh --bootstrap-server localhost:9092 --topic "$1" --delete
}# 查看指定主題描述
kdesc() {if [ -z "$1" ]; thenecho "請指定主題名稱!"return 1fikafka-topics.sh --bootstrap-server localhost:9092 --describe --topic "$1"
}# 創建一個新主題
create_topic() {if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; thenecho "請提供主題名稱、分區數和副本數!"return 1fikafka-topics.sh --create --topic "$1" --bootstrap-server localhost:9092 --partitions "$2" --replication-factor "$3"
}# 提示
echo "? Kafka 自定義工具函數已經加載成功(使用方式如下):"
echo " kt --list ----查看所有主題"
echo " kp my-topic ----使用主題生產"
echo " kc my-topic ----使用主題消費"
echo " kd my-topic ----刪除主題"
echo " kdesc my-topic ----主題描述"
echo " create_topic my-topic 3 1 ----創建主題 (例如:3個分區,1個副本)"
?
?2.將.sh文件移動到容器內部:
docker cp kafka-tools.sh kafka-0:/tmp/kafka-tools.sh
docker cp kafka-tools.sh kafka-1:/tmp/kafka-tools.sh
docker cp kafka-tools.sh kafka-2:/tmp/kafka-tools.sh
docker cp kafka-tools.sh kafka-0:/tmp/kafka-tools.sh
docker exec -it kafka-0 bash
source /tmp/kafka-tools.sh
?
3.進入容器?
docker exec -it kafka-0 bash
4.執行:
?source /tmp/kafka-tools.sh
?提示:則執行成功
生命周期是每次容器內執行后(容器不死,方便測試,復雜參數的命令還是需要自己去寫或者完善該腳本)
使用方法:
-
kt --list
:查看所有 Kafka 主題。 -
kp <topic>
:生產消息到指定主題。 -
kc <topic>
:消費指定主題的消息。 -
kd <topic>
:刪除指定的主題。 -
kdesc <topic>
:查看指定主題的描述。
通過這些簡化命令,我可以在容器內快速執行 Kafka 操作,而不需要記住每個命令的詳細參數。
加載成功后,你可以直接在容器內使用簡化命令,極大地方便了測試和管理 Kafka 集群。
六、總結
本文介紹了如何配置 KRaft 模式的 Kafka 4.0 集群,并解決了容器內的權限問題。通過自定義工具腳本,我們將常用的 Kafka 操作簡化為一系列簡單的命令,使得集群管理更加高效。
KRaft 模式是 Kafka 4.0 中的重要特性,它的引入讓 Kafka 不再依賴 ZooKeeper,簡化了集群的部署和管理。希望本文能幫助你順利部署并管理 KRaft 模式的 Kafka 集群。