Docker部署Kafka单机或者集群指南
=====================
前不久,Apache官方推出了Kafka的Docker镜像,这也使得我们可以容器化地部署Kafka消息中间件了。
那么今天我们就以KRaft模式部署Kafka的单机和集群为例,梳理一下如何使用Docker完成Kafka部署。
在学习本章节之前,建议大家先要弄清楚Kafka集群节点中的角色类型、常见的配置项意义等等,如果还不太熟悉建议先通过该博客进行学习:传送门
1,拉取镜像
通过下列命令即可:
docker pull apache/kafka
2,配置方式说明
在使用Docker部署Kafka时,我们可以通过下列方式来修改Kafka的配置:
- 使用数据卷暴露配置目录,然后修改其中的文件
- 使用环境变量指定
在使用Docker部署时,更加推荐使用环境变量的方式,这样我们一键就可以完成部署。
不过,配置文件中的配置名称和环境变量的名称格式是不一样的,因此在将配置文件中对应配置项转换成环境变量时,名称上需要进行一些转换:
- 配置文件中名称的
.
要替换成_
- 配置文件中名称的
_
要替换成__
(双下划线) - 配置文件中名称的
-
要替换成___
(三下划线) - 环境变量还需要在最前面加上
KAFKA_
前缀
下面举几个例子:
| 配置文件 | 环境变量 |
| — | — |
| node.id
| KAFKA_NODE_ID
|
| process.roles
| KAFKA_PROCESS_ROLES
|
| listeners
| KAFKA_LISTENERS
|
3,开始部署
本次在一台服务器上进行实验,该服务器的地址是gitdoc.swsk33-mcs.top
,我们下面都会使用这个地址代表外网地址。
(1) 单节点部署
在进行单节点部署并以KRaft模式运行时,该节点通常是混合节点的类型,通过下列命令:
docker run -id --name=kafka \
-p 9092:9092 \
-v kafka-config:/mnt/shared/config \
-v kafka-data:/var/lib/kafka/data \
-v kafka-secret:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=1 \
-e KAFKA_PROCESS_ROLES=broker,controller \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@127.0.0.1:9093" \
-e KAFKA_LISTENERS="PLAINTEXT://:9092,CONTROLLER://:9093" \
-e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://gitdoc.swsk33-mcs.top:9092" \
apache/kafka
可见我们挂载了下列数据卷:
kafka-config
持久化配置文件目录kafka-data
持久化数据文件夹,如果运行出现问题可以清空该数据卷文件重启再试kafka-secret
持久化秘钥相关文件夹
然后我们通过环境变量进行了许多了配置,除了指定容器环境为UTF-8
之外,还有下列关于Kafka的配置:
KAFKA_INTER_BROKER_LISTENER_NAME
Kafka的Broker地址前缀名称,固定为PLAINTEXT
即可KAFKA_CONTROLLER_LISTENER_NAMES
Kafka的Controller地址前缀名称,固定为CONTROLLER
即可CLUSTER_ID
集群ID,可以自定义任何字符串作为集群ID,同一个集群中所有节点的集群ID必须配置为一样KAFKA_NODE_ID
节点ID,用于标识每个集群中的节点,需要是不小于1
的整数,同一个集群中的节点ID不可重复KAFKA_PROCESS_ROLES
节点类型,broker,controller
表示该节点是混合节点,通常单机部署时需要配置为混合节点KAFKA_CONTROLLER_QUORUM_VOTERS
投票节点列表,通常配置为集群中所有的Controller节点,格式为节点id@节点外网地址:节点Controller端口
,多个节点使用逗号,
隔开,由于是混合节点,因此配置自己就行了KAFKA_LISTENERS
表示Kafka要监听哪些端口,PLAINTEXT://:9092,CONTROLLER://:9093
表示本节点作为混合节点,监听本机所有可用网卡的9092
和9093
端口,其中9092
作为客户端通信端口,9093
作为控制器端口KAFKA_ADVERTISED_LISTENERS
配置Kafka的外网地址,需要是PLAINTEXT://外网地址:端口
的形式,当客户端连接Kafka服务端时,Kafka会将这个外网地址广播给客户端,然后客户端再通过这个外网地址连接,除此之外集群之间交换数据时也是通过这个配置项得到集群中每个节点的地址的,这样集群中节点才能进行交互
大家可以和常用的配置项对应起来看,其实也很好理解,总的来说单机部署较为简单。
(2) 全混合节点集群
我们还可以部署多个混合节点,使它们构成一个集群,通常在开发或者实验环境下可以部署全混合节点,不过在生产环境就不推荐了。
我们本次实验的全混合节点集群信息如下:
| 容器名 | 节点id
| 节点外网地址 | 节点类型 | 容器9092
端口映射到的宿主机端口 | 容器9093
端口映射到的宿主机端口 |
| — | — | — | — | — | — |
| kafka-1
| 1
| gitdoc.swsk33-mcs.top
| broker,controller
| 9001
| 10001
|
| kafka-2
| 2
| gitdoc.swsk33-mcs.top
| broker,controller
| 9002
| 10002
|
| kafka-3
| 3
| gitdoc.swsk33-mcs.top
| broker,controller
| 9003
| 10003
|
在服务器上部署命令如下:
# 定义域名
# 这是fish shell的变量定义语法
# 使用bash请替换为:kafka_host="gitdoc.swsk33-mcs.top"
set kafka_host "gitdoc.swsk33-mcs.top"
# 节点1
docker run -id --name=kafka-1 \
-p 9001:9092 -p 10001:9093 \
-v kafka-config-1:/mnt/shared/config \
-v kafka-data-1:/var/lib/kafka/data \
-v kafka-secret-1:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=1 \
-e KAFKA_PROCESS_ROLES=broker,controller \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@$kafka_host:10001,2@$kafka_host:10002,3@$kafka_host:10003" \
-e KAFKA_LISTENERS="PLAINTEXT://:9092,CONTROLLER://:9093" \
-e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://$kafka_host:9001" \
apache/kafka
# 节点2
docker run -id --name=kafka-2 \
-p 9002:9092 -p 10002:9093 \
-v kafka-config-2:/mnt/shared/config \
-v kafka-data-2:/var/lib/kafka/data \
-v kafka-secret-2:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=2 \
-e KAFKA_PROCESS_ROLES=broker,controller \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@$kafka_host:10001,2@$kafka_host:10002,3@$kafka_host:10003" \
-e KAFKA_LISTENERS="PLAINTEXT://:9092,CONTROLLER://:9093" \
-e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://$kafka_host:9002" \
apache/kafka
# 节点3
docker run -id --name=kafka-3 \
-p 9003:9092 -p 10003:9093 \
-v kafka-config-3:/mnt/shared/config \
-v kafka-data-3:/var/lib/kafka/data \
-v kafka-secret-3:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=3 \
-e KAFKA_PROCESS_ROLES=broker,controller \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@$kafka_host:10001,2@$kafka_host:10002,3@$kafka_host:10003" \
-e KAFKA_LISTENERS="PLAINTEXT://:9092,CONTROLLER://:9093" \
-e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://$kafka_host:9003" \
apache/kafka
可以使用docker logs -f
命令查看日志,输出Kafka Server started
字样说明该节点启动成功,并已连结到其它集群节点:
我们可以在节点1中创建一个话题测试一下(调用容器中/opt/kafka/bin/
路径下脚本进行操作):
docker exec -it kafka-1 /opt/kafka/bin/kafka-topics.sh --create --topic wocaoop --bootstrap-server localhost:9092
然后通过节点3获取话题:
docker exec -it kafka-3 /opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092
这说明我们的集群之间是可以正常进行数据交换的:
可见部署混合节点时,每个节点的部署方式和单机部署时几乎类似,不过需要注意的是:
- 每个节点都需要暴露
9092
和9093
端口,这两个端口作用如下:9092
端口:用于客户端(生产者或者消费者)投递消息至Kafka消息队列或者从中取出消息,通常Java集成Kafka客户端时访问该端口,也就是客户端通信端口9093
端口:KRaft模式下节点直接投票选举通信或者是从Controller节点获取元数据的端口,由于KRaft模式下没有了Zookeeper,因此集群中所有Kafka节点会相互投票选择出存放和管理元数据的Controller节点,这个端口就是用于投票选举时的相互通信或者从Controller节点获取元数据,也就是控制器端口
- 由于都是混合节点,因此每个节点都有Controller属性,所以
KAFKA_CONTROLLER_QUORUM_VOTERS
都要配置为所有节点的外网地址和端口,端口需要是控制器端口 KAFKA_ADVERTISED_LISTENERS
配置为每个节点的外网地址及其客户端通信端口,需要保证客户端或者其它Kafka节点能够通过该地址端口在外网访问到
(3) Broker
+ Controller
集群
这是推荐的生产环境的集群部署方式,集群中不存在混合节点,每个节点要么是Broker类型,要么是Controller类型,而不是像上面一样“身兼多职”,这里我们的实验集群信息如下:
| 容器名 | 节点id
| 节点外网地址 | 节点类型 | 容器9092
端口映射到的宿主机端口 | 容器9093
端口映射到的宿主机端口 |
| — | — | — | — | — | — |
| kafka-1
| 1
| gitdoc.swsk33-mcs.top
| controller
| / | 10001
|
| kafka-2
| 2
| gitdoc.swsk33-mcs.top
| broker
| 9002
| / |
| kafka-3
| 3
| gitdoc.swsk33-mcs.top
| broker
| 9003
| / |
通过下列命令在服务器上部署:
# 定义域名
# 这是fish shell的变量定义语法
# 使用bash请替换为:kafka_host="gitdoc.swsk33-mcs.top"
set kafka_host "gitdoc.swsk33-mcs.top"
# 节点1-Controller
docker run -id --name=kafka-1 \
-p 10001:9093 \
-v kafka-config-1:/mnt/shared/config \
-v kafka-data-1:/var/lib/kafka/data \
-v kafka-secret-1:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=1 \
-e KAFKA_PROCESS_ROLES=controller \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@$kafka_host:10001" \
-e KAFKA_LISTENERS="CONTROLLER://:9093" \
apache/kafka
# 节点2-Broker
docker run -id --name=kafka-2 \
-p 9002:9092 \
-v kafka-config-2:/mnt/shared/config \
-v kafka-data-2:/var/lib/kafka/data \
-v kafka-secret-2:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=2 \
-e KAFKA_PROCESS_ROLES=broker \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@$kafka_host:10001" \
-e KAFKA_LISTENERS="PLAINTEXT://:9092" \
-e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://$kafka_host:9002" \
apache/kafka
# 节点3-Broker
docker run -id --name=kafka-3 \
-p 9003:9092 \
-v kafka-config-3:/mnt/shared/config \
-v kafka-data-3:/var/lib/kafka/data \
-v kafka-secret-3:/etc/kafka/secrets \
-e LANG=C.UTF-8 \
-e KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e CLUSTER_ID=the-custom-id \
-e KAFKA_NODE_ID=3 \
-e KAFKA_PROCESS_ROLES=broker \
-e KAFKA_CONTROLLER_QUORUM_VOTERS="1@$kafka_host:10001" \
-e KAFKA_LISTENERS="PLAINTEXT://:9092" \
-e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://$kafka_host:9003" \
apache/kafka
这样,我们就部署了一个由1
个Controller节点和2
个Broker节点构成的集群,需要注意的是:
- Broker节点无需暴露
9093
端口,Controller节点无需暴露9092
端口,因为它们只需要使用一个端口,混合节点才是两个端口都需要使用 - Broker节点需指定
KAFKA_PROCESS_ROLES
为broker
,同样的Controller需要指定为controller
KAFKA_CONTROLLER_QUORUM_VOTERS
配置只需要写集群中所有的Controller节点的地址端口列表- 对于
KAFKA_LISTENERS
配置项:- Broker节点需要配置为
PLAINTEXT://:9092
,表示本节点作为Broker节点,监听本机所有可用网卡的9092
端口,即使用9092
端口作为客户端通信端口 - Controller节点需要配置为
CONTROLLER://:9093
,表示本节点作为Controller节点,监听本机所有可用网卡的9093
端口,即使用9093
端口作为控制器端口
- Broker节点需要配置为
- 对于
KAFKA_ADVERTISED_LISTENERS
配置项:- Controller节点不能指定该配置
- Broker节点需要指定为自己的外网地址和端口,以
PLAINTEXT://
开头,和前面一样
4,Sping Boot连接到Kafka集群
在使用Spring Boot连接到Kafka集群时,需要先加入下列依赖:
<!-- 集成Kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
也可以在创建工程时,选择Messaging
分类中的Spring for Apache Kafka
作为依赖。
然后在application.yml
配置文件中加入相关的配置,对于生产者:
# Kafka-生产者配置
spring:
kafka:
bootstrap-servers: "127.0.0.1:9092"
producer:
key-serializer: "org.apache.kafka.common.serialization.StringSerializer"
value-serializer: "org.springframework.kafka.support.serializer.JsonSerializer"
对于消费者:
# Kafka-消费者配置
spring:
kafka:
bootstrap-servers: "127.0.0.1:9092"
consumer:
group-id: topic
key-deserializer: "org.apache.kafka.common.serialization.StringDeserializer"
value-deserializer: "org.springframework.kafka.support.serializer.JsonDeserializer"
properties:
"[spring.json.trusted.packages]": "*"
对于同时作为生产者和消费者的情况下:
# Kafka-既是生产者也是消费者配置
spring:
kafka:
bootstrap-servers: "127.0.0.1:9092"
producer:
key-serializer: "org.apache.kafka.common.serialization.StringSerializer"
value-serializer: "org.springframework.kafka.support.serializer.JsonSerializer"
consumer:
group-id: topic
key-deserializer: "org.apache.kafka.common.serialization.StringDeserializer"
value-deserializer: "org.springframework.kafka.support.serializer.JsonDeserializer"
properties:
"[spring.json.trusted.packages]": "*"
可见无论是哪种配置,都有spring.kafka.bootstrap-servers
配置表示配置Kafka的节点地址,上述配置的是本地单机节点,对于集群配置如下:
spring:
kafka:
bootstrap-servers: "kafka1地址:kafka1端口,kafka2地址:kafka2端口,kafka3地址:kafka3端口"
# 省略其它...
可见指定集群每个节点的外网地址和端口即可,每个节点之间使用逗号隔开。
需要注意的是,连接集群时只配置Broker节点和混合节点的地址端口即可,不要把Controller节点的地址端口配置进去了!
参考文档:
- Kafka Docker镜像主页:传送门
- Kafka Docker镜像使用文档:传送门
- Spring Kafka文档:传送门
- Spring Boot Kafka配置指引:传送门
原文链接: https://juejin.cn/post/7380421216019365897
文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/17244.html