开发者
openeuler环境下Kafka 单点容器化部署:从问题排查到功能验证
openeuler环境下Kafka 单点容器化部署:从问题排查到功能验证
原创
发表于03/28
3400

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

部署步骤(简化)

  1. 加载镜像
  2. ctr -n k8s.io images import /root/kafka_3.9.1.tar
  3. 创建数据目录
  4. mkdir -p /data/kafka/data
  5. 创建 PVkafka-pv.yaml
  6. 使用 NFS 提供存储,容量 10Gi,访问模式 ReadWriteMany,StorageClass 名为 kafka
  7. 创建 PVCkafka-pvc.yaml
  8. 引用 PV,请求 10Gi 存储,绑定到 kafka-pv
  9. 创建 Pod 与 Servicekafka.yaml
    • Pod 使用 KRaft 模式(无需 Zookeeper),配置环境变量、挂载 PVC。
    • Service 为 NodePort 类型,暴露 9092 端口到宿主机 30092。
  10. 应用资源
  11. kubectl apply -f kafka-pv.yaml
  12. kubectl apply -f kafka-pvc.yaml
  13. kubectl 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

kubectl get pod -A | grep kafka
kubectl get all

结果显示:No resources found in default namespace. 也没有其他命名空间有 kafka 相关 Pod。

2. 查看最近事件

事件中可能记录了资源创建失败的线索。

bash

kubectl get events --sort-by='.lastTimestamp'

输出中并没有与 kafka 相关的 Event,说明资源创建可能根本没成功。

3. 检查 YAML 语法

YAML 文件中的环境变量部分含有特殊字符 (可能是复制文档时带出的不可见字符),导致格式错误。使用 cat -A kafka.yaml 查看:

text

name: CLUSTER_ID$

这里的  实际上是一个 Unicode 字符(U+F0B7),在 YAML 解析器看来是无效的,因此整个 Pod 资源定义被忽略。

修复方法:将所有  替换为 -(减号),并确保缩进正确:

yaml

env:
- name: CLUSTER_ID
  value: "MkU3OEVBNTcwNTJENDM2Qk"
- name: KAFKA_PROCESS_ROLES
  value: "broker,controller"
...

4. 重新应用资源

修复 YAML 后,重新执行 kubectl apply -f kafka.yaml,终端输出 pod/kafka-kraft created,这次 kubectl get pod 终于显示了 Pod,但状态为 Pending

5. 查看 Pod 详情

bash

kubectl describe pod kafka-kraft

Events 部分显示:

text

Warning  FailedMount  2m   kubelet  MountVolume.SetUp failed for volume "kafka-pv" : mount failed: exit status 32

这表明存储挂载失败,需要进一步检查 NFS 服务。

6. 验证 NFS 共享

在节点 k8s-192-168-0-11 上执行:

bash

showmount -e 192.168.0.11

发现并没有导出 /data/nfs/kafka/data 路径。原来是 NFS 服务端未配置此共享目录。

修复方法

  • 确保 NFS 服务已安装:yum install -y nfs-utils
  • 编辑 /etc/exports,添加:
  • text
/data/nfs/kafka/data *(rw,sync,no_root_squash,no_subtree_check)
  • 重启 NFS 服务:systemctl restart nfs-server
  • 重新导出:exportfs -r

再次验证:

bash

showmount -e 192.168.0.11

输出中包含了 /data/nfs/kafka/data,问题解决。

7. 重启 Pod 并观察

由于 Pod 仍处于 Pending,可直接删除并重建:

bash

kubectl delete pod kafka-kraft
kubectl apply -f kafka.yaml

这次 Pod 状态变为 Running,所有问题解决。

功能验证

部署成功后,需要验证 Kafka 服务是否可用。验证分为内部访问和外部访问两种方式。

1. 确认 Pod 与 Service 状态

bash

kubectl get pod,svc

输出:

text

NAME               READY   STATUS    RESTARTS   AGE
pod/kafka-kraft    1/1     Running   0          2m

NAME                      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
service/kafka-kraft-svc   NodePort   10.96.xxx.xxx   <none>        9092:30092/TCP                   2m

2. 内部验证(在 Pod 内执行)

2.1 进入 Pod

bash

kubectl exec -it kafka-kraft -- /bin/bash

2.2 创建 Topic

bash

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server localhost:9092 \
  --create --topic test-topic --partitions 1 --replication-factor 1

输出类似:

text

Created topic test-topic.

2.3 列出 Topic

bash

/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list

输出:

text

test-topic

2.4 生产消息

bash

echo "hello kafka" | /opt/kafka/bin/kafka-console-producer.sh \
  --bootstrap-server localhost:9092 \
  --topic test-topic

2.5 消费消息

bash

/opt/kafka/bin/kafka-console-consumer.sh \
  --bootstrap-server localhost:9092 \
  --topic test-topic \
  --from-beginning

应能立即输出 hello kafka。按 Ctrl+C 退出。

2.6 查看集群信息

bash

/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092

输出各 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

- name: KAFKA_ADVERTISED_LISTENERS
  value: "PLAINTEXT://192.168.0.11:9092"

改为:

yaml

- name: KAFKA_ADVERTISED_LISTENERS
  value: "PLAINTEXT://192.168.0.11:30092"

重新应用:

bash

kubectl apply -f kafka.yaml

Pod 会自动重启。

3.2 在外部客户端验证

假设外部机器已安装 Kafka 客户端,执行:

bash

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server 192.168.0.11:30092 \
  --list

输出 test-topic,说明外部访问成功。

也可以使用其他语言客户端(如 Python kafka-python)进行生产和消费验证。

总结

本文通过一次 Kafka 容器化部署的实际案例,完整演示了从遇到 Pod 未创建到最终验证服务可用的全过程。关键点总结如下:

  • YAML 格式是首要检查点:复制文档时容易混入不可见字符,务必使用 cat -A 或语法高亮编辑器验证。
  • 存储是容器化应用的基础:NFS 必须正确导出且权限配置正确,否则 Pod 会卡在 Pending
  • 环境变量需与外部访问方式匹配advertised.listeners 决定了客户端如何连接 Broker,必须与实际暴露的地址一致。
  • 功能验证应覆盖内部与外部两种场景,确保服务在生产环境中可用。

收藏举报
Level 1
0
帖子
0
粉丝
0
获赞