简介这是一套专为Hadoop大数据平台运维与监控人员设计的Grafana可视化仪表盘资源聚焦HDFS、YARN、HBase、Kafka等核心组件的实时性能观测与健康诊断解决传统日志与命令行监控效率低、指标分散、难以快速定位瓶颈的问题。压缩包共14个文件全部为可直接导入Grafana的JSON格式仪表盘配置文件涵盖总览、HDFSNameNode/DataNode、YARNResourceManager/NodeManager、HBaseHMaster/RegionServer及Solr、EMQ、Prometheus等关联组件结构清晰、模块独立便于按需启用或组合部署整体包体仅64KB轻量易集成。已有373人学习下载用户导入后只需对接已部署的Prometheus或JMX数据源即可立即启用预调优的指标视图——包括存储利用率、任务队列长度、RPC延迟、GC耗时等关键维度并支持基于阈值的告警联动与多层级下钻分析显著降低定制化监控开发门槛。 我们组刚接手一个自建Hadoop集群的时候第一周就把我搞失眠了。集群跑着十几个定时任务HDFS上的数据源源不断落进来YARN上几十个作业在排队。按说主机监控一直开着CPU、内存、磁盘看着都挺正常可偏偏某天凌晨NameNode进程悄悄挂了监控大屏上所有主机指标都是绿的跑批任务却集体失败等到早上业务方找过来才知道出了问题。这事儿的根子就在于主机活着并不代表Hadoop服务活着。NameNode进程死了机器却毫发无伤你盯着CPU和内存怎么看都发现不了。从那之后我就下决心一定要给Hadoop生态做一套真正能反映组件健康状态的监控Dashboard让所有指标在Grafana上一目了然。这篇文章就把我搭这套从零到一的完整过程、技术选型和踩坑记录全部写出来希望能给同样被Hadoop监控折磨的人一点参考。1. Hadoop生态监控的痛点为什么通用方案在这里会失灵1.1 组件多、端口杂、指标口径不一Hadoop从来不是单一组件而是一个生态HDFS负责存储里面分NameNode和DataNodeYARN负责调度有ResourceManager和NodeManager往上还有HBase、Hive、ZooKeeper这些依赖件。每个组件都有自己独立的进程、独立的端口、独立的指标暴露方式。你打开Hadoop的监控页面NameNode上有500多MBeanDataNode上有200多个YARN、HBase各自的MBean数量也不小。这些指标又不遵循同一个命名规范——HDFS告诉你CapacityUsedYARN告诉你有多少ActiveApplicationsHBase的指标叫RegionCount。组件之间虽然都有基于JMX的Metrics接口但是面向终端用户的标准监控通道一直没有统一起来。更麻烦的是端口。Hadoop 3.x版本里NameNode的HTTP服务在9870端口DataNode是9864ResourceManager的WebUI在8088NodeManager在8044。不同发行版、不同版本还可能不一样。你没法用一个固定的规则把整个集群的指标全部收齐。要监控Hadoop首先要面对的其实不是图表问题而是指标采集的乱局。1.2 商业方案与开源方案的取舍市面上不是没有现成的方案。Cloudera Manager和Apache Ambari都自带完整的Hadoop监控开箱即用图表也很漂亮。但问题在于很多公司集群是自己手动装的所谓“裸Hadoop”没有绑定任何商业发行版这时候要引入CM或者Ambari等于把整个集群的管理方式推翻重来牵一发动全身。另外还有一层考虑这些管理平台本身就比较重占资源不说升级维护也要花不少精力。对一个运维团队来说为了一套监控把底层集群改掉风险收益比实在不划算。所以更现实的选择是基于现有的PrometheusGrafana这套生态把Hadoop各组件的JMX指标抓出来自己组装Dashboard。这种方式对集群本身零侵入只需要改一些JVM启动参数、部署几个exporter进程就能把指标接进来。数据流打通之后整个集群的状态用一套Grafana面板展示故障定位、容量规划、性能分析都能在一个视图里完成。2. 监控链路设计从MBean到Grafana面板的数据流向2.1 为什么选Prometheus这条链路如果你去搜Hadoop监控相关资料能看到很多种组合Zabbix、Graphite、InfluxDB、Telegraf等等。但我实测下来PrometheusGrafana是个人和中小团队最顺手的一套。Prometheus是拉模式采集也就是说由Prometheus主动去各个exporter拉数据不是agent往服务端推。这意味着什么集群里加一台新节点不用到服务端改配置只要在Prometheus的targets列表里加一条记录就行。扩容、缩容都是这么简单。而且Prometheus自带标签体系一个指标可以挂上host、role、cluster等任意维度的标签画图时的筛选和聚合就非常灵活。还有一点很关键Grafana对Prometheus的PromQL有原生支持不需要额外的适配层图表拖动、阈值线、模板变量全部直接可用。如果换InfluxDB图表查询语言要写成Flux和PromQL差异很大等于把简单问题复杂化了。2.2 链路各环节的职责拆分整套链路每个环节只干一件事职责分得很清楚Hadoop各组件通过JMX暴露MBean这是数据源头jmx_exporter负责把JMX指标取出来转成Prometheus的metric格式暴露一个HTTP端口Prometheus按照配置的抓取频率定期去exporter拉取指标存入本地时序数据库Grafana通过PromQL从Prometheus查询数据绘制成Dashboard并承担告警规则的触发。你可以把这条链路类比成自来水管Hadoop的JMX是水源头jmx_exporter是水龙头上的接头Prometheus是蓄水池和泵站Grafana就是你家里的水龙头。任何一个环节堵塞最终到你眼前的水流都会出问题。实际部署的时候jmx_exporter又分两种用法。一种是jmx_prometheus_javaagent作为Java Agent直接挂到Hadoop进程里JVM启动的时候带上-javaagent参数即可。另一种是独立的jmx_exporter进程通过JMX RMI协议去远程连接Hadoop进程。这两种我实测都跑过各有利弊。Java Agent方式部署简单不需要额外管理一个进程但每次Hadoop进程重启exporter也一起重启了而且如果agent配置写错了可能影响Hadoop本身的启动。独立jmx_exporter方式对Hadoop进程零侵入出问题也不影响集群就是需要自己用systemd把它管起来。我自己更倾向独立方式集群稳定优先多管几个进程完全不是问题。3. 实操第一步把HDFS的指标完整捞上来3.1 开启远程JMX并部署jmx_exporterHDFS的监控要从NameNode和DataNode上下手。先给NameNode开启远程JMX。这里以Hadoop 3.x为例编辑hadoop-env.sh找到HADOOP_NAMENODE_OPTS这一行往里面追加JMX参数export HADOOP_NAMENODE_OPTS-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port9010 -Dcom.sun.management.jmxremote.authenticatefalse -Dcom.sun.management.jmxremote.sslfalse -Dcom.sun.management.jmxremote.local.onlyfalse -Dcom.sun.management.jmxremote.rmi.port9011 -Djava.rmi.server.hostnamenode01 $HADOOP_NAMENODE_OPTS这里有两个细节容易踩坑。第一com.sun.management.jmxremote.port和com.sun.management.jmxremote.rmi.port是两回事前者是JMX连接端口后者是RMI数据交换端口。如果集群有防火墙而你把RMI端口设成动态随机分配很可能出现“客户端能连上但拿不到数据”的情况。所以最好把两个端口都固定下来统一在防火墙放行。第二java.rmi.server.hostname必须设置成其他机器能访问到的地址不能留空。否则jmx_exporter从别的机器连接时拿到的是Hadoop进程自己认为的主机名很可能连接失败或超时。接下来下载jmx_exporterwget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_httpserver/0.20.0/jmx_prometheus_httpserver-0.20.0-jar-with-dependencies.jar -O /opt/jmx_exporter/jmx_prometheus_httpserver.jar然后写exporter的抓取配置。这里的关键是不是把所有MBean都一股脑转出来那样指标爆炸Prometheus存储压力大看图也没意义。我是建议先按需去取。初始阶段可以先把NameNode的HDFS存储指标取出来配置文件按下面的方式写rules: - pattern: Hadoop:serviceNameNode,nameFSNamesystemState* - pattern: Hadoop:serviceNameNode,nameFSNamesystem* - pattern: Hadoop:serviceNameNode,nameCapacityTotal - pattern: Hadoop:serviceNameNode,nameCapacityUsed - pattern: Hadoop:serviceNameNode,nameCapacityRemaining - pattern: Hadoop:serviceNameNode,nameBlockStates*具体MBean字段你可以先打开NameNode的JMX页面看一眼再定。Hadoop 3.x的NameNode Web UI端口是9870地址是http://node01:9870/jmx会返回一大串JSON搜一下对应的对象就能确认名字。配置保存后启动exporterjava -jar /opt/jmx_exporter/jmx_prometheus_httpserver.jar 9101 /opt/jmx_exporter/namenode.yml这样一个独立的jmx_exporter就起来了监听9101端口输出Prometheus格式的指标。DataNode同理只是JMX端口换成9012exporter监听端口换成9102。3.2 Prometheus采集任务与标签规整Prometheus这边要新增采集任务。编辑prometheus.yml在scrape_configs里追加- job_name: hdfs-namenode static_configs: - targets: [node01:9101] labels: role: namenode cluster: prod - job_name: hdfs-datanode static_configs: - targets: [node01:9102, node02:9102, node03:9102] labels: role: datanode cluster: prod这里我自己习惯给每个target打上role和cluster标签。原因是同一个jmx_exporter配置可能同时用在多个集群上没有这个标签绘图时几个集群的数据会混在一起你就没法单独看某一套集群的状态了。配置好之后重启Prometheus在Targets页面就能看到这两个任务是UP状态。如果显示DOWN顺着地址排查exporter进程是否在跑防火墙是否放行。3.3 导入仪表盘并验证关键指标Prometheus采集正常后就可以去Grafana创建Dashboard了。如果你不想从零画Grafana官网的Dashboards列表里直接搜“Hadoop”能找到不少社区分享的面板。我推荐先导入一份ID为12769的HDFS Dashboard具体ID可能随时间变化请在官方页面确认然后基于它改。但要注意社区模板很多用的是别人的exporter配置和job名导入后大概率一片红需要把每个面板的查询改成你自己的job名。如果你倾向于自己画核心指标至少要包含这几个维度HDFS容量hadoop_namenode_capacity_total、hadoop_namenode_capacity_used、hadoop_namenode_capacity_remaining数据块状态hadoop_namenode_blockstates_pending_replication_blocks、hadoop_namenode_blockstates_corrupt_blocksDataNode存活通过up{jobhdfs-datanode}判断文件读写量按时间做rate()计算看流量趋势。验证指标是否采到的办法很简单在Grafana面板的Query里写一句hadoop_namenode_capacity_used如果图表有数据出来说明整条链路通了。看到数据在跳的那一瞬间我整个人都很踏实——之前那种“主机全绿但服务挂了”的焦虑一下子消失了因为现在看到的每一块数据都来自Hadoop进程本身。4. YARN与HBase的差异化监控同样的方法不同的关注点4.1 YARN队列资源和应用状态的指标HDFS搞通之后YARN的监控是同样的套路但关注点完全不一样。YARN的关键在于ResourceManager和NodeManager。ResourceManager有这些指标特别值得盯ActiveApplications当前活跃的应用数量快速判断集群负载PendingContainers等待分配的Container数量这个值持续升高说明集群资源饱和AvailableMB可用内存看资源池是否被占满各个队列的AllocatedMB、PendingMB这个配合Capacity Scheduler做多队列隔离时特别关键LostNodes、UnhealthyNodes这个与节点健康检查直接相关节点闹情绪的时候这个值会跳。NodeManager的指标则要看单机视角运行中的Container数量、分配的内存和CPU、本地日志占用。这些指标可以帮助你判断某台机器是不是资源分配不均衡。配置上启用ResourceManager的JMX参数改YARN_RESOURCEMANAGER_OPTSNodeManager改YARN_NODEMANAGER_OPTS然后各挂一个独立的jmx_exporter。exporter的配置文件按需抓取即可。目标端采集写进Prometheus- job_name: yarn-resourcemanager static_configs: - targets: [node01:9111] labels: role: resourcemanager cluster: prod4.2 HBase读写延迟与Region平衡HBase的监控相比YARN更细致因为它是直接面向在线业务的存储引擎读写延迟、Region分布、MemStore大小这些指标直接决定了业务的响应效果。RegionServer上重点看ServerReadRequestsPerSecond和ServerWriteRequestsPerSecond读写速率RegionCountRegion数量注意是否分配均衡有些RegionServer Region数远超其他节点就容易产生热点MemStoreSizeMemStore大小如果某个RegionServer的MemStore占用持续偏高说明Flush不及时可能有大Region或写入压力异常BlockCacheHitRatio块缓存命中率低了要检查读热点和BlockCache大小。HMaster上则关注MasterActiveTime、MasterStartTime这种基础指标以及RegionServer是否都正常注册。HBase的JMX端口配置跟前面一样改HBASE_REGIONSERVER_OPTS和HBASE_MASTER_OPTS。RegionServer的metrics相对多exporter的配置尽量按需要的字段去筛不要全量采集。4.3 ZooKeeper、Hive等的监控补充ZooKeeper虽然本身不是Hadoop组件但HDFS HA和HBase都依赖它。ZooKeeper的上层应用挂了大家都很难察觉。ZooKeeper的监控和别的不太一样因为它不是纯Java进程的JMX方式还有自己的一套四字命令协议比如ruok、mntr。配合zookeeper_exporter可以很方便地拿到指标- job_name: zookeeper static_configs: - targets: [node01:2182, node02:2182, node03:2182]重点看ZooKeeper的znode_count、watch_count、outstanding_requests以及连接的客户端数量。outstanding_requests如果持续偏高说明ZooKeeper处理不过来HBase和HDFS HA都会出问题。Hive的监控没那么标准HiveServer2本身没有特别完善的Metrics接口。我的做法是分两步HiveServer2的进程存活用JMX基本指标判断更精确的查询性能、执行时长则接日志或者通过beeline执行结果侧面观察。如果你用的是Hive on Tez还要同时盯Tez的ApplicationMaster运行状态。这一块没有一劳永逸的模板得结合自己集群的任务特征来定。5. 告警配置让Dashboard主动替你盯夜班5.1 告警规则设计原则与样例规则Dashboard做得再好看也不可能24小时盯着看。真正让监控有价值的是告警——出问题的时候有消息主动找到你。我自己的告警设计原则是三句话先保活再保容量最后保性能。保活是最基础的一层。任何核心进程挂了必须立刻通知。用Prometheus自带的up指标就能判断groups: - name: hadoop-core-alerts rules: - alert: NameNodeProcessDown expr: up{jobhdfs-namenode} 0 for: 2m labels: severity: critical annotations: summary: NameNode进程不可用 description: 主机 {{ $labels.instance }} 的NameNode进程已宕机 { for: 2m } 分钟注意这个for: 2m的延时我的经验是不要设成0。Hadoop在做滚动重启的时候进程会短暂消失如果你一秒钟内就把告警发出去了会收到大量误报。设成2分钟可以过滤掉这类正常维护窗口。容量告警是Hadoop运维里最容易遗忘的。HDFS磁盘写满时所有写入任务都会失败而且恢复非常费劲。所以我给HDFS容量和NameNode的SafeMode状态都加了告警- alert: HDFSCapacityLow expr: (hadoop_namenode_capacity_remaining / hasoop_namenode_capacity_total) * 100 10 for: 10m labels: severity: warning annotations: summary: HDFS容量不足 description: HDFS剩余空间已低于10%当前剩余比例{{ $value | humanizePercentage }}这里的10可以是任意阈值但如果你觉得10%才告警太晚建议拆成两个规则剩余低于30%发warning低于10%发critical。提前预警给运维留出做数据清理或扩容的时间。5.2 数据源级告警与Grafana通知策略Prometheus里的告警规则只是第一步还需要把告警事件发到通知渠道。一种方式是传统的AlertmanagerPrometheusPrometheus把告警推给AlertmanagerAlertmanager再负责路由、去重、发到钉钉、邮件或者Slack。这套适合告警量大、要精细管理的场景。如果你不想维护AlertmanagerGrafana本身也支持直接配置告警。Grafana 9以后把告警功能收编进统一告警中心可以直接在Dashboard面板上创建AlertRule。它的规则基于面板查询一旦阈值触发就能通过内置的“Notification policies”发到钉钉、邮件等渠道。我个人比较推荐先用Grafana自带的告警尤其是中小集群的运维场景。理由很简单Grafana的告警规则和Dashboard绑定在一起图表上画的是什么告警就在什么条件上触发直观且容易理解。Alertmanager的功能更强大但对于一个几十台机器规模的集群Grafana自带告警已经足够不用多维护一个组件。配置告警还有一个细节查询表达式最好带上rate()或irate()后再比较否则像读写请求量这类计数器指标数据一直在涨你拿原始值和阈值比怎么比都不对。比如rate(hadoop_namenode_blockstates_pending_replication_blocks[5m]) 0这样看的是5分钟内的速率变化才符合“复制请求积压”这个告警语义。6. 真实的坑与排错记录从“连不上”到“图全红”6.1 JMX连接失败排查链路这套监控搭建过程中我踩得最多的坑就是“Prometheus能访问exporter但exporter访问Hadoop的JMX失败”。最典型的报错是Connection refused或者java.rmi.ConnectException。碰到这类问题先不要怀疑prometheus.yml写错了而是先用命令行验证JMX端口通不通telnet node01 9010如果端口不通多半是防火墙没放行。把9010和9011两个端口都加上。如果端口通仍然连接失败排查方向就转向RMI。上面说过要设置java.rmi.server.hostname这里我再强调一次Hadoop进程如果跑在容器里或者主机名解析有问题不设置这个参数exporter拿到的是内网容器IP而不是宿主机IP你会发现本机能连跨机器就断。这个参数记得配成exporter机器能访问到的稳定地址。还有一个隐蔽的坑有些发行版的Hadoop在启动时会用JAVA_TOOL_OPTIONS覆盖HADOOP_XXX_OPTS里的JMX配置。你明明改好了hadoop-env.sh进程起来却没有监听9010端口。排查方法是看进程启动参数ps -ef | grep NameNode | grep java确认命令行里是否带上了-Dcom.sun.management.jmxremote.port9010。没有的话就是配置被覆盖了需要追一下HADOOP_NAMENODE_OPTS变量最终的取值。6.2 指标名对不上命名空间与标签的坑jmx_exporter配置好之后最烦人的问题是我以为会生成hadoop_namenode_capacity_total这个指标结果在Prometheus里怎么都查不到。原因在jmx_exporter对MBean的名字做了转换Hadoop:serviceNameNode,nameCapacityTotal会被转换成hadoop_namenode_capacity_total。中间的冒号、等号、逗号都会被转成下划线。问题在于MBean的名字里还可能有版本号之类的干扰项转换结果跟你预想不完全一样。解决办法很笨但很有效直接看exporter暴露的HTTP接口。curl一下exporter的端口curl -s http://node01:9101/metrics | grep Capacity看看实际生成的指标名、标签名叫什么按照实际的名字去写Dashboard查询。不要凭记忆写指标名一切以实际输出为准。命名空间也是一样。如果Hadoop集群里跑了多个namespace或备份集群MBean名字里会带namespace标签比如Hadoop:serviceNameNode,nameFSNamesystemState,namespacens1。你会发现同样的指标在Prometheus里出现了多个不同的标签组合画图的时候记得按namespace筛选免得把两个集群的数据合并起来看。6.3 仪表盘导入即全红采集路线的常见断点从Grafana官网导入社区模板后面板一片红是家常便饭。主要原因有三个第一模板用的数据源名和你Grafana里创建的不一致。比如模板里写的是Prometheus-1你创建的数据源叫Prometheus查询不到数据自然全红。导入时在参数设置页面把数据源换成你实际创建的即可。第二模板里的PromQL用到的指标名和实际不一致。模板作者可能用的是他的Hadoop发行版指标名而你的是Apache Hadoop命名有差异。这种就要逐个面板改查询或者干脆以模板为参考自己重新画。第三模板里的job标签和你的不匹配。这种需要先找到模板中用了哪个job名然后调整你Prometheus里的job_name或者改Dashboard的模板变量筛选条件。我建议的做法是不要“导入模板就完事”。把模板当作参考自己过一遍每个面板把不合适的查询改掉。整个过程等于把自己的集群指标翻了一遍之后哪里有问题心里清楚得很。6.4 多exporter进程管理systemd统一守护集群规模上来之后机器数量多每个节点上挂多个exporter进程单纯用nohup java -jar方式启动进程挂了也没人管监控本身反而成了新的故障点。所以每个exporter都必须交给systemd管理。下面是一个jmx_exporter的systemd unit文件示例[Unit] DescriptionJMX Exporter for NameNode Afternetwork.target [Service] ExecStart/usr/bin/java -jar /opt/jmx_exporter/jmx_prometheus_httpserver.jar 9101 /opt/jmx_exporter/namenode.yml Userhdfs Restartalways RestartSec10 [Install] WantedBymulti-user.target把unit文件放到/etc/systemd/system/下然后systemctl daemon-reload systemctl enable jmx_exporter_namenode systemctl start jmx_exporter_namenode这样exporter进程异常退出后systemd会自动拉起来监控链路本身的高可用才有保障。所有exporter配置和unit文件建议用Git管理集群扩容的时候直接复制修改省去重复劳动。最后再分享一个我自己的习惯每次搭完一套组件监控我会把整套配置文件和Prometheus的采集配置一并备份到版本库里。下次再搭一套新集群直接引用备份里的配置改个主机名就能用不用再从零摸索。这个习惯已经帮我省下了无数次重复排查的时间。本文还有配套的精品资源点击获取