Kubernetes 上部署 Kafka 应优先选 Strimzi(CRD 方式)或纯 KRaft StatefulSet,避免 Helm 旧模板;因 Kafka 是强有状态应用,需稳定主机名、正确 advertised.listeners、Headless Service、持久化存储及控制器法定人数(quorum)配置,否则易在存储、网络、副本同步上出错。

直接上结论:Kubernetes 上部署 Kafka,不要用 Helm chart 随便套用旧模板,优先选 Strimzi(CRD 方式)或纯 KRaft StatefulSet(无 ZooKeeper),否则大概率踩在存储、网络、副本同步这三类坑里。
为什么不能直接 kubectl apply 一个 kafka.yaml 就完事
Kafka 是有状态应用,但它的“状态”不只在磁盘里——还强依赖稳定的主机名、可预测的 DNS 解析、明确区分的监听地址(internal/external/controller)、以及 Broker 间低延迟通信。随便写个 Deployment 或 Service 会导致:
-
advertised.listeners配置错位,Producer/Consumer 连得上但发不出消息 - StatefulSet 没配
serviceName,Pod 启动后解析不到kafka-0.kafka-headless.namespace.svc.cluster.local,集群无法完成元数据初始化 - PVC 绑定失败或使用默认
StorageClass,导致 Kafka 日志目录落在慢速 HDD 上,吞吐骤降、ISR 频繁踢出 - 容器以非 root 用户运行,但
/var/lib/kafka目录权限没提前初始化,Pod 卡在CrashLoopBackOff
Strimzi Operator 是目前最省心的选择
它把 Kafka 的运维逻辑封装进 Kubernetes 原生资源模型,你只需要声明要什么,而不是手动调参数。关键点:
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
- 安装 Strimzi 0.39+(支持 KRaft),用官方 manifest:
kubectl apply -f https://github.com/strimzi/strimzi-kafka-operator/releases/download/0.39.0/strimzi-cluster-operator-0.39.0.yaml - 定义
KafkaCR 时,必须显式设置metadata.namespace,且该命名空间需已存在并启用strimzi.io/v1beta2RBAC - 若要用 KRaft 模式,
spec.kafka.metadataSource必须设为kraft,同时删掉所有zookeeper相关字段;否则 Operator 会静默回退到 ZooKeeper 模式 - 外部访问必须通过
spec.kafka.externalListeners配置,不能只改advertised.listeners环境变量——Strimzi 会自动生成 LoadBalancer / NodePort / Ingress,并注入正确 IP
自己写 StatefulSet 部署 KRaft 模式要注意的硬性条件
如果你坚持不用 Operator,想手写 YAML,以下四点缺一不可:
- Kubernetes 版本 ≥ 1.21,且集群启用
StatefulSetAutoDeletePVC和GenericEphemeralVolume特性开关(部分云厂商需手动开启) -
StatefulSet.spec.serviceName必须指向一个Headless Service,且该 Service 的clusterIP: None不能漏写 - 容器启动命令中必须包含
--override process.roles=broker,controller --override controller.quorum.voters=... --override listeners=...,这些不是环境变量,是 JVM 参数级配置 - 每个 Pod 的
hostname和subdomain必须与advertised.listeners中的域名完全一致,例如kafka-0.kafka-headless.test-kafka.svc.cluster.local,少一个段都会导致 controller 无法注册
验证集群是否真可用,别只看 Pod Running
Pod Running 只代表容器起来了,不代表 Kafka 能收发消息。必须做这三步验证:
- 进任意一个 Broker 容器执行:
kafka-metadata-quorum.sh --bootstrap-server localhost:9092 --status,输出里CurrentVoters和CurrentObservers必须包含全部 broker ID,且QuorumSize匹配预期 - 用
kafkacat创建 Topic:kafkacat -b kafka-0.kafka-headless.test-kafka.svc.cluster.local:9092 -t test-topic -p 0 -L,确认 Partition 0 的leader和isr字段非空 - 从集群外连
externallistener 地址(如localhost:9094via port-forward),跑一次 producer + consumer 循环,观察是否有消息延迟突增或连接重置
最容易被忽略的是 controller quorum 状态和 external listener 的 DNS 可达性——这两处出问题,现象都是“能连上、能建 Topic、但消息发不出去”,排查起来特别绕。


















