ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Prometheus与Grafana在大数据集群监控中的实战落地

Prometheus与Grafana在大数据集群监控中的实战落地 凌晨一点被电话叫起来不是偶然现象。大数据集群监控这个事做得糙和做得细差别就在半夜那通电话有没有人替你打。Prometheus负责采集和告警判断Grafana负责把指标变成人能一眼看懂的趋势图这套组合已经是开源监控里的默认选项尤其是在Hadoop、HBase、Kafka这类组件混布的大集群里它的轻量、易扩展、查询灵活比传统监控方案省心不少。这篇文章不是简单贴一份配置文件而是把我在多个生产集群里落地Prometheus和Grafana的过程拆开讲。适合刚接手集群监控、想从零搭一套可用体系的人也适合已经装了但告警乱响、大盘不会配的运维朋友。我会尽量把每一步的为什么也讲清楚因为只抄配置不改理解换个环境就又会踩坑。1. 这套监控组合的选型逻辑为什么是Prometheus和Grafana1.1 大数据集群监控到底监控什么先校准一个概念。大数据集群监控不是装个工具看CPU和内存就完事它的核心目标有三个第一在用户感知之前发现异常第二在故障发生后能快速定位是哪一层出了问题第三为扩容、调优、故障复盘提供历史数据。围绕这三个目标监控对象至少拆成四层。基础设施层包括CPU、内存、磁盘、网络、温度这些物理资源集群服务层包括HDFS的容量与DataNode存活数、YARN的资源池与队列状态、HBase的RegionServer堆内存和请求延迟中间件层包括ZooKeeper的连接数、Kafka的分区堆积、Hive Metastore的会话数再往上是应用作业层比如MapReduce和Spark任务的运行状态、失败率、运行时长。大多数团队一开始只盯第一层等集群真的出了事才发现主机指标正常但服务已经卡死很久了。所以我通常建议监控体系先按这个分层规划再决定采集什么指标。Prometheus的拉取模型非常适合这种分层采集每层通过exporter暴露指标统一被Prometheus抓取不需要在各个节点上装一堆agent和中心端保持心跳。1.2 与Zabbix等传统方案的差异我早期也用过Zabbix不是说它不行而是在大数据场景里有几个地方比较别扭。Zabbix的核心模型是模板触发器适合监控已知、稳定、变化缓慢的对象比如网络设备、服务器硬件状态。但大数据集群的节点会经常变扩容缩容、角色调整、组件升级都意味着监控对象的生命周期变化很快Zabbix的自动发现虽然能做但配置面和维护量都不小。Prometheus不一样核心是服务发现标签。Exporter只要在某个端口上提供/metricsPrometheus就能通过静态配置或文件发现把它拉进来。每个被监控对象以一组标签区分比如instancenode-01:9100、roledatanode告警规则和Grafana面板都基于标签做聚合扩缩容之后这些逻辑基本不用改。Grafana在这套组合里主要负责可视化。它本身不存储监控数据只是从Prometheus查询数据并渲染成图。PromQL查询语言比Zabbix的聚合函数灵活得多rate、histogram_quantile、topk这些函数能直接解决过去5分钟QPS趋势99分位延迟是多少这种问题。Zabbix不是做不到但配置过程繁琐得多尤其在多集群、多维度的场景下。1.3 整体架构的主线用一句话概括整体架构各类exporter暴露指标Prometheus按周期拉取并存储Alertmanager消费告警规则触发的通知Grafana从Prometheus查数据做可视化。组件之间的职责边界非常清晰。Prometheus负责采集和判断它的配置文件里既有抓取目标列表也有告警规则但告警通知的发送邮件、企业微信、钉钉、Webhook由Alertmanager统一处理它负责去重、分组、静默和路由。Grafana不参与判断逻辑只负责把时间序列数据画出来。这个架构还有一个好处每一层都能独立替换。今天用本地磁盘存储明天想接远程存储改的是Prometheus的启动参数今天用邮件告警明天换企业微信机器人改的是Alertmanager的路由配置。对于运维团队来说架构的演进成本低比all-in-one方案稳得多。2. 搭起第一块基石Prometheus的部署与核心配置2.1 二进制方式部署与systemd管理很多教程一上来就推荐Docker或Helm部署但我在生产环境更习惯先用手工二进制方式落一遍原因很简单排查问题的时候你能清清楚楚知道每个文件在哪、进程在哪、日志在哪。部署步骤不复杂。从Prometheus官网下载合适的版本这里建议选最新的稳定版--version那个包就是预编译的二进制。解压后目录里最核心的是prometheus.yml和prometheus可执行文件。把整个目录放到/opt/prometheus下数据目录单独指定到/data/prometheus避免和程序目录混在一起。然后写一个systemd unit文件让它在后台常驻[Unit] DescriptionPrometheus Server Documentationhttps://prometheus.io/docs/introduction/overview/ Afternetwork-online.target [Service] Userprometheus Groupprometheus Typesimple ExecStart/opt/prometheus/prometheus \ --config.file/opt/prometheus/prometheus.yml \ --storage.tsdb.path/data/prometheus \ --storage.tsdb.retention.time15d \ --web.listen-address:9090 Restarton-failure [Install] WantedBymulti-user.target这里几个启动参数要展开说。--storage.tsdb.retention.time15d是数据保留时间15天适合大多数分析场景既能看到每周同比又不至于把磁盘撑爆。--web.listen-address默认就是9090但建议显式写出来方便以后改端口。还有一个参数我没写进unit但经常用--web.enable-lifecycle加上之后可以通过curl -X POST http://localhost:9090/-/reload热加载配置不需要重启进程。启动之前先把目录权限给对useradd --no-create-home --shell /usr/sbin/nologin prometheus然后chown -R prometheus:prometheus /opt/prometheus /data/prometheus。这一步极其容易漏漏了之后服务会直接启动失败报错是permission denied。2.2 prometheus.yml全局配置与抓取任务Prometheus的核心配置都写在prometheus.yml里结构分三块全局配置global、告警规则文件rule_files、抓取任务scrape_configs。新手初期只关心global和scrape_configs就够了。一段最简单的配置长这样global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: prometheus static_configs: - targets: [localhost:9090]scrape_interval是Prometheus多久去拉一次指标。15秒是默认值对大多数集群监控都够用。如果某些exporter的数据量特别大比如HDFS的JMX exporter可以单独在job里覆盖这个间隔改成30秒给TSDB和网络都省点压力。evaluation_interval是告警规则多久被评估一次。这个参数经常被忽略但它直接决定告警触发的延迟15秒的评估周期意味着一条规则最长可能延迟15秒才被触发。像节点宕机这种严重告警evaluation_interval可以单独设成10秒但要承受一点CPU开销。2.3 数据保留与存储容量的估算Prometheus的默认本地存储是TSDB写入的是压缩后的样本数据。容量估算有个常见公式每秒写入样本数 × 样本大小 × 保留秒数。一个样本在内存和磁盘上大约占1到2字节再叠加索引和WAL开销实际可以用一个粗略系数来估算。我习惯按每个exporter每秒产生100~300个序列来算一个上百节点的大数据集群长期跑下来每秒新增样本大约在2万到5万个之间。这样15天数据量大概是几十GB到一两百GB。计算公式是2.5万样本/秒 × 86400秒/天 × 15天 × 平均2字节/样本得到约65GB。这个估算的意思是监控数据隔一段时间一定会涨所以数据盘要跟系统盘分开。我见过太多把TSDB放在根分区导致根分区写满的例子轻则监控失效重则拖垮整个节点。建议单独挂一块数据盘保留空间至少按估算值的两倍规划。3. 把集群的脉搏接进来大数据组件指标采集梳理3.1 主机层指标node_exporter铺底主机层指标是监控的地基不管上面跑了多少个大数据组件先保证每台物理机的CPU、内存、磁盘、网络都有数。这一步通常用node_exporter来完成。node_exporter安装简单二进制解压就能跑默认监听9100端口。它暴露的指标覆盖了node_cpu_seconds_total、node_memory_MemTotal_bytes、node_filesystem_avail_bytes、node_network_receive_bytes_total等等足够覆盖日常排查。部署时要注意三个细节。第一--collector.textfile.directory参数可以指定一个目录让node_exporter定期读取里面的txt文件作为附加指标。这个功能很实用比如crontab里每天生成的磁盘inode信息、集群角色标签都可以丢到textfile里省得单独写exporter。第二node_exporter进程最好用独立用户跑不要用root。第三9100端口不要暴露到公网它的/metrics没有任何鉴权被扫描到就相当于把主机状态免费送人。我在生产环境通常在scrape_configs里给主机任务打上机型和业务标签- job_name: node_exporter static_configs: - targets: - node-01:9100 - node-02:9100 labels: role: hadoop-worker这些标签后面会用到。比如Grafana面板按role分组展示不同角色节点的负载告警规则按role区分告警收件人都是靠这里打下去的标签。3.2 Hadoop生态的指标来源JMX与专用exporter大数据组件基本都基于JVM所以指标来源主要绕不开JMX。每种组件的做法略有差别HDFS NameNode和DataNode可以用jmx_exporter启动Java agent暴露HDFS的容量、块数量、DataNode状态。官方现在也提供Hadoop exporter但从我实践经验看jmx_exporter更通用一个agent搞定所有JVM进程。YARN ResourceManager和NodeManager关键指标是可用CPU和内存、活跃NodeManager数、队列中的等待应用数。这些都能通过JMX拿。HBase RegionServer堆内存使用、Region数量、MemStore大小、请求延迟都在JMX MBean里。KafkaKafka自己暴露了一套/metrics端点配合kafka_exporter或者JMX方式都可以。对于新版本KafkaPrometheus的端点更省事。ZooKeeper有官方提供的zookeeper_exporter连接数、znode数量、延迟等都有。每个exporter的本质都是把一个组件内部的计数器、Gauge、Histogram翻译成Prometheus的文本格式。比如jmx_exporter的配置里要指定一个rules文件把Java MBean的名字映射成指标名。这部分配置啰嗦但非常重要我把una HDFS NameNode的jmx规则文件单独抽出来维护在git里因为组件升级后MBean路径可能变出问题好回滚。举一个典型的jmx_exporter配置片段rules: - pattern: Hadoop:serviceNameNode,nameNameNodeInfo name: hadoop_namenode_info labels: component: namenode attrNameSnakeCase: true - pattern: Hadoop:serviceNameNode,nameFSNamesystemState name: hadoop_fs_namesystem_state labels: component: namenode attrNameSnakeCase: true这样抓出来的指标名类似hadoop_namenode_info_blocks_total后面写PromQL和Grafana面板时非常好用。3.3 让抓取列表可维护标签、任务分组与文件自动发现集群规模大了之后维护一个静态targets列表会变得痛苦。扩容一个DataNode就要改Prometheus配置还必须热加载。这个操作虽然不难但容易漏漏了节点就变黑盒。我的做法是用文件自动发现。Prometheus支持file_sd_configs可以指定一个目录Prometheus每隔一段时间默认5分钟重新读取该目录下的JSON或YAML文件。脚本或配置管理工具Ansible、SaltStack等只要负责生成这个文件即可。- job_name: node_exporter file_sd_configs: - files: - /opt/prometheus/sd/node_exporter.yml refresh_interval: 30ssd/node_exporter.yml内容- targets: - node-01:9100 - node-02:9100 labels: role: hadoop-worker - targets: - edge-01:9100 labels: role: edge-node文件自动发现还有一个好处告警和面板不需要跟着节点清单走。dashboard里只需要按角色筛选新增节点会自动出现在对应分组里不需要复制变更。4. 从指标到可视化Grafana配置与看板搭建4.1 数据源接入与常见配置项Prometheus装好、指标也采上来了接下来就是把数据画出来。Grafana安装同样很简单软件源或二进制都行默认监听3000端口。第一次打开会要求设置管理员账号密码这步别用默认的admin/admin哪怕内网环境也建议改掉因为Grafana有插件和执行查询的能力被改了配置很危险。进入Grafana后第一步是配置数据源。在Configuration - Data sources里选择Prometheus填写URL为http://localhost:9090。有几个要留意的配置项Scrape interval最好填Prometheus的实际抓取间隔也就是15s这样面板在计算时间范围时能对齐采样点避免画出稀疏的锯齿状曲线HTTP Method建议选POST因为复杂PromQL请求用GET可能会超出URL长度限制。数据源配好后可以先用Explore页面验证连通性输入一条最简单的查询up回车后如果能看到一系列值为1和0的时间序列就说明链路通了。4.2 用PromQL把指标翻译成趋势图Grafana面板上的每一块图背后都是一条PromQL查询。新手容易犯的错是把原始指标直接画出来结果图出来是单调递增的计数器看不出任何趋势。比如node_network_receive_bytes_total直接画出来就是一条一直向上的线没法判断当前网络速率。正确的写法是使用rate()函数计算每秒增量rate(node_network_receive_bytes_total{instancenode-01:9100}[5m])这条查询表示看过去5分钟窗口内网卡平均每秒接收多少字节。rate在画趋势图时基本是必须的因为计数器只增不减只有取速率才有意义。再看内存和CPU的例子100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100)这是CPU使用率通过把idle状态的CPU时间占比算出来再用100减掉得到使用率。内存使用率更简单(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100HDFS容量使用率可以这么查(hadoop_namenode_info_capacity_used_bytes / hadoop_namenode_info_capacity_total_bytes) * 100画图时建议把Y轴单位设置成数据单位Grafana支持自动转换比如bytes会自动显示成KB/MB/GB这样读图更直观。4.3 面板变量与大盘导入导出的实践方法一个大数据集群往往有几十台节点如果给每台机器都单独建面板维护起来就是灾难。正确的做法是使用Grafana的Dashboard变量让一个面板可以通过下拉框切换节点。在Dashboard Settings - Variables里添加一个变量比如nodeQuery类型填PromQL查询语句label_values(node_uname_info, instance)这样下拉框会自动列出所有上报过node_uname_info的节点面板里的查询只要改成{$node}就能动态切换。更粗粒度的场景可以在变量里用label_values(node_uname_info, nodename)按主机名分组。面板的导入导出也是一个很实用的功能。Grafana支持导出整个Dashboard为JSON文件这些JSON文件可以放进git仓库跟着集群配置一起做版本管理。搜索面板时Grafana官方社区已经有大量成熟模板比如Node Exporter Full、HDFS、Kafka等大盘搜到后直接Import填入数据源ID或名称就能用。有个从实际中总结的细节导入别人面板后一定要检查数据源名称是否和你的数据源一致。很多面板默认数据源叫Prometheus如果你的叫Prometheus-1导入后所有图都会显示No data。在导入面板时选择正确的数据源即可这也是新手最常见的困惑来源。5. 让监控主动说话告警规则与Alertmanager触达5.1 告警规则怎么写才不会被误报疲劳击垮监控的最终目的是让人在出事之前动手处理。如果没有告警Grafana画得再漂亮也只是一块透着绿光的展示屏。但告警规则设计得不好比没有告警更糟——半夜被一堆无关紧要的恢复通知轰炸之后第二天真正的故障来了反而没人看。告警规则写在Prometheus里用独立文件管理。一条规则至少包含三部分告警名alert、表达式expr、持续时间for。for的意义很关键它表示条件持续多久才触发用来过滤瞬时抖动。比如CPU使用率超过90%持续5分钟才告警就不会因为一次系统调用卡顿而误报。一条典型的节点存活告警groups: - name: node_alerts rules: - alert: NodeDown expr: up{jobnode_exporter} 0 for: 2m labels: severity: critical annotations: summary: 节点 {{ $labels.instance }} 已下线 description: 节点已连续2分钟无法抓取请立即检查网络和主机状态。表达式up 0表示Prometheus抓取目标失败。up是每个job默认带的一个指标值为1表示抓取成功0表示失败。再看一个磁盘使用率告警node_filesystem_avail_bytes{fstype~ext4|xfs} / node_filesystem_size_bytes{fstype~ext4|xfs} * 100 15这里要把tmpfs、overlay这些伪文件系统过滤掉否则磁盘告警会被一堆无关挂载点刷屏。告警规则数量要克制我建议第一批只加严重且明确的规则节点宕机、磁盘将满、HDFS容量告急、YARN的可用资源过低、关键进程JVM堆内存连续升高。告警太多人心会疲。5.2 Alertmanager的接收端配置Prometheus本身不负责发邮件它把命中的告警推给Alertmanager。Alertmanager负责统一去重、分组、静默、路由再转发给不同接收端。生产上最常用的是邮件、企业微信机器人、钉钉机器人、Webhook。Alertmanager配置文件alertmanager.yml核心结构route: group_by: [alertname, job] group_wait: 10s group_interval: 2m repeat_interval: 4h receiver: email-admin receivers: - name: email-admin email_configs: - to: opsexample.com from: alertexample.com smarthost: smtp.example.com:25 auth_username: alert auth_password: secretgroup_by决定哪些告警合并成一条通知比如所有NodeDown告警会合并成一条列出具体节点清单而不是一台一台刷屏。repeat_interval表示如果告警一直没恢复隔多久重新提醒一次一般设4到8小时避免持续轰炸。邮件部署不复杂但企业微信或钉钉机器人体验更好。它们的Webhook集成其实就是HTTP POSTAlertmanager支持webhook_configs把告警内容发给机器人API再由机器人发到群聊里。我在实际使用中更偏好这种方式因为群消息比邮件更容易被即时看到。5.3 从触发到恢复的完整告警生命周期Prometheus告警的状态流转值得解释一下因为很多人看到PENDING和FIRING会懵。一条告警规则在每个评估周期被计算一次表达式为真时进入PENDING状态持续为真达到for指定的时间后进入FIRING状态这时Alertmanager才收到通知表达式恢复为假后告警进入INACTIVE状态Alertmanager会发送恢复通知。所以你会看到一条节点宕机告警在PM2:00触发但通知可能PM2:07才发出其中2分钟是for窗口5分钟是Alertmanager路由处理和相关延迟。这个设计是故意的给临时故障一个自我修复的窗口避免频繁误报。告警恢复通知本身也很重要但要注意去重。Alertmanager默认会为恢复消息独立生成通知如果不想让恢复消息打扰深夜值守的人可以把恢复通知的路由单独指向一个低优先级接收端。6. 上线后的排障手记真实踩坑与验证方法6.1 抓取目标全down先从时间戳和网络查起第一套监控上线最常遇到的现象是Grafana里所有图都是No data打开Prometheus的Targets页面一堆目标红色DOWN。这时候不要急着怀疑配置按顺序排查三件事。第一Prometheus服务器到目标机器的网络通不通。最简单的方式是curl http://目标IP:端口/metrics如果curl通而Prometheus抓取失败大概率是权限或防火墙问题。第二时间是否同步。Prometheus抓取时对数据的时间戳有容忍度如果目标节点时钟偏了好几分钟就会导致样本被丢弃。大数据集群本身通常要求NTP同步但偶尔有节点漂出来值得查一下timedatectl。第三exporter进程是否真的活着。我用systemd挂了一堆exporter有时候启停顺序不对服务起来了但exporter没起来Targets页面会一直显示DOWN直到下一次抓取。注意一个小细节点击Targets页面里的Endpoint链接浏览器可以直接打开/metrics。如果浏览器能打开Prometheus抓不到那问题基本出在Prometheus服务器到目标的网络或认证上。6.2 磁盘被TSDB占满存储增长的复盘这是所有Prometheus长期运行后都会遇到的一堵墙。TSDB的数据文件是分块的每个block大约两小时默认保留时间之外的数据会被后台任务删除。但block合并和删除是异步的如果写入速率过高磁盘占用可能在一段时间内明显高于估算值。我遇到过一次节点扩容后加了20台exporter抓取量翻倍但保留期没有调低结果数据盘三天内从40%涨到95%。复盘后做了两个调整一是为高频job单独设置更长的抓取间隔比如30秒或60秒二是把保留时间从15天降到7天因为旧数据很少再用到了。平时要盯一下这个指标prometheus_tsdb_head_series它表示当前内存中活跃的时间序列数量。如果这个值持续上涨说明新增了某个不稳定的高基数标签比如把UUID或IP完整段当成标签这会急剧放大存储压力。6.3 Grafana图出现锯齿与断点采集间隔和查询窗口的影响Grafana面板上的图出现锯齿状或者时有断点不一定是指标本身有问题很可能是查询窗口和采集间隔不匹配。Prometheus的rate函数需要指定一个[5m]这样的窗口如果这个窗口小于两个抓取间隔就可能出现窗口内样本不足计算出0或空值。比如某exporter的抓取间隔是30秒你画趋势图时用[1m]窗口通常够用但如果某个时间点抓取刚好抖动[1m]窗口内可能只有一个样本rate就会显得不平滑。建议查询窗口至少是抓取间隔的5倍以上比如抓取间隔15秒查询窗口至少用[5m]。这样画出来的曲线更平滑也更接近真实趋势。断点还有一类原因是目标短暂不可达比如节点重启、网络抖动。这时up指标会短暂为0对应时间点的数据就是空的。要区分是采集断点还是查询问题直接回到Explore里用最小步长查原始指标如果原始数据有断点那是采集链路问题如果原始数据连续而面板有断点那是查询函数或时间范围的问题。6.4 压测验证监控是否真的有效监控搭建完不能只看绿灯要故意制造故障来验证。整个过程听起来有点吓人但很有必要。我习惯在业务低峰期做一次小规模演练。先看告警链路手动停掉一个node_exporter进程观察Targets页面状态再确认Alertmanager是否收到NodeDown告警各大盘是否出现断点。这验证的是从采集到告警的完整链路。再看指标正确性用dd写一个临时文件占满磁盘到某个比例确认磁盘使用率曲线和告警阈值是否符合预期。最后看Grafana在Explore里用压测产生的数据验证PromQL确认图表的Y轴单位和聚合逻辑没写错。做过这些验证之后这套监控系统才算真正可信。否则图上显示一切正常真到故障来临时才发现告警根本没发出去那才是最大的事故。我个人在实际配置中还有一个习惯把所有配置文件和面板JSON都纳入git管理每次变更都留记录。Prometheus配置热加载、Alertmanager配置重载、Grafana面板导出这些操作都能在分钟级完成回滚。监控是支撑系统不是一次性项目维护和扩展才是常态。把这些基础打牢后面接再多的组件和告警源也只是往这个框架里添砖加瓦。
返回列表