基于docker-compose的kafka集群搭建
使用
docker-compose
搭建
kafka
集群,解析一些参数含义及列出搭建过程的一些坑。
1. docker-compose文件
直接上yml文件
version: '3.3'
networks:
kafka:
services:
zookeeper:
image: zookeeper
container_name: zookeeper-kafka
ports:
- 2181:2181
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
volumes:
- /usr/local/etc/kafka/data/zookeeper/data:/data
- /usr/local/etc/kafka/data/zookeeper/datalog:/datalog
networks:
- kafka
restart: unless-stopped
kafka1:
image: wurstmeister/kafka
container_name: kafka1
depends_on:
- zookeeper
ports:
- 9091:9091
environment:
KAFKA_BROKER_ID: 0
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181/kafka
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9091
KAFKA_LOG_DIRS: /data/kafka-log
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9091
BOOTSTRAP_SERVERS: kafka1:9091,kafka2:9092,kafka3:9093
volumes:
- /usr/local/etc/kafka/data/kafka1:/kafka
- /var/run/docker.sock:/var/run/docker.sock
networks:
- kafka
restart: unless-stopped
kafka2:
image: wurstmeister/kafka
container_name: kafka2
depends_on:
- zookeeper
ports:
- 9092:9092
environment:
KAFKA_BROKER_ID: 1
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181/kafka
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
KAFKA_LOG_DIRS: /data/kafka-log
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092
BOOTSTRAP_SERVERS: kafka1:9091,kafka2:9092,kafka3:9093
volumes:
- /usr/local/etc/kafka/data/kafka2:/kafka
- /var/run/docker.sock:/var/run/docker.sock
networks:
- kafka
restart: unless-stopped
kafka3:
image: wurstmeister/kafka
container_name: kafka3
depends_on:
- zookeeper
ports:
- 9093:9093
environment:
KAFKA_BROKER_ID: 2
KAFKA_NUM_PARTITIONS: 3
KAFKA_DEFAULT_REPLICATION_FACTOR: 2
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181/kafka
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9093
KAFKA_LOG_DIRS: /data/kafka-log
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka3:9093
BOOTSTRAP_SERVERS: kafka1:9091,kafka2:9092,kafka3:9093
volumes:
- /usr/local/etc/kafka/data/kafka3:/kafka
- /var/run/docker.sock:/var/run/docker.sock
networks:
- kafka
restart: unless-stopped
kafka_manager:
image: hlebalbau/kafka-manager:latest
container_name: kafka_manager
ports:
- 9000:9000
environment:
ZK_HOSTS: zookeeper:2181
APPLICATION_SECRET: doper
networks:
- kafka
depends_on:
- zookeeper
- kafka1
- kafka2
- kafka3
复制
2. 各模块解析
2.1. zookeeper
这里
zookeeper
使用的是
zookeeper
官方提供的镜像,与大多数教程中的
wurstmeister/zookeeper
是一样的,在使用时可以挂载卷实现数据持久化,具体挂载的目录在官方的
README
中有,如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuU2YyEGNzEWN2M2Y5QmN5QjNiZjM3E2N1QWN2cTMhVTNvwVM4MzN0UjNtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
2.2. kafka
kafka
的参数配置在镜像
README
中也有说明,简单来说就是先从
kafka
官方文档中找到要配置的参数,然后在
docker-compose.yml
文件中配置时只需要将配置项的名字全部换成大写,然后
.
换成
_
,再加上
KAFKA_
前缀几个。举个例子,修改
broker.id
,则需要在配置文件中设置
KAFKA_BROKER_ID=XXX
即可。
- 参数说明
-
: 配置KAFKA_BROKER_ID
,每个broker.id
的broker
必须唯一id
-
: 设置KAFKA_NUM_PARTITIONS
的分区数topic
-
:KAFKA_DEFAULT_REPLICATION_FACTOR
的复制系数,也就是消息副本数topic
-
:KAFKA_ZOOKEEPER_CONNECT
的连接地址,这里注意的是加了zookeeper
后缀,是为了方便管理,把集群所有的信息都放入/kafka
的zookeeper
目录下。/kafka
-
: 监听器,指定以什么协议及哪个主机名和端口来访问KAFKA_LISTENERS
服务。这里设置了监听所有网卡,kafka
解决的是listeners
监听来自于哪个网卡的请求。kafka
-
:KAFKA_ADVERTISED_LISTENERS
真正要注册进broker
的监听信息,及zookeeper
对外开放的端口。broker
-
: 日志位置KAFKA_LOG_DIRS
-
:BOOTSTRAP_SERVERS
集群各个服务器的地址信息kafka
-
和listeners
的区别advertised.listeners
reference
- https://segmentfault.com/a/1190000020715650
- https://blog.csdn.net/weixin_38251332/article/details/105638535
在部署时对内外网暴露端口需要做区分时使用,原文:
listeners: INSIDE://172.17.0.10:9092,OUTSIDE://172.17.0.10:9094 advertised_listeners: INSIDE://172.17.0.10:9092,OUTSIDE://<公网 ip>:端口 kafka_listener_security_protocol_map: "INSIDE:SASL_PLAINTEXT,OUTSIDE:SASL_PLAINTEXT" kafka_inter_broker_listener_name: "INSIDE"监听器会注册在
advertised_listeners
zookeeper
中;
当我们对
请求建立连接,
172.17.0.10:9092
服务器会通过
kafka
中注册的监听器,找到
zookeeper
监听器,然后通过
INSIDE
中找到对应的 通讯
listeners
ip
和 端口;
同理,当我们对
请求建立连接,
<公网 ip>:端口
服务器会通过
kafka
中注册的监听器,找到
zookeeper
监听器,然后通过
OUTSIDE
中找到对应的 通讯
listeners
和 端口
ip
172.17.0.10:9094
;
总结:
是对外暴露的服务端口,真正建立连接用的是
advertised_listeners
。
listeners
即
broker
会把
advertised_listeners
中的信息注册进
zookeeper
,而客户端建立连接时会去找
zookeeper
中注册的
advertised_listeners
,然后根据找到的对应监视器去
listeners
中找对应的
ip
和端口进行访问。
因此这里可以有内外网分流的应用,具体见
reference
-
挂载volumne
volumes:
- /usr/local/etc/kafka/data/kafka3:/kafka # 挂载kafka使用过程中产生的数据
- /var/run/docker.sock:/var/run/docker.sock # 挂载宿主机的docker.sock
复制
在
kafka-docker
中给出的
docker-compose.yml
例子中就有挂载
docker.sock
了
这里为什么需要挂载
docker.sock
?
reference
: https://blog.csdn.net/boling_cavalry/article/details/92846483
首先需要明白
docker.sock
的作用
实际上
docker
是由
client
和
server
组成,通过
docker --version
可以查看:
⚡ root@doper /home/doper docker version
Client:
Version: 20.10.15
API version: 1.41
Go version: go1.18.1
Git commit: fd82621d35
Built: Thu May 5 23:16:45 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server:
Engine:
Version: 20.10.15
API version: 1.41 (minimum version 1.12)
Go version: go1.18.1
Git commit: 4433bf67ba
Built: Thu May 5 23:16:31 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.6.4
GitCommit: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16.m
runc:
Version: 1.1.2
GitCommit:
docker-init:
Version: 0.19.0
GitCommit: de40ad0
复制
我们发送的
docker
命令其实都是客户端发送请求到
docker daemon
服务,
docker daemon
再返回相关的命令结果即可。
而
docker daemon
默认监听的就是
/var/run/docker.sock
,
daemon
通过这个
socket
和其他进程通信,所以客户端只要将消息发送到这个
socket
即可实现与
daemon
通信。具体可见
api
文档
注意,这里和不同的是因为
reference
版本高于
curl
,这个版本的
7.50
在使用时需要提供的
curl
必须包括
URL
hostname
.
具体见-> Can cURL send requests to sockets?
eg:
⚡ root@doper /home/doper curl --unix-socket /var/run/docker.sock http://localhost/containers/json
[{"Id":"f2cce65f7b4752396843.... # 一大串的json信息
复制
那么在
kafka
容器中就可以通过
docker
命令来得到相关的容器信息,在官方
github
中的
start-kafka.sh
脚本中也确实看到了其使用了
docker port
命令
有了
socket
,那在容器中有
docker
的
client
可供使用吗?答案是有的,在
Dockerfile
其已经安装了
docker
2.3. kafka_manager
用来管理
kafka
集群的,在容器启动后可以通过
localhost:9000
访问可视化界面。
注意创建时由于上面
docker-compose.yml
中已经设置将所有的
kafka
集群信息放在
/kafka
目录下,所以这里也要加上
/kafka
后缀
但这里有一个坑,就是在创建集群后会遇到如下错误
Yikes! KeeperErrorCode = Unimplemented for /kafka-manager/mutex Try again.
复制
解决方法:
reference
: https://github.com/yahoo/CMAK/issues/731
➜ docker exec -it zookeeper bash
root@98747a9eac65:/zookeeper-3.4.14# ./bin/zkCli.sh
[zk: localhost:2181(CONNECTED) 2] ls /kafka-manager
[configs, deleteClusters, clusters]
[zk: localhost:2181(CONNECTED) 3] create /kafka-manager/mutex ""
Created /kafka-manager/mutex
[zk: localhost:2181(CONNECTED) 5] create /kafka-manager/mutex/locks ""
Created /kafka-manager/mutex/locks
[zk: localhost:2181(CONNECTED) 6] create /kafka-manager/mutex/leases ""
Created /kafka-manager/mutex/leases
复制