拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Grafana离线插件部署:完整交付链路与信创适配实践

Grafana离线插件部署:完整交付链路与信创适配实践

1. 项目概述:为什么离线环境下的Grafana部署必须“插件先行”

Grafana不是装上就能用的开箱即用工具,它真正的价值藏在插件里——数据源插件让监控系统能对接Prometheus、Doris、MySQL甚至私有API;面板插件把枯燥的折线图变成3D地理热力图或实时设备拓扑;告警插件把Alertmanager的静默规则翻译成企业微信/钉钉/飞书的可操作消息。但现实很骨感:金融核心机房禁止外网访问,能源集团内网与互联网物理隔离,军工研究所的服务器连DNS都只允许白名单解析。这时候你点开Grafana界面右上角的“+ Add new panel”,弹出的却是“Plugin not found”;想装一个支持国产达梦数据库的datasource插件,页面提示“Failed to fetch plugin list”。这不是配置错误,是网络策略在说话。

我去年帮某省级电网做SCADA系统可视化升级,三台Grafana服务器全部部署在生产控制大区(安全Ⅱ区),与管理信息大区(安全Ⅲ区)之间仅通过单向光闸传输数据,HTTP/HTTPS出向流量被完全阻断。当时团队花了整整两天时间,在一台能联网的笔记本上手动下载、校验、打包、拷贝、解压、签名、重启服务,才让第一个Zabbix数据源插件跑起来。后来我们把整个流程标准化为“离线插件交付包”,包含插件二进制文件、SHA256校验值、依赖清单、安装脚本和回滚方案,现在新项目上线插件部署时间压缩到15分钟以内。这篇文章不讲“Grafana怎么安装”,而是聚焦你真正卡住的地方:如何在没有网络的服务器上,让插件稳稳落地、一次成功、可审计、可复现。适合运维工程师、SRE、信创项目实施人员,以及所有需要在等保三级、分保、工控环境里部署监控系统的实战派。

2. 离线插件部署的核心逻辑:不是“下载”,而是“交付链路设计”

很多人把“离线插件下载”理解成“找个能联网的电脑,把插件zip包下下来,拷过去解压”。这就像把一整套手术器械消毒后直接扔进手术室——没分类、没清单、没灭菌记录、没适配主刀医生习惯。Grafana插件离线部署的本质,是一条从上游源站到下游生产环境的可信交付链路,它必须同时满足四个刚性条件:

  • 完整性:插件包必须包含所有运行时依赖,不能缺.plugin.json、不能少dist/目录、不能漏module.js入口文件;
  • 一致性:同一版本插件在不同环境安装后,行为必须100%一致,不能出现“开发机OK,测试机报错,生产机崩溃”;
  • 可验证性:每个文件必须附带官方签名或SHA256哈希值,确保未被中间环节篡改;
  • 可追溯性:插件来源、版本号、安装时间、操作人、变更原因必须留痕,满足等保审计要求。

这就决定了离线部署不能靠“手工下载+手动解压”这种原始方式。我见过最典型的失败案例:某银行数据中心运维小哥,在官网下载了grafana-simple-json-datasource-v1.5.0.zip,解压后发现plugin.json里写着"id": "simple-json",但实际安装时Grafana日志报错Plugin with ID "simple-json" is not valid。查了半小时才发现,这个插件在v1.4.0之后重构了ID,新版ID是"simplejson",而他下载的zip包里plugin.json文件名是plugin.json,但内容里ID字段写的是旧值——这是上游发布流程的bug,但离线环境下你根本没法实时反馈、没法自动更新。最终解决方案是:我们建立了一个内部插件仓库镜像,所有插件入库前必须通过grafana-cli plugins validate命令校验,并生成带版本戳的JSON元数据文件,再由CI流水线自动打包成simplejson-v1.5.0-offline.tar.gz,里面不仅有插件文件,还有manifest.json(含校验值)、install.sh(含权限设置、软链接创建、服务重载)、rollback.sh(一键卸载并恢复备份)。这才是离线部署该有的样子。

2.1 插件类型决定交付策略:Datasource、Panel、App三类插件的离线处理差异

Grafana插件按功能分为三大类,它们的离线部署复杂度逐级递增:

  • Datasource(数据源)插件:如Prometheus、MySQL、InfluxDB、Doris、达梦、人大金仓等。这类插件本质是Go语言编译的二进制文件(.so或.dll)或JavaScript模块,依赖关系相对简单。离线部署核心是版本锁定与协议兼容性验证。例如grafana-mysql-datasourcev2.4.0要求Grafana v9.5.0+,而v2.3.0只支持v8.x,如果混用会导致“Data source is not available”错误。实操中,我们用grep -r "min grafana version" /path/to/plugin/快速定位最低版本要求。

  • Panel(面板)插件:如Worldmap、Pie Chart、Gauge、Status Dot等。这类插件多为前端React/Vue组件,依赖Node.js构建环境。离线难点在于前端资源路径硬编码。比如某个面板插件在dist/module.js里写了fetch('/public/plugins/grafana-worldmap-panel/libs/leaflet.js'),但离线环境里Grafana的public目录结构可能因版本变化而不同。解决方案是:在打包前用sed -i 's|/public/plugins/|/plugins/|g' dist/*.js统一替换路径,再用grafana-cli plugins install --skip-verify跳过签名检查(仅限可信内网)。

  • App(应用)插件:如Alerting、Grafana Image Renderer、AWS CloudWatch App等。这是最复杂的类型,往往包含后端服务(如Image Renderer需独立运行grafana-image-renderer容器)、前端路由、RBAC权限定义。离线部署必须拆解为多组件交付包。以Image Renderer为例,离线包需包含:①grafana-image-renderer二进制文件(Linux AMD64/ARM64双架构);②renderer_config.json模板;③ systemd服务单元文件;④ Grafana主配置grafana.ini中[remote_image_renderer]段落的补丁;⑤ 验证脚本test-renderer.sh(调用curl -X POST http://localhost:8081/render --data '{"url":"http://localhost:3000/d-solo/xxx?orgId=1&panelId=2&width=1000&height=500&tz=Asia/Shanghai"}')。

提示:不要试图用grafana-cli plugins install xxx命令在离线机上执行——它会尝试连接https://grafana.com/api/plugins/,必然超时失败。所有插件安装必须通过文件系统拷贝+手动注册完成。

2.2 版本匹配是生死线:Grafana主版本、插件版本、依赖库版本的三角校验

Grafana的版本兼容性不是线性的,而是网状的。举个真实例子:某客户用Grafana v8.5.17部署Doris监控,选了社区热门插件apache-doris-datasourcev1.2.0。安装后一切正常,但当他们升级Grafana到v9.5.14时,面板加载报错TypeError: Cannot read property 'apply' of undefined。查日志发现,插件v1.2.0依赖的@grafana/data库版本是^8.0.0,而Grafana v9.x已升级到@grafana/data@9.5.14,其DataFrame接口发生了breaking change。根本原因在于:插件作者在package.json里写了"peerDependencies": {"@grafana/data": "^8.0.0"},但没做v9.x兼容测试。

我们总结出一套“三角校验法”来规避此类问题:

  1. Grafana主版本校验:运行grafana-server -v获取精确版本(如Version 9.5.14 (commit: 5a7b3e2d6, branch: HEAD)),注意commit和branch也影响插件兼容性;
  2. 插件版本校验:查看插件plugin.json中的"dependencies"字段,重点核对"@grafana/ui"、"@grafana/data"、"@grafana/runtime"三个核心包的版本范围;
  3. 依赖库版本校验:进入Grafana安装目录/usr/share/grafana/public/app/plugins/,用ls -la node_modules/@grafana/确认实际安装的依赖版本,与插件要求的范围做交集判断。

实操技巧:我们维护一个内部Excel表格,列明常用插件在各Grafana版本下的实测状态(✅通过 / ⚠️需补丁 / ❌不兼容),并标注已知问题。例如grafana-piechart-panel在v9.5.x中存在tooltip文字截断bug,解决方案是打一个patch文件,替换dist/module.js中第1234行的maxWidth: 200为maxWidth: 400。这个表格比官网文档更可靠,因为它是基于真实生产环境踩坑积累的。

3. 实操全流程:从插件发现、下载、校验到安装、验证、回滚的完整闭环

离线插件部署不是单点操作,而是一个包含7个标准步骤的闭环流程。下面以部署grafana-zabbix-datasourcev4.2.1(适配Grafana v9.5.x)为例,全程演示每一步的命令、参数、原理和避坑点。

3.1 步骤1:插件发现与元数据采集——别只看官网,要挖GitHub Release和CI Artifact

插件官方发布渠道有三个层级,优先级从高到低:

  • 第一优先级:GitHub Release页面(如https://github.com/alexanderzobnin/grafana-zabbix/releases)。这里发布的是经过CI流水线构建、签名、测试的正式版,包含sha256sum.txt校验文件和assets附件。注意看Release Note里的Compatibility字段,明确写着Grafana >= 9.0.0;
  • 第二优先级:Grafana官方插件库API(https://grafana.com/api/plugins/grafana-zabbix-datasource/versions)。返回JSON格式的版本列表,含version、downloadUrl、signature、createdAt等字段。可用curl -s https://grafana.com/api/plugins/grafana-zabbix-datasource/versions | jq '.versions[] | select(.version=="4.2.1")'精准提取;
  • 第三优先级:npm registry(https://registry.npmjs.org/@grafana/zabbix-datasource)。适用于纯前端插件,返回dist-tags和versions,但缺少Grafana版本兼容性声明。

注意:绝对不要从第三方博客、论坛、网盘下载插件!曾有客户从某技术社区下载了“破解版”Zabbix插件,里面植入了挖矿脚本,导致监控服务器CPU持续100%。

实操命令:

# 1. 创建工作目录 mkdir -p /tmp/grafana-zabbix-offline && cd /tmp/grafana-zabbix-offline # 2. 从GitHub Release下载插件包(注意URL中的tag名) curl -L -o grafana-zabbix-datasource-4.2.1.zip \ https://github.com/alexanderzobnin/grafana-zabbix/releases/download/v4.2.1/grafana-zabbix-datasource-4.2.1.zip # 3. 下载对应的SHA256校验文件 curl -L -o sha256sum.txt \ https://github.com/alexanderzobnin/grafana-zabbix/releases/download/v4.2.1/sha256sum.txt # 4. 校验下载完整性(关键!) sha256sum -c sha256sum.txt 2>&1 | grep "OK" # 输出应为:grafana-zabbix-datasource-4.2.1.zip: OK

3.2 步骤2:插件解包与结构分析——读懂plugin.json才是安装成功的前提

下载的zip包解压后,核心文件只有三个:

  • plugin.json:插件的“身份证”,必须包含"id"(唯一标识符,如"zabbix")、"name"(显示名称)、"type"("datasource")、"info"(作者、链接)、"dependencies"(依赖库);
  • dist/目录:编译后的前端资源,含module.js(入口文件)、plugin.css(样式)、img/(图标);
  • README.md:使用说明,重点关注Installation和Configuration章节。

关键检查点:

  • plugin.json中的"id"字段必须与Grafana配置文件中引用的ID一致。例如,如果你在grafana.ini里写了[zabbix],那么plugin.json里"id"就必须是"zabbix",不能是"grafana-zabbix"或"zabbix-datasource";
  • dist/module.js文件大小不能为0,且必须包含define(['./module'], function(module) { return module; });这样的AMD模块定义;
  • 检查plugin.json中"includes"字段,确认"pages"数组里是否包含"configuration"(配置页)和"dashboard"(仪表盘页),缺失会导致Grafana UI找不到插件入口。

实操命令:

# 解压并进入目录 unzip grafana-zabbix-datasource-4.2.1.zip && cd grafana-zabbix-datasource-4.2.1 # 查看plugin.json核心字段 jq '.id, .name, .type, .info.version, .dependencies' plugin.json # 检查dist目录结构 ls -la dist/ # 正常输出应包含:module.js plugin.css img/ fonts/ # 验证module.js是否为有效JS(防止被篡改) head -n 5 dist/module.js | grep -E "(define|import|export)"

3.3 步骤3:离线安装包构建——为什么不能直接拷贝zip包?

直接把zip包拷到生产机/var/lib/grafana/plugins/下解压是危险的。原因有三:

  • 权限错误:Grafana服务以grafana用户运行,但解压后文件属主可能是root,导致服务无法读取;
  • 路径错误:Grafana要求插件目录名必须与plugin.json中"id"字段完全一致(如"id": "zabbix"→ 目录名必须是zabbix),而zip包解压后目录名可能是grafana-zabbix-datasource-4.2.1;
  • 缺少软链接:某些插件(如Image Renderer)需要在/usr/local/bin/创建可执行文件软链接。

因此,我们必须构建一个标准化的离线安装包。结构如下:

zabbix-datasource-offline-v4.2.1/ ├── install.sh # 主安装脚本 ├── uninstall.sh # 卸载脚本 ├── zabbix/ # 重命名后的插件目录(与plugin.json.id一致) │ ├── plugin.json │ ├── dist/ │ └── README.md ├── manifest.json # 元数据:版本、校验值、Grafana兼容性 └── docs/ # 安装后配置指南(PDF/Markdown)

install.sh核心逻辑:

#!/bin/bash set -e PLUGIN_DIR="/var/lib/grafana/plugins" PLUGIN_ID="zabbix" PLUGIN_VERSION="4.2.1" # 1. 备份原有插件(防覆盖) if [ -d "$PLUGIN_DIR/$PLUGIN_ID" ]; then mv "$PLUGIN_DIR/$PLUGIN_ID" "$PLUGIN_DIR/${PLUGIN_ID}_backup_$(date +%Y%m%d_%H%M%S)" fi # 2. 拷贝新插件(保持权限) cp -r "./$PLUGIN_ID" "$PLUGIN_DIR/" # 3. 设置正确属主 chown -R grafana:grafana "$PLUGIN_DIR/$PLUGIN_ID" # 4. 重启Grafana服务(或发送SIGHUP) systemctl reload grafana-server echo "✅ Zabbix datasource v$PLUGIN_VERSION installed successfully."

3.4 步骤4:生产环境安装与服务重载——重启不是万能的,SIGHUP更优雅

在生产环境执行安装,有两条路径:

  • 路径A:systemctl reload grafana-server(推荐)。Grafana v8.0+支持热重载插件,只需发送SIGHUP信号,服务不中断,现有Dashboard和告警规则持续运行。命令:sudo systemctl reload grafana-server;
  • 路径B:systemctl restart grafana-server(谨慎)。全量重启会导致10-30秒监控数据断连,告警可能误触发。仅在插件修改了后端逻辑(如Datasource的Go二进制)时必须使用。

验证安装是否生效:

# 1. 检查插件目录权限 ls -la /var/lib/grafana/plugins/zabbix/ # 应显示:drwxr-xr-x 4 grafana grafana ... zabbix/ # 2. 查看Grafana日志(实时) sudo journalctl -u grafana-server -f | grep -i "zabbix" # 正常输出:t=2024-06-15T10:20:30+0800 lvl=info msg="Plugin registered" pluginID=zabbix # 3. 检查HTTP API(无需登录) curl -s http://localhost:3000/api/plugins | jq '.[] | select(.id=="zabbix")' # 返回包含:{"id":"zabbix","name":"Zabbix","type":"datasource",...}

注意:如果journalctl日志里出现"Plugin failed to load",90%原因是plugin.json里的"id"与目录名不一致,或dist/module.js路径错误。此时不要重启服务,先检查/var/log/grafana/grafana.log里的详细堆栈。

3.5 步骤5:功能验证与冒烟测试——用curl写一个自动化检测脚本

安装成功不等于能用。必须做三层次验证:

  • L1:插件注册验证(已做);
  • L2:UI可访问验证:打开http://<grafana-ip>:3000/plugins/zabbix-app/page/config,应显示Zabbix配置页面;
  • L3:数据查询验证:用curl模拟Grafana前端请求,验证数据源能否返回真实数据。

我们编写了一个smoke-test.sh脚本,作为每次插件部署后的必跑项:

#!/bin/bash # 冒烟测试:验证Zabbix插件能否连通并返回主机列表 GRAFANA_URL="http://localhost:3000" GRAFANA_USER="admin" GRAFANA_PASS="your_password" # 1. 获取API Key(避免密码明文) API_KEY=$(curl -s -X POST "$GRAFANA_URL/login" \ -H "Content-Type: application/json" \ -d '{"user":"'$GRAFANA_USER'","password":"'$GRAFANA_PASS'"}' \ | jq -r '.message') # 2. 创建临时Zabbix数据源(POST) DS_ID=$(curl -s -X POST "$GRAFANA_URL/api/datasources" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name":"SmokeTest-Zabbix", "type":"zabbix", "url":"http://zabbix-server/api_jsonrpc.php", "access":"proxy", "basicAuth":false, "jsonData":{"keepCookies":[],"timeout":"30"} }' | jq -r '.id') # 3. 查询Zabbix主机列表(GET) RESPONSE=$(curl -s -X GET "$GRAFANA_URL/api/datasources/$DS_ID/resources/hosts" \ -H "Authorization: Bearer $API_KEY") # 4. 判断是否返回有效JSON数组 if echo "$RESPONSE" | jq -e '. | type == "array"' > /dev/null; then echo "✅ Smoke test passed: Zabbix hosts list retrieved." exit 0 else echo "❌ Smoke test failed: $RESPONSE" exit 1 fi

3.6 步骤6:回滚方案设计——不是“删目录”,而是“原子化切换”

线上环境最怕“安装失败后手忙脚乱删文件”。我们的回滚方案基于符号链接原子切换:

  • 在/var/lib/grafana/plugins/下创建两个目录:zabbix-v4.2.1/和zabbix-v4.1.0/;
  • 创建软链接:ln -sf zabbix-v4.2.1 zabbix;
  • 回滚时只需执行:ln -sf zabbix-v4.1.0 zabbix,毫秒级切换,无服务中断。

rollback.sh脚本:

#!/bin/bash set -e PLUGIN_ID="zabbix" OLD_VERSION="4.1.0" NEW_VERSION="4.2.1" cd /var/lib/grafana/plugins # 1. 切换软链接指向旧版本 ln -sf "${PLUGIN_ID}-v${OLD_VERSION}" "$PLUGIN_ID" # 2. 重载服务 systemctl reload grafana-server # 3. 验证 curl -s http://localhost:3000/api/plugins | jq -r ".[] | select(.id==\"$PLUGIN_ID\") | .info.version" # 应输出:4.1.0

3.7 步骤7:审计日志与交付物归档——满足等保三级“安全审计”要求

等保三级要求:“应对分布式计算环境中重要节点的重要行为进行审计”。插件部署属于“重要行为”,必须留存以下交付物:

  • delivery-manifest.json:含插件ID、版本、下载时间、校验值、操作人、审批单号;
  • install-log.txt:install.sh执行时的完整stdout/stderr;
  • smoke-test-report.html:冒烟测试的截图和curl响应体;
  • rollback-plan.md:回滚步骤、影响范围、回退时间窗口。

我们用一个archive.sh脚本自动打包:

#!/bin/bash TIMESTAMP=$(date +%Y%m%d_%H%M%S) ARCHIVE_NAME="zabbix-offline-delivery-$TIMESTAMP.tar.gz" tar -czf "$ARCHIVE_NAME" \ delivery-manifest.json \ install-log.txt \ smoke-test-report.html \ rollback-plan.md \ install.sh \ uninstall.sh # 上传至内部审计系统(示例) curl -X POST "https://audit.internal/api/v1/deliveries" \ -F "file=@$ARCHIVE_NAME" \ -F "project=SCADA-Monitoring" \ -F "operator=$USER"

4. 常见问题与排查技巧实录:那些官网不会写的“血泪经验”

4.1 问题1:“Plugin with ID 'xxx' is not valid” —— 90%是plugin.json的ID与目录名不匹配

现象:Grafana日志报错Plugin with ID "mysql" is not valid,但plugin.json里明明写了"id": "mysql"。

根因分析:Grafana扫描/var/lib/grafana/plugins/目录时,会把子目录名作为插件ID。如果你把插件解压到/var/lib/grafana/plugins/mysql-datasource-1.0.0/,那么Grafana会认为插件ID是mysql-datasource-1.0.0,而不是plugin.json里声明的mysql。

解决方案:

  • 安装前,务必重命名目录:mv mysql-datasource-1.0.0 mysql;
  • 或者,在plugin.json里把"id"字段改成"mysql-datasource-1.0.0"(不推荐,破坏插件标准);
  • 最佳实践:在离线包构建阶段就用install.sh自动重命名。

实操心得:我们给所有插件目录加了前缀offline-,如offline-mysql,并在install.sh里用basename提取ID。这样既避免命名冲突,又一眼识别离线插件。

4.2 问题2:“Failed to load plugin” —— 前端资源404,其实是路径硬编码

现象:Grafana UI能看见插件,但点击“Add data source”时空白,浏览器F12 Console报错GET http://localhost:3000/public/plugins/mysql/img/logo.svg 404。

根因分析:插件dist/module.js里写了require('./img/logo.svg'),但Grafana v9.x的静态资源路径已从/public/plugins/改为/plugins/。

解决方案:

  • 用sed批量替换路径:sed -i 's|/public/plugins/|/plugins/|g' dist/*.js dist/*.css;
  • 或者,在Grafana配置grafana.ini中添加:[paths] plugins = /var/lib/grafana/plugins,确保路径映射正确;
  • 终极方案:联系插件作者,提交PR修复路径,我们已为grafana-worldmap-panel等5个主流插件提交了路径修复补丁。

4.3 问题3:“Data source is not available” —— Datasource插件的Go二进制缺失或架构不匹配

现象:插件注册成功,但添加数据源时提示Data source is not available,日志里有exec: "mysql_ds_linux_amd64": executable file not found in $PATH。

根因分析:Grafana v8.0+的Datasource插件很多采用Go编写,需提供对应CPU架构的二进制文件(如linux_amd64、linux_arm64)。离线下载时,如果只下了x86_64包,而生产机是ARM64(如鲲鹏、飞腾),就会失败。

解决方案:

  • 下载时确认目标服务器架构:uname -m(x86_64oraarch64);
  • 从GitHub Release的Assets里下载对应架构的二进制,如mysql-datasource-linux-arm64.zip;
  • 将二进制文件放入插件dist/目录,并在plugin.json的"backend"字段里指定路径。

4.4 问题4:“Plugin signature verification failed” —— 离线环境下如何安全绕过签名检查

现象:grafana-cli plugins install --skip-verify在离线机上无效,因为--skip-verify只是跳过网络签名验证,但Grafana服务启动时仍会校验本地文件签名。

根因分析:Grafana默认开启plugin_signature_enabled = true,要求所有插件必须有有效签名。离线环境无法连接https://grafana.com/api/plugins/signatures验证。

解决方案(三选一):

  • 方案A(推荐):在grafana.ini中关闭签名检查:
    [plugins] allow_loading_unsigned_plugins = mysql,postgres,zabbix # 注意:只允许可信插件ID,不要写*!
  • 方案B:用grafana-cli在联网机上生成签名,再拷贝到离线机(复杂,仅限高安全要求场景);
  • 方案C:编译Grafana时禁用签名(不推荐,失去官方更新能力)。

注意:allow_loading_unsigned_plugins参数必须用英文逗号分隔插件ID,不能有空格,否则整个参数失效。

4.5 问题5:“Grafana failed to upgrade legacy queries” —— 迁移老版本面板时的插件兼容性陷阱

现象:从Grafana v7.x升级到v9.x后,原有Dashboard加载失败,报错Grafana failed to upgrade legacy queries datasource im7_otuvz was not found。

根因分析:Grafana v8.0重构了查询引擎,老面板里保存的datasourceUid(如im7_otuvz)是旧版UID,而新插件注册后生成的是新UID(如P347A23F)。Grafana尝试自动映射失败。

解决方案:

  • 升级前,用grafana-cli admin reset-admin-password重置admin密码,登录后导出所有Dashboard JSON;
  • 升级后,用sed批量替换UID:sed -i 's/"datasource":"im7_otuvz"/"datasource":"P347A23F"/g' dashboard.json;
  • 或者,用Grafana API批量更新:curl -X PATCH http://localhost:3000/api/dashboards/db/<uid> -d '{"dashboard": {...}}'。

5. 工具链与自动化:把离线部署变成“一键交付”

手工执行7个步骤太慢,我们用Ansible+Shell构建了一套离线插件交付流水线,核心组件如下:

5.1 插件元数据管理器(Plugin Metadata Manager)

一个Python脚本,自动从GitHub/Grafana API抓取插件信息,生成plugins-catalog.json:

# catalog.py import requests import json def fetch_plugin_versions(plugin_id): url = f"https://grafana.com/api/plugins/{plugin_id}/versions" resp = requests.get(url) versions = resp.json()['versions'] # 过滤出兼容当前Grafana主版本的版本 compatible = [v for v in versions if v['grafanaVersion'] == '>=9.0.0'] return sorted(compatible, key=lambda x: x['version'], reverse=True)[0] catalog = {} for pid in ['zabbix', 'mysql', 'prometheus']: catalog[pid] = fetch_plugin_versions(pid) with open('plugins-catalog.json', 'w') as f: json.dump(catalog, f, indent=2)

5.2 离线包生成器(Offline Package Builder)

一个Makefile,定义插件构建规则:

# Makefile PLUGIN_ID = zabbix PLUGIN_VERSION = 4.2.1 all: $(PLUGIN_ID)-offline-$(PLUGIN_VERSION).tar.gz $(PLUGIN_ID)-offline-$(PLUGIN_VERSION).tar.gz: @echo "Building offline package for $(PLUGIN_ID) v$(PLUGIN_VERSION)..." @mkdir -p build/$(PLUGIN_ID) @curl -L https://github.com/.../$(PLUGIN_ID)-$(PLUGIN_VERSION).zip | \ unzip -d build/$(PLUGIN_ID) - @mv build/$(PLUGIN_ID)/$(PLUGIN_ID)-$(PLUGIN_VERSION)/* build/$(PLUGIN_ID)/ @rm -rf build/$(PLUGIN_ID)/$(PLUGIN_ID)-$(PLUGIN_VERSION) @cp install.sh build/$(PLUGIN_ID)/ @tar -czf $@ -C build $(PLUGIN_ID) clean: rm -rf build/ $(PLUGIN_ID)-offline-*.tar.gz

5.3 生产环境部署器(Production Deployer)

一个Ansible playbook,实现“零信任”部署:

# deploy-plugin.yml - name: Deploy Grafana plugin offline hosts: grafana_servers become: yes vars: plugin_tarball: "zabbix-offline-4.2.1.tar.gz" plugin_id: "zabbix" tasks: - name: Upload offline package ansible.builtin.copy: src: "files/{{ plugin_tarball }}" dest: "/tmp/{{ plugin_tarball }}" - name: Extract and install ansible.builtin.shell: | tar -xzf /tmp/{{ plugin_tarball }} -C /var/lib/grafana/plugins/ chown -R grafana:grafana /var/lib/grafana/plugins/{{ plugin_id }} args: executable: /bin/bash - name: Reload Grafana service ansible.builtin.systemd: name: grafana-server state: reloaded

这套工具链把单次插件部署时间从45分钟压缩到3分钟,且所有操作可审计、可回放、可批量。我们已将核心脚本开源在内部GitLab,命名为grafana-offline-deploy-kit,欢迎同行交流。

6. 扩展思考:离线部署不是终点,而是信创适配的起点

Grafana离线部署的价值,远不止于“没网也能用”。它实质上是信创改造的第一道关卡。我们正在做的几件事,或许对你有启发:

  • 国产CPU适配:为龙芯3A5000(LoongArch)、兆芯KX-6000(x86_64)、海光Hygon(x86_64)分别编译Grafana二进制和Datasource插件,构建多架构镜像;
  • 国产OS认证:在统信UOS、麒麟V10上验证所有插件,解决glibc版本兼容性问题(如麒麟V10默认glibc 2.28,而某些Go插件需2.31+);
  • 国密算法集成:修改Grafana源码,支持SM2/SM3/SM4国密算法,用于插件签名和HTTPS通信;
  • 离线AI增强:在离线环境中部署轻量级LLM(如Qwen1.5-0.5B),为Grafana提供自然语言查询(NLQ)能力,用户输入“显示最近24小时CPU使用率最高的3台服务器”,自动生成PromQL。

这些工作没有标准答案,每一步都在填坑。但正因如此,离线Grafana部署才不是一个技术点,而是一张通往自主可控监控体系的入场券。我最后想

返回列表