基于 Docker 部署 Kafka(KRaft + SASL/PLAIN 认证)

基于 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.propertieskafka_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 和客户端配置。

相关推荐
源图客3 小时前
Nacos3.1.1部署(Docker)
运维·docker·容器
howard20053 小时前
Docker实战:利用commit命令构建镜像
docker·commit·构建新镜像
从零开始学习人工智能3 小时前
《8076 能通 9003 却超时?一次 Docker 容器跨网段排障小记》
运维·docker·容器
熊出没3 小时前
Docker 实操命令大全
docker
KD7 小时前
设计模式——责任链模式实战,优雅处理Kafka消息
后端·设计模式·kafka
运维栈记15 小时前
如何排错运行在Kubernetes集群中的服务?
云原生·容器·kubernetes
Linux编程用C16 小时前
Docker+Vscode搭建(本地/远程)开发环境
vscode·后端·docker
林疏safe18 小时前
灯塔部署云服务器docker 部署方式,以及忘记密码如何查找
运维·服务器·docker
木卫二号Coding18 小时前
affine+docker+postgresql+备份数据库
数据库·docker·容器