Docker Compose 快速搭建 Kafka + AKHQ 同时支持 SSL 和非 SSL 访问
使用 Docker Compose 配置 Kafka 同时支持 SSL 和非 SSL 访问
在生产环境中,Kafka 安全性是非常重要的。通常,我们希望 Kafka 支持 SSL/TLS 加密访问,同时为了兼容一些测试或老客户端,也保留 非加密访问(PLAINTEXT)。本文将演示如何使用 Docker Compose 部署 Kafka,并配置 SSL。
Docker Compose 文件概览
下面是一个示例 docker-compose.yml:
version: "3.9"
services:
kafka:
image: apache/kafka:latest
container_name: kafka
ports:
- "9092:9092" # PLAINTEXT(可选,可删)
- "9094:9094" # SSL 客户端访问
- "9093:9093" # KRaft Controller 内部通信(可选映射)
environment:
# === KRaft 配置 ===
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
# === Listeners 配置 ===
KAFKA_LISTENERS: "PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9094,CONTROLLER://0.0.0.0:9093"
KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://10.100.100.110:9092,SSL://10.100.100.110:9094"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "PLAINTEXT:PLAINTEXT,SSL:SSL,CONTROLLER:PLAINTEXT"
# === Broker 间通信 ===
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM: "none"
# 单节点必须把所有内部 topic 副本数改成 1
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
# === SSL 配置 ===
KAFKA_SSL_KEYSTORE_FILENAME: kafka.keystore.jks
KAFKA_SSL_KEYSTORE_CREDENTIALS: keystore.pass
KAFKA_SSL_KEY_CREDENTIALS: key.pass
KAFKA_SSL_TRUSTSTORE_FILENAME: kafka.truststore.jks
KAFKA_SSL_TRUSTSTORE_CREDENTIALS: truststore.pass
KAFKA_SSL_CLIENT_AUTH: none
# === 数据目录 ===
KAFKA_LOG_DIRS: /var/lib/kafka/data
volumes:
- kafka-data:/var/lib/kafka/data
- ./kafka-certs:/etc/kafka/secrets
akhq:
image: tchiotludo/akhq
container_name: akhq
ports:
- "9000:8080"
environment:
AKHQ_CONFIGURATION: |
akhq:
connections:
kafka:
properties:
bootstrap.servers: "10.100.100.110:9092"
volumes:
- ./kafka-certs:/etc/kafka/secrets
depends_on:
- kafka
volumes:
kafka-data:
配置说明
Kafka Listener 配置
- PLAINTEXT (9092):非加密访问,方便测试或老客户端使用。
- SSL (9094):启用 SSL/TLS 访问,保证数据传输安全。
- CONTROLLER (9093):KRaft 内部通信端口,不建议直接暴露给客户端。
配置关键参数:
KAFKA_LISTENERS: "PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9094,CONTROLLER://0.0.0.0:9093"
KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT://10.100.100.110:9092,SSL://10.100.100.110:9094"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "PLAINTEXT:PLAINTEXT,SSL:SSL,CONTROLLER:PLAINTEXT"
PLAINTEXT://对应非加密访问SSL://对应加密访问KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT表示 broker 间通信使用 PLAINTEXT(可改成 SSL 以加密内部通信)
SSL 配置文件
kafka.keystore.jks:包含 Kafka broker 私钥和证书kafka.truststore.jks:包含 CA 根证书keystore.pass/key.pass/truststore.pass:存储密码
注意:确保
/etc/kafka/secrets下存在这些文件,并且 Docker Compose volume 挂载正确。
AKHQ 配置
AKHQ 用于 Kafka Web UI 管理。此示例只连接 PLAINTEXT,你也可以改成 SSL:
bootstrap.servers: "10.100.100.110:9092"
要使用 SSL,需要增加:
security.protocol: SSL
ssl.truststore.location: /etc/kafka/secrets/kafka.truststore.jks
ssl.truststore.password: truststore.pass
启动命令
docker-compose up -d
- Kafka broker 会监听 9092(PLAINTEXT)和 9094(SSL)
- AKHQ 会监听 9000 端口
注意事项
-
SSL 证书 SAN/IP
CN或subjectAltName必须包含 Kafka 的实际 IP 或主机名,否则客户端会报PKIX path building failed。
-
Broker 间通信
- 默认
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT可以兼容 PLAINTEXT 客户端 - 如果你希望 broker 间通信也加密,改成
SSL并确保KAFKA_ADVERTISED_LISTENERS包含 SSL
- 默认
-
文件挂载权限
- Docker volume 权限必须正确,Kafka 容器需要读取 keystore/truststore
这样,你就能在 Docker Compose 下运行 既支持 SSL 又支持非 SSL 客户端访问的 Kafka 了,同时使用 AKHQ 监控管理 Kafka。
准备Kafka证书
本地有Java环境可以跳过(如果也是在docker需要进入其中 keytool 需要用)
docker run -it --name java-environment -v "./kafka-certs:/certs" eclipse-temurin:17-jdk bash
生成 CA(根证书)
openssl genrsa -out ca.key 4096 openssl req -x509 -new -key ca.key -days 3650 -out ca.crt -subj "/CN=Kafka-CA"
生成 Kafka keystore
keytool -genkeypair -alias kafka -keyalg RSA -keystore kafka.keystore.jks -storepass changeit -keypass changeit -validity 3650 -dname "CN=10.100.100.110"
生成 CSR
keytool -certreq -alias kafka -keystore kafka.keystore.jks -file kafka.csr -storepass changeit
创建 SAN 扩展文件
cat > ext.cnf <<EOF
[v3_req]
subjectAltName = IP:10.100.100.110
EOF
用 CA 签发证书
openssl x509 -req -in kafka.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kafka.crt -days 3650 -extensions v3_req -extfile ext.cnf
导入 CA → keystore
keytool -importcert -alias CARoot -keystore kafka.keystore.jks -file ca.crt -storepass changeit -noprompt
导入 Kafka 证书
keytool -importcert -alias kafka -keystore kafka.keystore.jks -file kafka.crt -storepass changeit
创建 truststore
keytool -importcert -alias CARoot -keystore kafka.truststore.jks -file ca.crt -storepass changeit -noprompt
创建 Kafka 需要的密码文件
echo changeit > keystore.pass
echo changeit > truststore.pass
echo changeit > key.pass
最终证书检查
keytool -list -v -keystore kafka.keystore.jks -storepass changeit
看到
Alias name: kafka
Entry type: PrivateKeyEntry
Certificate chain length: 2
Owner: CN=10.100.100.110
Issuer: CN=Kafka-CA
执行完docker,用 openssl 测试 Kafka SSL 端口
在 Kafka 宿主机或任意客户端
openssl s_client -connect 10.100.100.110:9094 -CAfile kafka-certs/ca.crt
成功标志
在输出的内容中看到
Verify return code: 0 (ok)
为代码客户端准备证书
将 JKS 转换为 PKCS12 格式
keytool -importkeystore -srckeystore kafka.keystore.jks -destkeystore kafka.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass changeit -deststorepass changeit -srcalias kafka -destalias kafka
导出私钥(PEM 格式)
openssl pkcs12 -in kafka.p12 -nocerts -nodes -passin pass:changeit -out kafka.key
-nocerts → 只导出私钥
-nodes → 不加密输出(可选,如果你想用密码保护可以去掉)
输出 kafka.key
导出证书(PEM格式)
openssl pkcs12 -in kafka.p12 -nocerts -nodes -passin pass:changeit -out kafka.key
-clcerts → 只导出客户端证书,不包含 CA
-nokeys → 不导出私钥
输出 kafka.crt 上面其实已经有了

浙公网安备 33010602011771号