Grafana 数据源

概要

Grafana 可以与许多不同类型的存储后端接口,Grafana 将这些后端称为 数据源。由于“数据源”一词会导致混淆,因为它与 Watcher 中使用的定义重叠,因此这些**数据源被称为项目**。支持的项目示例包括 InfluxDB 或 Elasticsearch,而其他项目可能更熟悉,例如 Monasca 或 Gnocchi。Grafana 数据源提供检索 Grafana 中不同项目的指标的功能。此功能是通过使用 Grafana 中公开的代理接口直接与 Grafana 项目通信来实现的。

背景

由于检索 Grafana 中指标的查询会代理到项目,因此这些查询的格式会根据项目类型发生显著变化。项目本身的结构也会发生显著变化,因为它们由用户和管理员构建。例如,一些开发人员可能会决定将有关 compute_nodes 的指标存储在 MySQL 中,并使用 UUID 作为主键,而另一些人则使用 InfluxDB 并使用主机名作为主键。此外,Watcher 中的数据源应以特定单位返回指标,这些单位严格定义在 基类中,具体取决于指标在项目中存储的方式,可能需要在返回之前进行转换。Grafana 数据源的灵活配置参数允许精确指定部署的配置方式,这将能够正确检索指标并使用正确的单位。

需求

使用 Grafana 数据源需要可访问的 Grafana 端点以及用于访问所需项目的身份验证令牌。Grafana 后端项目需要包含 compute_nodes实例的指标,并且这些指标需要可以通过 Watcher 数据模型的属性(例如主机名或 UUID)来标识。

限制

  • 目前仅支持 InfluxDB 项目 [1]

  • 所有指标必须从相同的 Grafana 端点(相同的 URL)检索。

  • 所有指标必须使用相同的身份验证令牌检索。

配置

使用 Grafana 数据源需要几个步骤。大多数步骤都与配置 Watcher 以匹配部署的 Grafana 设置有关,例如代理到项目的查询或任何给定指标的项目类型。大多数配置可以通过传统的配置文件或在 特殊 yaml 文件中提供。

令牌

第一步是生成具有访问所需项目的访问令牌。这可以通过 api 或通过 Web 界面来完成。从 Web 界面生成的令牌将与创建它们的用户的项目访问权限相同,而使用 cli 允许为特定角色生成密钥。令牌只会显示一次,因此请妥善保存。此令牌将进入配置文件,并且此参数不能放在 yaml 中。

基础 URL

下一步是提供 Grafana 端点的基础 URL。基础 URL 参数需要指定 HTTP 协议的类型,并且强烈建议不要使用纯文本 HTTP,因为会传输访问令牌。此外,还需要提供到代理接口的路径,以防 Grafana 放置在 Web 服务器的子目录中。一个示例是:https://mygrafana.org/api/datasource/proxy/,其中 /api/datasource/proxy 是没有子目录的默认路径。同样,此参数不能放在 yaml 中。

为了防止发生许多错误并可能填充日志文件,建议在配置中指定所需的datasource,这将防止datasource 管理器在每次审计启动时迭代并尝试可能的datasource。为此,请在 [watcher_datasources] 组中指定 datasources

需要在传统配置文件中放置的当前配置如下

[grafana_client]
token = 0JLbF0oB4R3Q2Fl337Gh4Df5VN12D3adBE3f==
base_url = https://mygranfa.org/api/datasource/proxy

[watcher_datasources]
datasources = grafana

指标参数

最后五个剩余的配置参数都可以放在传统的配置文件或 yaml 中,但是不建议混合使用,但如果发生这种情况,yaml 将覆盖传统配置文件中的设置。这五个参数都是将特定指标映射到配置参数的字典。例如,project_id_map 将指定 Grafana 中要使用的特定项目 ID。参数的命名如下

  • project_id_map

  • database_map

  • translator_map

  • attribute_map

  • query_map

如果使用 yaml 配置,这些五个参数的命名方式如下,并且与传统配置文件的列表顺序相同

  • project

  • db

  • translator

  • attribute

  • 查询

当在 yaml 中指定时,这些参数不再是字典,而是需要将每个参数定义为每个指标的子参数。以下示例描述了 yaml 和传统配置中配置这些参数的示例。

project_id

只有在 Grafana 中具有管理员角色的用户才能确定项目 ID,因为该角色需要打开项目列表。可以在 Web 界面的 /datasources 中找到项目列表,但不幸的是,它不会立即显示项目 ID。要显示 ID,最好将鼠标悬停在项目上,URL 将显示项目 ID,例如 /datasources/edit/7563。或者,可以使用 REST api 检索整个项目列表。可以使用 Postman 等工具轻松地向 REST api 发出请求。

database

数据库是项目中实际定义的模式/数据库的参数。例如,如果项目基于 MySQL,则在此处指定 MySQL 服务器中使用的模式名称。对于许多不同的项目,可以列出当前可用的所有数据库。可以使用 Postman 等工具列出每个项目的可用数据库。对于基于 InfluxDB 的项目,路径和查询如下,但是请确保在 Postman 中构造这些请求,因为标头需要包含授权令牌

https://URL.DOMAIN/api/datasources/proxy/PROJECT_ID/query?q=SHOW%20DATABASES

translator

每个 translator 对应于特定类型的项目,将具有唯一可识别的名称,并且基类允许轻松支持新的项目类型,例如 Elasticsearch 或 Prometheus。目前仅支持基于 InfluxDB 的项目,因此此参数的唯一有效值为 ` influxdb`。

attribute

attribute 参数指定从 Watcher 的数据模型中使用哪个属性来构造查询。可用属性因数据模型中对象的类型而异,但下表显示了 ComputeNodes、Instances 和 IronicNodes 的属性。

ComputeNode

实例

IronicNode

uuid

uuid

uuid

id

name

human_id

hostname

project_id

power_state

status

watcher_exclude

maintenance

disabled_reason

locked

maintenance_reason

state

metadata

extra

memory

state

disk

memory

disk_capacity

disk

vcpus

disk_capacity

vcpus

其中许多属性(如果不是全部)都映射到从 Nova 等客户端获取的对象的属性。要查看如何将这些属性放入数据模型,可以分析以下源代码文件:NovaIronic

query

query 是最重要的参数,它将被传递到项目,应该为特定主机返回所需的指标,并以正确的单位返回该值。所有可用指标的单位记录在 datasource 基类中。这意味着 query 参数负责转换单位。以下 query 演示了如何实现这样的转换,并演示了从字节到兆字节的转换。

SELECT value/1000000 FROM memory...

query 将使用 Python 中的 .format 字符串方法格式化。当前此格式将暴露六个属性,标记为 {0}{4}。字符串中每次出现这些字符都将被替换为特定的属性。

{0}

是聚合通常 meanminmax,但 count 也受支持。

{1}

是 attribute 参数中指定的属性。

{2}

是聚合数据的时长,以秒为单位。

{3}

是粒度或数据点之间的间隔,以秒为单位。

{4}

是 translator 特定的,对于 InfluxDB 而言,它将用于 retention_periods。

InfluxDB

构造 query 或更准确地说,预测结果应该是什么样子以便 Watcher 正确解释结果可能是一个挑战。以下 json 示例演示了结果应该是什么样子以及用于获取此结果的 query。

{
"results": [
    {
        "statement_id": 0,
        "series": [
            {
                "name": "vmstats",
                "tags": {
                    "host": "autoserver01"
                },
                "columns": [
                    "time",
                    "mean"
                ],
                "values": [
                    [
                        1560848284284,
                        7680000
                    ]
                ]
            }
        ]
    }
]
}
SELECT {0}("{0}_value") FROM "vmstats" WHERE host =~ /^{1}$/ AND
"type_instance" =~ /^mem$/ AND time >= now() - {2}s GROUP BY host

示例配置

示例配置将显示如何通过配置文件实现整个配置,或使用常规文件和 yaml 的组合。建议使用 yaml 定义每个指标的所有参数,因为它具有更好的可读性并支持多行选项定义。

配置文件

重要的是要注意,配置文件中参数赋值之间的换行符不能在实际配置中使用,这些换行符仅用于提高可读性。

[grafana_client]
# Authentication token to gain access (string value)
# Note: This option can be changed without restarting.
token = eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk==

# first part of the url (including https:// or http://) up until project id
# part. Example: https://secure.org/api/datasource/proxy/ (string value)
# Note: This option can be changed without restarting.
base_url = https://monitoring-grafana.com/api/datasources/proxy/

# Project id as in url (integer value)
# Note: This option can be changed without restarting.
project_id_map = host_cpu_usage:1337,host_ram_usage:6969,
instance_cpu_usage:1337,instance_ram_usage:9696

# Mapping of grafana databases to datasource metrics. (dict value)
# Note: This option can be changed without restarting.
database_map = host_cpu_usage:monit_production,
host_ram_usage:monit_production,instance_cpu_usage:prod_cloud,
instance_ram_usage:prod_cloud

translator_map = host_cpu_usage:influxdb,host_ram_usage:influxdb,
instance_cpu_usage:influxdb,instance_ram_usage:influxdb

attribute_map = host_cpu_usage:hostname,host_ram_usage:hostname,
instance_cpu_usage:name,instance_ram_usage:name

query_map = host_cpu_usage:SELECT 100-{0}("{0}_value") FROM {4}.cpu WHERE
("host" =~ /^{1}$/ AND "type_instance" =~/^idle$/ AND time > now()-{2}s),
host_ram_usage:SELECT {0}("{0}_value")/1000000 FROM {4}.memory WHERE
 ("host" =~ /^{1}$/) AND "type_instance" =~ /^used$/ AND time >= now()-{2}s
 GROUP BY "type_instance",instance_cpu_usage:SELECT {0}("{0}_value") FROM
 "vmstats" WHERE host =~ /^{1}$/ AND "type_instance" =~ /^cpu$/ AND time >=
 now() - {2}s GROUP BY host,instance_ram_usage:SELECT {0}("{0}_value") FROM
 "vmstats" WHERE host =~ /^{1}$/ AND "type_instance" =~ /^mem$/ AND time >=
 now() - {2}s GROUP BY host

[grafana_translators]

retention_periods = one_week:10080,one_month:302400,five_years:525600

[watcher_datasources]
datasources = grafana

yaml

当使用 yaml 配置文件时,仍然需要在常规配置中定义一些参数,例如 yaml 文件的路径,这些参数如下所述

[grafana_client]
token = eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk==

base_url = https://monitoring-grafana.com/api/datasources/proxy/

[watcher_datasources]
datasources = grafana

[watcher_decision_engine]
metric_map_path = /etc/watcher/metric_map.yaml

使用 yaml 允许更有效地定义每个指标的参数,并由于多行选项可用而提高可读性。这些多行选项在 query 参数中进行了演示。

grafana:
  host_cpu_usage:
    project: 1337
    db: monit_production
    translator: influxdb
    attribute: hostname
    query: >
        SELECT 100-{0}("{0}_value") FROM {4}.cpu
        WHERE ("host" =~ /^{1}$/ AND "type_instance" =~/^idle$/ AND
        time > now()-{2}s)
  host_ram_usage:
    project: 6969
    db: monit_production
    translator: influxdb
    attribute: hostname
    query: >
        SELECT {0}("{0}_value")/1000000 FROM {4}.memory WHERE
         ("host" =~ /^{1}$/) AND "type_instance" =~ /^used$/ AND time >=
         now()-{2}s GROUP BY "type_instance"
  instance_cpu_usage:
    project: 1337
    db: prod_cloud
    translator: influxdb
    attribute: name
    query: >
        SELECT {0}("{0}_value") FROM
         "vmstats" WHERE host =~ /^{1}$/ AND "type_instance" =~ /^cpu$/ AND
         time >= now() - {2}s GROUP BY host
  instance_ram_usage:
    project: 9696
    db: prod_cloud
    translator: influxdb
    attribute: name
    query: >
        SELECT {0}("{0}_value") FROM
         "vmstats" WHERE host =~ /^{1}$/ AND "type_instance" =~ /^mem$/ AND
         time >= now() - {2}s GROUP BY host