简介:一套面向大数据运维与开发人员的 Grafana 监控模板,聚焦 Hadoop 生态组件的可视化可观测性,适用于快速搭建集群监控面板、排查性能瓶颈的场景。资源包共 14 个文件,全部为 JSON 格式的仪表盘定义,整体仅 54KB,可直接导入 Grafana 使用。模板覆盖 HDFS、YARN、HBase、Hive、Kafka、Spark、ZooKeeper 等核心组件,并细分 NameNode、DataNode、ResourceManager、NodeManager、HMaster、RegionServer 等子模块,分别提供磁盘利用率、副本数量、任务状态、内存与 CPU 使用、Region 分布、消息积压等关键指标视图,层次清晰、便于按需导入。目前已有 4453 人学习下载。借助该模板可省去从零配置图表的繁琐过程,配合 Prometheus 等数据源快速适配自有集群,且支持扩展定制,实现统一监控入口,提升 Hadoop 集群的运维效率与稳定性。
1. 基于Hadoop监控的Grafana模板:先解决“面板有了,指标没通”的难题
接手过几套 Hadoop 集群的监控改造,多数团队的第一步是去 Grafana 官方库找现成的 Hadoop 模板,导入后拉选数据源,然后盯着满屏的 0 和 No data 发呆。基于 Hadoop 监控的 Grafana 模板,本质不是一套画好的图表,而是把 HDFS 的容量水位、DataNode 的读写负载、YARN 的资源调度和作业队列压缩成一块能一眼看懂的战情看板。它解决的问题很具体:集群是不是快满了、副本是不是在掉、队列是不是在排队、哪台机器拖慢了整个批处理。适合谁用?维护着几十台到几百台节点、每天要和值班告警打交道的平台工程师,以及刚接手集群、急需建立监控体系但不想从零摸索 PromQL 的新人。我花了很长时间才搞明白,模板里最贵的不是那些面板,而是模板背后对指标口径、标签设计、采集链路和网络分区容错的理解。这篇笔记会把从指标采到面板落地的完整链路讲清楚,中间包含大量参数和踩坑记录,都是真金白银换来的经验。
2. 监控对象与指标口径:先搞清 Hadoop 到底能暴露什么
2.1 HDFS 与 YARN 的指标来源:JMX 端口与 HTTP 端点
Hadoop 自身不直接输出 Prometheus 格式的数据,它的监控数据主要藏在两个地方:一个是各守护进程的 JMX 端口,另一个是 NameNode 和 ResourceManager 自带的 HTTP 状态端点。常见做法是优先走 JMX,因为 jmx_exporter 能把 MBean 里的指标名完整映射出来,HDFS、YARN、ZooKeeper 都能统一用这一条链路采集,避免给每个组件写不同的解析器。
先确认你的集群里这些进程都开了哪些端口。NameNode 的 JMX 一般跟着 9870 的 HTTP 端口走,DataNode 是 9864,ResourceManager 是 8088,NodeManager 是 8042。不同发行版的默认端口有差异,但大差不差。用下面的命令先探一下端口通不通:
# 在集群任一节点上测试 NameNode 的 JMX 端口是否开放 curl -s http://namenode-host:9870/jmx | head -c 500 # 如果集群启用了 Kerberos,则需要带着认证票据访问 curl -s --negotiate -u : http://namenode-host:9870/jmx | head -c 500如果返回的是一段 JSON,里面有name字段和modelerType字段,说明 JMX 端点正常。这一步非常关键,很多模板面板全空,不是模板的问题,而是最底层的 HTTP 端点根本没暴露出来。生产环境我一般要求至少确认三个端点可访问:NameNode 的 FSNamesystem 状态、DataNode 的 FSDataSet 状态、ResourceManager 的 ClusterMetrics。这三个是集群级健康度的最小集合。
从 JMX 拿原始指标只是第一步,真正麻烦的是指标命名。Hadoop 的 MBean 名非常啰嗦,比如Hadoop:service=NameNode,name=FSNamesystemState下面挂着一大串CapacityTotal、CapacityUsed、BlocksTotal之类的属性。jmx_exporter 的配置文件里需要把这些 MBean 的 pattern 写准,才能把它们整理成可以查询的时间序列。下一节会给出完整配置示例。
2.2 指标选型:哪些监控项真正决定集群健康度
很多模板喜欢堆面板,一个集群监控看板三四十个图,真正值班时能用上的不到十个。我一般把 Hadoop 监控指标分成三类:容量类、吞吐类、资源调度类。容量类看的是 HDFS 总量和余量,核心指标是CapacityTotal、CapacityUsed、CapacityRemaining,以及UnderReplicatedBlocks(副本不足的块数)。吞吐类看的是读写压力,核心是 DataNode 的BytesWritten、BytesRead,以及 NameNode 的AddFileOps、GetBlockLocations。资源调度类看的是 YARN 队列和容器状态,核心是AvailableMB、AllocatedMB、PendingContainers和ActiveApplications。
选指标有一个原则:宁可少而准,不要多而杂。面板图一旦超过十几个,人的注意力就会被稀释,真正的故障信号反而被淹没。我自己的模板只保留三行四列,第一行是 NameNode 状态,第二行是 DataNode 聚合,第三行是 YARN 队列,所有面板加起来不超过十二个。
这里还涉及一个容易踩的坑:不同 Hadoop 版本里同名指标的单位不一致。比如CapacityUsed有的版本直接给字节,有的版本给的是 MB,还有的发行版把CapacityUsed改成Used。所以指标口径要以实际抓到的 JSON 为准,别拿文档死磕。用下面这条命令把 NameNode 的关键指标拉下来核一遍单位:
# 直接过滤 FSNamesystemState 里的容量指标,确认字段名和数值量级 curl -s http://namenode-host:9870/jmx \ | grep -o '"CapacityUsed":[^,]*' \ | head -1假设返回的是"CapacityUsed": 128849018880,这个数字 128849018880 除以 1024 的三次方正好是 120GB,说明单位是字节。如果返回的是一个三位数,那基本可以确定单位是 GB,后面写 PromQL 时就不能再套用除以 1024 的三次方了。这类细节多花十分钟确认,能省掉后面调面板的半天时间。
选好指标之后,下一步是决定采集频率。HDFS 的容量变化是慢变量,NameNode 的 JMX 每 30 秒拉一次完全够用;YARN 的队列指标稍微敏感一些,15 秒拉一次比较合适。DataNode 的吞吐可以放宽到 60 秒,因为这类指标在面板上主要用于趋势观察,不需要秒级精度。采集频率设低了面板看起来不够实时,设高了会给 NameNode 的 JMX 端点造成不必要的压力,后面避坑章节会展开说这个隐患。
3. 采集链路搭建:用 jmx_exporter 把监控数据送进 Prometheus
3.1 配置 jmx_exporter:从写 config.yaml 到启动守护进程
有了指标来源,下一步就是把 JMX 端点变成 Prometheus 能抓取的格式。常见做法是在每个 Hadoop 角色所在的节点上部署一个 jmx_exporter 进程,由它去访问本机或远端守护进程的 JMX,然后把结果暴露成一个 HTTP 端点。这个进程很小,本身不采集数据,只是做格式转换,所以对节点资源的占用非常有限。
jmx_exporter 需要一个配置文件来声明抓取哪些 MBean、指标重命名规则是什么。下面这份配置覆盖了 HDFS 和 YARN 的核心指标,直接保存为hadoop-jmx.yml:
# jmx_exporter 配置:抓取 HDFS 核心 MBean lowercaseOutputName: true lowercaseOutputLabelNames: true rules: # 抓取文件系统命名空间状态,前缀为 hdfs_namesystem - pattern: 'Hadoop:service=NameNode,name=FSNamesystemState' name: hdfs_namesystem_$1 labels: component: "namenode" attrNameSnakeCase: true # 抓取 DataNode 的活动状态 - pattern: 'Hadoop:service=DataNode,name=FSDataSetState' name: hdfs_datanode_$1 labels: component: "datanode" attrNameSnakeCase: true # 抓取 YARN 集群级指标 - pattern: 'Hadoop:service=ResourceManager,name=ClusterMetrics' name: yarn_cluster_$1 labels: component: "resourcemanager" attrNameSnakeCase: true这份配置里需要注意两个细节。attrNameSnakeCase: true的作用是把 MBean 属性名里的驼峰命名转成下划线,比如CapacityUsed会变成Capacity_Used,配合lowercaseOutputName最终在 Prometheus 里看到的是hdfs_namesystem_capacity_used。如果不开这两个选项,指标名里会留着大写字母和驼峰,写 PromQL 时每次都要小心翼翼地用引号包起来,非常折磨人。
配置写好后,用下面的命令把 jmx_exporter 起起来。这里我给每个组件一个独立端口,避免多个 exporter 实例抢同一个端口:
# 在 NameNode 节点上启动 jmx_exporter 实例,端口 9108,配置指向 hdfs-jmx.yml nohup java -jar jmx_prometheus_httpserver.jar 9108 hdfs-jmx.yml \ > /var/log/jmx_exporter_namenode.log 2>&1 & # 在 ResourceManager 节点上另起一个实例,使用同一份配置,端口 9109 nohup java -jar jmx_prometheus_httpserver.jar 9109 hdfs-jmx.yml \ > /var/log/jmx_exporter_resourcemanager.log 2>&1 &跑起来后务必验证一下抓取结果:
# 检查是否有 hdfs_namesystem_capacity_used 指标输出 curl -s http://localhost:9108/metrics | grep hdfs_namesystem | head -5如果 grep 出来是空的,先从 jmx_exporter 的日志里找 MBean 匹配不到的报错。常见原因是配置文件里的pattern写错,比如FSNamesystemState拼成了FSNamespaceState,MBean 匹配不上自然就没有任何输出。这类问题排查起来不复杂,但很容易被忽略,因为进程起来了、端口也通了,面板却是空的,看起来像玄学,实际是 pattern 拼写错了。
3.2 Prometheus 抓取配置:target、labels 与采集间隔怎么设
exporter 暴露了指标,接下来要告诉 Prometheus 去哪抓、多久抓一次、打上哪些标签。这一步直接决定后面 Grafana 模板的变量能不能联动起来。如果标签设计不合理,模板里的集群切换下拉框就会变成摆设。
一个简洁的抓取配置如下:
# prometheus.yml 里对 Hadoop 相关 exporter 的抓取配置 scrape_configs: - job_name: 'hdfs' scrape_interval: 30s metrics_path: '/metrics' static_configs: - targets: ['namenode-host:9108'] labels: cluster: 'prod-hadoop' role: 'namenode' - targets: ['datanode-host1:9108', 'datanode-host2:9108'] labels: cluster: 'prod-hadoop' role: 'datanode' - job_name: 'yarn' scrape_interval: 15s static_configs: - targets: ['rm-host:9109'] labels: cluster: 'prod-hadoop' role: 'resourcemanager'cluster这个标签非常关键。如果你的运维体系里有多套 Hadoop 集群,比如一套生产、一套测试,面板上的集群切换下拉框直接绑定这个标签。role 标签则可以让同一个模板里的不同面板按角色过滤出各自的数据源。scrape_interval 按上一章说的口径设:HDFS 慢变量 30 秒,YARN 调度敏感 15 秒。不需要再短,再短除了增加 Prometheus 的存储压力,面板上的曲线也不会有肉眼可见的变化。
配置完 Prometheus 后,第一件事不是去 Grafana 建面板,而是在 Prometheus 的页面上手动跑几条 PromQL,验证数据链路是通的。这一步能帮你把问题定位在采集层还是展示层:
# 验证 HDFS 容量是否被正确抓取 hdfs_namesystem_capacity_used{cluster="prod-hadoop"} # 验证 YARN 集群内存指标是否在更新 yarn_cluster_allocated_mb{cluster="prod-hadoop", component="resourcemanager"}如果查询结果有数字且在持续增长,说明链路已经通到了 Prometheus,后面去 Grafana 里配模板只是时间问题。如果这里就是空的,那问题一定出在 jmx_exporter 的配置或者 Prometheus 的 target 状态上,去 Targets 页面看 endpoint 是 up 还是 down,比在 Grafana 里反复调面板有效得多。
4. 写 Grafana 模板:从 JSON 结构到仪表盘变量与核心面板
4.1 dashboard JSON 的基本结构与模板导入
Grafana 的模板本质上是一个 JSON 文件,里面声明了仪表盘的标题、变量定义、面板数组和每个面板的查询语句。很多人不愿意学 JSON 结构,直接在页面上手工拖面板,一两个面板还能应付,到了十几个面板时效率极低。我自己的习惯是:先花半小时把 JSON 的关键字段读懂,然后直接在 JSON 里批量改,最后上传到 Grafana 导入,效率比手工点高一个量级。
一份最小可用的 dashboard JSON 骨架长这样:
{ "title": "Hadoop 集群监控", "uid": "hadoop-cluster-monitor-v1", "timezone": "browser", "tags": ["hadoop", "hdfs", "yarn"], "templating": { "list": [ { "type": "query", "name": "cluster", "datasource": "Prometheus", "query": "label_values(hdfs_namesystem_capacity_used, cluster)" } ] }, "panels": [] }templating.list里的变量就是面板左上角的下拉框。label_values这个查询方式会从 Prometheus 已有的 label 值里自动拉出所有集群名字。模板导入后,下拉框里就能直接选集群,不用手工填配置。这一点是模板能否复用到多套环境的关键,一个写死的模板只能服务一套集群,一个带变量的模板可以服务一个部门。
导入方式有两种。一种是在 Grafana 的 Dashboards 页面点 Import,把 JSON 粘贴进去;另一种是直接把 JSON 文件放到 Grafana 的 provisioning 目录里,实现启动即加载。后者适合用配置管理工具批量下发模板的场景,前一种适合快速验证。对于生产环境,我更推荐 provisioning 方式,模板变更走代码评审而不是在页面上直接改,能减少很多低级错误。
4.2 用变量串联多集群:datasource、job 与 nodename 的联动设计
多集群监控是模板设计里最容易翻车的地方。如果只有一个集群,变量怎么写都无所谓;一旦有了两套集群,你在模板里写的每一条 PromQL 都必须带着cluster标签去过滤,否则一选测试集群,面板上显示的却是生产集群的数据。
变量设计我一般分三层。第一层是cluster,来源是抓取配置里打上的标签。第二层是role,用来过滤 NameNode、DataNode 和 ResourceManager 的角色。第三层是具体实例的 host,这个变量通常只在排查单节点故障时才会用,日常值班看板不需要它出现在顶部。三层变量的 PromQL 可以设计如下:
# 容量使用率:按集群过滤,汇总所有 NodeManager 实例 sum(hdfs_namesystem_capacity_used{cluster=~"$cluster"}) / sum(hdfs_namesystem_capacity_total{cluster=~"$cluster"}) # 按实例维度看 DataNode 吞吐,方便定位单节点异常 sum by (instance) ( rate(hdfs_datanode_bytes_written{cluster=~"$cluster"}[5m]) )注意变量名后面跟的是=~"$cluster"而不是="$cluster",前者是正则匹配,即使变量多选也能正常工作。如果只选了一个集群,两种写法没有区别;一旦用户在下拉框里勾了多个集群,=就会查不到数据,面板全空。这是模板复用率高低的一个分水岭,很多共享出来的模板就死在这里。
联动设计的另一层是 job 与 role 的关系。Prometheus 里的 job 是抓配置时定义的,role 是静态标签。面板查询时优先用 role 来过滤,而不是用 job。因为 job 的名字可能因为运维习惯不同而改变,比如有人叫hdfs,有人叫hadoop-hdfs,但 role 标签是你在自己的配置里定义的,只要你的模板同时下发抓取配置,role 就永远是可控的。
4.3 核心面板怎么画:容量、吞吐与故障定位三类图
面板类型的选择比想象中重要。HDFS 容量用饼图是很多模板的通病,饼图除了好看没有任何排查价值。容量面板用时间序列的堆叠面积图更实用,横轴是时间,纵轴是字节,可以看到容量增长的趋势和速度。YARN 队列资源用仪表盘或者百分比刻度的时间序列都行,但要保证在容器堆积时颜色变化足够明显。
我这边核心面板的配置经验是:容量面板用stacked模式展示CapacityUsed和CapacityRemaining,这样可以一眼看出集群还能撑多久。吞吐面板用rate()函数包住计数型指标,比如BytesWritten这类计数器,如果不做 rate,图表数字会一直累加,曲线单调递增,几乎没有可读性。YARN 面板用sum by (queue)把队列维度单独画出来,不同队列之间的资源竞争关系能直接从图上看出来。
# HDFS 容量面板核心查询:已用容量与剩余容量堆叠 sum by (role) (hdfs_namesystem_capacity_used{cluster=~"$cluster"}) sum by (role) (hdfs_namesystem_capacity_remaining{cluster=~"$cluster"}) # YARN 队列资源面板:按队列分别展示分配的内存 sum by (queue) ( yarn_queue_allocated_mb{cluster=~"$cluster"} )面板的告警阈值配色也很重要。我习惯把 60% 以下设成绿色,60% 到 85% 设成黄色,85% 以上设成红色。这个阈值不是随便拍的,HDFS 一旦容量到 90% 以上,NameNode 会进入安全模式,很多写操作会直接失败,所以 85% 的告警线已经给运维留了处理时间。YARN 的可用内存低于 20% 时也要及时关注,否则提交的作业会一直卡在 PENDING 状态。
5. Hadoop 监控模板的高频故障排查与避坑指南
5.1 面板全空:指标名对不上与标签匹配失效
现象是导入模板后,所有面板的数据都是 No data,但 Prometheus 里明明能查到数据,Grafana 和 Prometheus 之间的链路也没有断。
这类问题九成出在指标名不匹配。模板里写的查询是hdfs_namesystem_capacity_used,但实际采集到的指标名可能是hdfs_fs_namesystem_capacity_used,中间多了个fs,或者地方发行版改过 MBean 的命名,导致 exporter 输出的指标前缀不一样。排查方法是在 Prometheus 的查询框里输入{cluster=~"$cluster"},把所有指标名列出来,和模板里的 PromQL 逐一比对。这一步虽然机械,但能直接定位问题,比在 Grafana 面板里猜快得多。
另一种常见原因是标签不匹配。模板里变量用的是cluster标签,但 Prometheus 抓取配置里打的是env标签。模板变量下拉框是空的,选无可选,面板自然全空。解决方法是保证抓取配置和模板变量设计出自同一份代码。我在负责模板下发时,会把 prometheus.yml 和 dashboard JSON 放在同一个目录里一起走版本管理,避免两者脱节。
5.2 数据断点与时间戳偏差:不该只怪网络
面板大多数时候正常,偶尔出现一段没有数据的断点,或者曲线在某个时刻突然回落。很多人本能地怀疑是网络抖动或者 exporter 挂了,但排查过后经常发现网络是通的,exporter 也活着。
真正的原因是节点时间不同步。HDFS 集群里的节点如果 NTP 配置有问题,多台机器的时间会慢慢漂移。jmx_exporter 打出的指标时间戳用的是本机时间,Prometheus 抓取时会按时间顺序写入存储。如果某台 DataNode 的时间比 Prometheus 快了几分钟,它上报的数据会被当作未来数据丢弃,造成面板上的间隙。处理办法是把 NTP 同步纳入集群的基础运维项,定时检查各节点与时间源的偏移。
另外一个常见原因是 jmx_exporter 进程因为 OOM 被系统杀掉。exporter 本身很轻,但如果 Java 进程的堆内存设置过小,又长期处理大量 MBean,确实可能崩溃。日志里会看到OutOfMemoryError,进程消失后 systemd 没有自动拉起,面板就会出现持续断点。用 systemd 管理 exporter 进程并配置Restart=always,能避免这个隐患。
5.3 资源开销失控:JMX 抓取对生产集群的隐性压力
捕获到面板全部正常之后容易掉进另一个坑:采集频率设得太快,导致 NameNode 的 JMX 压力过大。NameNode 的 FSNamesystemState 本身是轻量查询,但短时间内高频请求会让垃圾回收变频繁,表现为 NameNode 的 RPC 延迟偶尔飙升。
排查时的现象是集群日常没有大作业,但 NameNode 的监控曲线出现规律性的毛刺。把抓取频率和毛刺出现的时间点对齐后,才知道是采集造成的。解决方法是把 HDFS 的抓取间隔从 15 秒调整到 30 秒甚至 60 秒。容量类指标是慢变量,一分钟的间隔完全够用。YARN 的调度类指标保持 15 秒即可,因为它不涉及 NameNode 的 namespace 锁。
5.4 指标口径不一致:从 byte 到 MB 的换算陷阱
模板在开发环境调得好好的,搬到另一套集群后所有容量数字都放大了 1024 倍或者缩小了 1024 倍。这个坑非常隐蔽,因为它不报错,图表形状也正常,只差一个量级。
原因还是不同 Hadoop 版本对同名的 MBean 属性配备了不同单位。我在 2.2 节建议过先核单位,这里说一个更稳妥的解法:在 jmx_exporter 的配置里用value字段统一换算单位。比如FSNamesystemState下的容量指标统一转成 GB:
rules: - pattern: 'Hadoop:service=NameNode,name=FSNamesystemState' name: hdfs_namesystem_$1 labels: component: "namenode" attrNameSnakeCase: true value: 1 / 1024 / 1024 / 1024value字段会在指标输出前做一次算术变换,这里做了三次除法,把字节除以三个 1024 得到 GB。所有模板查询里直接用 GB 作单位,面板上统一显示成GB,无论底层版本怎么变,展示口径始终一致。这个方法是我在踩过一次单位翻车之后加上的,之后再没因为版本差异调整过面板。
6. 模板上线后必须做的三件事:验证、告警与容量预测
模板导入只是起点,上线后第二天才是真正检验它价值的时候。第一件事是模拟一次故障,验证面板是否真的能反映出异常。常见做法是找一个测试节点,把某个 DataNode 的进程停掉,观察面板上对应实例的曲线是否在几分钟内出现回落。如果面板毫无反应,说明要么抓取目标没配对这个节点,要么查询语句里漏掉了 instance 维度。我在每次上线新模板时都会做这个演练,花十几分钟换一个可靠的监控系统,这笔投入非常划算。
第二件事是配告警规则。模板把状态展示出来了,但人不可能 24 小时盯着屏幕。告警规则要选那些真正需要人工介入的异常,而不是把面板上的每个阈值都变成告警。HDFS 容量超过 85%、UnderReplicatedBlocks 持续增长、YARN PendingContainers 长时间不为 0,这三个是我必配的规则。避免对吞吐类指标做绝对阈值告警,因为读写速率和业务高峰强相关,很容易产生噪音。
# 告警规则示例:HDFS 容量与 YARN 队列积压 groups: - name: hadoop-monitor rules: - alert: HdfsCapacityHigh expr: | sum(hdfs_namesystem_capacity_used) / sum(hdfs_namesystem_capacity_total) > 0.85 for: 30m labels: severity: warning annotations: summary: "HDFS 容量使用率超过 85%" - alert: YarnPendingContainersHigh expr: sum(yarn_cluster_pending_containers) > 200 for: 15m labels: severity: warning第三件事是容量预测。把模板里容量面板的时间范围拉到 90 天,可以清楚地看到容量增长的斜率。用这个斜率做一个简单的线性外推,能估算出集群撑到什么时候需要加节点。相比等容量告警出来再被动响应,这种提前规划的思路要从容得多。我在经历了第一次集群写满的紧急扩容之后,养成了每个月最后一周翻一次容量面板的习惯,顺手把当前容量和去年同期做对比。等到我第三次做这件事时,这个模板已经成了团队值班离不开的工具。最后说一句:模板终究是辅助,它对集群的理解深度,取决于你对指标选型的判断力。希望帮到你。
本文还有配套的精品资源,点击获取