Grafana,是目前最流行的开源可视化监控工具之一。它功能强大,支持多种数据源,图表类型丰富,配置灵活,社区活跃,几乎成了监控可视化的标配。

我们公司,用Grafana做监控已经两年了。从最开始的几个简单的Dashboard,到现在几十个Dashboard,上百个Panel,覆盖了服务器、数据库、中间件、应用、业务等各个层面的监控。Grafana,帮我们发现了很多问题,也帮我们解决了很多问题,是我们运维和开发不可或缺的工具。

但是,随着业务的发展,Dashboard越来越多,配置越来越复杂,我们的Grafana可视化代码,也越来越混乱。很多Dashboard,是不同的人在不同的时间建的,风格不统一,配置不规范,重复代码很多,维护起来很痛苦。改一个Panel,要找半天;加一个指标,要复制粘贴一大堆配置;出了问题,不知道是哪里配错了。

最近,我实在受不了了,对我们的Grafana可视化代码,进行了一次全面的重构。花了一周的时间,把几十个Dashboard,上百个Panel,重新梳理、整理、规范化、模块化。重构之后,代码清晰了很多,维护起来也方便了很多,新增Dashboard的效率,提升了至少三倍。

今天,我想分享一下这次重构的过程、思路、方法和经验。包括为什么要重构、重构前的问题、重构的目标、重构的步骤、重构后的效果,以及一些经验总结。如果你也在用Grafana,也遇到了类似的问题,希望这篇文章能对你有帮助。

一、为什么要重构

在说重构之前,先说说为什么要重构。我们的Grafana,用了两年,积累了很多问题,已经到了不得不重构的地步。

1. Dashboard数量多,管理混乱

我们有几十个Dashboard,但是没有统一的命名规范,没有分类,没有目录。有的叫"服务器监控",有的叫"Linux Server",有的叫"主机监控-v2",有的叫"老王的服务器监控"。找一个Dashboard,要翻半天,经常找不到,或者找到了好几个,不知道哪个是最新的。

而且,很多Dashboard,已经没人用了,但是也没人删,就那么放在那里,越积越多。整个Grafana,看起来乱糟糟的,像个垃圾场。

2. 配置不规范,风格不统一

不同的人,建的Dashboard和Panel,风格不一样。有的用这个颜色,有的用那个颜色;有的用这种图表类型,有的用那种;有的Panel标题是"CPU使用率",有的是"cpu_usage",有的是"CPU Usage (%)"。同一个指标,在不同的Dashboard里,展示方式不一样,单位不一样,颜色不一样,看起来很不专业,也容易混淆。

而且,很多Panel的配置,很随意。坐标轴没有统一设置,单位没有统一设置,阈值没有统一设置,告警没有统一配置。有的Panel,Y轴从0开始,有的从最小值开始;有的单位是百分比,有的是小数;有的有阈值线,有的没有。看起来很不规范,也影响阅读和判断。

3. 重复代码多,维护成本高

很多Panel,配置几乎是一样的,只是数据源或者指标不一样。但是,因为Grafana的配置,是每个Panel独立的,所以每次加一个类似的Panel,都要复制粘贴一大堆配置。改一个通用的配置(比如颜色、单位、阈值),要改几十个Panel,很容易漏改,也很容易改错。

而且,Grafana的Dashboard JSON,结构很复杂,嵌套很深,手动修改很容易出错。很多时候,改一个配置,要在JSON里找半天,找到对应的位置,小心翼翼地改,还经常改错地方,导致Dashboard打不开。

4. 缺乏版本管理,出了问题不好回滚

我们的Grafana Dashboard,都是直接在界面上配置的,没有版本管理。改坏了,不知道之前是什么样的,也没法回滚。有一次,一个同事改一个Dashboard,不小心把整个Dashboard删了,找不回来了,只能重新建,花了大半天时间。

而且,没有版本管理,就不知道谁改了什么,什么时候改的,为什么改。出了问题,没法追溯,只能靠记忆,很不靠谱。

5. 新人上手难,知识无法传承

因为配置混乱,没有文档,没有规范,新人来了,不知道怎么建Dashboard,不知道怎么配置Panel,不知道用什么图表类型,不知道怎么设置告警。只能问老人,老人一遍一遍地教,效率很低。而且,老人走了,知识就带走了,新人又要重新摸索。

这些问题,已经严重影响了我们的工作效率,也影响了监控的质量。所以,我决定,对Grafana的可视化代码,进行一次全面的重构。

二、重构的目标

重构之前,我先明确了重构的目标。没有目标的重构,是盲目的,很容易越改越乱。

我的重构目标,有以下几个:

1. 规范化

建立统一的命名规范、配置规范、风格规范。所有的Dashboard和Panel,都按照统一的规范来配置,风格一致,看起来专业,用起来方便。

2. 模块化

把重复的配置,抽成模板,实现复用。新增Dashboard和Panel的时候,不需要从零开始配置,只需要基于模板,修改少量参数,就能快速生成。提高效率,减少错误。

3. 版本化

把所有的Dashboard配置,都纳入版本管理(Git)。每次修改,都有记录,都能追溯,都能回滚。出了问题,不怕改坏,随时可以回滚到之前的版本。

4. 自动化

通过脚本和工具,实现Dashboard的自动化生成、部署、更新。不需要手动在界面上配置,只需要写配置文件,运行脚本,就能自动生成Dashboard,部署到Grafana。提高效率,减少人为错误。

5. 文档化

编写完善的文档,包括规范说明、使用教程、最佳实践。新人来了,看文档就能上手,不需要老人手把手教。知识可以传承,不会因为人员流动而丢失。

这五个目标,是我这次重构的方向。所有的工作,都围绕这五个目标来展开。

三、重构的步骤

明确了目标之后,我开始了重构。重构,分了五个步骤:梳理现状、制定规范、模块化改造、版本化和自动化、文档化。

第一步:梳理现状

重构的第一步,是梳理现状。先搞清楚,我们现在有多少个Dashboard,多少个Panel,都是什么类型的,哪些在用,哪些没用,哪些有问题。

我做了以下几件事:

  1. 导出所有Dashboard:把Grafana里所有的Dashboard,都导出成JSON文件,保存到本地。
  2. 分类整理:对所有的Dashboard,进行分类。按用途分,有服务器监控、数据库监控、中间件监控、应用监控、业务监控等;按状态分,有在用的、废弃的、重复的。
  3. 统计分析:统计每个Dashboard的Panel数量、图表类型、数据源、指标等。分析哪些配置是重复的,哪些是不规范的,哪些是有问题的。
  4. 清理废弃:和团队成员确认,把废弃的、重复的、没人用的Dashboard,删掉。清理之后,Dashboard的数量,减少了将近一半。

梳理完现状之后,我对我们的Grafana,有了一个清晰的认识。哪些需要保留,哪些需要修改,哪些需要删除,都一目了然。这为后续的重构,打下了基础。

第二步:制定规范

梳理完现状之后,第二步,是制定规范。没有规矩,不成方圆。要让所有的Dashboard和Panel,都风格统一、配置规范,就必须有一套明确的规范。

我制定了以下几个方面的规范:

1. 命名规范

  • Dashboard命名:统一用中文,格式为"[分类] 名称",比如"[服务器] Linux主机监控"、"[数据库] MySQL监控"。分类清晰,名称明确。
  • Panel命名:统一用中文,简洁明了,比如"CPU使用率"、"内存使用率"、"磁盘IO"。不要用英文缩写,不要用变量名,不要加多余的描述。
  • 变量命名:统一用小写英文,下划线分隔,比如$host$service$env。含义明确,不要用$a$b这种无意义的名字。
  • 文件夹命名:按分类建文件夹,比如"服务器监控"、"数据库监控"、"中间件监控"、"应用监控"、"业务监控"。每个Dashboard,都放到对应的文件夹里。

2. 配置规范

  • 图表类型:明确什么场景用什么图表类型。趋势用折线图,对比用柱状图,占比用饼图,实时用仪表盘,分布用热力图。不要乱用图表类型。
  • 单位设置:统一单位。百分比用"percent"(0-100),字节用"bytes"(自动换算成KB/MB/GB),秒用"seconds"(自动换算),次数用"short"。不要有的用百分比,有的用小数,有的用原始值。
  • 坐标轴设置:Y轴统一从0开始(除非有特殊原因),最小值0,最大值自动。坐标轴标签清晰,单位明确。
  • 颜色设置:统一配色方案。用Grafana自带的配色方案,不要自己乱选颜色。同一个Dashboard里,颜色要协调,不要太花哨。
  • 阈值设置:统一阈值。比如,CPU使用率超过80%警告,超过90%严重;内存使用率超过80%警告,超过90%严重。所有的Dashboard,阈值都一致,不要有的80%,有的85%,有的90%。
  • 图例设置:统一图例位置,放在图表下方,显示最大值、最小值、平均值、当前值。不要有的在左边,有的在右边,有的显示,有的不显示。

3. 告警规范

  • 告警规则:明确什么指标需要告警,阈值是多少,持续多久告警,告警级别是什么。比如,CPU使用率超过90%,持续5分钟,严重告警;内存使用率超过90%,持续5分钟,严重告警。
  • 告警通知:统一告警通知渠道。严重告警,发邮件+短信+钉钉;警告告警,发邮件+钉钉。不要有的发邮件,有的发短信,有的什么都不发。
  • 告警标题:统一告警标题格式,比如"[严重][服务器] 主机192.168.1.1 CPU使用率超过90%"。标题清晰,一看就知道是什么级别的告警,什么地方出了问题。

4. 布局规范

  • Dashboard布局:统一布局。顶部是变量选择区,然后是概览区(关键指标的单值面板),然后是详细指标区(按类别分组的图表),最后是日志和事件区。
  • Panel大小:统一Panel大小。单值面板,宽度6,高度4;折线图,宽度12,高度8;柱状图和饼图,宽度6,高度8。不要有的大,有的小,参差不齐。
  • Panel间距:统一间距,Panel之间的间距,保持一致,不要有的挤在一起,有的离得很远。

制定完规范之后,我把规范文档,发给团队成员,大家一起讨论,修改,最终达成一致。规范,不是一个人定的,是团队共同认可的,这样大家才会遵守。

第三步:模块化改造

制定完规范之后,第三步,是模块化改造。把重复的配置,抽成模板,实现复用。这是重构的核心,也是最有价值的部分。

Grafana本身,提供了一些复用的机制,比如Dashboard模板、Panel模板、变量等。但是,这些机制,还不够灵活,不够强大。为了实现真正的模块化,我采用了"代码生成"的方式,用Python脚本,根据配置文件,自动生成Grafana Dashboard的JSON。

具体做法是:

1. 定义模板

把常用的Panel配置,抽成模板。比如,CPU使用率折线图模板、内存使用率折线图模板、磁盘使用率单值面板模板、网络流量折线图模板等。每个模板,定义了图表类型、单位、颜色、阈值、坐标轴、图例等配置,只需要传入数据源、指标、标题等参数,就能生成一个完整的Panel配置。

模板用Python的字典来定义,比如:

cpu_usage_panel_template = {
    "type": "graph",
    "title": "CPU使用率",
    "datasource": "$datasource",
    "targets": [
        {
            "expr": "100 - (avg by (instance) (irate(node_cpu_seconds_total{mode='idle', instance=~'$host'}[5m])) * 100)",
            "legendFormat": "{{instance}}",
        }
    ],
    "yaxes": [
        {"format": "percent", "min": 0, "max": 100},
        {"format": "short", "min": 0}
    ],
    "thresholds": "80,90",
    "aliasColors": {},
    "legend": {
        "show": true,
        "values": true,
        "max": true,
        "min": true,
        "avg": true,
        "current": true,
        "alignAsTable": true,
        "rightSide": false
    },
    "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
}

这个模板,定义了CPU使用率折线图的所有配置。用的时候,只需要传入数据源、主机变量等参数,就能生成一个完整的Panel。

2. 定义配置文件

每个Dashboard,对应一个YAML配置文件。配置文件里,只需要定义Dashboard的基本信息(标题、变量、数据源等),以及需要哪些Panel,每个Panel的参数是什么。不需要写完整的JSON配置,只需要写简洁的YAML配置。

比如,一个服务器监控Dashboard的配置文件:

dashboard:
  title: "[服务器] Linux主机监控"
  tags: ["服务器", "Linux", "监控"]
  timezone: "browser"
  
variables:
  - name: "datasource"
    type: "datasource"
    query: "prometheus"
  - name: "host"
    type: "query"
    datasource: "$datasource"
    query: "label_values(node_uname_info, instance)"
    refresh: 2

panels:
  - type: "row"
    title: "概览"
  - template: "cpu_usage_single"
    title: "CPU使用率"
  - template: "memory_usage_single"
    title: "内存使用率"
  - template: "disk_usage_single"
    title: "磁盘使用率"
  
  - type: "row"
    title: "CPU详细"
  - template: "cpu_usage_graph"
    title: "CPU使用率趋势"
  - template: "cpu_load_graph"
    title: "系统负载"
  
  - type: "row"
    title: "内存详细"
  - template: "memory_usage_graph"
    title: "内存使用率趋势"
  - template: "swap_usage_graph"
    title: "Swap使用率"

这个配置文件,非常简洁,只定义了Dashboard的基本信息和需要哪些Panel。每个Panel,通过template字段,指定用哪个模板,然后传入标题等参数。

3. 编写生成脚本

写一个Python脚本,读取YAML配置文件,根据模板,生成完整的Grafana Dashboard JSON。脚本的逻辑是:

  1. 读取YAML配置文件,解析Dashboard的基本信息和Panel列表。
  2. 遍历Panel列表,对于每个Panel,如果是模板类型,就加载对应的模板,传入参数,生成完整的Panel配置。
  3. 把所有的Panel配置,组合成完整的Dashboard JSON。
  4. 输出JSON文件,或者直接调用Grafana API,创建/更新Dashboard。

这样,新增一个Dashboard,只需要写一个简洁的YAML配置文件,运行脚本,就能自动生成完整的Dashboard JSON,甚至直接部署到Grafana。不需要手动在界面上配置,不需要复制粘贴一大堆JSON,效率大大提高,错误也大大减少。

而且,因为所有的Panel,都是基于统一的模板生成的,所以配置都是规范的,风格都是统一的。改一个通用的配置(比如颜色、单位、阈值),只需要改模板,然后重新生成所有的Dashboard,就能批量更新,不需要一个一个改。

4. 迁移现有Dashboard

模块化改造完成之后,我把现有的、在用的Dashboard,都按照新的规范和模块化方式,重新生成了一遍。这个过程,花了几天时间,但是很值得。迁移之后,所有的Dashboard,都是规范的、统一的、可维护的。

迁移的过程中,我也发现了很多之前配置的问题,比如单位不对、阈值不一致、图表类型不合适等,都一并修复了。迁移之后,Dashboard的质量,提升了很多。

第四步:版本化和自动化

模块化改造完成之后,第四步,是版本化和自动化。把所有的配置,都纳入Git版本管理,并且实现自动化部署。

1. 版本化

我建了一个Git仓库,把所有的模板、配置文件、生成脚本,都放到Git仓库里。每次修改,都提交到Git,写清楚提交信息,说明改了什么,为什么改。

这样,所有的修改,都有记录,都能追溯,都能回滚。出了问题,随时可以回滚到之前的版本。谁改了什么,什么时候改的,为什么改,都一目了然。

而且,用Git管理,还可以用分支。开发新的Dashboard,在开发分支上做,测试通过了,再合并到主分支,部署到生产环境。不会影响线上的Dashboard,很安全。

2. 自动化部署

我写了一个部署脚本,调用Grafana的API,自动创建/更新Dashboard。脚本的逻辑是:

  1. 读取YAML配置文件,生成Dashboard JSON。
  2. 调用Grafana API,检查Dashboard是否存在。
  3. 如果不存在,就创建;如果存在,就更新。
  4. 输出部署结果。

Grafana提供了完善的HTTP API,可以通过API创建、更新、删除Dashboard。只需要一个API Token,就能调用API,很方便。

我还配置了Git钩子(pre-commit和post-merge),提交代码的时候,自动检查配置文件的格式;合并到主分支的时候,自动部署到Grafana。这样,整个流程,都是自动化的,不需要手动操作。

版本化和自动化之后,我们的工作流程,变成了:

  1. 写YAML配置文件(新增或修改Dashboard)。
  2. 提交到Git,写清楚提交信息。
  3. 合并到主分支,自动部署到Grafana。
  4. 在Grafana上查看效果。

整个流程,简单、高效、可靠。不需要手动在界面上配置,不需要复制粘贴JSON,不需要担心改坏了没法回滚。

第五步:文档化

重构的最后一步,是文档化。编写完善的文档,让团队成员都知道规范是什么,怎么用,怎么新增Dashboard,怎么修改配置。

我写了以下几部分文档:

  1. 规范说明:详细说明命名规范、配置规范、告警规范、布局规范。每个规范,都有示例,让大家一看就懂。
  2. 使用教程:从零开始,教大家怎么新增一个Dashboard,怎么写YAML配置文件,怎么用模板,怎么运行生成脚本,怎么部署。步骤详细,图文并茂。
  3. 模板说明:列出所有可用的模板,每个模板的用途、参数、示例。大家新增Dashboard的时候,可以直接查文档,知道用哪个模板,传什么参数。
  4. 最佳实践:总结一些Grafana使用的最佳实践,比如怎么设计Dashboard,怎么选择图表类型,怎么配置告警,怎么优化性能。
  5. 常见问题:收集大家经常遇到的问题,以及解决方案。比如,Dashboard打不开怎么办,Panel不显示数据怎么办,告警不发怎么办。

文档写完之后,我组织了一次团队分享,给大家讲解新的规范和流程,演示怎么用。分享之后,大家都觉得新的方式很好,效率高,维护方便,都愿意用。

四、重构后的效果

重构完成之后,效果非常明显。主要体现在以下几个方面:

1. 效率提升

新增一个Dashboard,之前需要半天到一天的时间,手动在界面上配置,复制粘贴,调整样式。现在,只需要写一个简洁的YAML配置文件,运行脚本,几分钟就能生成并部署。效率提升了至少三倍。

修改一个通用配置(比如颜色、单位、阈值),之前需要改几十个Panel,很容易漏改错改。现在,只需要改模板,重新生成所有Dashboard,几分钟就能批量更新,而且不会出错。

2. 质量提升

所有的Dashboard,都是基于统一的模板生成的,配置规范,风格统一。单位一致,阈值一致,颜色协调,布局整齐。看起来专业,用起来方便,也不容易出错。

而且,因为有版本管理,每次修改都有记录,都能追溯,都能回滚。出了问题,不怕改坏,随时可以回滚。Dashboard的质量,有了保障。

3. 维护成本降低

之前,维护Dashboard,是一件很痛苦的事情。改一个Panel,要找半天;加一个指标,要复制粘贴一大堆配置;出了问题,不知道是哪里配错了。现在,所有的配置,都是代码化的,模块化的,清晰明了。维护起来,很方便,很轻松。

而且,因为有完善的文档,新人来了,看文档就能上手,不需要老人手把手教。知识可以传承,不会因为人员流动而丢失。

4. 团队协作更顺畅

之前,Dashboard都是个人在界面上配置的,别人不知道怎么配的,也不敢乱改。现在,所有的配置,都是代码化的,在Git仓库里,大家都可以看,可以改。改之前,提Merge Request,大家一起Review,通过了再合并部署。团队协作,更顺畅,更规范。

而且,因为有统一的规范,大家建的Dashboard,风格都是一致的,不会出现"千人千面"的情况。整个Grafana,看起来井井有条,很专业。

五、经验总结

这次Grafana可视化代码重构,让我收获很多。总结一些经验,分享给大家:

1. 重构要趁早,不要等问题积累到无法收拾

很多时候,我们觉得现在还能用,凑合用吧,等以后再说。但是,问题不会因为你不处理,就消失,只会越积越多,越积越严重。等到不得不重构的时候,成本会很高,难度会很大。

所以,重构要趁早。发现问题,及时处理,小步快跑,持续改进。不要等问题积累到无法收拾,才想起来重构。

2. 重构前,先明确目标和规范

重构,不能盲目。重构之前,一定要先明确目标,你想通过重构,达到什么效果。然后,根据目标,制定规范。规范,是重构的依据,也是团队协作的基础。

没有目标和规范的重构,是盲目的,很容易越改越乱,最后不了了之。

3. 模块化和代码化,是解决重复配置的关键

Grafana的配置,之所以混乱,很大程度上是因为重复配置太多,每个Panel都要独立配置,没有复用。解决这个问题的关键,是模块化和代码化。把重复的配置,抽成模板,用代码生成的方式,实现复用。

不要局限于Grafana本身提供的功能,要善于用外部工具和脚本,来弥补Grafana的不足。代码化,是解决一切配置混乱的万能钥匙。

4. 版本管理,是一切的基础

不管是什么配置,只要是重要的,都应该纳入版本管理。版本管理,能让你追溯历史,回滚错误,协作开发。没有版本管理的配置,就像没有备份的数据,随时可能丢失,随时可能出错。

Grafana的Dashboard,虽然可以在界面上配置,但是一定要导出成JSON,放到Git仓库里管理。这是最基本的,也是最重要的。

5. 文档和培训,不能少

重构,不是一个人的事情,是整个团队的事情。重构完成之后,一定要写文档,做培训,让团队成员都知道新的规范和流程,都愿意用。

如果只有你一个人用新的方式,其他人还是老样子,那重构就失败了。只有整个团队,都按照新的规范和流程来做,重构的成果,才能保持下去,才能持续发挥价值。

6. 重构不是一次性的,是持续的

重构,不是做完一次,就一劳永逸了。随着业务的发展,新的需求会不断出现,新的问题也会不断出现。所以,重构是持续的,要不断地优化,不断地改进。

建立持续改进的机制,定期回顾,发现问题,及时优化。让你的Grafana(以及其他系统),始终保持健康、高效、可维护的状态。

六、写在最后

Grafana,是一个强大的监控可视化工具。但是,工具再强大,如果用得不好,配置混乱,也发挥不出它的价值,反而会成为负担。

这次重构,让我们的Grafana,从混乱变得优雅,从难以维护变得轻松高效。新增Dashboard的效率,提升了三倍;维护成本,降低了很多;团队协作,也更顺畅了。

其实,不仅仅是Grafana,任何系统、任何代码,都是一样的。混乱的配置、重复的代码、不规范的风格,都会让维护成本越来越高,效率越来越低。而重构,就是解决这些问题的最好方式。

重构,不是为了重构而重构,而是为了让系统更健康,让代码更优雅,让工作更高效,让生活更美好。

最后,用一句话来结束这篇文章:"代码如人,需要定期梳理和保养。重构,不是推倒重来,而是在保留核心价值的基础上,让代码更优雅,让系统更健康。从混乱到优雅,只需要一次下定决心的重构。"

希望这篇文章,能给正在被Grafana(或者其他系统)配置混乱困扰的朋友,一些启发和帮助。如果你有不同的观点或者更好的方法,欢迎在评论区留言,我们一起交流。