摘要
文章封面图非原创,引用地址:volkovlabs.io/blog/provis…
登陆
Grafana UI
的账户/密码,设置数据源datasource
,新建仪表盘dashboards
等,这些数据都存储在哪里,这些应用数据如何迁移?更进一步,监控是一个持续开发工程,如何实现版本管理,加入到CI/CD
工作流中?
Grafana
作为一款强大的开源数据可视化与监控平台,在现代数据处理与分析领域占据着重要地位。本文探讨 Grafana
数据持久化与版本管理,文章由三大章节组成,第一章聚焦 Grafana
配置洞察,剖析核心配置文件及各项关键配置参数的意义与作用,这是加入 Grafana
应用开发的第一步;第二章围绕 Grafana
关系型数据库展开,简单阐述数据存储结构与原理,并介绍接管内嵌数据库sqilite3
的方法;第三章介绍 Grafana Provisioning
主动配置与版本管理,通过实践项目展示 Provisioning
配置迁移能力。
Grafana 配置洞察
从容器启动层面扒一扒所有相关参数
环境变量
进入启动的Grafana容器内,执行printenv
,打印所有环境变量
shell代码解读复制代码GF_PATHS_HOME=/usr/share/grafana HOSTNAME=4ff584f7c978 SHLVL=1 HOME=/home/grafana OLDPWD=/var/lib/grafana GF_PATHS_LOGS=/var/log/grafana GF_PATHS_PROVISIONING=/etc/grafana/provisioning TERM=xterm GF_PATHS_PLUGINS=/var/lib/grafana/plugins PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin GF_SECURITY_ADMIN_PASSWORD=admin GF_USERS_ALLOW_SIGN_UP=false GF_SECURITY_ADMIN_USER=admin GF_PATHS_CONFIG=/etc/grafana/grafana.ini GF_PATHS_DATA=/var/lib/grafana PWD=/var/lib/grafana/plugins TZ=Asia/Shanghai
配置解析
Linux操作系统中的命名习惯, /etc
配置, /var
数据, /usr
系统资源,下面列举出与用户配置相关的文件和目录。
类型 | 名称 | 变量名称 | 位置 | 文件类型 | 描述 |
---|---|---|---|---|---|
配置 | grafana.ini | GF_PATHS_CONFIG | /etc/grafana/grafana.ini | 文本文件 | Grafana初始化配置 |
provisioning | GF_PATHS_PROVISIONING | /etc/grafana/provisioning | 目录 | Provision Grafana主动配置 | |
数据 | data | GF_PATHS_DATA | /var/lib/grafana | 目录 | Grafana数据 |
plugins | GF_PATHS_PLUGINS | /var/lib/grafana/plugins | 目录 | Grafana插件 | |
日志 | logs | GF_PATHS_LOGS | /var/log/grafana | 目录 | Grafana日志 |
环境变量可以在 docker-compose.yaml
的启动参数 environment
中指定,建议不要改动。
服务启动参数
服务的二进制启动文件往往包含自身名称,可以查看容器内服务启动参数,执行命令
指令模板需要牢记:ps -ef | grep NAME,NAME无需与查询目标完全对应,该方式为模糊匹配
shell代码解读复制代码ps -ef | grep grafana
输出信息如下(格式化后):
shell代码解读复制代码grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:default.log.mode=console cfg:default.paths.data=/var/lib/grafana cfg:default.paths.logs=/var/log/grafana cfg:default.paths.plugins=/var/lib/grafana/plugins cfg:default.paths.provisioning=/etc/grafana/provisioning
启动参数可以在 docker-compose.yaml
的启动参数 command
中指定,建议不要改动。
服务启动配置文件加载
执行 docker logs CONTAINER
查看 grafana.log
文件,如下所示
在容器内部找不到日志文件
grafana.log
,原因是日志输出到 Stdout
可以进到容器中,查看
default.ini
和grafana.ini
,grafana.ini
是加了注释到default.ini
Grafana
容器在启动时,先读取默认初始化配置 /usr/share/grafana/conf/default.ini
,然后读取/etc/grafana/grafana.ini
,后者会合并(或覆盖)前者配置。
默认情况下,provisioning
目录是空的,这个在后面章节介绍。
Grafana 关系型数据存储
Grafana
所有应用数据都存储在关系型数据库中,数据库默认为: sqlite3
,数据库名称为 grafana.db
,存储在 /var/lib/grafana
目录下。
Grafana
应用数据存储官方支持(在系统文档中列举了的) mysql
, postgres
或 sqlite3
,下面介绍通过配置 grafana.ini
接管数据库存储。
mysql
适合 Web应用开发;postgres
更适合具有频繁写入操作和复杂查询的企业级应用程序;sqlite3
为内嵌数据库,适合Android
和iOS
上的移动端App
;
mysql
是最流行的开源关系型数据库,应用最为广泛。
配置文件 grafana.ini
数据库相关配置位于 [database]
下,默认是注释掉的,手动修改如下:
editorconfig代码解读复制代码#################################### Database #################################### [database] # You can configure the database connection by specifying type, host, name, user and password # as separate properties or as on string using the url properties. # Either "mysql", "postgres" or "sqlite3", it's your choice type = mysql host = grafana-mysql-demo port = 3306 name = my_grafana user = admin_grafana # If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" password = password_grafana # Use either URL or the previous fields to configure the database # Example: mysql://user:secret@host:port/database url = mysql://admin_grafana:password_grafana@grafana-mysql-demo:3306/my_grafana # Max idle conn setting default is 2 max_idle_conn = 2 # Max conn setting default is 0 (mean not set) max_open_conn = 0 # Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) conn_max_lifetime = 14400
创建 mysql 数据库
根据上一小节配置文件信息,创建数据库,命名为 my_grafana
,授权用户 admin_grafana
,密码为 password_grafana
。
在 docker-compose.yaml
中配置mysql
数据库,容器名为 grafana-mysql-demo
,在 mysql
启动时作初始化。
grafana
容器依赖于mysql
容器,所以应先启动mysql
容器并完成初始化后,再启动grafana
容器。
mysql
容器启动时,执行下列 sql
脚本,实现初始化
sql 代码解读复制代码# 创建数据库grafana
CREATE DATABASE my_grafana DEFAULT CHARACTER SET utf8mb4;
# 创建用户
CREATE USER 'admin_grafana'@'%' IDENTIFIED BY 'password_grafana';
# 权限授予(使用更安全的方式管理密码)
GRANT ALL PRIVILEGES ON my_grafana.* TO 'admin_grafana'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
使用 docker compose up -d
命令启动容器集群:
mysql
数据库端口 3306
暴露到本地 localhost
,使用 IDEA
右端数据库插件可登录查看,用户名密码: admin_grafana
/ password_grafana
。
此时已经接管内置数据库 sqlite3
,所有的落库操作都可以在 mysql
数据库中查询到,可以关注 dashboard
和 data_source
表。
Grafana Provisioning,主动配置与版本管理
Grafana Provisioning
通过配置文件的方式支持 datasources
、 dashboards
、 plugins
、 Alerting rules
等功能。
对于 Grafana
新手来说, Provisioning
是一个比较新的概念,需要花点时间去理解,我提出两个问题,引出 Grafana Provisioning
。
问题1:如何实现Grafana仪表盘的迁移?
作为一名运维开发人员,我辛辛苦苦手动配置了数十个仪表盘,以及数百个Panel,所有的数据都存储在开发环境中。
现在需要将仪表盘迁移到生产环境,如何实现?
公司招聘了新员工加入团队,如何将已有工作迁移给新员工?
Grafana
的所有数据都存储在关系型数据库 grafana.db
中,包括仪表盘、数据源、用户、权限、插件等。
方案一:数据库全量迁移
上一章节内容启动 grafana
容器时,不使用内置 sqlite3
,而主动托管 grafana.db
数据库。
与数据库迁移类似,将 grafana.db
文件拷贝到新的环境中,即可完成仪表盘迁移,详细过程可参考 备份Grafana
缺陷:操作复杂笨重,且全量数据库迁移,安全性低,很多用户私有数据一同被迁移。
方案二:描述文件迁移
grafana.db
中仪表盘描述文件是以 json
格式存储的,所以可以很方便的通过 json
文件进行导出和导入。
在 Grafana
容器启动后,手动在 Grafana UI
中导入 dashboard.json
,这依赖于手工操作,需要制定合理的制度规范。
在程序员的世界中,手工操作是笨拙的,遵行宗旨:尽可能自动化一切手工操作
Grafana Provisioning
提供了更好的解决方式,既不直接操作数据库,也不需要手动迁移 dashboard
,简单易用、安全性高且可迁移性好。
问题2:如何实现仪表盘的版本管理?
Grafana
仪表盘配置是一个长期工作,会随着需求的变化而更新,因此需要支持像源代码一样的版本管理。
Grafana
在仪表盘修改中支持了版本管理,通过版本管理,可以方便的回滚到之前的版本,也可以方便的查看变更历史。
Grafana UI
中的版本管理是Dashboard
级别的,而用户更新是Panel
级别的
Grafana
仪表盘的版本管理有局限性:
- 版本零碎:
Grafana
版本修改是仪表盘级别的,修改仪表盘内的任何一个Panel
,将会产生一个版本,这样会产生大量的版本。 - 操作风险:版本管理仅限于
Dashboard
中的Panel
等信息,如果数据源或数据格式已经发生变化,回滚版本可能无法正常工作。 - 协作困难:以某个版本为基准,多个人同时修改,合并困难且容易产生冲突。
理想情况是 Grafana
数据可以像源代码一样使用 Git
追踪和管理,并在类似于 GitLab
或 GitHub
上托管源代码,持续集成。
Grafana Provisioning
提供了这个能力。
Grafana Provisioning介绍与实践
Grafana has an active provisioning system that uses configuration files. This makes GitOps more natural since data sources and dashboards can be defined using files that can be version controlled.
Grafana
有一个使用配置文件的主动配置系统。使用可进行版本控制的文件来定义数据源和仪表板,这使得 GitOps 更加自然。
在
Provision Grafana
官方文档页面,有关于Provisioning
的详细参数定义描述文档,在此不做知识搬运式描述。下面将配置数据源
datasource
和dashboard
的方式快速实践体验。
数据源Datasource
在容器中查看 provisioning-datasource
示例 sample.yaml
,位置:
/usr/share/grafana/conf/provisioning/datasources/sample.yaml
yaml 代码解读复制代码# Configuration file version
apiVersion: 1
# # List of data sources to delete from the database.
# deleteDatasources:
# - name: Graphite
# orgId: 1
# # List of data sources to insert/update depending on what's
# # available in the database.
# datasources:
# # Sets the name you use to refer to
# # the data source in panels and queries.
# - name: Graphite
# # Sets the data source type.
# type: graphite
# # Sets the access mode, either
# # proxy or direct (Server or Browser in the UI).
# # Some data sources are incompatible with any setting
# # but proxy (Server).
# access: proxy
# # Sets the organization id. Defaults to orgId 1.
# orgId: 1
# # Sets a custom UID to reference this
# # data source in other parts of the configuration.
# # If not specified, Grafana generates one.
# uid: my_unique_uid
# # Sets the data source's URL, including the
# # port.
# url: http://localhost:8080
# # Sets the database user, if necessary.
# user:
# # Sets the database name, if necessary.
# database:
# # Enables basic authorization.
# basicAuth:
# # Sets the basic authorization username.
# basicAuthUser:
# # Enables credential headers.
# withCredentials:
# # Toggles whether the data source is pre-selected
# # for new panels. You can set only one default
# # data source per organization.
# isDefault:
# #
# jsonData:
# # Defines the Graphite service's version.
# graphiteVersion: '1.1'
# # Enables TLS authentication using a client
# # certificate configured in secureJsonData.
# tlsAuth: true
# # Enables TLS authentication using a CA
# # certificate.
# tlsAuthWithCACert: true
# #
# secureJsonData:
# # Defines the CA cert, client cert, and
# # client key for encrypted authentication.
# tlsCACert: '...'
# tlsClientCert: '...'
# tlsClientKey: '...'
# # Sets the database password, if necessary.
# password:
# # Sets the basic authorization password.
# basicAuthPassword:
# # Sets the version. Used to compare versions when
# # updating. Ignored when creating a new data source.
# version: 1
# # Allows users to edit data sources from the
# # Grafana UI.
# editable: false
定义 prometheus-demo
数据源,命名为 prometheus-datasource.yaml
yaml 代码解读复制代码apiVersion: 1
datasources:
- name: prometheus
type: prometheus
access: proxy
url: http://prometheus-demo:9090
user:
password:
isDefault: true
仪表盘Dashboard
与 datasources
不同的是, dashboards
有两层结构:
- 在
/etc/grafana/provisioning/dashboards
下定义dashboards
配置文件,其中指明dashboard
目录,推荐为/var/lib/grafana/dashboards
- 在
/var/lib/grafana/dashboards
目录下存放dashboard
描述文件,格式为json
,可由Grafana UI
导出
仪表盘信息示例位于 /usr/share/grafana/conf/provisioning/dashboards/sample.yaml
yaml 代码解读复制代码# # config file version
apiVersion: 1
#providers:
# - name: 'default'
# orgId: 1
# folder: ''
# folderUid: ''
# type: file
# options:
# path: /var/lib/grafana/dashboards
自定义 node-exporter-demo
仪表盘,配置文件
yaml 代码解读复制代码apiVersion: 1
providers:
- name: default
orgId: 1
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
仪表盘描述文件内容过大,见项目仓库 Node-Exporter-Full
项目文件编排
用户自定义的配置文件和数据文件,需 volume
挂载,下面进行编排规划。
在项目根目录下创建volumes
文件夹,编排如下
学习
Linux
文件管理规范
shell代码解读复制代码. ├── grafana │ ├── grafana.ini │ └── provisioning │ ├── etc │ │ ├── dashboards │ │ │ └── config.yaml │ │ └── datasources │ │ └── prometheus-datasource.yaml │ └── var │ └── dashboards │ └── node-exporter-full.json └── mysql └── init.d └── grafana.sql
最佳实践
在笔者实践中,没有体会到托管 grafana.db
的价值,内嵌 sqlite3
已经足够。
容器目录挂载,应只关注与用户相关并产生交互的文件和目录。
一切安排就绪,可以启动了。
shell代码解读复制代码docker compose up -d
在Grafana UI
中体验
不再使用时卸载
shell代码解读复制代码docker compose down
Git版本管理
本文提供2个 Git
分支: gf-provision
, gf-provision-mysql
,两个分支均为 Grafana
配置及数据持久化,后者使用 mysql
托管内嵌 sqlite3
。
总结
本文聚焦 Grafana
数据持久化,首先介绍了容器启动的 Grafana
环境变量、配置文件、启动参数,其应用数据默认存于内嵌 sqlite3
,接着阐述如何自行使用 mysql
接管;然后介绍 Grafana Provisioning
解决仪表盘迁移和版本管理问题,最后通过实践项目体验 Provisioning
的能力。
学完本章,对 Grafana
的理解更进一步,但开发范式仍达不到 CI/CD
的目标。如何使得 Grafana
仪表盘的开发像编写 Java
、 Python
代码一样方便,如何更方便地实现代码复制、开发测试、代码审查、代码发布等,并逐渐向 CI/CD
目标靠近,是下一步工作。
参考
- Grafana,grafana.com/
- Node-Exporter,github.com/prometheus/…
- Grafana dashboards, Node Exporter Full,grafana.com/grafana/das…
- Docker Compose,github.com/docker/comp…
- Run Grafana Docker image,grafana.com/docs/grafan…
- connect from a container to a service on the host,docs.docker.com/desktop/fea…
- Provision Grafana,grafana.com/docs/grafan…
- Grafana管理历史版本,grafana.org.cn/docs/grafan…
- Grafana Foundation SDK,github.com/grafana/gra…
- Provision dashboards and datasources,grafana.com/tutorials/p…
- Provisioning in Grafana,volkovlabs.io/blog/provis…
评论记录:
回复评论: