Ceph+K8s 中间件实战 | 第 12 天:K8s 部署 Kafka 集群(Ceph RBD + 消息队列架构 + 运维)

第 12/15 天

引言

在企业级微服务架构中,消息队列是解耦生产者与消费者、削峰填谷、异步通信的核心中间件。Apache Kafka 作为分布式流处理平台的标杆,凭借高吞吐、低延迟、可持久化、水平扩展的特性,被广泛应用于日志聚合、事件溯源、实时数据管道等场景。本篇是「Ceph+K8s 中间件实战」系列第 12 天,我们将基于 Bitnami 官方 Helm Chart,在已经接入 Ceph RBD 块存储的 Kubernetes 集群上部署一个多节点 Kafka 集群,并完成架构设计、持久化配置、登录验证与日常巡检。

设计架构

组件拓扑

本方案部署 3 节点 Kafka 集群(KRaft 模式,无需独立 ZooKeeper),每个 Broker 独占一个 Pod,数据通过 Ceph RBD 持久化到 Ceph 分布式存储池中,天然获得多副本高可用保障。

组件 副本数 角色 存储
Kafka Broker (KRaft) 3 combined controller+broker Ceph RBD PVC
Client(临时) 1 生产/消费测试 无

数据流向

💻 代码示例

生产者 → Kafka Broker(Leader) → Followers 同步 → Ceph RBD PVC → Ceph OSD(多副本)

↓

消费者拉取

Kafka 的分区日志以 segment 文件形式写入 PVC,由 Ceph RBD 的块设备承载。Ceph 层通过 CRUSH 算法将数据多副本分散到不同 OSD 节点,即使单个 K8s 节点宕机,只要 Ceph 集群健康,数据不丢、Pod 可漂移重建。

K8s Logo

高可用机制

  1. Broker 级高可用:3 节点集群,设置 default.replication.factor=3、min.insync.replicas=2,单 Broker 故障不影响读写。
  2. 分区 Leader 选举:KRaft 模式下由 Controller 仲裁分区 Leader 切换,毫秒级完成故障转移。
  3. 存储级高可用:Ceph RBD 数据在 OSD 层 3 副本,与 K8s 节点物理位置解耦。
  4. Pod 重调度:K8s Deployment/StatefulSet 机制保证 Pod 异常后自动在健康节点重建并挂载同一 PVC。

存储规划

  • StorageClass:ceph-rbd-sc(前面章节已创建,provisioner: rbd.csi.ceph.com)
  • 每个 Broker PVC:50Gi
  • 数据目录:/bitnami/kafka/data
  • 副本因子:replication.factor=3

部署实战

1. 添加 Bitnami Helm 仓库

💻 代码示例

# 添加 Bitnami 官方 Chart 仓库

helm repo add bitnami https://charts.bitnami.com/bitnami

helm repo update

 

# 搜索确认 kafka chart 可用

helm search repo bitnami/kafka –versions | head -n 10

预期输出包含 bitnami/kafka 及最新版本号(如 26.4.x)。

2. 编写 values.yaml 自定义配置

💻 代码示例

# kafka-values.yaml —— Ceph RBD 持久化 Kafka 集群

replicaCount: 3

 

# KRaft 模式(Kafka 3.3+ 内置元数据管理,无需 ZooKeeper)

kraft:

enabled: true

 

# 监听器配置

listenerSecurityProtocolMap: |

INTERNAL: PLAINTEXT

CONTROLLER: PLAINTEXT

listeners: |

INTERNAL://:9092

CONTROLLER://:9093

advertisedListeners: |

INTERNAL://kafka-0.kafka-headless.kafka.svc.cluster.local:9092

 

# 资源限制

resources:

requests:

cpu: "500m"

memory: "1Gi"

limits:

cpu: "2000m"

memory: "3Gi"

 

# JVM 堆

heapOpts: "-Xmx2g -Xms2g"

 

# Kafka 关键参数

config:

num.partitions: 12

default.replication.factor: 3

min.insync.replicas: 2

log.retention.hours: 168

log.segment.bytes: 1073741824

auto.create.topics.enable: false

 

# Ceph RBD 持久化

persistence:

enabled: true

storageClass: "ceph-rbd-sc"

accessModes:

– ReadWriteOnce

size: 50Gi

 

# ServiceAccount 与 RBAC

serviceAccount:

create: true

 

# Headless Service 用于 Broker 间通信

service:

type: ClusterIP

ports:

client: 9092

controller: 9093

关键点:storageClass: "ceph-rbd-sc" 让每个 Broker 的数据落盘到 Ceph 块存储;kraft.enabled: true 使用 KRaft 模式省去 ZooKeeper 依赖;min.insync.replicas=2 配合 default.replication.factor=3 保证生产者 acks=all 时的数据可靠性。

3. Helm 安装部署

💻 代码示例

# 创建独立命名空间

kubectl create namespace middleware

 

# 部署 Kafka 集群

helm install kafka bitnami/kafka

–namespace middleware

–version 26.4.0

-f kafka-values.yaml

–timeout 10m

 

# 等待所有 Pod 就绪

kubectl wait –for=condition=ready pod -l app.kubernetes.io/name=kafka

-n middleware –timeout=300s

4. 验证 Pod / Service / PVC 状态

💻 代码示例

# 查看 Pod 状态,应有 3 个 Running

kubectl get pods -n middleware -l app.kubernetes.io/name=kafka

 

# 查看 Service

kubectl get svc -n middleware | grep kafka

 

# 查看 PVC,应有 3 个 Bound 状态的 Ceph RBD 卷

kubectl get pvc -n middleware -l app.kubernetes.io/name=kafka

 

# 查看 StorageClass 确认使用 Ceph RBD

kubectl get sc ceph-rbd-sc

预期输出:

💻 代码示例

NAME READY STATUS RESTARTS AGE

kafka-0 1/1 Running 0 3m

kafka-1 1/1 Running 0 3m

kafka-2 1/1 Running 0 3m

登录验证

1. 进入容器查看集群元数据

💻 代码示例

# 获取集群元数据,确认 3 个 broker 已注册

kubectl exec -n middleware kafka-0 —

kafka-metadata-quorum.sh –bootstrap-server kafka-0.kafka-headless.middleware.svc.cluster.local:9092

describe –status

 

# 列出所有 Broker

kubectl exec -n middleware kafka-0 —

kafka-broker-api-versions.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092 | grep -E "^kafka-"

2. 创建测试 Topic 并生产消费

💻 代码示例

# 创建一个 3 分区 3 副本的测试 topic

kubectl exec -n middleware kafka-0 —

kafka-topics.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–create –topic test-ceph-kafka

–partitions 3 –replication-factor 3

 

# 查看 topic 详情与分区 Leader 分布

kubectl exec -n middleware kafka-0 —

kafka-topics.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–describe –topic test-ceph-kafka

 

# 启动生产者写入测试消息

kubectl exec -n middleware kafka-0 —

kafka-console-producer.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–topic test-ceph-kafka <<'EOF'

hello ceph kafka

hello k8s middleware

persistent on ceph rbd

EOF

 

# 消费者读取验证

kubectl exec -n middleware kafka-0 —

kafka-console-consumer.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–topic test-ceph-kafka –from-beginning –max-messages 3

预期输出应能看到三条消息被正确消费,证明集群端到端可用。

3. 验证 Ceph RBD 持久化

💻 代码示例

# 查看 Broker 数据落盘路径

kubectl exec -n middleware kafka-0 — ls -lh /bitnami/kafka/data

 

# 查看 Ceph 后端的 RBD image

kubectl exec -n middleware kafka-0 — df -h | grep kafka

 

# 在 Ceph 端确认 RBD image 存在(在 Ceph 客户端执行)

rbd ls -p kubernetes-pvc | grep kafka

日常巡检

1. 集群健康检查

💻 代码示例

# Pod 状态巡检

kubectl get pods -n middleware -l app.kubernetes.io/name=kafka -o wide

 

# KRaft 仲裁状态

kubectl exec -n middleware kafka-0 —

kafka-metadata-quorum.sh –bootstrap-server localhost:9092

describe –status | grep -E "LeaderId|HighWatermark"

 

# Controller 活跃节点

kubectl exec -n middleware kafka-0 —

kafka-metadata-quorum.sh –bootstrap-server localhost:9092 describe –active-controllers

2. Topic 与分区巡检

💻 代码示例

# 列出所有 topic

kubectl exec -n middleware kafka-0 —

kafka-topics.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092 –list

 

# 检查所有 topic 的副本分布与 ISR

kubectl exec -n middleware kafka-0 —

kafka-topics.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092 –describe | grep -E "UnderReplicated|OfflinePartition"

若 UnderReplicatedPartitions 出现非 0 值,说明有副本同步滞后,需排查 Broker 或 Ceph IO。

3. 消费者组与堆积监控

💻 代码示例

# 列出所有消费者组

kubectl exec -n middleware kafka-0 —

kafka-consumer-groups.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092 –list

 

# 查看指定消费者组 lag(堆积量)

kubectl exec -n middleware kafka-0 —

kafka-consumer-groups.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–describe –group my-consumer-group | grep -v TOPIC

4. 日志与容量巡检

💻 代码示例

# 查看 Kafka 运行日志

kubectl logs -n middleware kafka-0 –tail=100

 

# 查看 PVC 使用率

kubectl exec -n middleware kafka-0 — df -h /bitnami/kafka/data

 

# 集群级 PVC 容量概览

kubectl get pvc -n middleware -l app.kubernetes.io/name=kafka

-o custom-columns=NAME:.metadata.name,STATUS:.status.phase,CAPACITY:.status.capacity.storage,SC:.spec.storageClassName

 

# 磁盘 IO 性能巡检

kubectl exec -n middleware kafka-0 — iostat -xm 2 3 | grep -E "rbd|Device"

常见问题

FAQ 1:Pod 一直 Pending,PVC 无法绑定

现象:kubectl get pvc 显示 Pending,Events 提示 storageclass "ceph-rbd-sc" not found。

排查与解决:

💻 代码示例

# 确认 StorageClass 名称拼写正确

kubectl get sc

 

# 确认 Ceph-CSI provisioner Pod 正常运行

kubectl get pods -n ceph-csi | grep rbd

 

# 确认 Ceph RBD pool 存在且可写

ceph osd pool ls | grep kubernetes-pvc

常见原因:StorageClass 名拼写错误、Ceph-CSI 未部署、Ceph pool 权限不足。按上述顺序逐一排查。

FAQ 2:KRaft 集群无法选主,Broker 日志报 controller quorum 异常

现象:多节点同时退出后重新加入,日志反复出现 Unable to begin fence 或 Controller id is already registered。

排查与解决:

💻 代码示例

# 检查各节点 controllerQuorum voters 配置是否一致

kubectl exec -n middleware kafka-0 — cat /opt/bitnami/kafka/config/kraft/controller.properties | grep voters

 

# 检查 9093 端口连通性

kubectl exec -n middleware kafka-0 — nc -zv kafka-1.kafka-headless.middleware.svc.cluster.local 9093

 

# 查看 KRaft 日志

kubectl logs -n middleware kafka-0 | grep -i "quorum|controller"

通常是 listeners / advertisedListeners 配置中 controller 端口不一致,或 Headless Service DNS 解析异常导致。确保所有节点 CONTROLLER://:9093 配置完全一致。

FAQ 3:生产者写入报 NOT_ENOUGH_REPLICAS

现象:acks=all 时写入失败,提示 NOT_ENOUGH_REPLICAS。

排查与解决:

💻 代码示例

# 检查 ISR 数量

kubectl exec -n middleware kafka-0 —

kafka-topics.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–describe –topic test-ceph-kafka

 

# 检查 min.insync.replicas 与 replication.factor 配置

kubectl exec -n middleware kafka-0 —

kafka-configs.sh –bootstrap-server kafka.kafka.svc.cluster.local:9092

–entity-type topics –entity-name test-ceph-kafka –describe

通常是 ISR 数量低于 min.insync.replicas,往往因 Ceph IO 滞后或某 Broker 节点负载过高。临时降配(min.insync.replicas=1)可恢复写入,但需尽快排查根因。

总结

本篇我们在已接入 Ceph RBD 的 K8s 集群上,通过 Bitnami 官方 Helm Chart 部署了一个 3 节点 KRaft 模式 Kafka 集群。核心要点回顾:

  • 架构层面:KRaft 模式去除了 ZooKeeper 依赖,3 Broker 同时承担 controller + broker 角色,结构更简洁。
  • 存储层面:每个 Broker 通过 storageClass: ceph-rbd-sc 将日志持久化到 Ceph 块存储,获得数据多副本保障。
  • 可靠性层面:default.replication.factor=3 + min.insync.replicas=2 配合 Ceph 层副本,形成应用层与存储层双重高可用。
  • 运维层面:提供了从 Pod、PVC、KRaft 仲裁、Topic ISR、消费者 lag 到 Ceph RBD image 的全链路巡检命令。

Kafka 作为事件驱动架构的骨干,其稳定性直接决定上下游业务连续性。结合 Ceph RBD 的可靠存储底座,我们在 K8s 上获得了一个生产可用的消息流平台。

下期预告

下一篇「Ceph+K8s 中间件实战 | 第 13 天」将聚焦 K8s 部署 GitLab 代码托管平台,使用官方 gitlab/gitlab Helm Chart,配合 Ceph RBD 持久化代码仓库与 CI 产物,讲解 GitLab 在 K8s 上的组件拓扑、高可用架构与日常运维巡检。

系列目录

.series-toc { font-size: 0.95em; line-height: 1.8; }
.series-toc a { text-decoration: none; }
.series-toc .done { color: #28a745; }
.series-toc .current { color: #0366d6; font-weight: bold; }
.series-toc .upcoming { color: #999; }

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像 - 恒星
欢迎您留下宝贵的见解!
提交
头像 - 恒星

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容