
1. Grafana到底能干什么先搞清楚再动手先说句实在话在监控告警这个圈子里Grafana基本已经成了标配中的标配。如果你搞运维、做后端、碰过Kubernetes或者任何一套分布式系统几乎绕不开它。简单说Grafana就是一个开源的可视化平台它自己不存数据而是把Prometheus、InfluxDB、MySQL、Elasticsearch这些数据源里面的指标数据拉出来用图表、仪表盘的形式展示给你看。很多初学者第一次接触Grafana会觉得它就是个“画图的”。其实这个理解方向对但格局小了。Grafana真正厉害的地方在于它把数据源、可视化、告警、权限管理、团队协作这些能力揉在了一起。你可以在一个平台上同时看服务器CPU、数据库连接数、业务接口延迟、Nginx错误率甚至可以接上Alertmanager做统一告警。也就是说从“看数据”到“发现问题”再到“通知到人”整个链路都可以用Grafana串起来。这篇文章我就围绕Grafana的完整使用链路来写从最基础的Docker部署、Prometheus数据源接入到面板创建、面板拷贝再到接入Alertmanager告警最后把我在实际使用中踩过的坑一并整理出来。不管你是零基础刚入门还是已经用了一段时间想解决某个具体问题这篇内容都能给你一些直接能用的东西。适用对象我大概分三类第一类是刚接触监控体系的新人需要一套能跑通的完整示例第二类是已经在用Prometheus和Grafana但想优化面板和告警流程的工程师第三类纯粹是遇到了某个报错比如我标题里提到的“failed to upgrade legacy queries datasource”想快速找到解决方案的。不同阶段的读者可以跳着看但建议把第一章部署部分过一遍因为后面很多操作都依赖这个基础环境。2. 部署与基础环境搭建别在第一步就翻车2.1 Docker方式部署Grafana和Prometheus为什么推荐这种方式提到部署Grafana官方支持的安装方式有很多二进制包、系统包管理器、Docker、Kubernetes Helm Chart。但如果你要搭一套完整的Prometheus Grafana监控环境我最推荐的方式还是Docker Compose。原因很简单整个监控栈涉及的不只Grafana一个组件至少还要有一个Prometheus来采集数据偶尔还要加上Alertmanager、Node Exporter这些配套服务。如果用二进制一个个装版本依赖、服务管理、配置文件路径这些东西折腾起来非常费时间而Docker Compose可以把整个环境固定在一份YAML文件里做到一键起服务。还有一点很现实很多人的本机和测试环境用的不是同一套操作系统有的用Ubuntu有的用CentOS还有的用macOS。用Docker之后环境差异基本被抹平了我在这台机器上跑通的配置拿到另一台机器上一样能跑。下面给出一份我从实际项目中精简出来的docker-compose.yml包含Prometheus、Grafana和Node Exporter三个基础组件version: 3.8 services: prometheus: image: prom/prometheus:v2.47.0 container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus ports: - 9090:9090 restart: unless-stopped grafana: image: grafana/grafana:10.2.3 container_name: grafana environment: - GF_SECURITY_ADMIN_USERadmin - GF_SECURITY_ADMIN_PASSWORDadmin123 - GF_USERS_ALLOW_SIGN_UPfalse volumes: - grafana_data:/var/lib/grafana ports: - 3000:3000 restart: unless-stopped depends_on: - prometheus node-exporter: image: prom/node-exporter:v1.6.1 container_name: node-exporter ports: - 9100:9100 restart: unless-stopped volumes: prometheus_data: grafana_data:对应的prometheus.yml配置如下global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: prometheus static_configs: - targets: [localhost:9090] - job_name: node-exporter static_configs: - targets: [node-exporter:9100]这份配置里有两个细节值得注意。第一scrape_interval我设置了15秒这是监控粒度的问题。对于大多数业务系统15秒采集一次足够看出趋势了如果设置成1秒数据点会非常密存储开销和查询压力都会上来。第二Prometheus配置里的node-exporter:9100用的是服务名而不是IP因为Docker Compose默认会在同一个网络里做服务发现容器之间可以通过服务名互相访问。这个设计在单机环境下很好用但如果你把Prometheus部署在其他地方就得改成实际的IP地址。2.2 镜像下载慢和版本匹配问题很多人在部署这一步就卡住了原因不外乎两个镜像拉不下来或者镜像版本不匹配。镜像下载慢这个问题国内环境基本绕不开Docker Hub的限速。我的建议是给Docker配置镜像加速器具体怎么做这里不展开不同环境配置方式有差异搜一下就有。但要注意一点加速器只对Docker Hub的官方仓库生效如果你后续用到其他第三方镜像源可能还是慢。版本匹配方面我踩过一次比较深的坑。有一段时间我用的Prometheus是2.45版本但Grafana插件市场里有些面板模板要求Prometheus的数据格式是新版本的导致部分面板显示不出数据。后来统一把Prometheus升级到2.47问题就消失了。所以我的经验是尽量保持Prometheus和Grafana的大版本不过于落后至少选近一两年内还在维护的版本不要随便找个老镜像就开始用。另外提醒一句latest标签慎用。我有一次图省事直接拉grafana/grafana:latest结果两周后再拉镜像版本已经从9.x跳到了10.x面板配置没有任何兼容性处理登录页面样式也变了吓出一身冷汗。生产环境一定要锁定具体版本号测试环境随意。2.3 部署完成后的初始化检查服务起来之后不要急着去创建面板先做三个检查能省掉后面一堆问题。第一检查Prometheus的Targets状态。浏览器打开http://localhost:9090/targets正常情况下能看到两个targetState都是UP。如果显示Down先看网络通不通用docker exec进容器里ping一下对面服务名或者检查防火墙。第二确认Grafana能登录。打开http://localhost:3000默认账号是admin密码是你在环境变量里设置的GF_SECURITY_ADMIN_PASSWORD。如果你是第一次登录Grafana会提示修改密码建议直接修改尤其是多人共用的环境。第三用Prometheus的自带查询面板验证数据。在Prometheus的Graph页面输入up点击Execute如果能看到一组数值为1的序列说明采集链路通了。这一步验证的是Prometheus到各Exporters的链路后续在Grafana里查不到数据时排查范围能小很多。注意如果你是用docker run单独启动Grafana而不是Compose务必加上-v grafana_data:/var/lib/grafana把数据持久化出来。Grafana的面板配置、数据源配置、用户信息都存放在这个目录下容器一删就全没了到时候哭都来不及。3. 数据源接入与第一个可视化面板3.1 添加Prometheus数据源别忽略这几个字段Grafana默认没有配置任何数据源登录后第一步就是添加。路径是Configuration-Data Sources-Add data source找到Prometheus点进去。关键字段有三个Name你自己起的名字比如Prometheus-Prod建议起得有意义后面创建面板时要用它来区分数据源。URL填Prometheus的服务地址。如果你用的是我上面的Compose方案这里可以填http://prometheus:9090因为Grafana和Prometheus在同一个Docker网络里。如果你是分开部署的就填实际的IP比如http://192.168.1.100:9090。Scrape interval这个值建议与Prometheus的scrape_interval保持一致都设成15s。它的作用是告诉Grafana以什么频率去拉取数据如果两边不一致在查看短时间窗口的数据时可能出现锯齿状图形。填好后点击Save testGrafana会做一次连通性测试返回绿色的“Data source is working”说明通了。如果失败大概率是URL填错了或者容器网络没通回头检查一下。3.2 手工创建第一个面板从一条查询开始数据源就绪后我们来创建第一个面板。点击左侧菜单的Dashboards然后New dashboard-Add visualization这时Grafana会要求选择数据源我们选刚才创建的Prometheus。进到编辑界面后核心是配置查询语句。我们用Node Exporter采集到的指标来展示CPU使用率查询语句如下100 - avg(rate(node_cpu_seconds_total{modeidle}[5m])) * 100这条语句的逻辑是先取过去5分钟内CPU空闲时间的增长率求平均用100减去这个值得到CPU使用率。它是监控CPU最常用的写法没有之一。写完之后右上角点击Apply面板就创建好了。此时你应该能看到一条实时曲线。如果你发现面板上显示“No data”不要慌排查顺序是到Prometheus的Graph页面先执行这条SQL看有没有数据返回。如果Prometheus里也没有说明指标名写错了或者采集器没上报。如果Prometheus有数据但Grafana没有检查面板右上角的时间范围。默认可能只显示了最近15分钟如果你很久之前数据才存在图表自然是空的。检查数据源配置确认选中的是正确的数据源。3.3 处理“failed to upgrade legacy queries datasource”报错有一段时间我经常在打开一些旧面板时遇到一个非常恼人的报错failed to upgrade legacy queries datasource im7_otuvz was not found这明显是Grafana版本迭代留下的兼容性问题。早期Grafana面板中的查询语句使用的是旧格式被称为legacy queries当Grafana升级到新版本后系统会自动尝试把这些旧查询转换成新格式。如果转换过程中找不到对应的数据源ID就会报这个错面板上的所有图表都会失效。这个报错的常见触发场景有两个第一你是从老版本Grafana直接升级上来的第二你导入了一个别人用旧版本导出的面板JSON文件。解决方案分两种。如果面板还能打开并进入编辑模式最简单的办法是在Panel的Query编辑器中手动修改数据源选项。重新选择数据源并确认查询语句正常后点击Save就能覆盖旧的legacy格式报错消失。如果整个面板已经打不开只能通过导入新面板来修复。用Dashboards-Import粘贴那段JSON然后把数据源选为当前有效的那个重新导入一次。要根治这类问题我养成了两个习惯。一是定期备份面板JSON具体方法后面会说。二是不盲目升级Grafana大版本至少在升级前先检查当前仪表盘是否有关键依赖然后在测试环境先升一遍。4. 面板管理拷贝/导入导出/模板化4.1 在同一台Grafana里拷贝整个面板很多人用Grafana一段时间后会遇到一个很实际的需求我想把一个面板复制一份出来改几个查询就变成另一个面板但不想从头到尾重新配置一遍。Grafana本身没有直接的“Duplicate dashboard”按钮但只要懂一点操作逻辑拷贝面板非常简单。最常用的方法是导出再导入。在你要拷贝的面板上点右上角Share dashboard选择Export页签勾选Export for sharing externally然后点击Save to file会下载一个JSON文件。接着在Dashboards-Import里上传这个JSON重命名一下面板名称选择目标数据源点Import。这样你就得到了一份完整的新面板它和原面板互不影响你在新面板上的任何改动都不会影响旧面板。这个方法还有另一个好处——换数据源。比如你在测试环境搭了一套监控面板都调好了现在想搬到生产环境只需要把JSON导出来导入时把数据源从测试环境切换成生产环境所有查询会自动适配。注意要实现这种适配前提是两边用的指标名一致也就是Metrics名称不能变变的只是数据源地址。4.2 整个文件夹级别的备份技巧如果你管理的Grafana实例里有很多面板一个一个人工导出就太累了。更高效的方式是直接备份Grafana的数据库文件。当Grafana运行在Docker容器里时面板、数据源、用户等元数据都存储在/var/lib/grafana/grafana.db这个SQLite数据库文件中。要整体备份只需要把这个文件复制出来即可docker cp grafana:/var/lib/grafana/grafana.db ./backup_$(date %F).db恢复时将文件复制回去并重启容器就能还原。这个方法我用了很多次尤其在Grafana升级前一定要做一次全量备份。有些面板配置比较复杂的导出JSON时容易丢一些细节而数据库备份不会漏任何东西。顺便说一句SQLite备份是文件级别的复制不需要停服务但生产环境建议还是在低峰期操作避免有人在写入时备份导致潜在的不一致。4.3 从Grafana官方社区获取高质量面板很多人不知道Grafana社区有一个官方面板市场地址是grafana.com/grafana/dashboards。上面有成千上万份别人分享的面板JSON覆盖各种场景Kubernetes集群监控、MySQL性能监控、Nginx状态监控、JVM监控等。你要做的就是在Grafana的Dashboards-Import页面输入面板ID点Load然后选数据源导入即可。但这里我要给你一个忠告社区面板质量参差不齐不要看到一个高星面板就无脑导入。很多面板是在特定环境下制作的查询中用的指标名可能和你实际采集的完全不同导入后大概率是满屏No data。我的建议是优先选择下载量高、近期有更新的面板导入后先花几分钟看一遍所有查询语句理解每条alert和图表在问什么问题再决定是否直接使用。社区面板更像是“参考答案”别当“唯一标准”。我自己常用的几个面板ID可以分享一下Node Exporter Full模板的ID是1860适用于Linux主机基础监控Kubernetes集群监控常用ID为14205。这些都比较经典建议大家直接搜名字搜索找到合适的版本再导入。5. 接入Alertmanager把告警真正用起来5.1 Grafana Alerting和Alertmanager怎么选监控可视化只是第一步真正让监控有价值的是告警。在Grafana里做告警有两条路一是直接用Grafana自带的Alerting功能二是在Prometheus端配置告警规则然后把Alertmanager作为通知中枢再让Grafana展示Alertmanager的数据。在选择之前先说一下两者的区别。Grafana原生Alerting的优势是配置方便直接在面板的Alert页签里就可以编辑规则不需要碰Prometheus的告警规则文件而且告警规则可以基于多个数据源进行聚合计算。劣势是如果你已经有了一套Prometheus告警规则迁移到Grafana原生告警会需要额外工作。而Prometheus Alertmanager是社区更通用、更成熟的方案尤其适合大规模集群的场景告警规则可以通过Prometheus的rules文件统一管理支持分组、抑制、静默等高级功能。如果你的环境是Prometheus Grafana一套搭配我建议首选Prometheus Alertmanager方案原因有两点第一Prometheus的告警规则语言expr和PromQL完全一致书写起来顺手第二Alertmanager的通知分发能力和路由控制比Grafana原生告警更灵活尤其是对接钉钉、企业微信这类工具时社区现成的Webhook集成很多。5.2 搭建Alertmanager并配置告警通知使用Docker Compose时在原来的服务列表中加入Alertmanageralertmanager: image: prom/alertmanager:v0.26.0 container_name: alertmanager volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml ports: - 9093:9093 restart: unless-stopped对应的alertmanager.yml配置如下route: group_by: [alertname] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: webhook receivers: - name: webhook webhook_configs: - url: http://your-webhook-server:8080/hook send_resolved: true这里group_wait和group_interval是告警分组的等待时间含义是同一个分组内新告警需要在多长时间内合并发送。repeat_interval控制告警恢复前重复通知的间隔通常设1小时比较合理太频繁会打扰人太久了可能错过处理窗口。在Prometheus端我们需要配置告警规则。在prometheus.yml同目录下新建alert_rules.yml然后在prometheus.yml里加上rule_files: - /etc/prometheus/alert_rules.yml规则文件示例这里做一个CPU使用率超过90%持续5分钟的告警groups: - name: node_alerts rules: - alert: HighCPUUsage expr: 100 - avg(rate(node_cpu_seconds_total{modeidle}[5m])) * 100 90 for: 5m labels: severity: critical annotations: summary: Instance {{ $labels.instance }} CPU usage high description: CPU usage is above 90% for 5 minutesfor: 5m表示该条件需要持续满足5分钟才触发告警这个参数很关键可以有效过滤瞬时抖动造成的误报。配置完成后重启Prometheus容器加载规则。5.3 在Grafana中查看Alertmanager告警状态接入Alertmanager后Grafana侧要做两件事。第一件添加数据源。在Configuration-Data Sources里添加Alertmanager类型的数据源URL填http://alertmanager:9093保存并测试连通性。第二件确认Grafana的告警页面能看到数据。进入Alerting-Contact points或者Notification policies如果你只是想在Grafana里展示Alertmanager已有的告警那么在Alertmanager数据源配置好后左侧菜单的Alerting页面会自动展示来自Alertmanager的告警列表。这里需要注意如果你同时启用了Grafana原生Alerting官方老版本中继承模式下只能选择一个后端来统一管理。新版本中通过加数据源的方式集成后可以同时看到多个来源的告警但这个“同时看到”也带来一个麻烦告警去重。同一台主机的CPU告警可能既出现在Alertmanager里也被Grafana原生告警捕获查看时会看到两条。我的建议是二选一不要两者并行使用。既然选了Alertmanager路线就在Grafana里把所有原生告警规则清空用Alertmanager作为唯一的告警来源。6. 实战中那些“坑”每一步都是血泪教训6.1 时间范围与时间序列对齐面板上明明有数据但图表的曲线看起来“歪”了时间轴对不上这个问题在跨时区场景下特别常见。Grafana默认使用浏览器本地时区显示时间轴但Prometheus内部的时间戳是UTC标准时间。如果你的浏览器时区设置不对或者服务器时区不对最明显的现象就是图表高峰和低谷偏移了几个小时。解决方法是在Grafana的设置里指定时区Dashboard settings-General-Timezone选择UTC或者与你的业务环境一致的时区。对于跨地域协作的团队我统一建议使用UTC显示时间轴并且所有告警通知里的时间一律标注时区避免“3点告警了我们这里才凌晨”这种误解。6.2 电压点采样周期不同带来的采样偏差另一个常见问题是同一个面板上混用了不同scrape_interval的数据源图形会呈现锯齿状。比如Prometheus自身是15s采集但某个Exporters配置成了30s那么在查询时使用[5m]这样的时间范围参数计算出的速率在不同时间点统计的样本数量可能不一致。一句话经验监控系统的采集周期必须全局统一至少在同一个数据源内统一。不同数据源之间如果一定需要混合展示查询时尽量使用较长的range向量比如[10m]甚至[30m]让样本数足够多减小误差。6.3 导出面板时数据源名称错乱我在第一次导出面板给别人使用时就遇到过一个尴尬问题——对方的Grafana环境中没有我不用的那个数据源名称导入后面板里的查询全部显示红色错误。其实解决办法很简单在导出面板JSON时注意勾选Export for sharing externally选项。勾选之后Grafana会把面板中的dataSource引用替换成通用格式导入对方环境时Grafana会提示选择数据源。如果你忘了勾选导入时就会看到一个报错datasource not found。还有一点不同Grafana版本导出的JSON格式可能不兼容。比如你用10.x导出对方还在用8.x很可能导入失败。遇到这种情况让对方升级版本或者手动改JSON里的一些版本字段都不复杂但挺浪费时间所以我会在导出的文件里备注来源版本建议接收方使用兼容的版本。6.4 数据源权限与多团队隔离最后聊一下多人协作场景。如果你给团队搭了Grafana建议从一开始就建立权限管理意识。Grafana支持组织Organization、团队Team和用户User三层结构。最简单的做法是为不同部门建不同的Team然后给每个Team分配不同的Folder在Folder上配置对应权限。具体操作是选择Administration-Users and access-Teams创建团队后在Dashboards-Folder settings-Permissions里添加团队并设置View或Edit权限。有一个权限设计上的经验给普通用户默认设为View权限只有核心负责人才有Edit权限。因为在一个团队共享的Grafana实例上权限过宽会导致有人不小心改掉生产环境的仪表盘影响所有人。这种事故我碰到过一次后来就再也没放开过Edit权限。7. 几个提升效率的实用技巧7.1 用变量让一个面板适配多台机器面板变量是Grafana里非常实用但容易被忽略的功能。举个例子你监控的集群里有10台机器如果为每台机器建一个面板那就要维护10份一模一样的图表更新一次查询就要全部改一遍效率低到爆炸。而用变量的方式只需要建一个面板通过下拉框切换instance就能动态查询不同机器的数据。具体在面板编辑页面点击Settings-Variables-Add variable类型选Query数据源选Prometheus查询语句写label_values(node_cpu_seconds_total, instance)这条语句的意思是从所有node_cpu_seconds_total指标中自动提取所有instance标签的值作为下拉框选项。然后在面板查询语句中把固定的instance改成$instance变量100 - avg(rate(node_cpu_seconds_total{instance$instance, modeidle}[5m])) * 100这样切下拉框图表就会跟着变。数据中心ID、Region、Namespace这些维度都可以同理做成变量非常灵活。7.2 使用Annotation标记事件时间点有一次我们在排查线上问题时发现性能曲线在某天下午有异常掉点但不知道这个时间点到底发生了什么。后来通过查看Grafana的Annotation记录才找到是当时一次发布造成的。从那以后我就在关键面板上启用了Annotation功能。使用方法在面板的Settings-Annotations里添加一个Annotation查询数据源选Prometheus查询语句写你想要关注的某个指标变化比如changes(process_start_time_seconds[1m]) 0这个指标在进程重启时会从0跳到1一旦进程发生重启图表上就会显示一个垂直标记线。配合告警使用你看到某根丛线就知道那会儿进程重启了不用再翻日志。7.3 共享链接和快照方便沟通问题排查问题时与其截图发给同事不如直接分享一个带时间范围的链接。Grafana的面板右上角Share里可以复制当前面板的短链接并锁定当前时间范围。同事打开链接看到的和你看到的内容完全一致省去各种“你那边显示的是什么”的沟通成本。如果你要发给外部或者临时访客Grafana还支持生成Snapshot相当于把当前数据导出一份静态快照不依赖数据源是否可达。注意快照会真实暴露数据内容不要随意发给不可信的人。8. 最后再拆一个实际问题Alertmanager一直收不到告警讲完前面的内容我把最常见的“Alertmanager收不到告警”这个问题单独拿出来盘一遍。这套链路涉及Prometheus、Alertmanager、Grafana三层任何一个环节断开告警都送不出去。排查步骤按顺序来第一确认Prometheus里能查询到告警规则。在Prometheus的http://localhost:9090/rules页面能看到你配置的规则列表如果规则没有出现说明rule_files配置有问题或者文件路径不对如果规则存在但状态显示INACTIVE说明条件未满足等待触发条件形成。第二触发了告警后检查Alertmanager的http://localhost:9093/#/alerts页面看是否收到这个告警。如果没有检查Prometheus和Alertmanager的网络连通性再检查Alertmanager的--config.file是否加载了正确的配置文件这个参数在Docker镜像启动时默认是/etc/alertmanager/alertmanager.yml如果你的挂载路径不对告警即使发送了也会被丢弃。第三如果Alertmanager收到了但没有发送通知检查route路由配置和receivers配置。很多人踩坑的点是receiver名称匹配不上路由里写的receiver是webhook但receivers列表里定义的名字却是webhook1名字对不上就直接丢消息。第四如果上面全部正常最后再用amtool或者直接curl Webhook地址来测试接收端是否正常。把Alertmanager的接收URL临时改成http://httpbin.org/post做测试能收到POST请求就说明链路从Alertmanager到接收端没问题那问题基本出在接收端自己身上。这个排查思路其实适用于所有监控告警链路只要养成“逐层验证”的习惯大多数问题十分钟内就能定位。我自己在搭建这套Grafana Prometheus Alertmanager监控体系的过程中最大的感受就是工具本身不复杂但生态里的各种概念和版本兼容关系确实需要时间消化。如果用一句话给后来者建议那就是——环境尽量用Docker跑版本锁定具体数字面板从官方社区抄告警从简单规则开始这样学习曲线会平缓很多。遇到问题别慌按层排查大部分坑都是前人踩过的搜索引擎一定搜得到答案。