日期:2020-04-20
wurstmeister/kafka:2.12-2.3.0
docker-ce 版本18.09
CentOS 7.6
官网:
https://github.com/wurstmeister/kafka-docker
https://github.com/wurstmeister/kafka-docker/wiki/Connectivity
实践
依赖的zookeeper
KAFKA_ZOOKEEPER_CONNECT 是必须的,指定了kafka 连接哪个 zookeeper。 直接写zookeeper就可以,因为同一台物理机上,可以使用service的名字找到相应的服务。
两种写法
[官网](https://github.com/wurstmeister/kafka-docker/wiki/Connectivity)上说:
Deprecated
KAFKA_HOST:
KAFKA_PORT: 9092
KAFKA_ADVERTISED_HOST_NAME: one.prod.com
KAFKA_ADVERTISED_PORT: 9092
Current
KAFKA_LISTENERS: PLAINTEXT://:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://one.prod.com:9092
经实践,以下配置都可以正常启动和使用 kafka 向 topic 发送和消费数据
旧的写法
version: '3.2'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
restart: always
kafka:
image: wurstmeister/kafka:2.12-2.3.0
ports:
- "9092:9092"
environment:
- KAFKA_ADVERTISED_HOST_NAME=${IP}
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
新的写法
version: '3.2'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
restart: always
kafka:
image: wurstmeister/kafka:2.12-2.3.0
ports:
- "9092:9092"
environment:
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
- KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://${IP}:9092
- KAFKA_LISTENERS=PLAINTEXT://:9092
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
注意 KAFKA_LISTENERS=PLAINTEXT://:9092 不要写成 KAFKA_LISTENERS=PLAINTEXT://${IP}:9092, 否则启动kafka时会报错:
使用了namespace功能的部署方式
docker 有个高级功能 namespace, 它的主要功能就是:将物理机的非 root 用户映射为 docker 内的 root用户。这样 docker 容器内如果写物理机上的文件夹(文件),它的owner就不是 root 而是普通用户了。
具体参见另一篇笔记。
如果使用了这个高级功能,使用前面提到的部署方式部署 kafka 就不成了。需要将2种方式结合起来。
version: '3.2'
services:
zookeeper:
image: wurstmeister/zookeeper
ports:
- "2181:2181"
container_name: "zookeeper"
restart: always
kafka:
image: wurstmeister/kafka:2.12-2.3.0
container_name: "kafka"
ports:
- "9092:9092"
environment:
- TZ=CST-8
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
# 非必须,设置自动创建 topic
- KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
- KAFKA_ADVERTISED_HOST_NAME=${IP}
- KAFKA_ADVERTISED_PORT=9092
- KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://${IP}:9092
- KAFKA_LISTENERS=PLAINTEXT://:9092
# 非必须,设置对内存
- KAFKA_HEAP_OPTS=-Xmx1G -Xms1G
# 非必须,设置保存7天数据,为默认值
- KAFKA_LOG_RETENTION_HOURS=168
volumes:
# 将 kafka 的数据文件映射出来
- ${DATA_PATH}/kafka:/kafka
- /var/run/docker.sock:/var/run/docker.sock
restart: always
解决问题
在部署 kafka 的过程中遇到了很多问题,每遇到一个问题,就求助于搜索引擎,还问使用过的同事,结果发现效果并不好。因为环境不一样,kafka的版本不一样,还会有矛盾的说法,会误导。比如,我在搜索引擎查到的结果让我一直认为 KAFKA_LISTENERS 应该配置为:PLAINTEXT://0.0.0.0:9092 或 PLAINTEXT://${IP}:9092,各种试,各种卡,结果发现这根本是错的。汗~
反思解决问题的过程,发现,最有帮助的是官方文档和部署过程中打印出来的log。为了以后和给其他人参考,特此记录下来。
部署失败解决方式
查看log, 根据 log 提示添加或修改环境变量,解决问题
docker logs kafka
或者
docker-compose up
调试产生和消费数据
查询kafka log 中的 brokerId,假设 brokerId=1001
docker logs kafka
进入 kafka 的客户端,如果没有使用 kafka 容器自带的
docker exec -ti kafka bash
cd opt/kafa_<版本>/bin
-
查看 kafka 在 zookeeper 中的注册信息,出现图中类似的信息表示OK
假设:IP=10.1.10.33
./zookeeper-shell.sh 10.1.10.33 <<< "get /brokers/ids/1001"
如果没有出现信息,代表 kafka 和 zookeeper 没有连通,查看是否是部署问题。
注意上图中红框部分,如果没有出现具体 IP 或者映射过的域名,那么,修改环境变量。
-
测试产生数据
# 向k2_test topic写数据,输入任意内容后按回车输入下一条消息,按Crtl+c退出
./kafka-console-producer.sh --broker-list 10.1.10.33:9092 --topic k2_test出现提示符(>),可以打字,就代表可以了。
如果等待了几分钟也没有提示符出现,那么代表 kafka 不通。影响这个的环境变量:KAFKA_ADVERTISED_LISTENERS
-
测试消费数据
# 消费数据,应该能看到上一条命令时输入的消息,按Crtl+c退出
./kafka-console-consumer.sh --bootstrap-server 10.1.10.33:9092 --from-beginning --topic k2_test如果等待了几分钟也没有提示符出现,那么代表 kafka 不通。影响这个的环境变量:KAFKA_LISTENERS
问题记录
-
每次 kafka 部署之前要把之前的容器删除,否则会出现一会成功一会不成功的问题。
docker rm -f kafka zookeeper
-
一般来说,KAFKA_BROKER_ID 是不需要指定的。
每次移除两个容器后,重新部署后,brokerId 都会从 1001 开始。
如果不移除,brokerId 会自增, zookeeper 中会有之前的 brokerId 残留,在使用过程中会有一些 warning 但不影响使用
-
kafka 其他配置
docker exec -ti kafka bash
cat opt/kafa_<版本>/config/server.properties比如 kafka 的配置中有 log.retention.hours = 168
在 docker-compose.yml 中配置为 KAFKA_LOG_RETENTION_HOURS