ARTICLE DETAIL

资讯详情

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

用Grafana+Infinity重做Ambari监控面板:免后端取数实战

用Grafana+Infinity重做Ambari监控面板:免后端取数实战 1. 为什么一定要用 Grafana 重做 Ambari 的监控看板先说个场景。你在维护一套带有 Ambari 的 Hadoop 集群Ambari Web UI 里确实能看到 CPU、内存、HDFS 容量、YARN 应用数但真正用起来会很难受时间粒度只能跟着 UI 的固定选项走想同时对比 HDFS 已用容量和剩余容量要来回切页面更别说把多个服务指标叠到同一张图里观察因果。Ambari 自带的监控面板更像是能看离好用差得很远。Ambari-Metrics 本身就是一套独立运行的指标采集服务它会从集群各节点收集 CPU、内存、磁盘、HDFS、YARN、HBase 等组件的指标并对外暴露 HTTP 接口默认端口是 6188。也就是说数据一直都在只是 Ambari Web UI 替我们画了一部分图而已。如果我们能直接从这个 HTTP 接口取数再交给 Grafana 做面板和告警等于绕过了 Ambari UI 的限制自由度会大很多。Grafana 这边的关键角色是 Infinity 数据源插件。它允许我们在不写后端服务的情况下把任意返回 JSON 的 REST 接口直接变成 Grafana 可视化数据源。放在这个场景里就是Grafana - Infinity - Ambari-Metrics Collector 的 6188 接口一步到位。相比自己写一个 Grafana 数据源插件或额外接一套 Prometheus这个组合可以把搭建时间压缩到半小时以内特别适合快速做 DEMO、临时验证、向团队展示监控效果。这篇博文适合两类人一类是天天面对 Ambari 集群但不想再引入新组件的运维工程师另一类是想学习 Grafana Infinity 这套免后端取数玩法的开发者。我会按先看接口、再配数据源、最后搭面板的顺序完整走一遍并把我在实际操作中遇到的时间戳、JSON 解析、宏替换等问题一并写出来。2. 动手前先摸清 Ambari-Metrics Collector 的 API 长相很多人第一次接触 Ambari-Metrics都是直接去 Grafana 里配插件配完发现拉到一堆解析错误原因就是没先单独验证接口。Infinity 本质上是在替我们发 HTTP 请求所以接口本身必须能通、参数必须对后面这一切才成立。2.1 核心接口与关键参数Ambari-Metrics Collector 对外提供的是 Hadoop Timeline 风格的 REST API核心路径是http://AMS_HOST:6188/ws/v1/timeline/metrics其中AMS_HOST通常是部署 Ambari Metrics Collector 的那台服务器不是随便哪台 NameNode 或 DataNode。生产环境里如果集群开启了 Kerberos 认证请求还需要带认证信息内网快速验证时Ambari 默认配置下通常可以直接访问。这个接口常用的查询参数如下参数说明典型值metricName指标名可逗号分隔传多个cpu_user, cpu_idleappId指标所属应用的标识HOST、HDFS、YARN、HBASEhostname主机名不传通常代表聚合整个集群hadoop001 或留空startTime开始时间Unix 毫秒时间戳1690000000000endTime结束时间Unix 毫秒时间戳1690003600000precision数据点聚合粒度单位秒60、300、3600一个容易被忽略的点是precision。AMS 收集原始指标之后会根据时间维度做聚合precision60表示返回 1 分钟一个点precision3600表示返回 1 小时一个点。如果不传或者传得不合适要么数据点爆炸要么曲线锯齿严重所以后面配置 Infinity 查询时我习惯把precision和 Grafana 面板的$__interval绑定。2.2 先 curl 一下再往下走我强烈建议在浏览器或命令行先验证一次。比如要看整个集群的 HDFS 已用容量可以这么试curl -s http://AMS_HOST:6188/ws/v1/timeline/metrics?metricNamedfs_capacity_usedappIdHDFSstartTime1690000000000endTime1690003600000precision300 | jq .正常情况下返回的 JSON 大致长这样[ { metricname: dfs_capacity_used, appid: HDFS, instanceid: hadoop001.hadoop.com, starttime: 1690000000000, metrics: [ { timestamp: 1690000000000, value: 1024000000 }, { timestamp: 1690000300000, value: 1024005000 } ] } ]也就是一个数组每个元素里metricname是指标名appid是应用标识instanceid是数据来源主机metrics这个数组里装的才是真正的时序数据其中value在 JSON 里往往是字符串后面在 Infinity 里要转成数字才能绘图。这一步很关键你只有亲眼看到返回结构才能知道 Infinity 里的rows路径怎么写。不要凭记忆猜。2.3 指标名去哪查Ambari 里指标名非常多不同版本还会有差异。最稳妥的办法是去 Ambari Server 的 Metrics Collector 页面上看或者直接在 AMS 接口里模糊查。我常用的方式是把metricName换成可能的关键字比如:curl -s http://AMS_HOST:6188/ws/v1/timeline/metrics?metricNamedfsappIdHDFSstartTime毫秒endTime毫秒precision3600 | jq .[].metricname | sort -u有的环境里这个接口只要任意给一个不存在的指标名就能返回相近列表有的环境则需要靠 Ambari 页面里Metrics标签页辅助。总之遇到no data或者empty response时不要先怀疑 Infinity先怀疑指标名。3. Grafana 安装 Infinity并把 AMS 配成数据源3.1 插件安装两种方式Infinity 插件的仓库 ID 是yesoreyeram-infinity-datasource。如果你用的是 Grafana 官方安装包的环境命令行直接装就行grafana cli plugins install yesoreyeram-infinity-datasource systemctl restart grafana-server如果是 Docker 方式跑的 Grafana可以用环境变量预装插件docker run -d \ --namegrafana \ -p 3000:3000 \ -e GF_INSTALL_PLUGINSyesoreyeram-infinity-datasource \ grafana/grafana:latest装完去 Grafana 的Administration - Plugins里确认一下插件状态是 enabled。插件版本不同界面字段会有细节差异但总体的查询模型没有变。3.2 数据源配置要点进入 Configuration - Data sources - Add data source搜索Infinity。我习惯把数据源名称命名为Ambari Infinity方便后面在面板里区分。配置项里最重要的几个配置项推荐值说明NameAmbari Infinity自定义URLhttp://AMS_HOST:6188作为默认 URL后续查询里可以再覆盖AuthenticationNone 或 Basic Auth内网快速验证用 None生产按需开启Allowed Hostshttp://AMS_HOST:6188如果设置了默认 URL建议加上白名单Default URL勾选启用让查询只写路径部分即可配完点 Save testGrafana 会发一个探活请求。如果返回 JSON 数组或至少没报连接失败基本就通了。这里有个小提示数据源页面的 URL 如果填了http://AMS_HOST:6188后续 Infinity 查询里可以只写/ws/v1/timeline/metrics?...这种相对路径。但如果你在查询里写全路径插件会优先使用全路径。我个人的习惯是数据源里配默认地址查询里只写路径这样以后换集群地址只需要改一处。3.3 统一时区避免时间偏移AMS 返回的时间戳本身是绝对时间但 Grafana 面板左上角有时区设置。如果 Grafana 用的是本地时区而 AMS 集群跑在 UTC看起来曲线会偏移 8 个小时。DEMO 阶段为了省事直接在仪表板设置里把时区固定成 UTC等确认数据对上了再切换成自己熟悉的时区。4. 用 Infinity 查询编辑器把 REST 响应变成可绘图的时间序列很多人在这一步卡住。其实 Infinity 插件并不复杂关键是搞清楚它面对一份 JSON 时如何选行和选列。4.1 Infinity 查询的基本套路新建一个 Panel 后数据源选择Ambari Infinity然后会看到查询编辑器。核心字段通常是这几个Query Type: JSON URL: /ws/v1/timeline/metrics?metricNamecpu_userappIdHOSTstartTime$__fromendTime$__toprecision300 Parser: UQL 或 Backend Rows: [*].metrics[*] Columns: 这里写字段映射Rows表示从 JSON 里取哪些节点作为一行。以 AMS 返回结构为例最外层是数组数组每个元素里又有一个metrics数组真正包含timestamp和value的是最里层。所以我常用的 Rows 路径是[*].metrics[*]意思很直白先遍历最外层再展开每个对象的metrics数组。这样每一行就对应一个{ timestamp, value }对象。Columns是用来把行里的字段映射成 Grafana 面板字段的。常用的写法类似timestamp - time value - value有的插件版本是自动识别字段有的则需要手动加。如果自动识别出来没有正确转换就手动写映射。4.2 UQL 和字段提取的常见写法Infinity 在较新版本里提供了 UQL 这种过滤语言。假如你想直接过滤某个指标名并把 value 转成数字可以这样写rows [*].metrics[*] | { time: .timestamp, value: number(.value), metricname: .metricname }但要注意[*].metrics[*]取出内层对象后metricname在外层如果像我上面那样直接取能取到吗不同版本 Infinity 对上下文的处理不太一样。我在实际项目中更稳妥的写法是先在 Rows 里把外层信息带下来再展开内层例如rows [*] | { metricname: .metricname, instances: .metrics[*] } rows .instances[] | { time: .timestamp, value: number(.value), metricname: upper(.metricname) }整体思路就是先把外层字段保存成临时字段再展开内层数组。如果你用的 Infinity 版本界面不支持这么复杂的 UQL也没关系退回到最原始的[*].metrics[*]然后在 Columns 里手动补一个常量字段或者干脆用外层数组 index 区分多个序列。4.3 时间宏的传递Grafana 面板的时间范围会通过$__from和$__to传给查询。AMS 需要的是 Unix 毫秒时间戳Grafana 在 Infinity 里把这些宏解析出来时一般也是毫秒所以可以直接拼startTime$__fromendTime$__to如果你想按 Grafana 的 Interval 变量动态决定聚合粒度可以用precision$__interval不过有个细节Grafana 的$__interval会是类似30s、5m的可读格式AMS 要的是秒数所以更稳妥的方式是使用 Infinity 支持的$__interval_ms之类的毫秒宏并自己除以 1000或者直接在 URL 里写死成60。DEMO 阶段写死 60 完全够用等产品化时再优化成动态。列一个能直接抄的查询配置模板配置示例Query TypeJSONURL/ws/v1/timeline/metrics?metricName${metric}appId${appId}startTime$__fromendTime$__toprecision60Rows[*].metrics[*]Columnstimestamp映射 timevalue映射 value有了这个模板一个指标就能出图了。下面进入实操。5. 实战演练从零拼出一个 Ambari 集群监控面板这个部分我会带着你完整拼 3 个 PanelCPU 使用率、HDFS 容量、YARN 应用数。都跑通之后你就拥有一套可以由点及面的 AMS 监控 DEMO 看板。5.1 先建仪表板和下拉变量新建 Dashboard名字叫Ambari Metrics DEMO。先不要急着一个画图先去 Dashboard Settings - Variables 里加两个模板变量这样面板才能灵活切换。变量 1Name: appId Label: 应用 Type: Custom Values: HOST, HDFS, YARN变量 2Name: metric Label: 指标 Type: Custom Values: cpu_user, mem_free, dfs_capacity_used, dfs_capacity_remaining, YarnMetrics.RunningApps自定义变量的好处是 DEMO 阶段不依赖 Grafana 去探测真实指标名避免因为接口权限或指标名差异直接导致下拉列表为空。5.2 Panel 1HDFS 容量趋势这是最直观的一个面板。查询配置如下Query Type: JSON URL: /ws/v1/timeline/metrics?metricNamedfs_capacity_used,dfs_capacity_remainingappIdHDFSstartTime$__fromendTime$__toprecision300 Rows: [*].metrics[*] Columns: timestamp - time value - value Result format: Time series这里用逗号同时传两个指标名AMS 会把两个指标都返回来。但问题在于Infinity 怎么区分两条时间序列默认情况下里层metrics数组展开后只有timestamp和value面板区分序列名会很吃力所有点可能串在一起。解决办法是让 Rows 多保留一层外层信息。我的经验是直接用这样的 UQLrows [*].metrics[*] | { time: .timestamp, value: number(.value), metricname: upper(.metricname) }如果你的插件版本支持metricname上下文透传那序列名就会自动带上DFS_CAPACITY_USED和DFS_CAPACITY_REMAINING。如果不支持就在 Columns 里手动增加一个metricname字段并选择对应的外层路径这需要试验一次。面板的Unit建议选择bytes这样 Y 轴会自动显示 TB/GB而不是一串裸数字。Legend 里开启Last能在图例上直接看到最新值。5.3 Panel 2CPU 用户态利用率CPU 指标在 Ambari 里很常见但要注意cpu_user这个指标在部分版本里表示的是累计 CPU 时间或百分比需要看具体口径。我建议把它当作用户态 CPU 使用百分比来展示如果发现数值不符合常识就去 AMS 原始返回里核对单位。查询配置Query Type: JSON URL: /ws/v1/timeline/metrics?metricNamecpu_userappIdHOSTstartTime$__fromendTime$__toprecision60 Rows: [*].metrics[*] Columns: timestamp - time value - value Result format: Time series如果集群里有多台机器AMS 默认返回的是每条主机一个对象。展开后会在同一个图里看到很多条线。这是好事但 DEMO 阶段可以先在查询里加上hostname你某个节点名把范围缩小等确认图没问题后再放开到全集群。CPU 面板的Unit选择percentMin填 0Max填 100看起来更符合直觉。5.4 Panel 3YARN 运行中应用数YARN 的指标名在不同 Ambari 版本里差异比较大常见的有YarnMetrics.RunningApps、runningApps、ResourceManager.RunningApps这类。我建议先到 AMS 接口里跑一下curl -s http://AMS_HOST:6188/ws/v1/timeline/metrics?metricNameYarnMetrics.RunningAppsappIdYARNstartTime毫秒_startendTime毫秒_endprecision60 | jq .如果返回空就换成metricNamerunningApps再试。找到真实指标名后把 URL 里的指标名替换掉即可。这个面板我把Result format设为Table因为运行中应用数更适合用实时表格突出当前值而不是看趋势。Rows 和 Columns 不变最后在面板右侧加一个stat类型的可视化并选择最新值字段。5.5 三个面板拼完后的整体检查面板都能出数之后用仪表板右上角的刷新按钮从 1h 范围逐步扩展到 6h、24h重点观察时间轴是否有空档曲线是否有锯齿形跳跃Legend 里是否出现大量无法识别的序列名正常情况下1h 范围配合precision60能拿到 60 个点最适合肉眼验证。如果 24h 范围下数据点过多AMS 响应会很慢这时候把precision调成3600面板依旧流畅。我把这套配置整理成一个可复制的对照表方便你按需修改面板URL 关键参数Result formatUnitHDFS 容量metricNamedfs_capacity_used,dfs_capacity_remainingappIdHDFSprecision300Time seriesbytesCPU 利用率metricNamecpu_userappIdHOSTprecision60Time seriespercentYARN 应用数metricNameYarnMetrics.RunningAppsappIdYARNprecision60Tablenone6. 实际运行中总会踩到的几个坑我从日志里挑着讲这个 DEMO 我前后做过两次第一次几乎每一步都卡住。下面这几条不是理论是真实踩完后的记录。6.1 Grafana 升级后提示 old query 找不到数据源你可能会遇到这样一个报错failed to upgrade legacy queries datasource im7_otuvz was not found这不是 Infinity 的专属问题而是 Grafana 在升级时旧面板里记录的数据源 UID 失效了。Grafana 的 Dashboard JSON 里每个 Panel 的 datasource 会带一个 uid。如果你把 Grafana 从旧版本大版本升级或者删掉旧数据源重新建了一个同名数据源uid 就会对不上。解决办法有两个把旧面板导出的 JSON 里datasource的uid改成新数据源的 uid更省事的做法是重新创建一个 Panel从零选择新数据源然后重新粘贴查询配置。我第二次做的时候直接走第二条路因为面板数量本来就不多DEMO 阶段没必要在迁移上花时间。6.2 AMS 不返回历史数据只有最近一段AMBARI Metrics Collector 默认对原始指标数据有保留时间超过保留窗口的数据会被压缩或删除。所以 DEMO 阶段如果选 30 天前的范围很可能是一片空白这不是 Grafana 或 Infinity 的问题而是 AMS 里已经查不到那么老的数据了。这个可以在 AMS 的配置项里调具体参数名在不同版本略有不同一般是timeline.metrics.service.default.retention或类似的轮转周期配置。DEMO 阶段建议先把时间范围控制在最近 7 天内避免浪费时间去查一个根本不存在的数据。6.3 value 是字符串绘图全乱前面提到过AMS 返回的value经常是字符串1024000000。Grafana 对字符串类型的时序数据态度很保守默认可能把它当离散值处理画出来就是一堆跳变点。Infinity 的处理方法就是在 UQL 里显式转换value: number(.value)如果不用 UQL在 Columns 映射时看看有没有transform或者Type选项选择Number。6.4 数据源测试通但面板 No data这是最高频的问题。测试通过只能说明 Grafana 到 AMS 的网络是通的不能说明查询路径对。遇到 No data我建议按这个顺序排查先在浏览器里手动拼一下同样的 URL确认返回 JSON 有内容在 Infinity 查询编辑器里查看 Raw Response 或 Response Preview看拉回来的原始数据是否为空如果原始数据有内容但 Grafana 面板还是 No data重点看 Rows 路径是否正确如果 Rows 路径正确再看 Columns 字段名是否和 JSON 里完全一致特别是大小写。Infinity 一般会在查询编辑器下方显示请求响应预览这功能我几乎每次都用比一遍遍刷新面板高效得多。6.5 时间范围对不上老是少一个点Grafana 在传$__from和$__to时包含边界。AMS 对边界处理也有自己的逻辑导致首尾可能出现一个点差。这个不用太在意如果非要精确可以在 URL 里给 startTime 加上一个偏移比如把开始时间整体减掉precision毫秒让曲线首尾更完整。少一个点不影响 DEMO 展示但如果做容量趋势分析边界点缺失会让人误判起止值这个注意一下即可。7. DEMO 完成后的延伸从演示到可维护监控到这里你已经可以用 Grafana Infinity 把 Ambari-Metrics 的数据画成面板了。这套方案最大的价值是快不用在集群里安装任何新的 Agent不改变 Ambari 既有架构Grafana 侧一个插件就搞定。如果你只是需要临时演示、给领导看一版监控效果、或者排查某个指标是否真的有问题这个 DEMO 完全可以胜任。但我也得说点实在话它并不适合直接当成生产级长期监控方案。原因有几个。第一Infinity 是边查边拉数据每个面板刷新都会打一次 AMS REST 接口。面板一多、刷新频率一高AMS 本身会感受到压力。虽然短期不会拖垮集群但长期没必要这么依赖一个可视化工具去定时轰炸采集服务。第二AMS 的保留时间有限长期趋势分析迟早会遇到数据查不到的问题。正经的监控架构应该在采集端就把数据落到 Prometheus 或 Elasticsearch 这类长期存储里。第三告警配置虽然能用Infinity 的数据源在 Grafana Alerting 里并不是最优选择。像 HDFS 容量突增这种告警更合理的做法是让 Prometheus 周期性抓取指标然后在 Alertmanager 里触发规则。所以我的建议是DEMO 做出来之后把它当成需求确认工具用来快速和团队对齐到底要看哪些指标、哪些维度、哪些粒度。等需求冻结了再用 Prometheus node_exporter 或者 Spark 对外暴露 PushGateway 的方式把这些指标用更稳的通道接到 Grafana。如果你是第一次接触 Grafana Infinity 这套组合我的个人体会是不要被界面上的各种字段吓到先手动 curl 接口再按Rows 选行、Columns 选列的直觉去套最后用响应预览对照90% 的问题都能自己解决。真正难的不是插件而是你对自己数据接口的理解程度。这个 DEMO 后续还有很多可以扩展的地方比如把 hostname 变成 Grafana 下拉模板变量、把多指标查询封装成统一模板、通过 Dashboard Provisioning 把看板 JSON 提交到 Git 仓库做版本管理。你完全可以把今天的成果作为底座慢慢长成一套符合自己团队习惯的监控体系。
返回列表