跳转到内容

Kubernetes 上的 Kafka 运维面试题

8 道题
分类
Kubernetes
子分类
middleware-ops
题目数
8 道
已阅读 0 / 8 题
1 Kubernetes 上 Kafka 的部署模式如何选型(Strimzi、Confluent for Kubernetes 与自建方案)

答案:

在 Kubernetes 上运行 Kafka,选型的核心不是“有没有 Operator”,而是团队能否持续维护 Kafka、存储、网络、安全和升级链路。Operator 可以把这些操作声明化和自动化,但不会替代容量规划、故障演练或消息语义设计。

维度StrimziConfluent for Kubernetes(CFK)自建或其他 Operator
主要定位运行 Apache Kafka 的 Kubernetes 原生方案运行 Confluent Platform 的 Kubernetes 方案由团队或第三方维护实现与生命周期
管理接口Kafka、KafkaNodePool、KafkaTopic、KafkaUser 等 CRConfluent Platform 对应的 CR 和工具链取决于实现,可能是 Helm、脚本或另一套 CR
适合的组织条件希望采用开源社区方案,并具备 Kubernetes/Kafka 运维能力已使用 Confluent 生态或需要其商业支持与产品集成有明确维护责任、兼容性验证和升级能力
主要风险CRD、Operator 与 Kafka 版本的兼容性要持续跟踪许可、支持范围和平台依赖要提前确认生命周期、KRaft 支持和故障处理质量差异很大

选型前至少核对以下事项:

  • 目标 Kafka、KRaft、Kubernetes 与 Operator 版本是否处于支持组合;不要依据旧版对比表判断。
  • 是否需要主题、用户、Kafka Connect、MirrorMaker 2、再均衡和证书管理等声明式能力。
  • 存储类的 IOPS、吞吐、扩容、故障恢复和卷保留语义能否满足 Kafka 的恢复窗口。
  • 团队是否需要商业支持、审计、Schema Registry、数据治理等 Confluent 平台能力。
  • Operator 失效、CRD 升级失败、节点驱逐和跨可用区故障时,谁负责诊断与恢复。

历史项目中常见的其他 Operator 不能只看产品名称或一张能力表。先确认维护者、发布节奏、目标 Kafka 版本、KRaft 支持状态和实际演练记录;这些结论比“支持或不支持”四个字更可靠。

2 Strimzi 运维控制器(Operator)的架构与核心自定义资源(CRD)

答案:

Strimzi 使用运维控制器(Operator)持续对账:用户通过自定义资源(Custom Resource,CR)表达期望状态,控制器将其收敛为 Kafka 配置、证书、服务、存储资源以及实际运行的 Broker/Controller 容器组(Pod)。用户应修改源 CR,而不应直接修改控制器生成的工作负载。

自定义资源主要职责
Kafka集群级配置,例如监听器、Kafka 参数、认证授权、模板和 Entity Operator
KafkaNodePool声明 Broker/Controller 节点的角色、数量、存储和资源,支持异构节点池
KafkaTopic声明 Topic 的分区数、复制因子与可管理配置
KafkaUser管理客户端认证材料、ACL 和配额
KafkaConnect / KafkaConnector运行 Kafka Connect 集群并管理连接器
KafkaMirrorMaker2运行 MirrorMaker 2 跨集群复制
KafkaBridge提供 HTTP Bridge 时的运行配置
KafkaRebalance在启用 Cruise Control 的集群中请求和审批重平衡方案
Kafka + KafkaNodePool
        │
        ▼
Cluster Operator ──> 服务、证书、配置、卷与受管工作负载 ──> Broker / Controller Pod

KafkaTopic + KafkaUser
        │
        ▼
Entity Operator ──> Kafka Admin API ──> Topic、用户、ACL、配额

当前 Strimzi 会使用节点池,并可能使用内部的 StrimziPodSet 等受管资源来维持 Kafka 节点;具体生成资源随 Operator 版本演进。它们是控制器的实现细节,不应成为手工扩缩容、修复配置或删除重建的入口。

面试中应说明的边界:

  • Cluster Operator 负责 Kafka 集群生命周期;Entity Operator 负责 Topic 和用户,不负责 Broker 集群本身。
  • Operator 的“已对账”不等于业务已经可用。还要检查 ISR、监听器连通性、客户端认证和端到端读写。
  • 在 CR 与 kafka-topics.sh、kafka-configs.sh 同时修改同一个对象,会产生两个事实来源。生产环境应规定哪些对象由 CR 管理。
3 Strimzi 的 Kafka 节点池(KafkaNodePool)与有状态工作负载管理

答案:

Kafka 需要稳定的节点 ID、网络地址和持久日志目录。Strimzi 通过 KafkaNodePool 描述这些节点的角色、存储和资源,并由 Cluster Operator 创建和维护底层工作负载。旧版本可能生成 StatefulSet;新版本可能使用其他受管资源。无论底层实现是什么,都不要直接修改它。

下面是 KRaft 集群的最小结构示意。示例使用双角色节点池以便说明;生产环境应根据规模和故障域决定是否分离 Controller 与 Broker。

apiVersion: kafka.strimzi.io/v1
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    listeners:
      - name: tls
        port: 9093
        type: internal
        tls: true
    config:
      default.replication.factor: 3
      min.insync.replicas: 2
      offsets.topic.replication.factor: 3
      transaction.state.log.replication.factor: 3
      transaction.state.log.min.isr: 2
  entityOperator:
    topicOperator: {}
    userOperator: {}
apiVersion: kafka.strimzi.io/v1
kind: KafkaNodePool
metadata:
  name: dual-role
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 3
  roles:
    - controller
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 200Gi
        deleteClaim: false
  resources:
    requests:
      cpu: "2"
      memory: 8Gi
    limits:
      cpu: "4"
      memory: 16Gi

该示例面向使用 kafka.strimzi.io/v1 的 KRaft 集群。较早的 0.x 版本曾通过 feature gate 及 strimzi.io/node-pools、strimzi.io/kraft 注解启用节点池和 KRaft;升级或迁移时必须遵循对应版本文档,不能把旧注解机械复制到新版本。

节点池常见角色运维重点
Controller 池controller多数派、稳定元数据盘和跨故障域分布;通常使用 3 或 5 个节点
Broker 池broker日志容量、网络、分区密度、Leader 流量和副本迁移能力
双角色池controller + broker适合较小集群;高负载下控制面会与业务 I/O 竞争资源

增加 Broker 副本数只提供了新容量,不会自动让旧分区均匀迁移。缩容更不能只改 replicas:先完成分区重分配、确认待下线节点无副本和无 Leader,再按 Operator 版本支持的流程变更节点池。Controller 成员变更、KRaft 迁移和 Kafka 大版本升级同样需要遵循目标版本的官方步骤。

4 Strimzi 的实体运维控制器(Entity Operator)

答案:

Entity Operator 是 Strimzi 管理 Topic 和用户的组件。它由 Cluster Operator 部署和维护,通常以一个 Pod 中的 Topic Operator、User Operator 两个容器运行;也可以按产品能力单独部署。它不是 Kafka Broker 的边车,也不负责 Cluster Operator 的证书或节点生命周期。

子组件管理对象典型动作
Topic OperatorKafkaTopic创建/更新 Topic、调整可变配置、回写状态条件
User OperatorKafkaUser生成认证材料、写入 Secret、配置 ACL 和配额
KafkaTopic 变更 → Topic Operator 校验期望状态 → Kafka Admin API → 更新 CR 状态
KafkaUser 变更  → User Operator 创建凭据与授权     → Secret / Admin API → 更新 CR 状态

Topic 与用户是否由 CR 作为唯一事实来源,应在团队规范中明确。若对象已经由 Topic Operator 管理,再用命令行手工变更,后续对账可能覆盖或报告这项变更;不同 Strimzi 版本对可管理属性和同步行为也存在差异。

常见排查顺序:

  1. 查看 KafkaTopic 或 KafkaUser 的 status.conditions,确认是校验失败、认证失败还是 Kafka Admin API 超时。
  2. 查看相应 Operator 容器日志,核对目标 bootstrap 地址、TLS 信任链、认证材料和 ACL。
  3. 检查请求是否合理,例如副本数是否超过可用 Broker/机架数、是否试图减少不允许减少的分区数。
  4. 修复 CR 或集群根因后等待下一次 reconcile,不要通过删 Secret、删受管 Pod 的方式掩盖问题。
5 Kafka 代理节点(Broker)的机架感知(Rack Awareness)在 Kubernetes 上如何实现

答案:

机架感知让 Kafka 在分配副本时使用故障域信息,例如可用区(Availability Zone,AZ)。Kubernetes 还需要把实际 Pod 分散到这些故障域。两件事缺一不可:前者影响 Kafka 的副本选址,后者决定调度器是否真的把节点放开。

apiVersion: kafka.strimzi.io/v1
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    rack:
      type: topology-label
      topologyKey: topology.kubernetes.io/zone
    template:
      pod:
        topologySpreadConstraints:
          - maxSkew: 1
            topologyKey: topology.kubernetes.io/zone
            whenUnsatisfiable: DoNotSchedule
            labelSelector:
              matchLabels:
                strimzi.io/cluster: my-cluster

工作过程如下:

  1. Strimzi 从 Pod 所在 Kubernetes 节点读取 topology.kubernetes.io/zone,写入 Broker 的 broker.rack 信息。
  2. Kafka 根据 broker.rack 尽量把同一分区的副本安排在不同机架。
  3. topologySpreadConstraints、反亲和性或专用节点池让调度器实际分散 Pod,避免所有 Broker 恰好落在一个可用区。

rack 配置本身不会强迫 Kubernetes 重调度,也不能在只有一个可用区或副本数大于故障域数量时创造冗余。节点替换、容量不足或历史副本分布不均时,仍需检查实际 broker.rack、副本分配和 Pod 位置,必要时通过重分配恢复均衡。

6 Kafka 的 MirrorMaker 2 跨集群复制

答案:

MirrorMaker 2(MM2)基于 Kafka Connect,在源集群与目标集群之间复制 Topic 数据,并可生成心跳、检查点和消费者位点映射信息。它是跨集群复制工具,不是完整的灾备切换编排系统。

apiVersion: kafka.strimzi.io/v1
kind: KafkaMirrorMaker2
metadata:
  name: dr-mirror
spec:
  replicas: 2
  connectCluster: target
  clusters:
    - alias: source
      bootstrapServers: source-kafka.example.com:9093
    - alias: target
      bootstrapServers: target-kafka.example.com:9093
  mirrors:
    - sourceCluster: source
      targetCluster: target
      topicsPattern: "^(orders|payments)\\..*$"
      groupsPattern: "^(order|payment)-.*$"
      sourceConnector:
        config:
          replication.factor: 3
          offset-syncs.topic.replication.factor: 3
      checkpointConnector:
        config:
          checkpoints.topic.replication.factor: 3
          sync.group.offsets.enabled: true
      heartbeatConnector:
        config:
          heartbeats.topic.replication.factor: 3
组件作用
MirrorSourceConnector从源集群消费并写入目标集群
MirrorCheckpointConnector生成消费者组位点映射与 checkpoint
MirrorHeartbeatConnector写入心跳 Topic,帮助观察链路与复制拓扑

默认复制策略通常会给目标 Topic 加上源集群别名,例如 source.orders。切换为不带前缀的策略前,要先设计双向复制时的循环防护和 Topic 名冲突处理。

复制语义与切换边界:

  • MM2 基于 Connect,默认应按至少一次投递看待。专用 MM2 集群可在受支持 Kafka 版本和正确配置下启用恰好一次能力,但这只覆盖源记录到目标 Kafka 的写入范围。
  • 位点同步依赖 Topic 映射、checkpoint 和消费者组状态;不能仅凭“已同步 offset”就认为消费者可无缝切换。
  • 故障切换时,同一消费者组不能在两地同时对同一业务流并发处理,除非业务已设计好去重和冲突解决。
  • Topic 配置、ACL、Schema Registry、外部系统写入、DNS/服务发现和客户端重连都要有单独的切换步骤。

运行 MM2 的位置应同时满足源端读取、目标端写入、网络带宽、认证与故障隔离要求。任务数、刷新周期和 RPO 不是固定常数,应在压测和灾备演练中按分区数、数据量和链路延迟确定。

7 Kubernetes 上 Kafka 的生产准备清单

答案:

Kafka 上 Kubernetes 前,要把“Pod 能启动”与“集群可长期承载业务”分开验收。下面的清单比固定版本、固定 JVM 堆大小或固定分区上限更有用。

领域需要确认的事项
版本与变更Operator、Kafka、Kubernetes 和 CRD API 的支持组合;升级、回滚和 KRaft 迁移演练
调度与故障域Broker/Controller 跨节点和可用区分布;专用节点、反亲和性、拓扑分散、维护窗口与驱逐策略
存储CSI 的绑定、扩容、快照、IOPS、吞吐和故障恢复语义;卷是否会在缩容或重建时被误删
资源请求与限制、JVM Heap、页缓存、CPU 限流、文件描述符、GC 和磁盘水位必须基于压测确定
网络客户端、Broker 间、Controller 间监听器;advertised.listeners、DNS、NetworkPolicy、负载均衡和跨区带宽
安全TLS、SASL/mTLS、ACL、Operator 服务账号权限、Secret 轮换、镜像来源与审计日志
可观测性Kafka 状态条件、控制器日志、ISR、离线分区、磁盘、GC、网络、重启、消费者滞后与客户端错误

几个容易踩坑的运维结论:

  • 不要按 CPU 指标为 Broker 直接配置 HPA。增加 Broker 是容量变更,还需要副本重分配和故障域校验。
  • JVM Heap 不是容器内存的固定比例。Kafka 依赖操作系统页缓存,应在真实负载下平衡 Heap、页缓存、GC 和 cgroup 内存限制。
  • PodDisruptionBudget 可以限制自愿驱逐,但不能代替跨可用区副本、min.insync.replicas 和维护演练。
  • 证书轮换要考虑 CA 信任链重叠、客户端重连和已有长连接;不能只确认 Secret 已更新。
  • 再均衡、磁盘扩容、版本升级和节点下线都应有低峰窗口、限速、状态检查及明确回退条件。

告警至少覆盖:

UnderReplicatedPartitions / UnderMinIsrPartitionCount 持续大于 0
离线分区、Broker 或 Controller quorum 不可用
Kafka CR 或 NodePool 长时间 NotReady
卷空间、磁盘延迟、网络错误、GC 暂停或 Pod 重启异常
关键消费者组 lag 超过业务 SLO

指标名会随 Kafka 版本和 Prometheus 导出器映射变化。告警表达式应在测试集群验证标签与单位,再接入生产,不要直接复制其他集群的规则。

升级时先阅读目标 Operator 的升级说明和 CRD 变更,再在预生产完成一次相同路径的演练。每一步都等待 Cluster Operator reconcile 完成,并验证 Broker/Controller 可用性、ISR、客户端兼容性和业务读写;不要跨多个不兼容版本直接跳升,也不要假设旧的 inter.broker.protocol.version、ZooKeeper 配置仍适用于 KRaft 集群。

8 Kubernetes 上 Kafka 的常见故障排查

答案:

Kubernetes 环境排查 Kafka 时,要同时区分 Kafka 的副本、网络和存储问题,以及 Pod 调度、持久卷声明(PVC)、服务(Service)和 Operator 对账问题。先确认故障发生在容器启动、Broker 通信、客户端访问还是 Strimzi 资源协调阶段。

场景一:Kafka Broker 对应的 Pod 无法启动或反复重启

症状:Pod 处于 Pending、CrashLoopBackOff 或 OOMKilled。

优先检查:
  1. kubectl describe pod <broker-pod>
  2. kubectl logs <broker-pod> -c kafka --previous
  3. kubectl describe pvc <broker-data-pvc>

常见原因:
  - 节点资源、污点/容忍、亲和性或拓扑约束导致无法调度。
  - PVC 未绑定、卷挂载失败、权限不正确或 StorageClass 行为不符合预期。
  - JVM Heap 与容器内存限制不匹配,或节点内存压力触发 OOM。
  - TLS、监听器、Controller quorum 或 ZooKeeper 连通性配置异常。

先修复调度、存储或配置根因,再让 Operator 进行受控恢复。不要为了让 Pod 重建而直接删除 PVC、受管工作负载或 StrimziPodSet,否则可能扩大数据损失。

场景二:副本未完全同步(Under Replicated Partitions)持续大于 0

kubectl exec <broker-pod> -- \
  bin/kafka-topics.sh --bootstrap-server localhost:9092 \
  --describe --under-replicated-partitions

kubectl get pod -l strimzi.io/cluster=my-cluster -o wide

除检查 Broker Pod 状态、网络和磁盘 I/O 外,还要关注节点重建、Pod 重调度、PV 延迟、CNI/NetworkPolicy 是否阻断 Broker 间监听器,以及资源限制是否造成长时间 GC。恢复故障副本后等待 ISR 追平;只有在容量或副本分布确认有问题时,再通过 KafkaRebalance 或分区重分配处理。

场景三:消费者滞后(Consumer Lag)增长,但消费者 Pod 看似正常

kubectl exec <broker-pod> -- \
  bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --group order-processor --describe

kubectl get pod -l app=order-processor

除排查业务处理耗时、热点分区和再均衡外,还需检查消费者 Pod 的重启次数、CPU 限流、内存限制、HPA 扩缩容事件和下游 Service 延迟。增加 Pod 数量前,要确认 Topic 分区数足以提供并行度;同一分区同一时刻仍只能分配给一个消费者实例。

场景四:KafkaTopic 或 KafkaUser 处于未就绪(NotReady)

kubectl describe kafkatopic my-topic
kubectl describe kafkauser my-user
kubectl get pod -l strimzi.io/cluster=my-cluster
kubectl logs <entity-operator-pod> -c topic-operator
kubectl logs <entity-operator-pod> -c user-operator

常见原因包括 Operator 无法访问 Kafka Admin API、TLS 信任链或 Secret 异常、Topic 副本因子超过可用 Broker/机架数、名称或配置不合法,以及 ACL 不允许 Entity Operator 操作。应从 CR 状态条件和 Operator 日志确认根因,避免只改 CR 而忽略实际集群容量或授权限制。

场景五:外部客户端连不上 Kafka,但集群内部正常

检查外部监听器类型、advertised.listeners、证书 SAN、DNS、负载均衡地址和 NetworkPolicy。尤其要确认客户端拿到的地址可从其网络位置解析和访问;Broker Pod 内 localhost:9092 的成功并不能证明外部监听器可用。