KRaft (Kafka 4.0) 集群配置指南(超简单,脱离 ZooKeeper 集群)还包含了简化测试指令的脚本!!!

发布于:2025-05-09 ⋅ 阅读:(15) ⋅ 点赞:(0)

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.0
    container_name: kafka-0
    ports:
      - "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=2
    volumes:
      - /data/kafka/kafka-0:/bitnami/kafka

 这是第一个节点::1

services:
  kafka-1:
    image: bitnami/kafka:4.0.0
    container_name: kafka-1
    ports:
      - "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=2
    volumes:
      - /data/kafka/kafka-0:/bitnami/kafka

 这是第三个节点:2

services:
  kafka-2:
    image: bitnami/kafka:4.0.0
    container_name: kafka-2
    ports:
      - "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=2
    volumes:
      - /data/kafka/kafka-0:/bitnami/kafka

 

每个 Kafka 节点的配置都类似,只是 KAFKA_CFG_NODE_IDKAFKA_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 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" ]; then
    echo "请指定主题名称!"
    return 1
  fi
  kafka-console-producer.sh --broker-list localhost:9092 --topic "$1"
}

# 消费指定主题的消息
kc() {
  if [ -z "$1" ]; then
    echo "请指定主题名称!"
    return 1
  fi
  kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic "$1" --from-beginning
}

# 删除指定主题
kd() {
  if [ -z "$1" ]; then
    echo "请指定主题名称!"
    return 1
  fi
  kafka-topics.sh --bootstrap-server localhost:9092 --topic "$1" --delete
}

# 查看指定主题描述
kdesc() {
  if [ -z "$1" ]; then
    echo "请指定主题名称!"
    return 1
  fi
  kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic "$1"
}

# 创建一个新主题
create_topic() {
  if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
    echo "请提供主题名称、分区数和副本数!"
    return 1
  fi
  kafka-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 集群。


网站公告

今日签到

点亮在社区的每一天
去签到