基于 Docker 部署 Kafka(KRaft + SASL/PLAIN 认证)
搭建后发现问题:
生产者能生成消息,但消费者消费不了,好奇怪!
版本:Apache Kafka 3.7.0 | 模式:KRaft(无 ZooKeeper)| 安全:SASL/PLAIN 用户名密码认证
适用于开发/测试环境
日志文件与数据文件完全分离
使用官方
apache/kafka镜像,无需自定义构建支持跨平台(Linux / macOS / Windows)
docker安装可参照 day02 -- docker
一、架构概览
| 组件 | 路径(容器内) | 路径(宿主机) | 说明 |
|---|---|---|---|
| 配置文件 | /opt/kafka/config/kraft/server.properties |
./kafka/server.properties |
KRaft + SASL 配置 |
| JAAS 文件 | /etc/kafka/kafka_server_jaas.conf |
./kafka/kafka_server_jaas.conf |
用户名/密码定义 |
| Topic 数据 | /var/lib/kafka/data |
./kafka-logs-data/ |
分区、索引、元数据 |
| 运行日志 | /var/log/kafka/ |
./kafka-logs-run/ |
server.log, controller.log 等 |
二、项目目录结构
bash
kafka-sasl-plain/
├── docker-compose.yml # 主编排文件
├── kafka/
│ ├── server.properties # Kafka 核心配置
│ └── kafka_server_jaas.conf # SASL 用户凭证
├── kafka-logs-data/ # 持久化 Topic 数据(自动创建)
└── kafka-logs-run/ # 持久化运行日志(自动创建)
三、配置文件详解
1. kafka/server.properties
vi kafka/server.properties
内容如下:
properties
# ===== KRaft 模式配置 =====
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@kafka:9093
# ===== 监听地址 =====
listeners=SASL_PLAINTEXT://:9092,CONTROLLER://:9093
advertised.listeners=SASL_PLAINTEXT://公网ip:9092
# 映射自定义 listener 名称到安全协议
listener.security.protocol.map=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
# 内部通信使用 SASL
inter.broker.listener.name=SASL_PLAINTEXT
controller.listener.names=CONTROLLER
# ===== SASL/PLAIN 认证 =====
sasl.enabled.mechanisms=PLAIN
sasl.mechanism.inter.broker.protocol=PLAIN
# ===== 存储路径 =====
log.dirs=/var/lib/kafka/data
注意:
advertised.listeners使用宿主机 IP
2. kafka/kafka_server_jaas.conf
vi kafka/kafka_server_jaas.conf
内容如下:
conf
KafkaServer {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="StrongPassword123!"
user_admin="StrongPassword123!"
user_producer="StrongPassword456!"
user_consumer="StrongPassword789!";
};
说明:
username/password:Broker 自身连接 Controller 用(内部)user_xxx="password":客户端可使用的用户(如user_admin对应用户名admin)
四、Docker Compose 编排文件
docker-compose.yml
vi docker-compose.yml
内容如下:
yaml
services:
kafka:
image: apache/kafka:3.7.0
container_name: kafka-sasl
ports:
- "9092:9092" # 客户端连接端口
environment:
# 启用 JAAS + 指定日志目录(关键!)
KAFKA_OPTS: >
-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf
-Dkafka.logs.dir=/var/log/kafka
volumes:
# 配置挂载
- ./kafka/server.properties:/opt/kafka/config/kraft/server.properties
- ./kafka/kafka_server_jaas.conf:/etc/kafka/kafka_server_jaas.conf
# 数据目录(Topic 分区)
- ./kafka-logs-data:/var/lib/kafka/data
# 运行日志目录(server.log 等)
- ./kafka-logs-run:/var/log/kafka
command: >
bash -c "
mkdir -p /var/log/kafka && \
cd /opt/kafka && \
if [ ! -f /var/lib/kafka/data/meta.properties ]; then \
echo 'Formatting Kafka storage...' && \
STORAGE_ID=$$(bin/kafka-storage.sh random-uuid) && \
bin/kafka-storage.sh format -t $$STORAGE_ID -c config/kraft/server.properties; \
fi && \
exec bin/kafka-server-start.sh config/kraft/server.properties
"
networks:
- kafka-net
networks:
kafka-net:
driver: bridge
关键设计:
- 通过
-Dkafka.logs.dir动态指定日志目录,无需自定义 log4j.properties- 自动格式化存储目录(首次启动)
- 设置正确权限(UID=1000 为官方镜像中
kafka用户)
五、部署步骤
1. 创建目录
bash
mkdir -p /opt/kafka-sasl-plain/kafka kafka-sasl-plain/kafka-logs-data kafka-sasl-plain/kafka-logs-run
cd /opt/kafka-sasl-plain
2. 创建配置文件
将上述 server.properties 和 kafka_server_jaas.conf 内容分别写入对应文件。
3. 设置权限(安全)
bash
chmod 644 kafka/kafka_server_jaas.conf
sudo chown -R 1000:1000 kafka-logs-data kafka-logs-run
4. 启动服务
bash
docker compose up -d
5. 验证状态
bash
# 查看容器日志(启动过程)
docker compose logs -f kafka
# 检查日志文件是否生成
ls -l kafka-logs-run/
# 应包含:server.log, controller.log, state-change.log
# 检查数据目录
ls -l kafka-logs-data/
# 应包含 meta.properties 和 __cluster_metadata-* 目录
# 停止并清理(选)
docker compose down
成功标志(日志中出现):
INFO [KafkaServer id=1] started (kafka.server.KafkaServer)
INFO Awaiting connections on port 9092

六、客户端测试
1. 创建客户端配置
mkdir ./client
client.properties(用于命令行工具):
vi ./client/client.properties
内容如下:
properties
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
kafka_admin_client_jaas.conf(推荐):
vi ./client/kafka_admin_client_jaas.conf
内容如下:
conf
KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="StrongPassword123!";
};
2. 测试命令(在宿主机执行)
创建 Topic
bash
docker run --rm --add-host=host.docker.internal:host-gateway -v $(pwd)/client/kafka_admin_client_jaas.conf:/tmp/jaas.conf -v $(pwd)/client/client.properties:/tmp/client.properties apache/kafka:3.7.0 bash -c "
export KAFKA_OPTS='-Djava.security.auth.login.config=/tmp/jaas.conf' && \
/opt/kafka/bin/kafka-topics.sh \
--bootstrap-server host.docker.internal:9092 \
--command-config /tmp/client.properties \
--create --topic hello --partitions 1 --replication-factor 1
"

列出 Topic
bash
# 同上,将 --create ... 替换为 --list
七、安全与运维建议
| 项目 | 建议 |
|---|---|
| 传输安全 | 开发可用 SASL_PLAINTEXT;生产必须用 SASL_SSL |
| 认证机制 | 生产环境建议使用 SCRAM-SHA-256 替代 PLAIN |
| 日志管理 | 可对 kafka-logs-run/ 配置 logrotate |
| 数据备份 | 定期备份 kafka-logs-data/ |
| 网络暴露 | 切勿将 9092 端口暴露到公网 |
八、常见问题排查
认证失败(SASL)
- 检查:
- 客户端密码是否匹配
user_xxx(不是username) - JAAS 文件路径是否正确挂载
client.properties是否包含security.protocol=SASL_PLAINTEXT
- 客户端密码是否匹配
日志未写入 kafka-logs-run
- 检查:
KAFKA_OPTS是否包含-Dkafka.logs.dir=/var/log/kafka- 宿主机目录是否有写权限(容器内 UID=1000)
九、附录:用户凭证速查
| 用户名 | 密码(示例) | 用途 |
|---|---|---|
admin |
StrongPassword123! |
管理员(创建 Topic) |
producer |
StrongPassword456! |
生产者 |
consumer |
StrongPassword789! |
消费者 |
修改密码请同步更新
kafka_server_jaas.conf和客户端配置。