结论:应弃用 helm 原生 chart,优先选用 strimzi 或 kraft 模式纯 manifests 部署;kafka 在 k8s 中必须基于 statefulset + headless service 实现稳定网络标识与独占存储,严禁 deployment + clusterip;kraft 模式需显式配置 process.roles、node.id 和 controller.quorum.voters,彻底移除 zookeeper 依赖,并确保 initcontainer 完成元数据目录初始化及 pvc 使用 ssd 类 storageclass。

直接上结论:别用 Helm 原生 chart 部署 Kafka,优先选 Strimzi 或 KRaft 模式纯 manifests;ZooKeeper 依赖已过时,Kubernetes 上强推无 ZooKeeper 架构。
StatefulSet + Headless Service 是 Kafka 在 K8s 的唯一合理起点
Kafka Broker 必须有稳定网络标识(如 kafka-0.kafka-headless.namespace.svc.cluster.local)和独占存储,否则启动失败或分区失联。StatefulSet 提供序号命名、有序启停、PVC 绑定;Headless Service(clusterIP: None)提供 DNS A 记录直解析到每个 Pod IP,这是 Broker 间通信和客户端发现的基础。
- 不要用
Deployment+ClusterIP Service:Broker 无法互相识别 hostname,advertised.listeners配置必然错乱 -
serviceName字段在StatefulSet.spec中必须显式指定,且值必须与 Headless Service 名称一致,否则 DNS 不生效 - 每个 Pod 的
hostname和subdomain由 StatefulSet 自动注入,无需手动写入env或hostAliases - 示例中若使用
apache/kafka:3.9.0,需确认镜像内已预置 KRaft 启动脚本(默认不启用),否则仍会尝试连 ZooKeeper 并卡住
KRaft 模式部署必须关闭 ZooKeeper 依赖
Kafka 3.3+ 生产就绪的 KRaft 模式彻底移除 ZooKeeper,元数据由 Kafka 自身 Raft 日志管理。但很多 manifest 或 Helm chart 默认仍走 ZooKeeper 路径,部署后 Pod 会报类似错误:
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
ERROR Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer)Caused by: java.lang.IllegalArgumentException: zookeeper.connect must be specified when processing.config is not set
- 关键配置项是
process.roles=broker,controller和node.id(每个 Pod 必须唯一),二者缺一不可 -
controller.quorum.voters必须列出所有 controller 节点的id@hostname:port,例如"1@kafka-0.kafka-headless.default.svc.cluster.local:29093,2@kafka-1.kafka-headless.default.svc.cluster.local:29093" - 若只部署单节点,
replicas: 1时process.roles只能设为broker,不能含controller;多节点才可分离角色 - Strimzi 0.39+ 自动处理 KRaft 初始化,包括格式化元数据日志目录(
/var/lib/kafka/data/meta),手写 manifests 需在 InitContainer 中补全该步骤
StorageClass 和 PVC 配置稍错即丢消息
Kafka 对磁盘延迟极度敏感,随机 IO 延迟 > 20ms 就可能触发 ISR 踢出,acks=all 场景下直接写失败。
- 云环境务必选 SSD 类型 StorageClass:
aws-ebs-csi(gp3)、gce-pd-csi(balanced)、azure-disk-csi(Premium_LRS) - 禁用默认的
standardStorageClass(通常是 HDD),它在多数云平台实际映射为机械盘 - PVC 的
accessModes必须为ReadWriteOnce,且每个 Broker 独占一个 PVC —— 共享 PVC 会导致日志目录冲突、JVM crash - 如果用本地盘(
Local PV),必须配合volumeBindingMode: WaitForFirstConsumer,否则调度器无法感知拓扑约束,Pod 可能被调度到无本地盘节点 - Kafka 日志目录(
log.dirs)应指向 PVC 挂载路径,而非容器根文件系统;否则 Pod 重建后数据全丢
KRaft 模式下最易被忽略的一点:首次启动时 controller 节点必须完成元数据日志初始化,这个过程不可中断、不可跳过,且不打印明显日志。如果看到 Pod 卡在 Running 但 kubectl logs 无输出,大概率是 controller 投票未达成或磁盘权限不对(fsGroup: 1000 必须匹配 Kafka 进程 UID)。










