Apache Kafka 作为高吞吐量消息队列,在微服务和数据集成场景中应用广泛。随着容器化技术的普及,将 Kafka 部署在 Kubernetes 上已成为主流选择。本文记录了在一次 Kafka 单点容器化部署过程中遇到的“Pod 未创建”问题,并详细阐述了排查思路与最终的功能验证过程。希望通过此文,为读者提供一份可复用的故障排查指南和验证清单。
部署环境与步骤回顾
环境信息
- Kubernetes 集群:单节点(
k8s-192-168-0-11) - 容器运行时:containerd
- 镜像:Kafka 3.9.1(已导入为
kafka:3.9.1) - 存储:NFS 共享目录
/data/nfs/kafka/data
部署步骤(简化)
- 加载镜像
ctr -n k8s.io images import /root/kafka_3.9.1.tar- 创建数据目录
mkdir -p /data/kafka/data- 创建 PV(
kafka-pv.yaml) - 使用 NFS 提供存储,容量 10Gi,访问模式
ReadWriteMany,StorageClass 名为 kafka。 - 创建 PVC(
kafka-pvc.yaml) - 引用 PV,请求 10Gi 存储,绑定到
kafka-pv。 - 创建 Pod 与 Service(
kafka.yaml)- Pod 使用 KRaft 模式(无需 Zookeeper),配置环境变量、挂载 PVC。
- Service 为 NodePort 类型,暴露 9092 端口到宿主机 30092。
- 应用资源
kubectl apply -f kafka-pv.yamlkubectl apply -f kafka-pvc.yamlkubectl apply -f kafka.yaml
问题现象:Pod 未创建
执行 kubectl apply -f kafka.yaml 后,终端输出了 pod/kafka-kraft created 和 service/kafka-kraft-svc created,但随后执行 kubectl get pod 却没有任何 Pod 显示,仿佛从未创建过。
这种异常通常意味着 Pod 对象虽然被 API Server 接收,但在调度或创建阶段被立即删除或未能持久化。下文将详细拆解排查过程。
问题排查全流程
1. 检查资源存在性
首先确认 Pod 是否真的不存在,或者只是命名空间不对。
bash
结果显示:No resources found in default namespace. 也没有其他命名空间有 kafka 相关 Pod。
2. 查看最近事件
事件中可能记录了资源创建失败的线索。
bash
输出中并没有与 kafka 相关的 Event,说明资源创建可能根本没成功。
3. 检查 YAML 语法
YAML 文件中的环境变量部分含有特殊字符 (可能是复制文档时带出的不可见字符),导致格式错误。使用 cat -A kafka.yaml 查看:
text
这里的 实际上是一个 Unicode 字符(U+F0B7),在 YAML 解析器看来是无效的,因此整个 Pod 资源定义被忽略。
修复方法:将所有 替换为 -(减号),并确保缩进正确:
yaml
4. 重新应用资源
修复 YAML 后,重新执行 kubectl apply -f kafka.yaml,终端输出 pod/kafka-kraft created,这次 kubectl get pod 终于显示了 Pod,但状态为 Pending。
5. 查看 Pod 详情
bash
Events 部分显示:
text
这表明存储挂载失败,需要进一步检查 NFS 服务。
6. 验证 NFS 共享
在节点 k8s-192-168-0-11 上执行:
bash
发现并没有导出 /data/nfs/kafka/data 路径。原来是 NFS 服务端未配置此共享目录。
修复方法:
- 确保 NFS 服务已安装:
yum install -y nfs-utils - 编辑
/etc/exports,添加: - text
- 重启 NFS 服务:
systemctl restart nfs-server - 重新导出:
exportfs -r
再次验证:
bash
输出中包含了 /data/nfs/kafka/data,问题解决。
7. 重启 Pod 并观察
由于 Pod 仍处于 Pending,可直接删除并重建:
bash
这次 Pod 状态变为 Running,所有问题解决。
功能验证
部署成功后,需要验证 Kafka 服务是否可用。验证分为内部访问和外部访问两种方式。
1. 确认 Pod 与 Service 状态
bash
输出:
text
2. 内部验证(在 Pod 内执行)
2.1 进入 Pod
bash
2.2 创建 Topic
bash
输出类似:
text
2.3 列出 Topic
bash
输出:
text
2.4 生产消息
bash
2.5 消费消息
bash
应能立即输出 hello kafka。按 Ctrl+C 退出。
2.6 查看集群信息
bash
输出各 API 版本支持情况,表明连接正常。
3. 外部验证(通过 NodePort)
由于 Service 类型为 NodePort,可以在集群外通过任意节点 IP + NodePort 访问。但需要注意,Pod 中配置的 KAFKA_ADVERTISED_LISTENERS 为 PLAINTEXT://192.168.0.11:9092,而外部实际访问的是 192.168.0.11:30092,两者端口不一致会导致元数据返回的地址无法连接。
解决方案(二选一):
- 修改
advertised.listeners:将 KAFKA_ADVERTISED_LISTENERS 改为 PLAINTEXT://192.168.0.11:30092,然后重启 Pod。 - 使用 Ingress 或负载均衡器:统一对外端口为 9092,但这在生产环境更复杂。
此处为了快速验证,我们采用第一种方法。
3.1 修改 kafka.yaml
将环境变量:
yaml
改为:
yaml
重新应用:
bash
Pod 会自动重启。
3.2 在外部客户端验证
假设外部机器已安装 Kafka 客户端,执行:
bash
输出 test-topic,说明外部访问成功。
也可以使用其他语言客户端(如 Python kafka-python)进行生产和消费验证。
总结
本文通过一次 Kafka 容器化部署的实际案例,完整演示了从遇到 Pod 未创建到最终验证服务可用的全过程。关键点总结如下:
- YAML 格式是首要检查点:复制文档时容易混入不可见字符,务必使用
cat -A 或语法高亮编辑器验证。 - 存储是容器化应用的基础:NFS 必须正确导出且权限配置正确,否则 Pod 会卡在
Pending。 - 环境变量需与外部访问方式匹配:
advertised.listeners 决定了客户端如何连接 Broker,必须与实际暴露的地址一致。 - 功能验证应覆盖内部与外部两种场景,确保服务在生产环境中可用。
Apache Kafka 作为高吞吐量消息队列,在微服务和数据集成场景中应用广泛。随着容器化技术的普及,将 Kafka 部署在 Kubernetes 上已成为主流选择。本文记录了在一次 Kafka 单点容器化部署过程中遇到的“Pod 未创建”问题,并详细阐述了排查思路与最终的功能验证过程。希望通过此文,为读者提供一份可复用的故障排查指南和验证清单。
部署环境与步骤回顾
环境信息
k8s-192-168-0-11)kafka:3.9.1)/data/nfs/kafka/data部署步骤(简化)
ctr -n k8s.io images import /root/kafka_3.9.1.tarmkdir -p /data/kafka/datakafka-pv.yaml)ReadWriteMany,StorageClass 名为kafka。kafka-pvc.yaml)kafka-pv。kafka.yaml)kubectl apply -f kafka-pv.yamlkubectl apply -f kafka-pvc.yamlkubectl apply -f kafka.yaml问题现象:Pod 未创建
执行
kubectl apply -f kafka.yaml后,终端输出了pod/kafka-kraft created和service/kafka-kraft-svc created,但随后执行kubectl get pod却没有任何 Pod 显示,仿佛从未创建过。这种异常通常意味着 Pod 对象虽然被 API Server 接收,但在调度或创建阶段被立即删除或未能持久化。下文将详细拆解排查过程。
问题排查全流程
1. 检查资源存在性
首先确认 Pod 是否真的不存在,或者只是命名空间不对。
bash
结果显示:
No resources found in default namespace.也没有其他命名空间有 kafka 相关 Pod。2. 查看最近事件
事件中可能记录了资源创建失败的线索。
bash
输出中并没有与 kafka 相关的 Event,说明资源创建可能根本没成功。
3. 检查 YAML 语法
YAML 文件中的环境变量部分含有特殊字符
(可能是复制文档时带出的不可见字符),导致格式错误。使用cat -A kafka.yaml查看:text
这里的
实际上是一个 Unicode 字符(U+F0B7),在 YAML 解析器看来是无效的,因此整个 Pod 资源定义被忽略。修复方法:将所有
替换为-(减号),并确保缩进正确:yaml
4. 重新应用资源
修复 YAML 后,重新执行
kubectl apply -f kafka.yaml,终端输出pod/kafka-kraft created,这次kubectl get pod终于显示了 Pod,但状态为Pending。5. 查看 Pod 详情
bash
Events 部分显示:
text
这表明存储挂载失败,需要进一步检查 NFS 服务。
6. 验证 NFS 共享
在节点
k8s-192-168-0-11上执行:bash
发现并没有导出
/data/nfs/kafka/data路径。原来是 NFS 服务端未配置此共享目录。修复方法:
yum install -y nfs-utils/etc/exports,添加:systemctl restart nfs-serverexportfs -r再次验证:
bash
输出中包含了
/data/nfs/kafka/data,问题解决。7. 重启 Pod 并观察
由于 Pod 仍处于
Pending,可直接删除并重建:bash
这次 Pod 状态变为
Running,所有问题解决。功能验证
部署成功后,需要验证 Kafka 服务是否可用。验证分为内部访问和外部访问两种方式。
1. 确认 Pod 与 Service 状态
bash
输出:
text
2. 内部验证(在 Pod 内执行)
2.1 进入 Pod
bash
2.2 创建 Topic
bash
输出类似:
text
2.3 列出 Topic
bash
输出:
text
2.4 生产消息
bash
2.5 消费消息
bash
应能立即输出
hello kafka。按Ctrl+C退出。2.6 查看集群信息
bash
输出各 API 版本支持情况,表明连接正常。
3. 外部验证(通过 NodePort)
由于 Service 类型为 NodePort,可以在集群外通过任意节点 IP + NodePort 访问。但需要注意,Pod 中配置的
KAFKA_ADVERTISED_LISTENERS为PLAINTEXT://192.168.0.11:9092,而外部实际访问的是192.168.0.11:30092,两者端口不一致会导致元数据返回的地址无法连接。解决方案(二选一):
advertised.listeners:将KAFKA_ADVERTISED_LISTENERS改为PLAINTEXT://192.168.0.11:30092,然后重启 Pod。此处为了快速验证,我们采用第一种方法。
3.1 修改
kafka.yaml将环境变量:
yaml
改为:
yaml
重新应用:
bash
Pod 会自动重启。
3.2 在外部客户端验证
假设外部机器已安装 Kafka 客户端,执行:
bash
输出
test-topic,说明外部访问成功。也可以使用其他语言客户端(如 Python
kafka-python)进行生产和消费验证。总结
本文通过一次 Kafka 容器化部署的实际案例,完整演示了从遇到 Pod 未创建到最终验证服务可用的全过程。关键点总结如下:
cat -A或语法高亮编辑器验证。Pending。advertised.listeners决定了客户端如何连接 Broker,必须与实际暴露的地址一致。