11.9.4 JMX与Prometheus导出方案

ZooKeeper 监控导出通常通过 JMX 暴露运行时指标,再由 Prometheus 抓取。核心流程为:启用 JMX 端口 → 通过 jmx_exporter 将 JMX 指标转换为 Prometheus 格式 → Prometheus 抓取与告警。该方案通用、稳定,便于与现有监控体系整合。

原理草图

文章图片

JMX 启用方式与参数建议(含命令解释)
启动 ZooKeeper 时追加 JVM 参数,开启 JMX 远程监控:

# /opt/zookeeper/bin/zkServer.sh
# 关键参数解释:
# -Dcom.sun.management.jmxremote.port=9999 指定 JMX 监听端口
# -Dcom.sun.management.jmxremote.authenticate=false 关闭认证(仅实验环境)
# -Dcom.sun.management.jmxremote.ssl=false 关闭 SSL
export JVMFLAGS="$JVMFLAGS \
 -Dcom.sun.management.jmxremote \
 -Dcom.sun.management.jmxremote.port=9999 \
 -Dcom.sun.management.jmxremote.authenticate=false \
 -Dcom.sun.management.jmxremote.ssl=false"

生产建议:启用认证与访问控制,限制网段访问,避免暴露公网。

# 开启认证示例(需要 jmxremote.password / jmxremote.access)
export JVMFLAGS="$JVMFLAGS \
 -Dcom.sun.management.jmxremote \
 -Dcom.sun.management.jmxremote.port=9999 \
 -Dcom.sun.management.jmxremote.authenticate=true \
 -Dcom.sun.management.jmxremote.password.file=/opt/zookeeper/conf/jmxremote.password \
 -Dcom.sun.management.jmxremote.access.file=/opt/zookeeper/conf/jmxremote.access \
 -Dcom.sun.management.jmxremote.ssl=false"

jmx_exporter 安装与部署(Java Agent 模式)
推荐 Java Agent 方式,资源开销低、部署简洁。

# 1) 下载
mkdir -p /opt/jmx_exporter
cd /opt/jmx_exporter
wget -O jmx_prometheus_javaagent.jar \
  https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.20.0/jmx_prometheus_javaagent-0.20.0.jar

# 2) 编写规则文件
cat >/opt/jmx_exporter/zk.yml <<'EOF'
rules:
  - pattern: "org.apache.ZooKeeperService<name0=ReplicatedServer_id(\\d+)><>(.*)"
    name: "zookeeper_$2"
    labels:
      server_id: "$1"
  - pattern: "org.apache.ZooKeeperService<name0=ReplicatedServer_id(\\d+),name1=replica.(\\d+)><>(.*)"
    name: "zookeeper_replica_$3"
    labels:
      server_id: "$1"
      replica_id: "$2"
EOF

启动参数追加 Java Agent:

# /opt/zookeeper/bin/zkServer.sh
# 关键参数解释:
# =9404 表示导出端口
# :/opt/jmx_exporter/zk.yml 规则文件
export JVMFLAGS="$JVMFLAGS \
 -javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent.jar=9404:/opt/jmx_exporter/zk.yml"

Prometheus 抓取配置示例(完整可用)

# /etc/prometheus/prometheus.yml
scrape_configs:
  - job_name: "zookeeper"
    scrape_interval: 15s
    static_configs:
      - targets: ["zk1:9404","zk2:9404","zk3:9404"]
    relabel_configs:
      - source_labels: [__address__]
        regex: "(.*):.*"
        target_label: instance
        replacement: "$1"

验证与排错(含命令与预期)

# 1) 验证 JMX 端口是否监听
ss -lntp | grep 9999
# 预期:出现 java 进程监听 9999

# 2) 验证指标输出
curl -s http://zk1:9404/metrics | head
# 预期:输出以 zookeeper_ 开头的指标

# 3) 检查规则文件加载
grep -i "Loaded" /var/log/zookeeper/zookeeper.out
# 预期:出现 jmx_exporter 规则加载日志

# 4) 常见错误排查
# 端口不可达:检查防火墙
iptables -S | grep 9404
# 指标为空:检查 MBean 匹配
jcmd $(pgrep -f zookeeper) VM.system_properties | grep -i jmx

常见问题定位清单
- curl /metrics 空白:规则不匹配 → 调整 zk.yml 的 pattern。
- Prometheus 无数据:目标未就绪 → Targets 页面检查状态码。
- CPU 升高:采集频率过快 → 将 scrape_interval 调大。
- 端口冲突:9404 已被占用 → 修改导出端口并同步 Prometheus 配置。

安全与稳定性建议
- 仅在内网开放监控端口,必要时通过反向代理或服务发现封装。
- 指标输出端口纳入安全基线与端口白名单。
- 变更规则文件需走变更流程,避免误删关键指标导致告警失效。

练习
1. 将 JMX 端口从 9999 改为 19999,并验证 Prometheus 仍能抓取。
2. 在 zk.yml 中新增一个规则,将 PacketsReceived 指标映射为 zookeeper_packets_received
3. 模拟采集失败:临时关闭 9404 端口,观察 Prometheus Target 状态变化并恢复。