使用 Docker-Compose 部署 Kafka
1. Kafka 镜像选择
这里使用的是 Docker Hub 上使用最多的镜像:bitnami/kafka
,为什么使用这个镜像,看下官方的介绍:
- Bitnami closely tracks upstream source changes and promptly publishes new versions of this image using our automated systems.
- With Bitnami images the latest bug fixes and features are available as soon as possible.
- Bitnami containers, virtual machines and cloud images use the same components and configuration approach - making it easy to switch between formats based on your project needs.
- All our images are based on minideb -a minimalist Debian based container image that gives you a small base container image and the familiarity of a leading Linux distribution- or scratch -an explicitly empty image-.
- All Bitnami images available in Docker Hub are signed with Notation. Check this post to know how to verify the integrity of the images.
- Bitnami container images are released on a regular basis with the latest distribution packages available.
- Bitnami密切跟踪上游源的变化,并使用我们的自动化系统及时发布此图像的新版本。
- 有了Bitnami映像,最新的错误修复和特性就可以尽快获得。
- Bitnami容器、虚拟机和云映像使用相同的组件和配置方法——使得根据项目需要在格式之间切换变得很容易。
- 我们所有的映像都基于minideb——一个基于Debian的极简的容器映像,它为您提供了一个小型的基本容器映像,并使您熟悉领先的Linux发行版——或者scratch——一个显式空映像。
- Docker Hub中可用的所有Bitnami映像都使用Notation签名。查看这篇文章,了解如何验证图像的完整性。
- Bitnami容器映像会定期发布,其中包含可用的最新发行包。
在服务器国产化的趋势下,有的时候我们需要在 ARM 架构的机器上部署 Kafka,而 bitnami/kafka
不但更新的快,而且很多版本都是支持 X86 和 ARM 架构的,所以这也是我决定用这个发行版的原因。
这里贴一下官方的说明文档,喜欢原汁原味的可以直接看官方文档,以下内容可参考使用。
2. 版本选择
版本可以根据个人喜好,新版本的 Kafka ,从 3.3
版本后,Kafka 引入了 KRaft
来替代 ZooKeeper
,也就是说后面的版本,可以不用部署 ZooKeeper
就可以使用了。
当然如果还想使用 ZooKeeper
也是可以的。
这里我使用 3.4
版本;目前最新的版本已经是 3.7
了,并且对于 bitnami/kafka
的 Kafka 镜像来说,部署脚本不区分 X86 和 ARM 架构的,两者的使用是没有区别的,这点可以放心使用;
3. 无密码部署
新建 docker-compose.yaml 文件,内容如下:
version: '2'
networks:
app-tier:
driver: bridge
services:
kafka:
image: 'bitnami/kafka:3.4'
container_name: kafka
hostname: kafka
privileged: true
ports:
- "9092:9092"
- "9094:9094"
networks:
- app-tier
environment:
- TZ=Asia/Shanghai
- KAFKA_KRAFT_CLUSTER_ID=iZWRiSqjZAlYwlKEqHFQWI
- KAFKA_CFG_NODE_ID=0
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://宿主机IP地址:9094 # 传递回客户端的元数据,填写宿主机IP地址
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
参数说明:
KAFKA_KRAFT_CLUSTER_ID=iZWRiSqjZAlYwlKEqHFQWI
使用 Kafka 时的集群id,集群内的Kafka都要用这个id做初始化,生成一个UUID即可;KAFKA_ENABLE_KRAFT=yes
允许使用 kraft,即 kraft 替代 Zookeeper, 默认 yes 可不用配置;KAFKA_CFG_NODE_ID=0
节点ID,同一集群中需唯一;KAFKA_CFG_PROCESS_ROLES=controller,broker
kafka角色,做 broker,也要做 controller;KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
定义kafka 服务端 socket 监听端口(Docker内部的ip地址和端口);KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://ip:19092
定义外网访问地址(宿主机ip地址和端口)ip不能是0.0.0.0;KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka:9093
集群内部通信地址KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
定义安全协议,默认无密码;KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=false
如果主题不存在时,是否允许自动创建主题;
直接使用 docker-compose up -d 启动 Kafka 服务;
参数配置错误,可能导致 Kafka 无法正常启动,可以通过查看 Kafka 服务的日志来看是否正常启动,如果出现各种奇奇怪怪的异常问题,就得排查配置的环境变量了。
启动成功,日志如下:
[2024-04-30 16:53:21,101] INFO Awaiting socket connections on 0.0.0.0:9092. (kafka.network.DataPlaneAcceptor)
[2024-04-30 16:53:21,103] INFO Awaiting socket connections on 0.0.0.0:9094. (kafka.network.DataPlaneAcceptor)
[2024-04-30 16:53:21,106] INFO [BrokerServer id=0] Waiting for all of the authorizer futures to be completed (kafka.server.BrokerServer)
[2024-04-30 16:53:21,106] INFO [BrokerServer id=0] Finished waiting for all of the authorizer futures to be completed (kafka.server.BrokerServer)
[2024-04-30 16:53:21,106] INFO [BrokerServer id=0] Waiting for all of the SocketServer Acceptors to be started (kafka.server.BrokerServer)
[2024-04-30 16:53:21,106] INFO [BrokerServer id=0] Finished waiting for all of the SocketServer Acceptors to be started (kafka.server.BrokerServer)
[2024-04-30 16:53:21,106] INFO [BrokerServer id=0] Transition from STARTING to STARTED (kafka.server.BrokerServer)
[2024-04-30 16:53:21,107] INFO Kafka version: 3.7.0 (org.apache.kafka.common.utils.AppInfoParser)
[2024-04-30 16:53:21,107] INFO Kafka commitId: 2ae524ed625438c5 (org.apache.kafka.common.utils.AppInfoParser)
[2024-04-30 16:53:21,108] INFO Kafka startTimeMs: 1714467201107 (org.apache.kafka.common.utils.AppInfoParser)
[2024-04-30 16:53:21,110] INFO [KafkaRaftServer nodeId=0] Kafka Server started (kafka.server.KafkaRaftServer)
接着使用命令行测试下 Kafka。
4. 命令行操作 Kafak 生产消息、消费消息
新开两个窗口,一个作为生产者,进入容器后,直接执行命令:
kafka-console-producer.sh --producer.config /opt/bitnami/kafka/config/producer.properties --bootstrap-server 127.0.0.1:9094 --topic test
这里直接操作名为 test
的主体,因为上面配置了允许自动创建主题,所以这里不会报错,如果不允许自动创建主题,这里会报错;
正常这里会有个WARN
提醒:
[2024-04-30 16:56:27,895] WARN [Producer clientId=console-producer] Error while fetching metadata with correlation id 6 : {test=UNKNOWN_TOPIC_OR_PARTITION} (org.apache.kafka.clients.NetworkClient)
但是并不影响控制台使用,如果出现 >
则表示已自动进入控制台,等待接收消息了。
输入一条消息,消息内容为: Hello
这里使用的是 9094
端口,也就是外部机器访问的端口,当然也可以直接使用 9092
端口,如果在外部机器上执行这个脚本的话,就得使用当前机器的IP:9094
;
第一次发消息时,有个 WARN
提醒:
WARN [Producer clientId=console-producer] Error while fetching metadata with correlation id 6 : {test=UNKNOWN_TOPIC_OR_PARTITION} (org.apache.kafka.clients.NetworkClient)
这是因为未设置主体的分区导致的,如果是手动创建的主题,并且设置了副本数和分区数,就应该不会有这个提醒了。
再打开一个窗口,作为消费者,进入容器执行命令:
kafka-console-consumer.sh --consumer.config /opt/bitnami/kafka/config/consumer.properties --bootstrap-server 127.0.0.1:9094 --topic test --from-beginning
接着可以看到自动打印未消费的消息;
保持两个窗口开启状态,在生产者窗口里,再次生成一条消息,可以看到消费者窗口,正常打印新的消息。