基于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
複制