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目录中,即使容器停止或删除,数据也不会丢失。
三、遇到的权限问题及解决方法
在配置过程中,我遇到了一个权限问题:容器内的脚本无法删除临时文件或执行一些操作。
解决方法:
1.容器内操作权限问题:由于容器内没有sudo权限,导致无法执行一些文件删除操作。
解决方案是在宿主机上执行相关操作,使用docker exec执行命令时确保使用正确的权限。
2.文件系统权限:挂载到容器的宿主机目录/data/kafka/kafka-0必须确保有正确的读写权限,否则Kafka容器无法正常写入数据。
确保宿主机上的目录拥有正确的权限,例如使用chmod命令修改目录权限。
四、集群测试
测试Kafka集群是否成功部署,我们使用了以下步骤:
1.启动Kafka容器:使用docker-compose up分别启动集群。
2.这个问题!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用户,使容器能够访问和操作该目录。
1.检查Kafka主题:
使用kafka-topics.sh --list --bootstrap-server localhost:9092命令查看集群中的所有主题。
2.创建测试主题:
通过kafka-topics.sh --create --topic test --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1创建一个名为test的测试主题。
docker exec -it kafka-0 bashkafka-topics.sh --create --topic test --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1kafka-topics.sh --list --bootstrap-server localhost:9092
五、自定义工具简化命令
为了方便测试,我编写了一个自定义工具脚本kafka-tools.sh,通过简单的命令执行Kafka常用操作:
1.宿主机(容器外部)执行:vim kafka-tools.sh
# 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.shdocker cp kafka-tools.sh kafka-1:/tmp/kafka-tools.shdocker cp kafka-tools.sh kafka-2:/tmp/kafka-tools.sh
docker cp kafka-tools.sh kafka-0:/tmp/kafka-tools.shdocker exec -it kafka-0 bashsource /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集群。

