这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

模块:Kafka

使用 Pigsty 部署、保护与监控 Apache Kafka 4.x dynamic KRaft 集群。

Kafka 是一个分布式事件流平台。Pigsty 的 KAFKA 模块使用 RPM/DEB 软件包,在纳管节点上部署 Apache Kafka 4.x dynamic KRaft 集群,并统一管理安全、资源、生命周期与可观测性。


模块能力

KAFKA 模块当前提供:

  • 使用原生 dynamic KRaft,不安装 ZooKeeper,也不渲染静态 controller.quorum.voters
  • 支持 combinedbrokercontroller 三种原生角色和复合/分离拓扑
  • 为新集群随机生成 Cluster ID 与 Controller Directory ID,并以最小 Bootstrap Manifest 保护身份
  • 根据实时健康状态选择冷启动/修复、纯 Broker 串行准入或严格单节点滚动路径
  • 在滚动前后检查 Controller 多数派与 Voter 追平、Offline Partition、Under Min ISR 与 ISR 追平
  • 提供 plaintext 与生产 scram 两种安全档位;后者启用 TLS、SCRAM-SHA-512、Controller mTLS、ACL 与默认拒绝授权
  • 声明式收敛 Topic、用户凭据、ACL 与 Quota,不隐式删除业务 Topic
  • 保护性轮换内部凭据与证书,并在失败时保留当前有效材料
  • 采集 JMX、Broker、请求、复制、KRaft、Topic、Partition 与 Consumer Group 指标
  • 将 Kafka 与 Exporter 日志接入 VictoriaLogs,并提供三个 Grafana Dashboard 与配套告警

模块架构

KAFKA 模块依赖 NODE 完成节点纳管、仓库与基础监控,依赖 INFRA 提供 VictoriaMetrics、VictoriaLogs、Grafana 与 Alertmanager。

flowchart LR
    admin["Pigsty 管理节点"] -->|"kafka.yml / exact cluster"| kafka["Kafka 4.x / dynamic KRaft"]
    kafka --> jmx["每个 Kafka JVM / JMX :9404"]
    kafka --> exporter["最多两个 Broker / kafka_exporter :9308"]
    kafka --> journal["Journald"]
    jmx --> vm["VictoriaMetrics"]
    exporter --> vm
    journal --> vector["Vector"] --> vl["VictoriaLogs"]
    vm --> grafana["Grafana"]
    vl --> grafana
    vm --> alert["Alertmanager"]

    style kafka fill:#70C1B3,stroke:#4f968b,color:#fff
    style vm fill:#E66B7A,stroke:#b84e5c,color:#fff
    style vl fill:#C98367,stroke:#9e634e,color:#fff
    style grafana fill:#F29C64,stroke:#c77845,color:#fff

每个 Kafka JVM 都注入 JMX Exporter 并注册为 job=kafka。协议型 kafka_exporter 只在按 kafka_seq 排序后的前两个 Broker-capable 节点运行;单 Broker 集群只运行一个,纯 Controller 不运行。它们返回的是同一逻辑集群视图,Recording Rule 会先去重再聚合。


文档导航

文档内容
快速上手从单节点到三节点安全集群、客户端接入、参数修改与上线检查
集群配置拓扑、dynamic KRaft、网络、存储、安全与资源声明
参数参考15 项持久公开参数及临时运维变量
日常管理状态检查、Topic、消息、Consumer Group 与拓扑变更
预置剧本kafka.yml 生命周期、任务标签、轮换与清理保护
监控告警指标链路、Dashboard、日志查询与告警规则
指标定义JMX、协议 Exporter 与 Recording Rule 指标字典
常见问题角色、身份、安全、Exporter 与扩缩容答疑

第一次使用

快速上手 提供一条从零开始、由浅入深的完整路径:

  1. 部署一个 combined 单节点开发集群,完成 Topic 与消息读写;
  2. 部署独立的三节点 dynamic KRaft 集群,启用 TLS/SCRAM/ACL;
  3. 创建应用 Principal、Topic、Quota,并从外部客户端安全接入;
  4. 修改 Heap、Broker 与 Topic 参数,观察在线收敛和严格滚动;
  5. 按 Quorum、ISR、网络、安全、监控和运行手册完成上线检查。

如果您已经熟悉 Kafka/Pigsty,可以直接进入 集群配置参数参考


默认端口

端口服务部署范围plaintextscram
9092Kafka BrokerBroker-capable 节点PLAINTEXTSASL_SSL + SCRAM-SHA-512
9093KRaft ControllerController-capable 节点PLAINTEXT双向 TLS
9308kafka_exporter最多两个 Broker-capable 节点HTTP 指标HTTP 指标,后端使用 TLS/SCRAM
9404JMX Exporter所有 Kafka 节点HTTP 指标HTTP 指标

四个端口必须彼此不同,均可通过参数调整。JMX 与协议 Exporter 的 HTTP 端口仍应通过防火墙限制在监控网络内。


当前边界

当前角色提供的是 Kafka 核心生产基线,不替代完整的流平台或托管服务。下列能力仍需显式运行手册或独立组件:

  • Controller 增删/替换:集群使用 dynamic quorum,但成员变更必须显式执行格式化、追平与 add-controller/remove-controller 流程;修改清单本身不会加入或移除 Voter
  • Broker 扩容后的既有 Partition Reassignment、Broker 退役与副本再均衡
  • 扩容后提升冻结的 default.replication.factor:Kafka 4.3 需要显式数据迁移与静态配置维护窗口
  • 已有 Topic 的副本因子变更、Topic 删除与用户删除
  • 已格式化集群从 plaintext 在线迁移到 scram
  • Kafka 版本升级、Feature Level 终结、数据备份、恢复与灾难演练
  • 多 Listener、NAT/公网地址、同一 Broker 多客户端网络、Tiered Storage
  • Kafka Connect、Schema Registry、MirrorMaker 2、Cruise Control 与 Web UI

这些边界应在生产方案、审批流程与演练中明确记录,不能用普通清单重跑代替。

1 - 快速上手

从零部署单节点与三节点 Kafka,完成安全接入、参数调整和上线检查。

本教程从一个最小单节点集群开始,完成 Topic 创建与消息读写;随后部署一套独立的三节点安全集群,配置应用用户、ACL、Quota 和生产 Topic;最后演示核心参数修改、客户端接入、监控验证与上线检查。


学习路径

阶段目标最终结果
1部署单节点开发集群1 个 combined 节点、PLAINTEXT、RF=1 Topic、CLI 读写
2部署三节点生产基线3 个 combined 节点、dynamic KRaft、TLS/SCRAM/ACL、RF=3/minISR=2
3接入应用客户端使用应用 Principal、Pigsty CA 与 SASL_SSL 生产/消费
4修改核心参数演示 Heap、Broker 参数、Topic Partition/保留和安全滚动
5上线验收检查 Quorum、ISR、端到端读写、监控、容量与运行手册

开始前准备

以下命令默认在 Pigsty 管理节点的项目目录执行:

cd ~/pigsty

开始前确认:

  • pigsty.yml 是当前环境的配置源,先备份并审阅现有内容;
  • Kafka 节点的 inventory_hostname 可以被所有 Kafka 成员和客户端直接解析、路由;
  • 管理节点与 Kafka 节点时间同步;
  • 9092909393089404 没有端口冲突;
  • /data/kafka 对应专用数据盘或专用目录,且没有混放其他数据;
  • 每次 kafka.yml 都使用 -l 精确选择同一 Kafka 集群的全部成员;
  • 真实变更前先执行 --check,审阅输出并取得变更批准。

配置清单必须保留 all.children 层级。下面的组应合并到现有 pigsty.yml,不要用示例覆盖已有的 all.varsinfraetcdpgsql 等配置。


一、部署单节点 Kafka

1. 定义集群

将以下 kf-dev 组加入 all.children。该节点省略 kafka_role,因此使用默认 combined,同时承担 Broker 与 Controller:

all:
  children:
    # 现有 infra、etcd、pgsql 等分组继续保留

    kf-dev:
      hosts:
        10.10.10.10: { kafka_seq: 1 }
      vars:
        kafka_cluster: kf-dev
        kafka_data: /data/kafka
        kafka_security: plaintext
        kafka_topics:
          - name: quickstart.events
            partitions: 1
            replication_factor: 1
            config:
              retention.ms: 86400000   # 1 天,仅用于教程

这个配置会得到:

  • 一个随机 Cluster ID;
  • 一个 dynamic KRaft combined 节点;
  • 默认 RF=1、minISR=1;
  • 一个名为 quickstart.events 的单 Partition Topic;
  • JMX Exporter :9404 与一个协议 Exporter :9308

plaintext 没有传输加密、认证和 ACL,只能用于本机开发或可信隔离网络。

2. 纳管节点

如果该主机尚未完成 NODE 初始化,先执行检查模式:

./node.yml --check -l kf-dev

审阅结果并取得批准后再纳管节点:

./node.yml -l kf-dev

已经由 Pigsty 纳管、软件仓库和时间同步均正常的节点可以跳过这一步。NODE 的完整准备与日常管理见 节点管理

3. 部署 Kafka

先对完整集群执行检查:

./kafka.yml --check -l kf-dev

确认目标确实只有 kf-dev 的完整成员,审阅数据路径、软件包、端口与配置变化后执行:

./kafka.yml -l kf-dev

角色会安装 Java 与 kafka-stack、生成随机身份和 Bootstrap Manifest、格式化 KRaft 存储、启动服务、创建 Topic,并注册监控目标。

4. 验证服务与 Quorum

登录 Kafka 节点,检查服务:

systemctl is-active kafka kafka_exporter
journalctl -u kafka --since '-10 min' --no-pager

使用角色自有健康检查:

sudo -u kafka /usr/local/bin/pigsty-kafka-health cluster \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties

返回 JSON 中应有 "healthy": true。继续检查 dynamic quorum 与 Topic:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --status

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --topic quickstart.events

应看到有效 LeaderId、包含本节点的 CurrentVoters,以及 RF=1、ISR=1 的 quickstart.events

5. 生产与消费消息

启动 Console Producer:

/opt/kafka/bin/kafka-console-producer.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic quickstart.events

输入几行消息后按 Ctrl-D 结束。在另一个终端消费:

/opt/kafka/bin/kafka-console-consumer.sh \
  --bootstrap-server 10.10.10.10:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic quickstart.events \
  --group quickstart.demo \
  --from-beginning

到这里,单节点部署、Topic 收敛和消息读写已经完成。进一步的状态检查见 日常管理


二、部署三节点生产基线

三节点示例是一套全新的 kf-main 集群,使用三个 combined 节点。它可以容忍一个 Controller 故障;业务 Topic 使用 RF=3/minISR=2,并启用 scram 生产安全档位。

1. 定义安全集群与资源

将以下组加入现有 all.children

all:
  children:
    # 现有分组继续保留

    kf-main:
      hosts:
        10.10.10.11: { kafka_seq: 1 }
        10.10.10.12: { kafka_seq: 2 }
        10.10.10.13: { kafka_seq: 3 }
      vars:
        kafka_cluster: kf-main
        kafka_data: /data/kafka
        kafka_heap_opts: '-Xms4G -Xmx4G'
        kafka_security: scram

        kafka_parameters:
          num.partitions: 12
          num.network.threads: 6
          num.io.threads: 16
          log.retention.hours: 168
          log.segment.bytes: 1073741824

        kafka_users:
          - name: quickstart-app
            password: "{{ vault_kafka_quickstart_password }}"
            acls:
              - resource: topic
                name: quickstart.
                pattern: prefixed
                operations: [Read, Write, Describe]
              - resource: group
                name: quickstart.
                pattern: prefixed
                operations: [Read]
              - resource: cluster
                name: kafka-cluster
                operations: [Describe, IdempotentWrite]
            quota:
              producer_byte_rate: 10485760
              consumer_byte_rate: 20971520

        kafka_topics:
          - name: quickstart.events
            partitions: 12
            replication_factor: 3
            config:
              min.insync.replicas: 2
              cleanup.policy: delete
              retention.ms: 604800000

vault_kafka_quickstart_password 必须由现有的 Ansible Vault、KMS 或其他秘密注入机制提供,至少 12 个字符。不要把真实密码直接提交到 Git、日志或工单。

这个配置的关键语义:

  • 三个节点全部省略 kafka_role,因此一致使用 combined
  • 新集群直接 Bootstrap 为 dynamic KRaft;
  • scram 同时启用节点 TLS、Controller mTLS、SCRAM-SHA-512、ACL 和默认拒绝;
  • 三 Broker 初始复制策略自动派生为 RF=3、minISR=2;
  • quickstart.events 显式创建 12 个 Partition、3 副本;
  • quickstart-app 可读写 quickstart.* Topic、读取 quickstart.* Group,并可使用幂等 Producer;
  • 最多两个 Broker 运行 kafka_exporter,三个 Kafka JVM 都运行 JMX Exporter。

如果三个 Broker 确实位于不同故障域,可以在全部节点上分别增加 kafka_rack: az-a/az-b/az-c。不要用虚构 Rack 标签制造不存在的容灾保证,详细规则见 集群配置:Rack

2. 纳管并部署

如果节点尚未纳管:

./node.yml --check -l kf-main
./node.yml -l kf-main

部署 Kafka 时必须选择全部三个成员:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

不能只 -l 10.10.10.11,也不能一次选择 kf-dev,kf-main。角色会拒绝缺失、部分或跨集群 Limit。

3. 验证三节点健康

从管理节点检查三个 Kafka 服务:

ansible kf-main -b -m command -a 'systemctl is-active kafka'

在任一 Broker 上执行完整健康检查:

sudo -u kafka /usr/local/bin/pigsty-kafka-health cluster \
  --bootstrap-server 10.10.10.11:9092 \
  --command-config /etc/kafka/admin.properties

查询 quorum 和 Topic:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server 10.10.10.11:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --status

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server 10.10.10.11:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --topic quickstart.events

上线前应看到:一个 Active Controller、三个 Current Voters、三个可用 Broker;所有 quickstart.events Partition 均有三副本、ISR=3,没有 Offline、Under Replicated 或 Under Min ISR Partition。


三、接入应用客户端

1. 分发 CA 公钥证书

将管理节点上的公共 CA 证书安全复制到应用主机:

files/pki/ca/ca.crt  ->  /etc/kafka-client/pigsty-ca.crt

ca.crt 是可以分发的公钥证书。绝不要复制、暴露或分发 files/pki/ca/ca.key 应用主机上的 CA 文件建议由 root 管理并设为只读。已被 Pigsty 纳管的应用主机无需复制:NODE 模块已把同一 CA 安装在 /etc/pki/ca.crt,客户端可直接引用。

2. 创建客户端配置

在应用主机创建 /etc/kafka-client/client.properties

bootstrap.servers=10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092

security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="quickstart-app" password="<secret-from-vault>";

ssl.truststore.type=PEM
ssl.truststore.location=/etc/kafka-client/pigsty-ca.crt
ssl.endpoint.identification.algorithm=https

Kafka Java 客户端支持 SASL_SSL + SCRAM,并支持 PEM Truststore。实际应用应在运行时从 Secret Manager 注入密码,而不是把包含密码的文件提交到仓库。完整字段见 Kafka 4.3 SASL/SCRAMProducer 配置

3. 为什么应用应直连多个 Broker

Kafka 客户端本身就是具备集群感知能力的智能客户端。bootstrap.servers 只用于取得初始元数据;连接成功后,客户端会根据元数据直接连接各 Partition 的 Leader Broker,并在 Leader 变化后刷新路由。因此生产环境的常规做法是:

  • bootstrap.servers 中配置至少两个、通常三个位于不同故障域的 Broker 地址;
  • 放通应用到所有 Broker9092,并保证 Broker 宣告的 inventory_hostname 可解析、可路由;
  • 让 Producer/Consumer 使用 Kafka 客户端自身的重试、元数据刷新、幂等与 Consumer Group 协议;
  • 不把 HAProxy、Keepalived VIP、四层 LB 或七层反向代理放在 Kafka 数据面前方。

单个 VIP/LB 不能替代 Kafka 元数据中的 Broker 地址,也不能把一个连接透明转发到正确的 Partition Leader;它还会增加长连接状态、故障定位和容量规划复杂度。若平台必须提供统一的发现入口,可以使用 DNS 名称或 TCP LB 作为仅用于 bootstrap 的入口,但 Broker 的 advertised.listeners 仍必须返回客户端可直达的每个 Broker 地址,应用也不能只获准访问 LB。

跨 NAT、公网、Kubernetes 或多网络场景通常需要为每个 Broker 设计独立的外部可达地址/端口和额外 Listener。当前模块固定使用清单地址作为 advertised.listeners,不支持这类任意 Listener 映射;不要用一个 HAProxy VIP 掩盖地址模型不成立的问题。

4. 用应用身份验证读写

在安装了 Kafka 4.3 CLI 的应用主机上执行:

kafka-console-producer.sh \
  --bootstrap-server 10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092 \
  --command-config /etc/kafka-client/client.properties \
  --topic quickstart.events

消费时使用 ACL 允许的 Group 前缀:

kafka-console-consumer.sh \
  --bootstrap-server 10.10.10.11:9092,10.10.10.12:9092,10.10.10.13:9092 \
  --command-config /etc/kafka-client/client.properties \
  --topic quickstart.events \
  --group quickstart.demo \
  --from-beginning

生产应用还应显式评审客户端语义:

客户端配置建议起点说明
acksall与 RF=3/minISR=2 配合,避免只等待 Leader
enable.idempotencetrue降低重试导致重复写入的风险,需要 IdempotentWrite ACL
group.id独立稳定名称不同业务/消费语义不要复用 Group
Offset 提交按业务选择自动提交简单;手动提交更容易绑定业务处理结果
client.id可识别实例名便于日志、Quota 与客户端诊断

客户端 acks、重试、幂等、批量、压缩和 Offset 策略属于应用配置,不应写入 Broker 的 kafka_parameters


四、修改核心参数

Kafka 的持久意图始终修改 pigsty.yml,不要直接编辑 /etc/kafka/server.properties。常见意图对应关系:

目标参数行为
调整 JVM Heapkafka_heap_opts静态变化,健康集群进入严格单节点滚动
调整线程、保留、Segmentkafka_parameters非角色自有 Broker 参数;静态变化需要滚动
调整 Topic Partition/保留kafka_topics在线资源收敛;Partition 只增不减
调整应用密码/ACL/Quotakafka_users在线资源收敛;密码由秘密系统提供
声明故障域kafka_rack所有 Broker-capable 节点全有或全无;变化会滚动但不搬迁数据
选择安全档位kafka_security只能在新集群 Bootstrap 时决定,不能普通重跑在线切换

示例:调整 Heap 与 Broker 默认参数

假设压测后决定将 Heap 调整为 6G、提高线程数,并把新 Topic 的默认保留时间改成 72 小时:

kf-main:
  vars:
    kafka_cluster: kf-main
    kafka_heap_opts: '-Xms6G -Xmx6G'
    kafka_parameters:
      num.partitions: 12
      num.network.threads: 8
      num.io.threads: 24
      log.retention.hours: 72
      log.segment.bytes: 1073741824

不要照抄 6G/8/24;这些值必须由 CPU、内存、连接数、消息大小、Partition 数、磁盘和 Page Cache 压测决定。

示例:增加 Partition 并缩短 Topic 保留

quickstart.events 从 12 个 Partition 增加到 24,并把保留时间改成三天:

kafka_topics:
  - name: quickstart.events
    partitions: 24
    replication_factor: 3
    config:
      min.insync.replicas: 2
      cleanup.policy: delete
      retention.ms: 259200000

Partition 不能减少。replication_factor 与现场不一致时,角色会拒绝普通收敛并要求显式 Partition Reassignment;不会自动搬迁既有副本。

应用变更

无论修改静态参数还是动态资源,都运行完整状态机:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

不要只运行 -t kafka_config。角色会自动判断:静态变化执行严格逐节点滚动;只修改 Topic/User 等动态资源时不重启 Kafka。

以下键属于角色自身,不能放入 kafka_parameters

kafka_parameters:
  min.insync.replicas: 2          # 错误:角色拥有
  default.replication.factor: 3   # 错误:角色拥有
  listeners: ...                  # 错误:角色拥有

全部 15 项公开参数、默认值和保留键见 参数参考


五、上线前关键检查

拓扑与数据安全

  • 生产至少使用三个 Broker,并使用奇数 Controller;关键/大型集群考虑 3 Controller + N Broker 分离拓扑;
  • Topic RF、minISR 与生产者 acks 形成一致的故障模型;
  • kafka_rack 只表达真实故障域,且副本放置已经核验;
  • 数据盘容量、吞吐、延迟、保留时间、峰值写入和恢复时间已经压测;
  • 新 Broker 加入后有显式 Reassignment 计划,现有 Topic RF 不会自动提高;
  • 已明确 Kafka 数据备份/重建、Broker 替换、Controller 成员和灾难恢复流程。

安全与网络

  • 新生产集群从 Bootstrap 起就使用 kafka_security: scram
  • 应用密码由 Vault/KMS/Secret Manager 注入,未进入 Git 或日志;
  • 只向客户端分发 CA 公钥证书,不分发 CA 私钥;
  • 客户端可以解析并直达所有 Broker 的 inventory_hostname
  • 9092/9093 只向必要主体开放,9308/9404 只向监控网络开放;
  • 已建立应用 Principal、Topic/Group/Cluster ACL 与 Quota 审核清单;
  • 已安排内部凭据和证书的 受保护轮换

运行与监控

  • /usr/local/bin/pigsty-kafka-health cluster 返回健康;
  • dynamic quorum 只有一个 Leader,所有预期 Controller 都在 Current Voters;
  • 没有 Offline、Under Replicated 或 Under Min ISR Partition;
  • 使用真实应用网络、真实 Principal 完成生产与消费验证;
  • Kafka OverviewKafka InstanceKafka Node 数据正常;
  • 告警路由、日志检索、容量阈值、值班责任和回退条件已经确认;
  • 升级、Feature Level、Topic 删除、用户删除与集群下线均有独立审批流程。

详细告警与 PromQL 见 监控告警,指标语义见 指标定义


文档索引与下一步

建议按以下路径继续阅读:

您接下来要做什么对应文档
规划 combined 或 Controller/Broker 分离拓扑、网络、Rack、存储与安全集群配置
查找 15 项公开参数、默认值、Schema 和保留键参数参考
理解 kafka.yml 生命周期、严格滚动、轮换与集群下线预置剧本
查看 Quorum、Topic、用户、消息、Consumer Group 与扩容操作日常管理
使用 Dashboard、告警、PromQL 和 VictoriaLogs监控告警
理解每一项 JMX/Exporter/Recording Rule 指标指标定义
排查身份冲突、连接、SCRAM、Exporter、Lag 与扩缩容问题常见问题
回到模块能力、默认端口与边界总览Kafka 模块首页

一条推荐阅读链路是:快速上手 → 集群配置 → 参数参考 → 预置剧本 → 日常管理 → 监控告警 → 常见问题

2 - 集群配置

规划 Kafka dynamic KRaft 拓扑、身份、网络、存储、安全与声明式资源。

KAFKA 模块使用 15 项持久公开参数表达集群意图,其余拓扑、监听器、存储子目录、复制安全、授权与 Exporter 放置由角色统一推导。首次部署建议先完成 快速上手;完整字段见 参数参考


部署前检查

填写清单前至少确认:

  • 目标主机已由 NODE 纳管,软件仓库可用,inventory_hostname 可被所有 Kafka 成员与客户端直接路由
  • 一次操作将用 -l 精确选择同一 kafka_cluster 的全部成员,而不是单节点、部分成员或多个集群
  • kafka_seq 在集群内唯一,Controller 为奇数,Broker 数量、故障域与容量目标匹配
  • 9092909393089404 互不冲突,Infra 节点可以访问两个指标端口
  • kafka_data 对应专用文件系统,并已按保留时间、写入峰值、复制流量、恢复时间与增长余量规划
  • 生产使用 kafka_security: scram;节点与管理端时间同步,Pigsty CA 可用,应用密码来自 Vault 等秘密来源
  • Topic 的 Partition、副本、min.insync.replicas、保留策略,以及客户端 acks、重试与消费恢复策略已经评审
  • 扩缩容、Partition Reassignment、升级、备份、恢复与 Controller 成员变更有独立运行手册

角色与拓扑

kafka_role 只接受三个值:

角色Kafka process.rolesBroker 端口Controller 端口JMXkafka_exporter
combinedbroker,controller可被选择
brokerbroker可被选择
controllercontroller

kafka_role 按节点独立声明,省略即为默认 combined。集群必须至少包含一个 Controller-capable 节点和一个 Broker-capable 节点;偶数 Controller 会给出警告, 生产通常使用 3 个 Controller。


单节点开发集群

单节点同时承担 Broker 与 Controller,无法容忍节点故障,只适合开发、测试与功能验证:

kf-dev:
  hosts:
    10.10.10.10: { kafka_seq: 1 }
  vars:
    kafka_cluster: kf-dev

角色会从初始 Broker 数量推导 RF=1、minISR=1。不要把单节点拓扑或默认 plaintext 安全模式直接用于生产。


三节点复合部署

三个节点都承担 Broker 与 Controller,是紧凑的生产起点。省略全部角色字段即可使用默认 combined

kf-main:
  hosts:
    10.10.10.11: { kafka_seq: 1 }
    10.10.10.12: { kafka_seq: 2 }
    10.10.10.13: { kafka_seq: 3 }
  vars:
    kafka_cluster: kf-main
    kafka_heap_opts: '-Xms4G -Xmx4G'
    kafka_security: scram
    kafka_parameters:
      num.partitions: 3
      num.network.threads: 6
      num.io.threads: 16
    kafka_topics:
      - name: order.events
        partitions: 12
        replication_factor: 3
        config:
          min.insync.replicas: 2
          cleanup.policy: delete

初始三个 Broker 会自动得到 RF=3、minISR=2 的角色自有复制策略,无需也不允许在 kafka_parameters 中覆盖内部 Topic RF、default.replication.factormin.insync.replicas。示例中的 4G Heap 只是写法示意;生产应通过压测平衡 JVM Heap、操作系统 Page Cache 与同机其他进程。


Controller 与 Broker 分离

关键或较大集群可以把控制面与数据面分离。因为存在显式角色,所有成员都必须声明角色:

kf-main:
  hosts:
    10.10.10.11: { kafka_seq: 1, kafka_role: controller }
    10.10.10.12: { kafka_seq: 2, kafka_role: controller }
    10.10.10.13: { kafka_seq: 3, kafka_role: controller }
    10.10.10.21: { kafka_seq: 4, kafka_role: broker }
    10.10.10.22: { kafka_seq: 5, kafka_role: broker }
    10.10.10.23: { kafka_seq: 6, kafka_role: broker }
  vars:
    kafka_cluster: kf-main
    kafka_security: scram

纯 Controller 不监听 9092,也不运行协议 Exporter;它仍通过 JMX 暴露 KRaft 与 JVM 状态。最多两个 kafka_exporter 会放在 kafka_seq 最小的 Broker-capable 节点上。


Dynamic KRaft 与 Bootstrap Manifest

新集群直接使用 dynamic quorum:所有节点渲染 controller.quorum.bootstrap.servers,不会生成静态 controller.quorum.voters。首次格式化时:

  • Cluster ID 随机生成,不由集群名哈希;
  • 初始 Controller 的 Directory ID 随机生成并冻结;
  • 每个节点显式使用 --initial-controllers--no-initial-controllers 格式化模式;
  • 启动后角色等待 dynamic quorum 选出 Leader,并校验每个初始 Controller 的 Directory ID 都在现场 quorum 中。

Bootstrap-only 事实保存在管理节点缓存:

files/kafka/<kafka_cluster>/manifest.yml

同时每个集群成员都保留一份权威副本 /etc/kafka/manifest.ymlscram 集群还有 /etc/kafka/secrets.yml)。Manifest 只记录集群身份、初始 Controller Identity、安全模式和初始 RF/minISR。活集群始终是运行事实权威:

  • Manifest 与现场身份或安全模式冲突时,普通剧本失败关闭;
  • 旧 Manifest 存在但全部数据盘为空时拒绝复活旧集群;
  • 管理节点缓存丢失时,可以从任一成员的节点副本自动恢复,不会重新格式化;
  • 管理节点与所有成员都找不到 Manifest 而存储已格式化时,失败关闭并提示先恢复 Manifest;
  • 已格式化的 scram 集群在管理节点与所有成员都没有 Secret 材料时同样失败关闭。

增加、替换或删除 Controller 不是普通清单操作。新 Controller 必须针对现有集群显式格式化、启动并追平,然后执行 Kafka add-controller;删除则需要对应的 remove-controller 流程。角色会拒绝把未登记的新 Controller 仅凭 inventory 自动加入 Voter 集合。


身份参数

身份来源示例约束
集群名kafka_clusterkf-main字母或数字开头,只含字母、数字、下划线和连字符
节点号kafka_seq1非负整数,同一集群内唯一
实例名自动生成kf-main-1${kafka_cluster}-${kafka_seq}
节点角色kafka_rolecombined三种原生角色之一
KRaft Cluster IDBootstrap 随机生成22 字符 Kafka UUIDkafka_cluster_id 仅作接管/恢复断言

已格式化节点会从 ${kafka_data}/metadata/meta.properties 读取 cluster.idnode.id,并与 Manifest 及清单交叉校验;初始 Controller 的 Directory ID 则在启动后与活 quorum 比对。身份不匹配是保护性失败,不应通过删除 meta.properties 或清空数据绕过。


网络与监听器

角色只公开端口,不公开 bind、advertised address 或 listener map:

参数默认值用途
kafka_port9092Broker、客户端与 Broker 间通信
kafka_controller_port9093KRaft Controller 仲裁
kafka_exporter_port9308协议 Exporter HTTP 指标
kafka_jmx_exporter_port9404JMX Exporter HTTP 指标

固定监听器约定如下:

  • Broker listener 绑定 0.0.0.0,Controller listener 绑定 inventory_hostname
  • Broker 的 advertised.listeners 使用 inventory_hostname
  • Controller bootstrap 地址也使用 inventory_hostname
  • plaintext:BROKER 与 CONTROLLER 都使用 PLAINTEXT;
  • scram:BROKER 使用 SASL_SSL + SCRAM-SHA-512,CONTROLLER 使用双向 TLS。

因此客户端必须能够解析并直达每一个 Broker 的 inventory_hostname。当前 v1 不支持 NAT、公网映射、同一 Broker 多客户端网络或任意 raw listener 覆盖;这些场景不能通过 kafka_parameters 拼装绕过。

Kafka 的标准接入模型是智能客户端直连 Broker:bootstrap.servers 配置多个种子地址,客户端获取集群元数据后直接连接 Partition Leader。HAProxy、Keepalived VIP、云 LB 不应作为常规 Kafka 数据面入口,因为它们不了解 Kafka 元数据和 Partition Leader,且无法免除客户端访问所有 advertised.listeners 地址的要求。DNS 或 TCP LB 最多作为可选的 bootstrap 发现入口;即使如此,应用网络仍必须直达全部 Broker。详见快速上手:接入应用客户端

最小网络流向:

来源目标端口用途
Kafka 客户端、其他 Broker所有 Broker9092Produce、Fetch、元数据与 Broker 间通信
所有 Kafka 成员所有 Controller9093KRaft 元数据仲裁
Infra/VictoriaMetrics所有 Kafka 节点9404JVM/Kafka 指标
Infra/VictoriaMetrics被选择的 Exporter 节点9308集群/Topic/Consumer 指标

指标端口为 HTTP,即使 Kafka 使用 scram,也应通过防火墙限制在监控网络内。


存储、Heap 与 Rack

用户只设置根目录:

kafka_data: /data/kafka

角色固定派生 Topic 数据目录 ${kafka_data}/data 与 KRaft 元数据目录 ${kafka_data}/metadatakafka_data 必须是专用绝对路径,不能是 //data/var/etc/opt/usr/home/root/pg

生产规划至少考虑保留时间、消息峰值、复制流量、Partition/Segment 数、磁盘延迟与吞吐、文件描述符、恢复时间、JVM Heap 与 Page Cache。当前角色只生成一个 log.dirs;多盘 JBOD、磁盘替换和自动数据迁移需要独立运行手册。

跨故障域部署可以在所有 Broker-capable 节点上一致声明 kafka_rack

10.10.10.21: { kafka_seq: 4, kafka_role: broker, kafka_rack: az-a }
10.10.10.22: { kafka_seq: 5, kafka_role: broker, kafka_rack: az-b }
10.10.10.23: { kafka_seq: 6, kafka_role: broker, kafka_rack: az-c }

Broker-capable 节点必须全部设置或全部省略 Rack。修改 Rack 会触发安全滚动,但不会自动迁移既有副本。


复制策略

首次 Bootstrap 根据初始 Broker 数量派生:

replication_factor = min(3, broker_count)
min_insync_replicas = max(1, replication_factor - 1)

初始的未来 Topic 默认 RF、内部 Topic RF 与集群 minISR 都会写入 Manifest 并冻结。扩容后:

  • default.replication.factor 保持初建值;Kafka 4.3 不允许通过动态 Broker 配置在线修改它;
  • 已有内部/业务 Topic 的 RF 不会自动提高;
  • 角色不会把“Broker 已加入”报告成“数据已均衡”;
  • RF 变化必须使用经过评审的 kafka-reassign-partitions.sh 计划;提升静态默认值还需要 Controller 高可用或明确维护窗口,并通过完整集群安全滚动生效。

生产者 acks、幂等、重试、批量和压缩属于客户端策略,不是 Kafka Broker 角色参数。


kafka_parameters

kafka_parameters 是唯一的 Broker 参数逃生舱,默认 {},只渲染到 Broker-capable 节点。它适合 num.partitions、线程数、Buffer、保留与 Segment 等非角色自有键。

以下模式由角色拥有,禁止覆盖:

process.roles
node.id
controller.quorum.*
listeners
advertised.listeners
listener.security.protocol.map
inter.broker.listener.name
controller.listener.names
log.dirs
metadata.log.dir
min.insync.replicas
default.replication.factor
offsets.topic.replication.factor
transaction.state.log.replication.factor
transaction.state.log.min.isr
share.coordinator.state.topic.replication.factor
share.coordinator.state.topic.min.isr
broker.rack
authorizer.class.name
super.users
allow.everyone.if.no.acl.found
sasl.*
ssl.*
listener.*

出现任一保留键时,身份预检会在写文件前直接失败。


安全与声明式资源

kafka_security: scram 是一个完整生产档位,而不是一组可任意组合的开关。它自动启用:

  • Pigsty CA 签发的每节点证书;
  • Controller listener 双向 TLS;
  • Broker/client 与 Broker 间 SASL_SSL + SCRAM-SHA-512;
  • StandardAuthorizer、默认拒绝,以及角色自有管理/监控身份;
  • 在协议 Exporter 启动前收敛其最小监控 ACL。

应用资源由两个领域对象声明:

kafka_security: scram
kafka_users:
  - name: order-service
    password: "{{ vault_kafka_order_password }}"
    acls:
      - resource: topic
        name: order.
        pattern: prefixed
        operations: [Read, Write, Describe]
      - resource: group
        name: order.
        pattern: prefixed
        operations: [Read]
    quota:
      producer_byte_rate: 10485760
      consumer_byte_rate: 20971520
kafka_topics:
  - name: order.events
    partitions: 12
    replication_factor: 3
    config:
      min.insync.replicas: 2
      cleanup.policy: delete

资源收敛语义:Topic 创建幂等、Partition 只增加、只更新显式声明的配置;RF 变化会拒绝并提示 Reassignment。声明用户的密码、ACL 与给出的 Quota 字段会幂等收敛。移除 Topic/User 条目不会作为隐式删除流程。

安全模式在 Bootstrap 后不能通过普通剧本切换。内部凭据与证书可以使用 受保护轮换,但 plaintextscram 的在线迁移仍需未来的显式状态机。


软件包与文件布局

角色通过平台映射安装 java-runtimekafka-stack。2026-07-16 验证的载荷为 Kafka 4.3.1、kafka_exporter 1.9.0、JMX Exporter 1.6.0;实际版本仍以目标平台仓库与已安装包为准。

路径用途
/opt/kafka/Kafka 程序与 CLI
/etc/kafka/server.properties角色生成的服务配置
/etc/kafka/admin.properties角色生成的 Broker 管理通道;CLI 应始终使用
/etc/kafka/controller.properties角色生成的 Controller 管理通道
/etc/kafka/log4j2.yamlJournald 日志配置
/etc/kafka/jmx_exporter.yml有界 JMX 指标规则
/etc/kafka/manifest.yml节点上的 Bootstrap Manifest 权威副本
/etc/kafka/secrets.ymlscram 节点上的内部 Secret 副本
/etc/kafka/pki/kafka.pemscram 节点 PEM 私钥与证书;信任锚使用系统 /etc/pki/ca.crt
${kafka_data}/data/Topic 日志数据
${kafka_data}/metadata/KRaft 元数据与 meta.properties
files/kafka/<cluster>/管理节点上的 Manifest/Secret/PKI 缓存

这些文件由角色管理。持久意图应写入 pigsty.yml,不要在节点上直接编辑生成文件,也不要把密码、私钥或角色自有 Secret 内容复制到清单、日志或工单。

3 - 参数参考

KAFKA 模块 15 项持久公开参数与临时受保护运维变量。

KAFKA 角色刻意只公开 15 项持久参数。拓扑、Listener、安全实现、存储子目录、复制安全与 Exporter 放置等细节由角色统一推导,不能作为额外持久变量覆盖。


参数概览

参数层级默认值说明
kafka_cluster集群必填Kafka 集群身份
kafka_seq实例必填集群内唯一 KRaft node.id
kafka_role实例combinedcombinedbrokercontroller
kafka_cluster_id集群未设置接管/恢复断言;新集群随机生成
kafka_data实例/data/kafka角色自有数据根目录
kafka_heap_opts实例-Xms1G -Xmx1GKafka JVM Heap
kafka_port实例9092Broker/client 端口
kafka_controller_port实例9093KRaft Controller 端口
kafka_rack实例未设置Broker 故障域标签
kafka_parameters集群/实例{}非角色自有 Broker 参数
kafka_jmx_exporter_port实例9404JMX Exporter HTTP 端口
kafka_exporter_port实例9308协议 Exporter HTTP 端口
kafka_security集群plaintextplaintext 或生产 scram 档位
kafka_users集群[]用户凭据、ACL 与 Quota
kafka_topics集群[]声明式 Topic

kafka_clusterkafka_seq 必须定义;kafka_role 有真实默认值。集群角色要么全部省略,要么全部显式声明。


身份与拓扑

kafka_cluster

必填的集群身份。必须以字母或数字开头,只能包含字母、数字、下划线和连字符:

kafka_cluster: kf-main

它用于发现完整集群成员、生成实例名和定位 Bootstrap Manifest。每次 kafka.yml 生命周期操作必须用精确 -l 选择该集群的全部成员。

kafka_seq

必填的非负整数,在同一 kafka_cluster 中唯一,直接成为 KRaft node.id

10.10.10.11: { kafka_seq: 1 }

实例名派生为 ${kafka_cluster}-${kafka_seq}。节点格式化后不要修改或复用仍有关联数据的序号。

kafka_role

默认 combined,只接受:

Kafka process.roles语义
combinedbroker,controllerBroker 与 Controller 合设
brokerbroker纯 Broker
controllercontroller纯 Controller

集群所有成员都省略时一致使用 combined;只要任一成员显式设置,所有成员都必须显式设置。不提供旧角色别名。

kafka_cluster_id

默认未设置,仅用于接管或恢复时断言现有集群身份,必须是 22 字符 Kafka UUID:

kafka_cluster_id: MkU3OEVBNTcwNTJENDM2Qk

普通新建集群不要设置。角色会随机生成 Cluster ID,并写入 files/kafka/<kafka_cluster>/manifest.yml。该参数不会重新标记现有数据;与 Manifest 或 meta.properties 冲突时会失败关闭。

kafka_rack

可选的 Broker 故障域标签,渲染为 broker.rack

10.10.10.21: { kafka_seq: 4, kafka_role: broker, kafka_rack: az-a }

所有 Broker-capable 节点必须全部声明或全部省略。纯 Controller 不使用该值。修改 Rack 属于静态变化,会进入严格滚动,但不会重新分配既有副本。


存储、JVM 与网络

kafka_data

数据根目录,默认 /data/kafka

kafka_data: /data/kafka

角色固定派生 ${kafka_data}/data${kafka_data}/metadata。该路径必须是专用绝对路径,不能是 //data/var/etc/opt/usr/home/root/pgkafka-rm.yml 默认会删除整个根目录,因此不要混放其他服务或业务文件。

kafka_heap_opts

Kafka JVM Heap,默认:

kafka_heap_opts: '-Xms1G -Xmx1G'

生产应根据负载与内存压测设置,通常保持 XmsXmx 相同,并为操作系统 Page Cache 与其他进程留出足够内存。

kafka_port

Broker/client 监听端口,默认 9092,只在 Broker-capable 节点监听。plaintext 模式使用 PLAINTEXT;scram 模式使用 SASL_SSL + SCRAM-SHA-512。

kafka_controller_port

KRaft Controller 监听端口,默认 9093(Kafka KRaft 惯例端口),只在 Controller-capable 节点监听。与其他服务共用节点时请自行确认端口无冲突,角色不会自动检测跨服务端口占用。

四个公开端口必须彼此不同。Broker listener 绑定 0.0.0.0,Controller listener、Broker advertised address 与 Controller bootstrap address 固定使用 inventory_hostname,不另设地址参数。


kafka_parameters

默认 {},是唯一的 Kafka Broker 参数逃生舱,只渲染到 Broker-capable 节点:

kafka_parameters:
  num.partitions: 12
  num.network.threads: 6
  num.io.threads: 16
  log.retention.hours: 168
  log.segment.bytes: 1073741824

以下键或模式由角色拥有,不能通过该映射覆盖:

process.roles
node.id
controller.quorum.*
listeners
advertised.listeners
listener.security.protocol.map
inter.broker.listener.name
controller.listener.names
log.dirs
metadata.log.dir
min.insync.replicas
default.replication.factor
offsets.topic.replication.factor
transaction.state.log.replication.factor
transaction.state.log.min.isr
share.coordinator.state.topic.replication.factor
share.coordinator.state.topic.min.isr
broker.rack
authorizer.class.name
super.users
allow.everyone.if.no.acl.found
sasl.*
ssl.*
listener.*

身份、监听器、安全、存储与复制策略必须保持单一权威;包含保留键时预检会直接失败。


可观测性

kafka_jmx_exporter_port

JMX Exporter HTTP 端口,默认 9404。角色为每个 Kafka JVM 无条件注入 JMX Exporter Java Agent,并注册为 job=kafka;没有单独的开关参数。生命周期健康门禁使用角色自有 Kafka CLI/metadata 通道,不依赖 JMX。Infra 监控节点必须可以访问该端口;端点不因 kafka_security: scram 自动启用 HTTPS,应通过监控网络和防火墙保护。

kafka_exporter_port

协议型 kafka_exporter HTTP 端口,默认 9308。角色只在按 kafka_seq 排序后的前两个 Broker-capable 节点配置、启动与注册;单 Broker 集群只运行一个。监控 Target 文件每次完整运行都会按当前放置刷新,但曾经被选中节点上的旧 Exporter 服务不会被普通剧本自动停止。

Exporter 使用的 Kafka 协议版本、TLS/SCRAM 参数和副本放置均为角色内部约定,没有额外公开开关或 options 参数。


安全与资源

kafka_security

默认 plaintext,只接受:

Broker/clientController授权用途
plaintextPLAINTEXTPLAINTEXT开发或可信隔离网络
scramSASL_SSL + SCRAM-SHA-512双向 TLSStandardAuthorizer,默认拒绝生产安全基线

scram 同时配置 Pigsty CA 签发的节点证书、角色自有管理/监控/内部身份、TLS/SCRAM 与 ACL 启用顺序。安全模式写入 Bootstrap Manifest;集群格式化后,普通重跑不能把 plaintext 切换成 scram,也不能反向切换。

kafka_users

默认 [],仅允许在 scram 模式声明。每个对象只接受 namepasswordaclsquota

kafka_users:
  - name: order-service
    password: "{{ vault_kafka_order_password }}"
    acls:
      - resource: topic
        name: order.
        pattern: prefixed
        operations: [Read, Write, Describe]
      - resource: group
        name: order.
        pattern: prefixed
        operations: [Read]
      - resource: transactional_id
        name: order.
        pattern: prefixed
        operations: [Write, Describe]
    quota:
      producer_byte_rate: 10485760
      consumer_byte_rate: 20971520

约束:

  • name 在列表中唯一;password 必填且至少 12 个字符,应引用秘密管理系统;
  • ACL resourcetopicgrouptransactional_idcluster
  • patternliteral(默认)或 prefixed
  • 操作为 ReadWriteCreateDeleteAlterDescribeClusterActionDescribeConfigsAlterConfigsIdempotentWrite
  • Quota 键为 producer_byte_rateconsumer_byte_raterequest_percentagecontroller_mutation_rate

角色为声明用户收敛 SCRAM 密码、完整 ACL 集合与显式给出的 Quota 字段。移除用户条目不会隐式删除 Principal 或凭据;删除/撤权需要独立受审操作。

kafka_topics

默认 []。每个对象只接受 namepartitionsreplication_factorconfig

kafka_topics:
  - name: order.events
    partitions: 12
    replication_factor: 3
    config:
      min.insync.replicas: 2
      cleanup.policy: delete
      retention.ms: 604800000

name 在列表中唯一;Partition 与 RF 都必须至少为 1,RF 不能超过当前 Broker 数。收敛语义是:

  • Topic 不存在时幂等创建;
  • Partition 只允许增加,减少会失败;
  • RF 与现场不同时拒绝普通收敛,并要求显式 Reassignment;
  • 只更新 config 中声明的键;
  • 从列表中移除 Topic 永远不会删除 Topic。

临时受保护运维变量

以下变量只通过命令行 -e 用于一次性运维动作,不属于 15 项持久 API,也不应写入 pigsty.yml

动作剧本临时变量保护条件
轮换内部凭据kafka.ymlkafka_rotate_credentials=truekafka_rotate_confirm=<cluster>健康、全员已格式化的 scram 集群
轮换证书kafka.ymlkafka_rotate_certificates=truekafka_rotate_confirm=<cluster>健康、全员已格式化的 scram 集群
下线集群kafka-rm.ymlkafka_rm_data(默认 true)、kafka_rm_pkg(默认 false)、kafka_safeguard(默认 falsekafka_safeguard=true 时中止一切删除

两种轮换动作互斥,且必须以精确完整集群为目标。kafka-rm.yml 默认删除数据目录与管理节点上的 Manifest/Secret/PKI 缓存,执行前必须显式确认目标集群与备份/重建意图。命令与完整语义见 预置剧本

4 - 日常管理

Kafka 集群健康、声明式资源、消息、Consumer Group 与拓扑变更管理。

KAFKA 模块把 Kafka 安装在 /opt/kafka,使用 Systemd 管理服务,并把持久意图保存在 pigsty.yml。节点上的生成文件不应手工修改。

以下 Kafka CLI 示例都使用角色生成的 /etc/kafka/admin.properties。即使当前是 plaintext,也建议始终保留 --command-config,这样切换到 scram 管理通道时命令结构不变。将 <broker>:9092 替换为可达的 inventory_hostname 与端口。


状态检查

在任意 Kafka 节点检查服务与最近日志:

systemctl status kafka
systemctl is-enabled kafka
journalctl -u kafka --since '-30 min' --no-pager

协议 Exporter 只在 kafka_seq 最小的至多两个 Broker-capable 节点运行。被选择的节点再检查:

systemctl status kafka_exporter
journalctl -u kafka_exporter --since '-30 min' --no-pager

检查监听器与指标端点:

ss -lntp | grep -E ':9092|:9093|:9308|:9404'
curl -fsS http://<kafka-ip>:9404/metrics | grep -E '^(jmx_scrape_error|kafka_server_raft_state|kafka_server_broker_messages_in_total)'
curl -fsS http://<exporter-ip>:9308/metrics | grep -E '^(kafka_brokers|kafka_topic_partitions)'

kafka_upkafka_exporter_up 是 VictoriaMetrics 侧的记录指标,不一定出现在原始端点。JMX 端点应包含 jmx_scrape_error 0.0、JVM 指标和与节点角色匹配的 kafka_ 指标。


角色自有健康检查

角色的生命周期门禁不依赖 JMX,而是通过同一管理通道检查 dynamic quorum、不可用 Partition、副本不足与 Under Min ISR:

sudo -u kafka /usr/local/bin/pigsty-kafka-health cluster \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties

返回 JSON 中 healthy: true 才表示该门禁通过。它适合只读诊断,但不能替代业务端到端验证。


KRaft 仲裁状态

从任一可用 Broker 查询 dynamic quorum:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --status

重点检查:

  • LeaderId 存在且对应预期 Controller;
  • CurrentVoters 与现场 dynamic quorum 一致;
  • MaxFollowerLagMaxFollowerLagTimeMs 没有持续增长;
  • Dashboard 中恰好有一个 Active Controller。

如需确认 dynamic quorum(KIP-853)特性级别,可用 /opt/kafka/bin/kafka-features.sh ... describe 查看 kraft.version

查看 Controller 复制状态:

/opt/kafka/bin/kafka-metadata-quorum.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  describe --replication

如果没有 Leader、成员长期落后或 Voter 集合与预期不一致,应停止拓扑变更,保留日志、Manifest 与 meta.properties,再分析网络、节点/Directory Identity 和显式 Controller 成员操作。不要用普通清单重跑强行改写 quorum。


声明式 Topic

生产 Topic 应优先在 pigsty.ymlkafka_topics 中声明:

kafka_topics:
  - name: orders
    partitions: 12
    replication_factor: 3
    config:
      min.insync.replicas: 2
      retention.ms: 604800000

使用完整集群目标收敛:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

角色会幂等创建 Topic、只增加 Partition,并只修改声明的配置键。RF 变化会失败并要求显式 Partition Reassignment;从清单中移除条目不会删除 Topic。

只读查看 Topic:

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --list

/opt/kafka/bin/kafka-topics.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --topic orders

临时或外部管理的 Topic 可以使用 Kafka CLI 创建,但不会自动写回 pigsty.yml。不要让声明式与手工管理同时拥有同一个 Topic。Topic 删除是业务数据删除动作,必须走独立审批、精确名称确认和恢复方案,本文不提供通用删除命令。


声明式用户、ACL 与 Quota

kafka_security: scram 时,应用身份应通过 kafka_users 管理:

kafka_users:
  - name: order-service
    password: "{{ vault_kafka_order_password }}"
    acls:
      - resource: topic
        name: orders
        operations: [Read, Write, Describe]
      - resource: group
        name: order-worker
        operations: [Read]
    quota:
      producer_byte_rate: 10485760
      consumer_byte_rate: 20971520

完整剧本会幂等收敛密码、该用户的 ACL 集合与显式给出的 Quota 字段。密码不要以明文提交到仓库或输出到日志。移除用户条目不会自动删除 Principal/凭据;删除或彻底撤权需要独立受审流程。


消息读写验证

使用测试 Topic 做端到端验证。Console Producer/Consumer 使用同一客户端配置文件:

/opt/kafka/bin/kafka-console-producer.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic ops-smoke

在另一个终端消费:

/opt/kafka/bin/kafka-console-consumer.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --topic ops-smoke \
  --from-beginning \
  --group ops-smoke-check

生产验收应从真实客户端网络执行,覆盖 DNS/advertised.listeners、证书校验、ACL、生产者 ACK、消费提交与端到端延迟,而不只验证 Broker 本机路径。


Consumer Group

列出和查看 Consumer Group:

/opt/kafka/bin/kafka-consumer-groups.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --list

/opt/kafka/bin/kafka-consumer-groups.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --group order-worker

Lag 要结合消费速率与业务 SLO 判断:短暂积压可能是批处理行为,持续增长且消费速率低于生产速率才表示无法追平。重置 Offset 可能造成重复消费或跳过消息,必须有独立审批、精确 Group/Topic 确认与回放方案。


持久配置变更

修改 pigsty.yml 后始终对完整集群执行:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

角色根据现场健康和静态指纹自动选择路径:

  • 集群不健康或停止:只启动已停止的 Controller,恢复并追平 quorum 后再启动 Broker;若同时存在静态变化,仍在线成员随后进入严格滚动;
  • 健康集群新增纯 Broker:逐个格式化、启动并确认注册;
  • 健康集群存在静态变化:严格逐节点滚动,每节点重启前后执行 Controller 零 Lag/最近追平、quorum、Offline Partition、Under Min ISR 与 ISR 追平门禁;
  • 没有静态变化:不重启 Kafka。

不要用 -t kafka_config 绕过完整状态机。动态 Topic/User/ACL/Quota 收敛位于 kafka_provision 资源收敛阶段,静态变化是否重启由角色决定。


扩容与拓扑变更

增加纯 Broker

健康集群可以新增 kafka_role: broker 节点。为新节点分配从未冲突的 kafka_seq,更新完整 inventory,然后仍以完整集群为目标:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

角色会将新格式化的纯 Broker 一次准入一个,并验证 Broker 已注册且未 Fenced。不能只 -l 新节点;也不能把新的 combinedcontroller 当作普通 Broker 加入。

新 Broker 加入不会迁移已有 Partition。必须另外生成、评审并监控 kafka-reassign-partitions.sh 计划,控制磁盘/网络负载并准备回退。“服务已注册”不等于“扩容完成”。

复制策略也不会随 Broker 数自动放大。尤其是 Kafka 4.3 的 default.replication.factor 不能动态修改:由 1 Broker 扩到 3 Broker 后,它仍为初建的 RF=1,未来未显式指定 RF 的 Topic 也仍按 RF=1 创建。应先完成既有 Partition Reassignment,再规划 Controller 高可用或维护窗口,最后让新的静态默认值通过完整集群 安全滚动生效;不能为了改默认值绕过停机门禁。

增加、替换或删除 Controller

集群从一开始就是 dynamic quorum,但 Controller 成员关系仍是显式 Kafka 管理动作:

  1. 核对当前 Leader、Voter、Directory ID 与多数派;
  2. 针对现有 Cluster ID 显式格式化新 Controller;
  3. 启动并确认其追平;
  4. 执行并验证 add-controller
  5. 删除时执行对应 remove-controller,确认新多数派后再退役节点。

普通 inventory 变更不会自动执行这些步骤;角色会拒绝未在初始 Manifest 中登记的未格式化 Controller。该操作应使用 Kafka 官方成员变更流程与经过演练的独立运行手册。

修改地址或端口

角色固定使用 inventory_hostname 作为 Broker advertised address 与 Controller bootstrap address。修改清单地址、kafka_portkafka_controller_port 会影响客户端元数据、Broker 通信或 quorum,属于静态高风险变更;必须同步检查 DNS、证书 SAN、路由、防火墙、Bootstrap 地址、监控 Target 与所有成员。


安全材料轮换

已格式化且健康的 scram 集群支持两种互斥的受保护动作:内部凭据轮换和证书轮换。两者都要求精确完整集群、匹配的 kafka_rotate_confirm 确认字符串,并且建议先执行 --check。证书由同一 Pigsty CA 重新签发,新旧证书互信,轮换通过严格滚动逐节点生效。

具体命令和失败语义见 预置剧本:受保护轮换。安全模式本身是 Bootstrap-only 属性;这些动作不等于支持 plaintextscram 的在线迁移。


数据保护与恢复

Kafka 的数据保护依赖跨故障域副本、正确的 minISR、生产者 ACK 和经过演练的恢复流程。当前角色不提供 Kafka 数据备份、自动 Broker Drain、KRaft 恢复编排或跨地域灾难恢复。

发生磁盘或节点故障时:

  1. 先查看 Kafka Overview/Node、quorum、ISR、Offline Partition 与 Under Min ISR;
  2. 保存 journalctl -u kafka、节点指标、Manifest、server.propertiesmeta.properties 证据;
  3. 确认节点角色、node.id、Cluster ID、Directory ID 与剩余副本可用性;
  4. 在明确恢复/替换方案前,不执行 kafka-rm.yml,不删除 meta.properties
  5. 对重格式化、身份替换、Reassignment 或 Controller 成员操作使用独立运行手册。

日志诊断

journalctl -u kafka -f
journalctl -u kafka_exporter -f
journalctl SYSLOG_IDENTIFIER=kafka --since today
journalctl SYSLOG_IDENTIFIER=kafka_exporter --since today

VictoriaLogs/Grafana 查询:

job:syslog unit:kafka
job:syslog app:kafka
job:syslog unit:kafka_exporter

常见诊断顺序是:服务日志 → 监听端口 → 管理通道健康 → dynamic quorum → Broker/Partition/ISR → 客户端地址与证书/ACL → Consumer Lag。详细面板与告警映射见 监控告警

5 - 预置剧本

使用 kafka.yml 与 kafka-rm.yml 执行 dynamic KRaft 生命周期、严格滚动、资源收敛、轮换与下线。

KAFKA 模块提供两个剧本:kafka.yml 用于部署 Apache Kafka 4.x dynamic KRaft 集群并收敛其安全、 资源与监控状态;kafka-rm.yml 用于下线集群或移除成员。


基本用法

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

检查模式验证公开 API、完整集群、角色、Rack、端口、Manifest 与可检查的文件变化,但会跳过格式化、服务启动和实时健康验收。因此 --check 成功不等于运行时一定成功。


执行阶段

kafka.yml 本身是一个薄封装:单一 Play 依次执行 node_idkafka 两个角色,与 pgsql.yml 的结构一致。角色内部把生命周期拆成六个任务阶段;所有跨节点排序(并行 Bootstrap、逐个 Broker 准入、严格逐节点滚动)由启动阶段统一负责:

阶段标签作用
身份预检kafka-id派生并断言身份、完整集群 Limit、角色、Rack、端口与保留键
安装kafka_install创建 kafka 系统用户,安装 java-runtimekafka-stack 软件包
配置kafka_config读取/恢复/创建 Manifest,签发安全材料,渲染配置,计算静态指纹,格式化空存储,判定生命周期路径
启动kafka_launch收敛不健康集群、逐个准入新 Broker、严格逐节点滚动,确认 Manifest 与已生效静态状态
资源收敛kafka_provision收敛动态 minISR、用户凭据、ACL、Quota 与声明式 Topic,报告内部 Topic RF 漂移
监控kafka_monitor配置协议 Exporter 并注册 VictoriaMetrics Target

Play 使用 any_errors_fatal: true。某个阶段失败时,后续危险推进会停止;修正原因后可以重跑完整集群,角色会从现场状态和持久指纹恢复,而不是盲目重复格式化。


生命周期路径

配置阶段使用角色自有管理通道判断集群健康,并选择唯一后续路径:

冷启动、首次部署或修复

当集群停止或健康谓词不通过时,进入 Converge:

  1. 启动所有 Controller-capable 节点;
  2. 等待 Controller listener 与 dynamic quorum Leader;
  3. 验证初始 Controller Directory ID 仍在现场 quorum;
  4. 启动纯 Broker;
  5. 等待 Broker listener 并要求完整集群健康;
  6. 只有配置已证明成功运行后,才持久化静态指纹。

JMX 不参与生命周期门禁:启动、准入与滚动的判定完全基于角色自有的 Kafka CLI/metadata 管理通道。

健康集群增加纯 Broker

角色只自动准入新格式化的 kafka_role: broker。每次处理一个新 Broker,并要求它已经注册且未 Fenced 后才继续。新增 Controller 或 combined 节点不能走该捷径。

准入只证明服务加入;已有 Partition 不会自动迁移到新 Broker,必须另行执行显式 Reassignment。

健康集群静态变化

当渲染后的静态指纹变化时,严格滚动每次只处理一个节点:

  • 重启前检查 Controller 多数派、全部 Voter 零 Lag 且最近完成追平、Offline Partition、Under Replicated、Under Min ISR,以及移除目标后每个 Partition 的有效 ISR;
  • 重启后要求目标 Controller 回到 Voter 且重新追平、目标 Broker 注册且未 Fenced、其副本重新进入 ISR;
  • 任一门禁失败立即停止后续节点。

如果故障修复与静态变化同时存在,Converge 只启动已停止的成员,不并行重启仍在线成员;quorum 恢复并追平后,尚未加载的静态变化继续进入严格滚动。

如果静态指纹没有变化,Kafka 不重启。动态资源变化仍会在资源收敛阶段在线生效。


任务标签

标签阶段/作用
kafka-id始终执行的身份、完整集群与拓扑派生断言
kafka_install安装阶段总入口
kafka_user创建 kafka 系统用户与用户组
kafka_pkg按平台映射安装 java-runtimekafka-stack 软件包
kafka_configManifest、安全材料、配置渲染、静态指纹、存储格式化与路径判定
kafka_launchConverge、纯 Broker 串行准入、严格单节点滚动与 Manifest Commission
kafka_provision动态 minISR、Topic、User、ACL 与 Quota 收敛
kafka_monitor / monitor协议 Exporter 配置与监控注册总入口
kafka_register / register / add_metrics仅刷新 VictoriaMetrics 文件发现 Target

正常配置变更应运行完整 kafka.yml,让角色自行选择生命周期路径。阶段标签主要用于开发、诊断和受控修复;不能用 -t kafka_config 或只限制单节点来绕过完整状态机。


Identity、格式化与 Manifest

角色在写配置前校验:

  • Limit 精确包含一个 Kafka 集群的所有成员;
  • kafka_seq 唯一,角色全部省略或全部显式;
  • 至少一个 Controller 和一个 Broker;
  • Rack 在所有 Broker-capable 节点上全有或全无;
  • 端口有效、互不冲突,角色自有键未被 kafka_parameters 覆盖;
  • Manifest、安全模式、meta.properties 与现场集群身份一致。

新集群随机生成 Cluster ID 和初始 Controller Directory ID,并以明确 dynamic 模式格式化每个节点。已有 ${kafka_data}/metadata/meta.properties 时只验证 Cluster ID、Node ID 与 Directory ID,不会自动重新格式化。

Bootstrap Manifest 位于:

files/kafka/<kafka_cluster>/manifest.yml

每个集群成员还保留一份权威副本 /etc/kafka/manifest.ymlscram 集群另有 /etc/kafka/secrets.yml)。活集群是运行事实权威,但普通剧本不会在冲突时擅自改写任何一方:

  • 管理节点缓存丢失时,自动从任一成员的节点副本恢复,不会重新格式化;
  • 管理节点与所有成员都没有 Manifest 而存储已格式化时,失败关闭并提示先恢复 Manifest;
  • Manifest 存在而所有数据盘为空时失败关闭;
  • Cluster ID、安全模式或 Controller Identity 冲突时失败关闭;
  • inventory 中新增的非初始 Controller 不会自动成为 Voter。

不要删除 meta.properties、Manifest 或 Secret 来绕过保护。


静态指纹与可恢复重跑

角色对影响 Kafka 进程的静态文件计算期望指纹,并只在以下条件之一成立后写入 /etc/kafka/.pigsty-applied-static.sha256

  • Converge 已经成功启动并通过全局健康检查;
  • 严格滚动已经让该节点重启、追平并通过后置门禁。

如果执行中断,未被证明生效的变化不会被记成“已应用”。下一次完整重跑仍能识别待处理的静态重启。


资源收敛与监控注册

完整健康后,资源收敛与监控阶段依次:

  1. 收敛角色拥有的动态 cluster minISR;
  2. 幂等处理 kafka_users 的凭据、ACL 与声明 Quota;
  3. 幂等处理 kafka_topics 的创建、Partition 增长与显式配置;
  4. 检查内部 Topic RF 漂移,但不自动 Reassignment;
  5. 在按 kafka_seq 排序后的前两个 Broker-capable 节点配置并启动协议 Exporter;
  6. 在全部 Infra 节点刷新文件发现 Target。

每个实例对应一个 Target 文件,JMX 目标与(被选中节点的)协议 Exporter 目标都在同一 kafka 采集任务下:

/infra/targets/kafka/<kafka_instance>.yml

Target 文件每次完整运行按当前 Exporter 放置刷新;Target 的删除由 kafka-rm.yml 的注销步骤完成。


受保护轮换

轮换变量是一次性 extra-vars,不应写入 pigsty.yml。两种动作互斥,每次只能执行其一;前提是所有成员已格式化、集群健康、安全模式为 scram、角色自有 Secret 材料存在,且 kafka_rotate_confirm 与集群名完全一致。

内部凭据轮换

./kafka.yml --check -l kf-main \
  -e kafka_rotate_credentials=true \
  -e kafka_rotate_confirm=kf-main

./kafka.yml -l kf-main \
  -e kafka_rotate_credentials=true \
  -e kafka_rotate_confirm=kf-main

角色使用 active/standby 内部身份:先通过活管理通道更新非活动凭据,再原子切换本地受保护记录,并进入正常严格滚动。旧 active 保留为下一轮 standby,使中断后的重跑可恢复。

证书轮换

./kafka.yml --check -l kf-main \
  -e kafka_rotate_certificates=true \
  -e kafka_rotate_confirm=kf-main

./kafka.yml -l kf-main \
  -e kafka_rotate_certificates=true \
  -e kafka_rotate_confirm=kf-main

角色废弃管理节点缓存中已签发的节点证书,用同一 Pigsty CA 为每个节点重新签发私钥与证书,更新节点上的 PEM 证书包并进入严格滚动。新旧证书由同一 CA 签发、彼此互信,因此不需要分阶段互换信任;健康预检失败时不会开始轮换,节点上的现有证书保持不变。


集群下线

集群移除不在 kafka.yml 中,而是使用独立的 kafka-rm.yml 剧本:

./kafka-rm.yml -l kf-main                          # 移除集群:注销监控、停服务、删配置,默认删除数据与 Manifest
./kafka-rm.yml -l kf-main -e kafka_rm_data=false   # 保留磁盘数据,只移除服务与配置
./kafka-rm.yml -l kf-main -e kafka_rm_pkg=true     # 同时卸载 kafka-stack 软件包(共享的 Java 运行时不会卸载)

执行顺序为:注销 VictoriaMetrics Target(kafka_deregister)→ 停止并禁用 kafka/kafka_exporter 服务(kafka)→ 删除配置、Systemd Unit 与辅助脚本(kafka_config)→ 删除数据目录与管理节点 Manifest/Secret/PKI 缓存(kafka_data,受 kafka_rm_data 控制)→ 可选卸载软件包(kafka_pkg,受 kafka_rm_pkg 控制)。

防误删开关是 kafka_safeguard:设置为 true(命令行或清单中)时剧本直接中止,不删除任何东西。

kafka-rm.yml 也可以只选择单个成员用于缩容(如 -l 10.10.10.13)。但移除 Controller-capable 成员属于 quorum 成员变更,必须先完成显式 remove-controller 流程并确认新多数派;身份冲突、Exporter 异常或一般启动失败都不是删除数据的理由。


剧本边界

kafka.yml 当前不会自动完成:

  • Controller add-controller / remove-controller 成员流程;
  • 新 Broker 加入后的既有 Partition Reassignment、退役 Drain 与数据均衡;
  • 已有 Topic RF 变化、Topic 删除或用户删除;
  • 已格式化集群 plaintextscram 之间的在线迁移;
  • Kafka 版本升级、Feature Level 终结、跨版本迁移与回滚;
  • Kafka 数据备份、恢复编排与灾难演练;
  • Connect、Schema Registry、MirrorMaker、Cruise Control 等生态组件。

这些操作需要独立的生产运行手册。日常只读检查和资源管理见 日常管理

6 - 监控告警

Kafka 指标采集、Grafana Dashboard、日志查询与告警规则。

Pigsty 为 KAFKA 模块提供指标、日志、Dashboard 与告警一体化的可观测能力。监控同时覆盖 Kafka JVM 内部状态与 Kafka 协议视角,避免只看到进程存活而看不到 Partition、ISR 与 Consumer Lag,也避免只看到集群元数据而看不到 JVM、请求队列与 KRaft Controller 健康。


采集架构

KAFKA 模块使用两个互补的 Exporter:

采集面服务/方式Job节点范围主要内容
JVM 与 Kafka 内部JMX Exporter Java Agent :9404kafka(带 role 标签)所有 Kafka 节点JVM、Broker 吞吐、复制、请求路径、KRaft、Controller
Kafka 协议视角kafka_exporter :9308kafka(无 role 标签)kafka_seq 最小的至多两个 Broker-capable 节点Broker、Topic、Partition、Offset、Consumer Group、Lag
主机资源node_exporternode纳管节点CPU、内存、磁盘、网络、文件系统
日志Journald → Vector → VictoriaLogssyslog所有 Kafka 节点Kafka 与 Exporter 结构化检索日志

角色在每一个 Infra 节点为每个实例生成一个文件发现目标,JMX 目标与(被选中节点的)协议 Exporter 目标都在同一文件、同一 kafka 采集任务下:

/infra/targets/kafka/<kafka_instance>.yml

单 Broker 集群只运行一个协议 Exporter;多 Broker 集群最多运行两个。纯 Controller 只注册 JMX 目标;未被选择的 Broker 与纯 Controller 都没有协议 Exporter 目标,这是预期行为。Target 文件每次完整运行按当前放置刷新;实例 Target 的删除由 kafka-rm.yml 的注销步骤完成。


标签模型

两类目标都注册在同一 job=kafka 采集任务下,通过有无 role 标签区分。

JMX 目标

标签含义示例
job采集任务kafka
clsKafka 集群名kf-main
insKafka 实例名kf-main-1
ip清单主机地址10.10.10.11
instanceJMX 抓取端点10.10.10.11:9404
rolePigsty Kafka 角色combinedbrokercontroller
node_idKRaft 节点号1

协议 Exporter 目标

协议 Exporter 目标只包含 clsinsipinstance10.10.10.11:9308),没有 role/node_id 标签。vmagent 端的记录规则据此区分两类可用性:kafka_upup{job="kafka",role=~".+"}kafka_exporter_upup{job="kafka",role=""}

Exporter 从 Broker 查询整个 Kafka 集群,因此同一集群的两个 Exporter 可能返回相同 Topic/Partition/Consumer Group 视图。集群级 Recording Rule 会先在 Exporter 实例间去重,再汇总逻辑集群速率。scram 模式下,Exporter 连接 Kafka 所需的 TLS/SCRAM 参数由角色自有监控身份自动生成。


Grafana Dashboard

Pigsty 提供三个互补 Dashboard:

Kafka Overview

集群与全局总览。cls=All 是全部 Kafka 集群的 Overview;选择具体 cls 后,同一 Dashboard 就成为该 Kafka Cluster 的总览,而不是另一套独立面板。

主要内容:

  • 集群、Broker、Topic、Partition 与 Consumer Group 清单
  • Broker 可用性、Exporter 健康与集群工作负载
  • Leaderless、Under Replicated、ISR Deficit、Non-Preferred Replica
  • Topic Offset 进展、Consumer Commit 进展与总 Lag
  • Consumer Group 成员、Lag 排名和 Topic/Group 下钻
  • Kafka/Exporter 日志量、Firing Alerts 与日志明细

常用变量:clsmemberstopicgrouptopk

Kafka Instance

ins 变量选择一个运行 kafka_exporter 的 Broker 实例,从协议视角查看集群元数据与 Consumer 状态,并联动宿主机资源。

主要内容:

  • Exporter 可用性、身份、运行时与抓取成本
  • Broker Directory、Topic Inventory、Partition Topology
  • Leader Distribution、ISR Deficit、Leaderless 与 Non-Preferred
  • Topic Offset Span、Append/Commit Progress
  • Consumer Group Inventory、Members、Offsets 与 Lag
  • 节点 CPU/内存、磁盘 I/O、网络、文件系统与日志

常用变量:insclsiptopicconsumergrouptopk

Kafka Node

ins 变量选择任何 Kafka JVM,包括纯 Controller 节点,查看 JMX、Broker 与 KRaft 内部状态。

主要内容:

  • JVM Heap、GC、Thread、Buffer Pool、CPU、FD 与 Uptime
  • Broker 消息/网络/复制吞吐和 ISR Churn
  • 请求率、错误、P95/P99 延迟、队列与 Handler/Network Idle
  • Under Replicated、Under Min ISR、Offline Replica/Log Directory
  • KRaft Member State、Metadata Log、传播延迟与 Snapshot
  • Active Controller、Fenced Broker、Offline Partition 与事件延迟
  • JMX 抓取质量、宿主机压力与 Kafka 日志

常用变量:clsinsip


Dashboard 选择

问题首选 Dashboard下钻方向
哪个集群或 Topic 出现异常?Kafka Overview选择 clstopicgroup
某个 Consumer Group 为什么积压?Kafka InstanceGroup → Topic → Partition Offset
某个 Broker 是否过载?Kafka Node请求路径 → JVM → Node 资源
KRaft Controller 是否健康?Kafka NodeKRaft Metadata Plane → Controller Health
是否存在 Leaderless/URP/ISR 问题?Kafka OverviewCluster → Kafka Node
Exporter 缺数还是 Kafka 本身异常?Instance + Node对比 kafka_exporter_upkafka_up

Recording Rule

Kafka 规则文件位于 /infra/rules/kafka.yml。主要记录指标如下:

指标含义
kafka:topic:msg_rate1m/5mTopic 当前 Offset 的 1/5 分钟正向变化速率
kafka:ins:msg_rate1m/5m单个 Exporter 视图中的消息追加速率
kafka:cls:msg_rate1m/5m去重后的集群消息追加速率
kafka:topic:csg_rate1m/5mConsumer Group Commit Offset 的 1/5 分钟正向变化速率
kafka:ins:csg_rate1m/5m单个 Exporter 视图中的消费提交速率
kafka:cls:csg_rate1m/5m去重后的集群消费提交速率
kafka:ins:jvm_heap_used_ratioKafka JVM Heap 使用率
kafka:ins:jvm_cpu_coresKafka JVM 消耗的 CPU Core 数
kafka:ins:jvm_gc_time_rate5m5 分钟 GC 时间速率
kafka:ins:messages_in_rate5mBroker 5 分钟消息接收速率
kafka:ins:bytes_in_rate5mBroker 5 分钟客户端入站字节速率
kafka:ins:bytes_out_rate5mBroker 5 分钟客户端出站字节速率

基于 Offset 变化得到的是进展速率,不是客户端请求数。日志截断、Offset 回退或 Exporter 重启可能造成瞬时负变化;规则使用 clamp_min(..., 0) 只保留正向进展。


告警规则

告警条件持续时间级别首选下钻
KafkaDownup{job="kafka"} < 11mCRITKafka Node / ins
KafkaExporterDownup{job="kafka_exporter"} < 11mCRITKafka Instance / ins
KafkaJmxScrapeErrorjmx_scrape_error > 03mWARNKafka Node / JMX Collector
KafkaJvmHeapHighHeap 使用率 > 90%15mWARNKafka Node / JVM Memory
KafkaJvmDeadlockJVM Deadlocked Thread > 01mCRITKafka Node / JVM Threads
KafkaRequestHandlerSaturatedHandler Idle < 10%10mWARNKafka Node / Request Path
KafkaUnderReplicatedPartitionsURP > 05mWARNKafka Node / Replication
KafkaUnderMinISRUnder Min ISR > 01mCRITKafka Node / Replication
KafkaOfflineLogDirectoryOffline Log Directory > 01mCRITKafka Node / Disk Pressure
KafkaOfflinePartitionsController Offline Partition > 01mCRITKafka Node / cls
KafkaControllerCountMismatchActive Controller 数不等于 11mCRITKafka Node / cls
KafkaFencedBrokersFenced Broker > 05mWARNKafka Node / cls
KafkaUncleanLeaderElection5 分钟出现不干净 Leader 选举立即CRITKafka Node / cls

不干净 Leader 选举可能意味着数据丢失,应立即保留 Controller/Broker 日志,确认受影响 Topic 与副本,再决定恢复动作。


常用 PromQL

检查采集目标:

kafka_up
kafka_exporter_up
up{job="kafka"}

检查某集群复制健康:

sum by (cls) (kafka_server_replica_manager_under_replicated_partitions{job="kafka"})
sum by (cls) (kafka_server_replica_manager_under_min_isr_partitions{job="kafka"})
max by (cls) (kafka_controller_offline_partition_count{job="kafka"})

检查 Consumer Lag:

topk(20, kafka_consumergroup_lag_sum{cls="kf-main"})

检查请求饱和与延迟:

kafka_server_request_handler_idle_ratio{job="kafka",cls="kf-main"}
max by (ins,request,quantile) (
  kafka_network_request_total_time_seconds{job="kafka",cls="kf-main",quantile=~"0.95|0.99"}
)

日志查询

Kafka 服务把标准输出与错误写入 Journald,节点 Vector 的 Journald Source 会转发到 VictoriaLogs,统一使用 job:syslog

job:syslog unit:kafka
job:syslog app:kafka
job:syslog unit:kafka_exporter
ip:10.10.10.11 job:syslog (unit:kafka OR app:kafka)

Kafka Node Dashboard 的日志面板使用类似查询,并展示时间、级别、Systemd Unit 与消息。诊断时应把日志与同一时间窗口内的 KRaft、ISR、请求队列、GC、磁盘 I/O 和网络指标对齐。


验证监控链路

在 Kafka 节点验证原始端点:

curl -fsS http://<kafka-ip>:9404/metrics | grep '^jmx_scrape_error'
curl -fsS http://127.0.0.1:9308/metrics | grep '^kafka_brokers'

在 Infra 节点检查文件发现(每实例一个文件,被选中节点的文件含 JMX 与协议 Exporter 两个目标):

ls -l /infra/targets/kafka/
cat /infra/targets/kafka/kf-main-1.yml

然后在 VictoriaMetrics 查询 up{job="kafka"}(或记录指标 kafka_upkafka_exporter_up)。自定义 exporter 指标在抓取失败后可能短暂保留旧样本,端点存活应以 Prometheus 原生 up 为准。若原始端点正常但记录指标缺失,依次检查文件发现、VictoriaMetrics Target、网络可达性、规则加载与标签;若 JMX HTTP 正常但 jmx_scrape_error1,检查 Kafka 日志和 /etc/kafka/jmx_exporter.yml 的 MBean 匹配情况。

完整指标语义参阅 指标定义

7 - 指标定义

Kafka JMX、协议 Exporter 与 Recording Rule 指标字典。

KAFKA 模块使用两类指标源,都注册在同一 job=kafka 采集任务下:JMX 目标(带 role 标签)采集每个 JVM 的内部状态;协议 Exporter 目标(无 role 标签)通过 Kafka 协议采集逻辑集群、Topic、Partition 与 Consumer Group 状态。协议 Exporter 只放在 kafka_seq 最小的至多两个 Broker-capable 节点上,单 Broker 集群只运行一个。

JMX 配置采用白名单,只导出 JVM 基线和有界的 Broker、复制、请求路径与 KRaft 指标;高基数的 per-client 与 per-partition JMX MBean 被有意排除,Partition 详情由协议 Exporter 提供。


公共标签

指标源公共标签
JMX 目标(:9404job, cls, ins, ip, instance, role, node_id
协议 Exporter 目标(:9308job, cls, ins, ip, instance

两类目标的 job 都是 kafka;是否携带 role 标签是区分两类序列的依据。

部分指标还有 topicpartitionbrokerconsumergrouprequestversionerrorquantilestateoperation 等维度。


可用性与抓取指标

指标类型含义
kafka_upGauge/RecordingJMX 目标抓取可用性:up{job="kafka",role=~".+"}
kafka_exporter_upGauge/Recording协议 Exporter 目标抓取可用性:up{job="kafka",role=""}
upGaugeVictoriaMetrics 对原始 Target 的抓取状态
jmx_scrape_errorGaugeJMX Exporter 最近一次抓取是否出错,健康值为 0
jmx_scrape_duration_secondsGaugeJMX 抓取耗时
jmx_scrape_cached_beansGaugeJMX Exporter 缓存的 MBean 数量
scrape_duration_secondsGaugeVictoriaMetrics 抓取 Exporter 的耗时
scrape_samples_scrapedGauge本次抓取的样本数量

协议 Exporter 指标

以下指标来自协议 Exporter 目标。同一集群的多个 Exporter 会看到相同的逻辑集群状态,直接做集群聚合时必须按语义去重,不能简单把所有 ins 相加。

Broker 与 Topic

指标类型关键维度含义
kafka_brokersGauge集群Exporter 发现的 Broker 数量
kafka_broker_infoGaugeid, addressBroker 信息,以值 1 携带标签
kafka_topic_partitionsGaugetopicTopic 的 Partition 数量
kafka_topic_partition_current_offsetGaugetopic, partitionPartition 当前 Log End Offset
kafka_topic_partition_oldest_offsetGaugetopic, partitionPartition 当前最早可读 Offset
kafka_topic_partition_leaderGaugetopic, partition当前 Leader Broker ID;无 Leader 时用于识别异常
kafka_topic_partition_replicasGaugetopic, partition, broker分配给 Partition 的副本集合
kafka_topic_partition_in_sync_replicaGaugetopic, partition, broker当前 ISR 成员
kafka_topic_partition_under_replicated_partitionGaugetopic, partitionPartition 是否处于副本不足状态
kafka_topic_partition_leader_is_preferredGaugetopic, partition当前 Leader 是否为 Preferred Replica

current_offset - oldest_offset 可以估计当前可保留的 Offset Span,但 Offset 数量不等于字节数,Compact Topic 也不等于精确消息条数。

Consumer Group

指标类型关键维度含义
kafka_consumergroup_membersGaugeconsumergroupGroup 当前成员数
kafka_consumergroup_current_offsetGaugeconsumergroup, topic, partitionGroup 已提交 Offset
kafka_consumergroup_current_offset_sumGaugeconsumergroup, topic已提交 Offset 汇总
kafka_consumergroup_lagGaugeconsumergroup, topic, partitionPartition 级消费滞后
kafka_consumergroup_lag_sumGaugeconsumergroup, topicGroup/Topic 消费滞后汇总

没有提交 Offset 的临时消费者、使用外部 Offset 存储的客户端,或尚未消费某 Topic 的 Group,不一定产生这些时间序列。

Exporter 自身

指标类型含义
kafka_exporter_build_infoGaugeExporter 版本、Revision 与构建信息
process_*Gauge/CounterExporter 进程 CPU、内存、FD、启动时间等
go_*Gauge/CounterExporter Go Runtime、GC、Goroutine 与内存状态
promhttp_metric_handler_*Counter/metrics 请求处理状态

JMX:JVM 基线

excludeJvmMetrics: false 使 JMX Exporter 暴露标准 JVM/进程指标。Kafka Node Dashboard 主要使用:

指标含义
jvm_memory_used_bytes按 Heap/Non-Heap 与 Memory Pool 划分的已用内存
jvm_memory_committed_bytesJVM 已提交内存
jvm_memory_max_bytesJVM 可用最大内存
jvm_gc_collection_seconds_countGC 次数
jvm_gc_collection_seconds_sumGC 累计耗时
jvm_threads_state按线程状态统计的线程数
jvm_threads_deadlocked检测到的死锁线程循环数
jvm_buffer_pool_used_bytesDirect/Mapped Buffer Pool 使用量
process_cpu_seconds_totalKafka JVM 累计 CPU 时间
process_open_fds / process_max_fds已打开与最大文件描述符
process_start_time_secondsKafka JVM 启动时间

JMX:Broker 流量

指标类型含义
kafka_server_broker_messages_in_totalCounterBroker 接收的消息总数
kafka_server_broker_bytes_in_totalCounterBroker 接收的客户端字节总数
kafka_server_broker_bytes_out_totalCounterBroker 发送的客户端字节总数
kafka_server_broker_replication_bytes_in_totalCounterBroker 接收的复制字节总数
kafka_server_broker_replication_bytes_out_totalCounterBroker 发送的复制字节总数
kafka_server_broker_produce_requests_totalCounterProduce 请求总数
kafka_server_broker_failed_produce_requests_totalCounter失败 Produce 请求总数
kafka_server_broker_fetch_requests_totalCounterFetch 请求总数
kafka_server_broker_failed_fetch_requests_totalCounter失败 Fetch 请求总数

这些是 Broker 总量,不包含 Topic 维度,避免 JMX Series 随 Topic 数膨胀。Topic 级 Offset 与进展来自协议 Exporter。


JMX:复制与存储

指标类型含义
kafka_server_replica_manager_under_replicated_partitionsGaugeISR 少于已分配副本的 Partition 数
kafka_server_replica_manager_under_min_isr_partitionsGaugeISR 低于 min.insync.replicas 的 Partition 数
kafka_server_replica_manager_at_min_isr_partitionsGaugeISR 恰好等于 min.insync.replicas 的 Partition 数
kafka_server_replica_manager_offline_replicasGauge当前 Broker 上离线副本数
kafka_server_replica_manager_partitionsGauge当前 Broker 承载的副本数
kafka_server_replica_manager_leadersGauge当前 Broker 领导的 Partition 数
kafka_server_replica_manager_isr_shrinks_totalCounterISR 收缩事件总数
kafka_server_replica_manager_isr_expands_totalCounterISR 扩张事件总数
kafka_server_replica_manager_failed_isr_updates_totalCounterISR 更新失败总数
kafka_server_replica_manager_reassigning_partitionsGauge正在进行 Reassignment 的 Leader Partition 数
kafka_server_delayed_operation_purgatory_sizeGaugeoperation 划分的延迟操作等待数
kafka_log_manager_offline_log_directoriesGaugeKafka 标记为离线的日志目录数

Under Replicated 表示副本没有全部同步;Under Min ISR 更严重,表示写入可用性或持久性条件已经低于设置的最小 ISR。At Min ISR 虽未越线,但已经没有额外副本余量。


JMX:请求路径

指标类型额外标签含义
kafka_network_request_totalCounterrequest, version各 Kafka API 请求总数
kafka_network_request_errors_totalCounterrequest, error各 API/错误码响应错误总数
kafka_network_request_total_time_secondsGaugerequest, version, quantileAPI 总耗时 P50/P95/P99
kafka_network_request_queue_sizeGauge等待 Request Handler 的请求数
kafka_network_response_queue_sizeGauge等待 Network Processor 的响应数
kafka_server_request_handler_idle_ratioGaugeRequest Handler 平均空闲比例
kafka_network_processor_idle_ratioGaugeNetwork Processor 平均空闲比例

排查高延迟时,应同时查看请求量、错误码、P95/P99、两个队列、Handler/Processor Idle、GC、CPU、磁盘 I/O 与网络。单独看到低 Idle 不足以判断瓶颈位置。


JMX:KRaft 与 Broker 元数据

指标类型含义
kafka_server_raft_stateGauge当前成员的 KRaft 状态,以 state 标签表示
kafka_server_raft_current_leaderGauge当前 KRaft Leader Node ID,-1 表示未知
kafka_server_raft_current_epochGauge当前 KRaft Epoch
kafka_server_raft_high_watermarkGauge元数据日志 High Watermark
kafka_server_raft_log_end_offsetGauge元数据日志 Log End Offset
kafka_server_broker_metadata_last_applied_record_lag_secondsGaugeBroker 应用元数据记录的时间滞后
kafka_server_broker_metadata_load_errors_totalCounterBroker 加载元数据错误总数
kafka_server_broker_metadata_apply_errors_totalCounterBroker 应用元数据镜像错误总数
kafka_server_metadata_snapshot_bytesGauge最近生成或加载的元数据 Snapshot 大小
kafka_server_metadata_snapshot_age_secondsGauge最近元数据 Snapshot 的年龄

log_end_offset - high_watermark 可辅助判断元数据提交滞后;还应结合成员角色、当前 Leader、Epoch 和 Controller 事件延迟判断。


JMX:Controller

这些 MBean 只存在于带 Controller 角色的 Kafka 进程中:

指标类型含义
kafka_controller_active_controller_countGaugeActive Controller 上为 1,其他 Controller 为 0
kafka_controller_fenced_broker_countGaugeActive Controller 观察到的 Fenced Broker 数
kafka_controller_active_broker_countGaugeActive Broker 数
kafka_controller_global_topic_countGaugeController 观察到的 Topic 数
kafka_controller_global_partition_countGaugeController 观察到的 Partition 数
kafka_controller_offline_partition_countGauge离线的非内部 Partition 数
kafka_controller_preferred_replica_imbalance_countGaugeLeader 不是 Preferred Replica 的 Partition 数
kafka_controller_metadata_errors_totalCounterController 元数据处理错误总数
kafka_controller_last_applied_record_lag_secondsGaugeController 应用元数据记录的时间滞后
kafka_controller_timed_out_broker_heartbeats_totalCounterBroker Heartbeat 超时总数
kafka_controller_elections_totalCounter本节点观察到的新 Active Controller 选举总数
kafka_controller_unclean_leader_elections_totalCounter不干净 Leader 选举总数
kafka_controller_event_queue_time_secondsGaugeController 事件排队 P50/P95/P99
kafka_controller_event_processing_time_secondsGaugeController 事件处理 P50/P95/P99

健康集群应恰好存在一个 Active Controller。offline_partition_countmetadata_errors_totalunclean_leader_elections_total 的增加都应优先处理。


Recording Rule 指标

Offset 进展

指标聚合层级窗口含义
kafka:topic:msg_rate1mTopic/Exporter1mCurrent Offset 正向增长速率
kafka:topic:msg_rate5mTopic/Exporter5mCurrent Offset 正向增长速率
kafka:ins:msg_rate1mExporter 实例1m实例视图消息追加速率
kafka:ins:msg_rate5mExporter 实例5m实例视图消息追加速率
kafka:cls:msg_rate1m逻辑集群1mExporter 间去重后的消息追加速率
kafka:cls:msg_rate5m逻辑集群5mExporter 间去重后的消息追加速率
kafka:topic:csg_rate1mGroup/Topic/Exporter1mCommit Offset 正向增长速率
kafka:topic:csg_rate5mGroup/Topic/Exporter5mCommit Offset 正向增长速率
kafka:ins:csg_rate1mExporter 实例1m实例视图消费提交速率
kafka:ins:csg_rate5mExporter 实例5m实例视图消费提交速率
kafka:cls:csg_rate1m逻辑集群1mExporter 间去重后的消费提交速率
kafka:cls:csg_rate5m逻辑集群5mExporter 间去重后的消费提交速率

JVM 与 Broker

指标含义
kafka:ins:jvm_heap_used_ratioHeap Used / Heap Max
kafka:ins:jvm_cpu_cores5 分钟 JVM CPU Core 消耗
kafka:ins:jvm_gc_time_rate5m5 分钟 GC 时间速率
kafka:ins:messages_in_rate5m5 分钟 Broker 消息接收速率
kafka:ins:bytes_in_rate5m5 分钟 Broker 客户端入站字节速率
kafka:ins:bytes_out_rate5m5 分钟 Broker 客户端出站字节速率

基数与解释注意事项

  • 不要把同一 cls 的多个 kafka_exporter 结果直接求和;它们可能是同一集群视图的副本。
  • kafka_topic_partition_current_offset 是 Offset,不是精确字节、请求或业务事件数量。
  • Consumer Lag 只覆盖 Kafka 中可见且已提交 Offset 的 Group。
  • 纯 Controller 缺少 Broker 指标和协议 Exporter 指标属于正常角色差异;未被选择的 Broker 没有协议 Exporter 指标也属于正常放置结果。
  • 某个 MBean 在具体 Kafka 版本/角色中不存在时,对应 JMX Series 也不会出现;应结合 role 判断。
  • per-client/per-partition JMX 指标被白名单排除,以避免不可预测的时间序列基数。

Dashboard 与告警使用方式参阅 监控告警

8 - 常见问题

Pigsty Kafka 4.x dynamic KRaft 模块常见问题与故障排查。

当前 KAFKA 模块是什么成熟度?

当前角色已实现生产级 v1 基线:dynamic KRaft、完整集群护栏、冷启动/修复、纯 Broker 串行准入、严格滚动、TLS/SCRAM/ACL、Topic/User 声明式收敛、内部凭据/证书轮换以及完整监控链路。

它不是托管 Kafka 产品。生产仍需使用 kafka_security: scram、奇数 Controller、足够 Broker/RF/minISR,并补充容量、Reassignment、Controller 成员、升级、备份、恢复与故障演练。默认 plaintext 只适合开发或可信隔离网络。


为什么没有 ZooKeeper,也没有 controller.quorum.voters

本模块面向 Kafka 4.x,使用原生 dynamic KRaft,不安装 ZooKeeper,也不创建静态 quorum。所有成员渲染 controller.quorum.bootstrap.servers;新集群显式使用 --initial-controllers/--no-initial-controllers 格式化,启动后角色会校验初始 Controller 的 Directory ID 已进入现场 quorum。

初始 Controller Identity 写入 Bootstrap Manifest。后续 Controller 增删仍必须执行显式 add-controller/remove-controller 管理流程,不能只编辑 inventory。


combinedbrokercontroller 有什么区别?

  • combined:同时承担 Broker 与 Controller,监听 90929093,是默认值;
  • broker:纯数据面,只监听 9092
  • controller:纯控制面,只监听 9093

集群角色要么全部省略并一致使用 combined,要么全部显式声明。不再提供旧角色别名。


Controller 端口 9093 会和 Alertmanager 冲突吗?

Controller 默认使用 Kafka KRaft 的惯例端口 9093。Pigsty Infra 节点上的 Alertmanager 默认也使用 9093:两者只有在 Kafka 与 Infra 复用同一节点时才会冲突。此时请为该集群调整 kafka_controller_port;角色只强制 9092909393089404 四个 Kafka 端口彼此不同,不会自动检测与其他服务的端口冲突。


服务已启动,但远程客户端连不上?

Broker 的 advertised.listeners 固定使用 inventory_hostname。客户端连接 Bootstrap Server 后,还必须解析并访问元数据返回的每一个 Broker 地址。

依次检查:

grep '^advertised.listeners' /etc/kafka/server.properties
ss -lntp | grep ':9092'
getent hosts <inventory-hostname>

scram 客户端还要检查 CA、SASL mechanism、用户名/密码与 ACL。当前 v1 不提供自定义 advertised address、多 Listener 或 NAT/公网映射;如果客户端不能直接路由 inventory_hostname,该网络模型不在当前核心契约内,不能用 kafka_parameters 覆盖 raw listener 绕过。


为什么提示 Cluster ID、Node ID 或 Directory ID 不匹配?

角色会交叉校验 Bootstrap Manifest、${kafka_data}/metadata/meta.properties、inventory 与活 dynamic quorum。常见原因包括:

  • 修改了 kafka_clusterkafka_seq
  • 把其他集群的数据盘挂载到当前节点;
  • 恢复/接管时给出了错误的 kafka_cluster_id
  • Controller 数据目录或 Directory ID 与现场 Voter 记录不一致;
  • 选错了目标集群或使用了过期 Manifest。

这是保护性失败。不要删除 meta.properties、Manifest 或直接执行 kafka-rm.yml。先确认数据归属、剩余副本、真实 Cluster/Node/Directory Identity 与恢复目标。


Manifest 丢失或只剩旧 Manifest 会怎样?

每个集群成员都保留一份 Manifest 权威副本 /etc/kafka/manifest.ymlscram 集群另有 /etc/kafka/secrets.yml)。管理节点的 files/kafka/<cluster>/ 缓存丢失时,角色会自动从任一成员的节点副本恢复,不会重新格式化。只有当管理节点与所有成员的副本都丢失、而存储已经格式化时,角色才失败关闭并提示先恢复 Manifest;已格式化的 scram 集群在两边都找不到 Secret 材料时同样失败关闭。

反过来,如果 Manifest 存在而全部 Kafka 数据盘为空,角色会失败关闭,避免用旧身份意外复活已消失的集群。确实要重建时必须先执行 kafka-rm.yml 和明确的重建流程。


为什么 kafka_parameters 中的某些键被拒绝?

身份、dynamic quorum、Listener、存储、复制、Rack 和安全必须由角色统一管理。保留模式包括:

process.roles, node.id, controller.quorum.*,
listeners, advertised.listeners, listener.security.protocol.map,
inter.broker.listener.name, controller.listener.names,
log.dirs, metadata.log.dir, broker.rack,
min.insync.replicas, default.replication.factor,
offsets.topic.replication.factor,
transaction.state.log.*, share.coordinator.state.topic.*,
authorizer.class.name, super.users, allow.everyone.if.no.acl.found,
sasl.*, ssl.*, listener.*

使用对应的 15 项公开参数;没有公开地址、路径子目录、Listener Map 或 Exporter options 变量。


如何启用 TLS、SCRAM 与 ACL?

新集群设置:

kafka_security: scram

这会一次启用 Pigsty CA 节点证书、Controller mTLS、Broker/client SASL_SSL + SCRAM-SHA-512、StandardAuthorizer 与默认拒绝。应用用户通过 kafka_users 声明密码、ACL 和可选 Quota。

安全模式是 Bootstrap-only 属性。已格式化集群不能通过普通剧本从 plaintext 在线切换到 scram;这需要独立迁移状态机。健康 scram 集群可以使用受保护动作轮换内部凭据或证书。


kafka_topicskafka_users 会删除资源吗?

不会因为从清单移除条目而隐式删除 Topic 或用户。

Topic 会幂等创建、Partition 只增加、只更新声明的配置;RF 变化要求显式 Reassignment。声明用户会收敛密码、完整 ACL 集合与给出的 Quota 字段。Topic 删除、用户删除或彻底撤权都是独立受审操作。


JMX Exporter 与 kafka_exporter 有什么区别?

JMX Exporter 注入每个 Kafka JVM,采集 JVM、Broker、复制、请求路径与 KRaft 内部指标,注册为带 role 标签的 job=kafka 目标。

kafka_exporter 通过 Kafka 协议查询逻辑集群、Topic、Partition、Offset、Consumer Group 与 Lag,注册为同一 job=kafka 下不带 role 标签的目标。角色只在按 kafka_seq 排序后的前两个 Broker-capable 节点运行;单 Broker 集群运行一个,纯 Controller 不运行。

两者互补。生命周期健康门禁使用角色自有 Kafka CLI/metadata 通道,不依赖任一 Exporter。


为什么某个 Broker 或纯 Controller 没有 kafka_exporter?

这是预期的派生放置。协议 Exporter 返回的是整个逻辑集群视图,不是节点指标;最多两个副本可以避免监控单点,同时控制重复采集成本。

检查当前目标(每实例一个文件,被选中节点的文件里含 :9308 的协议 Exporter 目标):

ls -l /infra/targets/kafka/
grep 9308 /infra/targets/kafka/*.yml

完整运行会按当前放置刷新每个实例的 Target 文件,不应只针对单节点运行注册标签。注意:若 Exporter 放置因拓扑变化而转移,曾被选中节点上的旧 kafka_exporter 服务不会被普通剧本自动停止,需要手工或通过 kafka-rm.yml 清理。


为什么 JMX 端点可访问,但 jmx_scrape_error=1

HTTP 可访问只说明 Java Agent 已加载;jmx_scrape_error=1 表示本轮 MBean 采集失败:

journalctl -u kafka --since '-30 min' --no-pager
curl -fsS http://<kafka-ip>:9404/metrics | head -n 40

检查 /etc/kafka/jmx_exporter.yml 与当前 Kafka/JMX Exporter 包是否匹配,以及 JVM 是否已经过 startDelaySeconds。真实启动验收要求 jmx_scrape_error 0.0、JVM 指标和至少一项与角色匹配的 kafka_ 指标。


为什么 Consumer Lag 没有数据?

常见原因:Consumer 没使用 Group、未向 Kafka 提交 Offset、把 Offset 存在外部系统、Group 尚未消费目标 Topic,或协议 Exporter 的 TLS/SCRAM/ACL/网络异常。

/opt/kafka/bin/kafka-consumer-groups.sh \
  --bootstrap-server <broker>:9092 \
  --command-config /etc/kafka/admin.properties \
  --describe --group <group>

再检查 kafka_exporter_up、Exporter 日志、Dashboard 变量和原始 kafka_consumergroup_* 指标。端点存活以 Prometheus 原生 up 为准,不要用抓取失败后可能短暂保留的自定义指标代替。


为什么两个 kafka_exporter 的集群指标不能相加?

两个 Exporter 查询同一逻辑集群,可能返回相同 Topic/Partition/Consumer Group 状态;直接求和会重复计算。Pigsty 的 kafka:cls:* Recording Rule 会先跨 Exporter 副本去重,再聚合到集群。


应用要经过 HAProxy、Keepalived VIP 或 LB 吗?

通常不要。Kafka Producer/Consumer 是集群感知的智能客户端:它先连接 bootstrap.servers 中任一可用种子获取元数据,随后直接连接各 Partition Leader。生产配置应给出至少两个、通常三个 Broker 种子地址,并允许应用直达所有 Broker 宣告的地址。

一个 VIP 或通用 TCP LB 既不理解 Partition Leader,也不会改写 Kafka 元数据中的 Broker 地址;把它放在数据面通常只会增加长连接状态、额外故障点和排障复杂度。若企业平台强制要求统一发现入口,DNS 或 TCP LB 可以仅承担 bootstrap,但 advertised.listeners 仍要返回每个 Broker 的客户端可达地址,LB 不能成为唯一网络路径。

跨 NAT、公网、多网络或 Kubernetes 暴露通常需要每 Broker 独立外部地址与额外 Listener。当前模块固定宣告清单地址,不支持这类映射。参见快速上手:为什么应用应直连多个 Broker集群配置:网络与监听器


可以直接增加一个 Broker 吗?

健康集群支持新增纯 Broker。更新完整 inventory 后,仍需使用精确完整集群 Limit:

./kafka.yml --check -l kf-main
./kafka.yml -l kf-main

角色逐个格式化、启动并验证新 Broker 注册。不能只限制新节点。加入后既有 Partition 不会自动迁移,还要独立执行并监控 Reassignment;“Broker 已注册”不等于“容量已经均衡”。


可以直接增加或移除 Controller 吗?

不能仅靠 inventory。集群虽然使用 dynamic quorum,但新 Controller 必须针对现有 Cluster ID 显式格式化、启动、追平,再执行 add-controller;删除需要 remove-controller、多数派验证和节点退役流程。

角色会拒绝把 inventory 中的新 Controller 自动当成 Voter。应使用 Kafka 4.3 KRaft 成员变更 与经过演练的独立运行手册。


软件包版本由哪个参数控制?

角色使用 package_map['java-runtime']package_map['kafka-stack'],不提供 kafka_versionscala_version 或 Exporter 版本参数。实际版本由目标平台的 Pigsty 仓库和已安装包决定。

2026-07-16 验证的载荷为 Kafka 4.3.1、kafka_exporter 1.9.0、JMX Exporter 1.6.0。升级仍需单独评审兼容性、备份/回退、滚动顺序与 Feature Level,不能只替换包。


如何安全清空 Kafka 数据?

kafka.yml 永远不执行清理;集群下线使用独立的 kafka-rm.yml 剧本。它默认(kafka_rm_data=true)会永久删除数据/KRaft 元数据、节点安全状态、监控 Target 与管理节点上的 Manifest/Secret/PKI 缓存;kafka_safeguard=true 可强制中止一切删除。

该剧本没有确认字符串等额外闸门,执行前必须人工确认精确 -l 目标、可恢复备份或明确重建意图与业务停用状态。完整语义见 预置剧本:集群下线