
凌晨两点接到值班电话十有八九没好事。那次是某数据平台的Hadoop集群DataNode磁盘写入告警等我和值班同事爬起来看的时候HDFS副本已经开始掉了NameNode控制台里待复制副本的计数跳个不停。最后折腾了半个多小时才把集群拉回健康状态。事后复盘问题不在磁盘容量本身而在于我们的监控只有CPU、内存、磁盘这类主机指标完全没盯住HDFS副本健康度、块数量、RPC延迟这些真正决定集群生死的数值。那次之后我花了差不多一个月把Hadoop集群的监控与管理工具重新梳理了一遍从采集、存储、展示到告警逐层选型、落地、踩坑。这篇博文就是那段时间的完整记录。如果你正在给自建的Hadoop集群搭一套像样的监控体系或者在做大数据平台、需要替线上集群把把关这篇内容大概率能帮你少走不少弯路。1. Hadoop集群为什么比普通应用服务难监控先理解监控对象1.1 一个集群里到底有多少层需要盯很多人第一次接Hadoop集群习惯性地拿监控Web应用那套经验来套看CPU、看内存、看磁盘、看进程在不在。这套逻辑用在单机服务上没问题放到Hadoop上远远不够。原因很简单Hadoop集群不是一个服务而是一组角色各异、互相依赖的分布式进程它们之间还有跨主机的数据流转和任务调度。我习惯把监控对象分成四层主机层CPU、内存、磁盘、网卡、文件句柄、系统负载。这是基础但只是起点。JVM进程层NameNode、DataNode、ResourceManager、NodeManager、ZooKeeper每个角色都是一个独立JVM。关键指标是堆内存使用率、GC次数、GC暂停时长、线程状态。集群整体状态层HDFS的容量使用率、副本数量、损坏块数、活跃/失活节点数YARN的资源总量、已分配资源、排队应用数。作业/任务层正在跑的任务数、失败任务数、Map/Reduce进度、Shuffle数据量、任务运行时长。这四层之间是联动的。一个DataNode的磁盘写满表面是主机层问题实际会触发HDFS层的副本复制风暴接着拖慢YARN上的MapReduce作业最后业务侧看到的就是任务卡死。如果只盯主机层你看到的永远是最后一个症状而不是第一个原因。1.2 主机巡检救不了你HDFS和YARN的独有指标主机层指标是通用货架商品HDFS和YARN的指标才是Hadoop的定制件。我用一张表总结一下上线监控时必须先覆盖的核心指标层级关键指标典型问题HDFS容量使用率、CapacityRemaining、UnderReplicatedBlocks、DeadNodes、损坏块数磁盘写满、副本丢失、节点失活HDFSNameNode的RPC队列耗时、RPC请求量NameNode过载、业务卡顿YARNAppsPending、AppsRunning、AvailableMB、AvailableVCores、ContainersPending资源不足、任务排队YARNContainerLaunchDuration、节点心跳延迟节点异常、调度缓慢JVM堆内存使用、GC次数、GC暂停时长内存泄漏、Full GC风暴作业失败任务数、运行时长、数据倾斜指标作业异常、业务受影响举个例子UnderReplicatedBlocks——待复制副本数。这个数字长期大于0说明集群的容错能力在下降某个节点再挂就可能丢数据。它在主机层完全看不出来但比磁盘使用率更早提醒你集群正在变脆弱。RPC队列耗时也是同理NameNode的CPU可能看起来正常但请求已经排长队了业务侧的表现就是HDFS操作奇慢无比。理解了监控对象下一步才是选工具。2. 工具选型经验把监控拆成四层来挑别指望一个工具通吃2.1 按采集、存储、展示、告警四层拆解需求我在选型时犯过一个错总想找一个All-in-One的大而全方案把采集、存储、画图、告警全包了。结果要么上手太重要么某个环节特别弱。后来我学乖了先把需求拆成四层每一层单独选型采集层负责从主机和JVM进程里把指标捞出来常见方式有Agent主动上报、服务端主动拉取、JMX协议直采。存储层时序数据存放决定你能回溯多久、查询多快。展示层把指标变成图表让值班的人一眼能看出集群是否健康。告警层根据阈值规则触发通知决定你是在问题爆发前被叫醒还是问题爆发后才知道。这四层拆开之后工具之间的取舍就清晰了。我用下面这张表对比几个主流方向方案采集方式数据模型上手难度适用场景Prometheus全家桶服务端拉取 Exporter指标时序模型中等自建开源Hadoop集群商业发行版自带管理控制台内置Agent上报平台自有指标库较低买了商业版的企业ZabbixAgent主动上报监控项模型中等已有Zabbix基础设施的团队ELK日志方案Journal推送日志为主指标为辅较高强日志分析需求的团队商业发行版自带的管理控制台确实省心装好组件就能看到集群拓扑、节点状态、告警通知Web UI做得也不错。但问题在于扩展性一般想自定义某个业务指标、想统一所有集群的告警出口、想跟已有的监控大盘打通都会被平台限制住。Zabbix在主机层很成熟但对HDFS的块复制状态、YARN的队列资源这类JVM内部指标支持偏弱。ELK本身不是为数值监控设计的硬要用它做指标存储查询灵活性和资源消耗都不划算。2.2 Prometheus这套体系为什么成了主流选择我最终选了Prometheus Grafana Alertmanager这条开源路线核心原因有三点。第一拉取模型符合指标不止属于进程、更属于集群的语义。Prometheus直接从各个Exporter的HTTP端口拉数据不需要在每台机器上维护一个常驻Agent的注册逻辑。新增节点时只要改一下配置文件里的targets就能接入。这个模型对Hadoop这种多角色、多主机的系统特别友好。第二Exporter生态覆盖了我上面说的全部四层。node_exporter管主机层JMX exporter管JVM层HDFS和YARN的指标通过JMX exporter也能掰出来第三方的HDFS Exporter可以直接暴露块复制的关键指标。没有哪个All-in-One方案能在一个被动配置里同时做到这件事。第三Grafana的表达力足够强。Hadoop监控的受众很杂值班运维需要红绿灯式的健康面板容量规划的人需要看趋势曲线开发同学需要看作业运行情况。Grafana一个实例上可以同时维护这几套视角C盘一套模板改改就能用。这些讲清楚了下面直接说落地过程。3. 落地一套够用的监控方案Prometheus Grafana实战记录3.1 先盘点资产画一张角色-端口对照表动手装任何东西之前先把集群资产摸清楚。我当时做了一张表列清楚每台机器跑什么角色、哪些端口对外、监控机能不能打通网络。别小看这一步后面所有Exporter的targets配置、防火墙放行、JVM进程的Agent注入全部依赖这张表。Hadoop 3.x常见的默认端口大致如下NameNode Web UI在9870DataNode在9864ResourceManager在8088NodeManager在8042。如果你用的是Hadoop 2.x可能是50070、50075那一段。注意端口号以你集群实际配置为准不要照抄文档就以为全世界都一样。3.2 主机层接入node_exporter主机层最简单但也最容易拖到最后一刻才做。我当时的做法是从官方release页面下载匹配操作系统架构的二进制包解压后丢到/usr/local/node_exporter目录用systemd托管起来。[Unit] DescriptionNode Exporter Afternetwork.target [Service] ExecStart/usr/local/node_exporter/node_exporter --web.listen-address:9100 Restartalways Usermonitor [Install] WantedBymulti-user.target启动后先别急着配Prometheus先用curl确认一下指标真的在吐curl -s http://localhost:9100/metrics | head -n 20看到node_cpu_seconds_total这类标准指标名说明采集通道已经通了。这一步很多人跳过结果后面折腾半天发现是端口没放行。3.3 JVM层用JMX exporter以javaagent方式注入Hadoop的NameNode、DataNode、ResourceManager、NodeManager都是JVM进程JVM层指标最标准的采集方式就是JMX。Prometheus本身不认JMX的JSON格式所以需要JMX exporter做一道转换。JMX exporter有两种用法的常见坑一种是独立启动一个小服务让它通过JMX远程端口去连目标进程另一种是做成javaagent直接塞进目标JVM里在本地暴露一个HTTP端口。我推荐用javaagent方式省掉配置JMX远程认证的麻烦也让监控端口随进程生灭进程挂了端口自然消失不会留一个僵尸Exporter误导你。在hadoop-env.sh里给不同角色追加各自的javaagent参数export HADOOP_NAMENODE_OPTS-javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent-0.18.0.jar9101:/opt/jmx_exporter/hdfs-jmx.yaml $HADOOP_NAMENODE_OPTS export HADOOP_DATANODE_OPTS-javaagent:/opt/jmx_exporter/jmx_prometheus_javaagent-0.18.0.jar9102:/opt/jmx_exporter/hdfs-jmx.yaml $HADOOP_DATANODE_OPTS这里有一个关键经验不要偷懒让JMX exporter把所有JMX属性全量暴露出来。默认配置会拉出成千上万个Bean属性大部分你根本用不上还白白增加采集开销和时序存储压力。一定要用规则文件做白名单只留你真正要盯的指标。规则文件的语法大致长这样startDelaySeconds: 0 ssl: false rules: - pattern: java.langtypeMemoryHeapMemoryUsage: (.*) name: hadoop_jvm_heap_memory_used iName: hadoop_jvm_heap_memory_used labels: role: $role写规则之前先到对应角色的Web UI JMX端点去看指标的真实Bean名和属性名再照着写pattern别凭记忆硬猜。curl -s http://namenodeHost:9870/jmx?qryHadoop:serviceNameNode,nameFSNamesystemState3.4 配置Prometheus抓取与Grafana展示Prometheus的配置文件我用静态目标列表就够了。集群节点固定没必要上服务发现简单可靠最优先。scrape_interval我设的是30秒既不会给Exporter增加太大压力也足够覆盖节点失活容量超阈值这类分钟级问题。global: scrape_interval: 30s evaluation_interval: 30s scrape_configs: - job_name: hadoop-hosts static_configs: - targets: [node01:9100, node02:9100, node03:9100] - job_name: hadoop-jvm static_configs: - targets: [node01:9101, node01:9102, node02:9101, node02:9102]Grafana那边主机层可以直接找社区里比较成熟的node_exporter大盘模板导入省时省力。HDFS和YARN的展示面板我建议自己搭原因很简单社区模板追求面面俱到面板多到根本看不过来最后你的同事都只看第一块。我自己只保留了五个核心面板集群总览HDFS已用容量、待复制副本数、活跃/失活节点数、YARN运行中的应用数。红绿灯式的一屏速览。容量趋势HDFS容量使用率90天走势用来做扩容决策。JVM健康所有角色的堆内存使用与GC暂停耗时。YARN资源可用/已分配的内存与核数帮助定位资源配额问题。主机水位CPU、负载、磁盘占用辅助排查物理层故障。3.5 告警规则与阈值建议多盯症状少盯漂亮数字告警规则我只列了一部分但思路值得展开说说。Hadoop集群的告警第一原则是宁可少而准不要多而烦。阈值设得太敏感告警疲劳之后真出事反而没人看。我实际用下来的阈值参考如下指标警告阈值严重阈值说明HDFS容量使用率85%持续10分钟92%持续5分钟留出写副本的临时空间失活DataNode数大于0持续5分钟大于1持续5分钟立即排查UnderReplicatedBlocks大于100持续15分钟大于500持续10分钟检查磁盘、网络、进程单节点磁盘使用率85%95%预判DataNode写入故障JVM堆内存使用率85%持续15分钟95%持续5分钟结合GC告警一起看GC暂停时间单次超1秒每分钟多次超1秒Full GC风险信号YARN AvailableVCores占比低于10%持续10分钟低于5%持续10分钟资源饥饿作业排队告警规则的配置长这样groups: - name: hadoop-alerts rules: - alert: HDFSUsageHigh expr: (sum(hadoop_hdfs_capacity_used_bytes) / sum(hadoop_hdfs_capacity_total_bytes)) * 100 85 for: 10m labels: severity: warning annotations: summary: HDFS容量已用超过85% - alert: HDFSUnderReplicatedBlocks expr: sum(hadoop_hdfs_under_replicated_blocks) 100 for: 15m labels: severity: warning annotations: summary: 待复制副本数超过100这里的指标名取决于你在JMX exporter规则文件里起的名字所以再次强调先确认metrics端口的真实指标名再写PromQL。另外for子句一定要用。HDFS在做均衡或者大规模写入了临时高水位时短时间阈值越线很正常持续几分钟才值得报警。4. 告警之后要会接得住管理与自动化是另一半4.1 告警触发了第一步永远是止血然后才是查因工具搭好只算完成了一半另一半是告警触发后有人知道怎么处理。我后来总结了一套简单的分级runbook塞给值班文档里磁盘告警先查最大目录确认是HDFS写入、YARN日志还是本地临时文件导致的清理或扩容禁止在没有确认的情况下删数据。节点失活先检查进程是否存活、磁盘是否只读、网络是否隔离再考虑加入exclude名单走下线流程。副本不足优先检查是否有节点失活、磁盘满导致写入失败先恢复节点或迁移副本不要盲目重启整个集群。YARN资源告警先看是否有异常大作业抢占资源再检查队列配置必要时临时调整队列容量。这份文档一开始是我自己写的后来值班的同事也会补充。它比任何自动化工具都重要因为它定义了一个标准处理路径。4.2 管理自动化三步走清理、均衡、下线监控给你信息管理工具帮你动手。我常用的三个自动化操作都是Hadoop自带命令加脚本封装的。第一定时清理。YARN的容器日志、HDFS回收站是最爱填满磁盘的两大主力。写一个脚本每天低峰期跑一次先扫描出超过设定阈值的目录列表和大小人工确认后再清理。自动化清理我强烈建议分两步走先产出报告再执行删除不要一个cron把rm动作直接挂上去。第二HDFS均衡。数据倾斜会导致部分节点磁盘先满。用balancer在低峰期执行hdfs balancer -threshold 10这个命令会把数据从高占用节点往低占用节点迁移。阈值10表示节点使用率与集群平均值偏差超过10%就触发迁移。执行前先看集群副本是否健康副本没补齐就跑balancer会加重复制压力。第三节点下线流程。不要直接把节点拉闸。正常流程是把主机名写进dfs.hosts.exclude文件执行刷新命令让其进入decommissioning状态系统会把该节点上的副本迁移走等Web UI显示decommissioned后再停进程。整个过程靠副本复制机制保证数据安全抢时间往往是出事故的根源。hdfs dfsadmin -refreshNodes4.3 把监控融入日常运维而不是只在半夜响铃监控体系上线三个月后我发现一个问题告警确实少了但团队对集群的关注也变少了。大盘放在那就是没人主动看。后来我们加了一个机制每天早上一张健康报告通过脚本调Grafana的渲染接口出图推送到团队成员都能看到的内部群。这个微小改变的效果远超预期。大家每天上班先扫一眼报告容量趋势、副本健康度、资源水位一目了然很多问题在变成告警之前就被发现并处理掉了。监控的意义不在于响了再救火而在于每天都有人知道它在什么状态。5. 踩坑实录这套体系上线后碰到的真实问题5.1 scrape频率与JMX采集开销别让监控吃了业务资源上线初期我把scrape_interval设成5秒想着监控越实时越好。结果发现JMX exporter本身对JVM有额外开销每5秒全量把所有HDFS指标翻一遍NameNode的RPC处理都出现了肉眼可见的波动。后来把间隔调到30秒并且用规则文件做了指标白名单只保留核心指标集NameNode的GC曲线立刻平稳了。另外JMX exporter默认会暴露带JVM线程名、线程状态等标签的高基数指标。如果某个时间段线程名组合爆炸Prometheus的内存和存储都会跟着遭殃。做白名单时遇到带name标签、且取值范围不确定的指标优先排除。5.2 时序数据膨胀与存储回收监控上线后Prometheus的本地存储增长比我想象的快得多。原因在于两个一是没有限制指标白名单二是没有设置保留时间。本地时序库默认保留15天对于容量趋势分析来说足够了但如果你没有单独给Prometheus挂一块独立磁盘这15天数据很容易把监控机自己的盘塞满。管理上的做法是给Prometheus单独规划磁盘并把retention时间显式写出来不要依赖默认值。还遇到一种情况是某个label设计不当导致基数爆炸比如把TaskId这样的唯一值放进label。时序数据库最怕高基数一个job每次跑几千个task、每个task一个独特标签组合等于每跑一轮就写几千条序列存储直接翻几倍。5.3 告警疲劳是真的而且会反噬有一段时间告警特别多团队开始把通知静音。后来某天集群真的出事了YARN资源耗尽导致作业大面积失败反而没人第一时间响应。复盘时发现根源是阈值设得太严单节点磁盘使用率75%就开始提示HDFS容量70%就开始警告每天十几个低级别告警大家早就麻木了。修法是分严重级别、合并同类告警。磁盘类、副本类、进程类分别用不同的severity相同根因的告警在Alertmanager里配置抑制规则只发一条最严重的。另外所有告警都加for持续时间短时波动不触发宁可慢5分钟收到一条准的不抢这5分钟收一条假的。5.4 仪表盘没人看等于没搭搭了十几个面板最后日常只有我自己打开看同事根本不知道哪个是入口。后来我把仪表盘收敛到四块并且按用途切分值班健康盘、容量规划盘、作业性能盘、主机排障盘。四块的命名和用途贴在告警runbook里谁接到告警第一件事就知道去哪个盘看什么指标。还有个更实际的经验仪表盘上的每个数字都应该是可操作的。某个面板如果看完了不能告诉你接下来该干什么那这个面板就该删掉。UnderReplicatedBlocks这个数字有用因为它直接关联到要不要重启节点、要不要检查网络的行动而某些看起来炫酷但含义模糊的百分比就该趁早移出去。这套体系从规划到稳定运行花了大概一个多月最深的体会是工具选型其实只是第一步真正起作用的是你盯什么、阈值依据是什么、告警触发后谁来干什么。Prometheus和Grafana的作用是把这三个问题落成可执行的配置而已。如果你也准备动手我的建议是别追求大而全让主机、JVM、HDFS、YARN各上两块核心面板告警不超过五条核心规则先跑起来再在真实运维中慢慢补细节。监控这件事先让人愿意看比什么都重要。