Sensu和InfluxDB:存储指标收集检查的数据

导航到

Sensu是一个流行的应用和基础设施监控解决方案,旨在满足现代云计算环境的需求。

Sensu框架由客户端和服务器应用程序组成,它们通过消息总线(默认为RabbitMQ)进行通信。配置完全使用JSON文件完成,这使得它易于与Ansible或Chef等自动化工具集成,并且可以在不重启服务器的情况下注册和注销客户端。

您的基础设施中的每个主机上都驻留了一个客户端副本。客户端从传输中拉取健康检查请求,执行它们,并将结果作为“事件”推回消息总线。Sensu检查遵循与Nagios插件相同的格式,这使得开发者可以利用Nagios生态系统中的大量插件以及Sensu社区提供的插件。检查可以是任何将数据写入STDOUTSTDERR的程序或脚本,并返回一个与给定状态相对应的错误代码:0 OK1 Warning2 Critical,以及3或更高用于未知或自定义状态。

一旦检查结果被推送到消息总线,一个或多个Sensu服务器会从总线上拉取事件并处理它们,处理结果、触发警报或将指标转发到长期存储。

默认情况下,Sensu不会对检查期间可能收集到的数据进行任何操作,但它提供了配置处理器的功能,这些处理器将处理并将数据转发到外部存储——在我们的例子中,是InfluxDB

通过存储指标数据,开发团队可以在以后的时间分析数据;通过查看性能数据来推动工程路线图,或作为事件响应或事后分析的组成部分。此外,通过在时间序列数据库中查询指标,Sensu可以对多个数据点执行检查,减少噪声和闪烁警报。

那么我们如何保存这些数据呢?

设置

本文假设您已经将Sensu作为您基础设施的一部分运行,客户端上运行着指标收集检查,并且您已经设置了一个InfluxDB实例。如果没有,您可以在以下位置找到安装说明。

在这个例子中,我们将使用来自Sensu CPU Checks插件CPU百分比检查来收集关于处理器使用的指标。

我配置了两个运行Ubuntu 16.04的主机:运行Sensu、Redis、RabbitMQ和Uchiwa的Sensu服务器本身,以及一个用于InfluxDB的第二个服务器。Sensu服务器配置了除devubuntu-servers订阅之外的legacy-servers订阅。订阅允许您确定各种客户端运行的检查;在这种情况下,我们将假设我们的现有基础设施配置为通过Sensu收集资源指标,而InfluxDB服务器使用Telegraf收集这些指标。我们将使用legacy-servers订阅来确保我们只在我们没有安装Telegraf的服务器上运行我们的指标收集检查。

Sensu InfluxDB插件

Sensu有许多社区贡献的插件,这些插件提供了Sensu和从Apache到Zookeeper的第三方应用程序之间的简单集成,可以在GitHub上的Sensu Community Plugins组织下找到。

我们将使用InfluxDB Sensu插件,它提供了InfluxDB和Sensu之间的一些集成。

我们可以使用以下命令将InfluxDB插件安装到Sensu的嵌入式Ruby环境中 /opt/sensu/embedded/

$ sudo sensu-install influxdb

我们已经在我们的“遗留”主机上运行了指标检查,因此我们希望设置InfluxDB处理程序来处理Sensu服务器接收到的事件。首先,我们将通过将其添加到/etc/sensu/conf.d/handlers.json来启用处理程序

{
  "handlers": {
    "influx-tcp": {
       "type": "pipe",
       "command": "/opt/sensu/embedded/bin/metrics-influxdb.rb"
    }
  }
}

并在/etc/sensu/conf.d/influx.json中添加配置

{
    "influxdb": {
        "host"          : "192.168.227.134",
        "port"          : "8086",
        "database"      : "sensumetrics"
    }
}

在这个示例中,InfluxDB实例没有使用任何类型的身份验证或SSL,因此我们使用了非常简单的配置,但还有许多其他配置选项可以指定。

现在我们已经配置了处理程序,我们希望在从我们的CPU百分比检查获得结果时调用它,通过将处理程序添加到检查配置中,在我们的例子中为/etc/sensu/conf.d/cpu_percentage.json

{
  "checks": {
    "cpu_metrics": {
      "type": "metric",
      "command": "metrics-cpu-pcnt-usage.rb",
      "subscribers": [
        "legacy-hosts"
      ],
      "interval": 10,
      "handlers": [
        "debug",
        "influxdb-tcp"
      ]
    }
  }
}

如您所见,我们已将订阅者配置为仅包括legacy-hosts。较新的主机将通过Telegraf进行设置,因此我们不需要在那里运行这些检查。

现在让我们重新启动Sensu服务以获取任何配置更改

$ sudo systemctl restart sensu-server sensu-api sensu-client

收集指标

此时,我们应该在InfluxDB中看到数据。Sensu的默认指标格式是Graphite纯文本;每个指标都表示为点划线分隔的路径、值和时间戳。对于我们使用的CPU百分比检查,我们返回九个指标,如下所示

sensu.cpu.user 0.50 1515534170
sensu.cpu.nice 0.00 1515534170
sensu.cpu.system 0.00 1515534170
sensu.cpu.idle 99.50 1515534170
sensu.cpu.iowait 0.00 1515534170
sensu.cpu.irq 0.00 1515534170
sensu.cpu.softirq 0.00 1515534170
sensu.cpu.steal 0.00 1515534170
sensu.cpu.guest 0.00 1515534170

另一方面,InfluxDB使用标签和字段的概念来提高效率。一个InfluxDB“测量”可以包含多个存储在字段中的值,以及可以用于在以后执行更复杂查询的索引标签。

所有上述指标都可以存储在InfluxDB中作为一个单独的测量值,其中主机由一个标签表示,每个指标由一个字段表示。在InfluxDB行协议中的相同指标可能看起来像这样

cpu,host=sensu user=0.50,nice=0.00,system=0.00,idle=99.50,iowait=0.00,softirq=0.00,steal=0.00,guest=0.00 1515534170

然而,Sensu的InfluxDB插件旨在与所有可能由检查生成的指标一起工作,因此它并没有在标签和字段中将Graphite值解析太多。插件为每个Graphite指标创建一个测量值,从Graphite路径的开头提取主机名,并从事件数据中提取指标名称作为标签。因此

sensu.cpu.user 0.50 1515534170

变成

cpu_user,host=sensu,metric=cpu_percentage 0.50 1515534170

这不是一个理想的解决方案;它没有充分利用标签和字段的效率,但它可以将指标快速放入InfluxDB并放置在仪表板上的快速方法,并且可能是许多InfluxDB用户将尝试的第一个。

我们可以使用InfluxDB CLI验证数据是否被InfluxDB接收。登录到InfluxDB主机并在提示符中输入influx

$ influx
Connected to https://127.0.0.1:8086 version 1.4.2
InfluxDB shell version: 1.4.2
>

使用SHOW MEASUREMENTS命令验证是否已创建所有指标

>SHOW MEASUREMENTS
name: measurements
name
----
cpu_guest
cpu_idle
cpu_iowait
cpu_irq
cpu_nice
cpu_softirq
cpu_steal
cpu_system
cpu_user

最后,我们可以查询其中一个测量值以查看单个数据点

SELECT * from cpu_idle WHERE time > now() - 1m
name: cpu_idle
time                host  metric         value
----                ----  ------         -----
1515534170000000000 sensu cpu_percentage 99.5
1515534270000000000 sensu cpu_percentage 100
1515534370000000000 sensu cpu_percentage 100
1515534470000000000 sensu cpu_percentage 100
1515534570000000000 sensu cpu_percentage 100
1515534670000000000 sensu cpu_percentage 100

另一种方法:将Graphite纯文本发送到Telegraf

通过为每个指标创建一个测量值,我们已经在没有充分利用InfluxDB,而且,Sensu InfluxDB插件的工作方式效率不是很高。

Sensu的Graphite处理程序包含以下警告

然而,将此突变体作为突变命令使用可能会非常昂贵,因为Sensu必须为每个指标检查的结果启动一个新的Ruby进程来运行此脚本。请考虑从您的插件生成正确的指标名称,并通过套接字处理器直接将它们发送到Graphite。有关更多信息,请参阅https://groups.google.com/d/msg/sensu-users/1hkRSvL48ck/8Dhl98lR24kJ

我们使用的处理器 check-influxdb-query.rb 同样存在相同的问题,因为需要为每个结果运行脚本。链接的线程中的讨论建议使用 only_check_output,这是Sensu的一个内置突变扩展,它不需要Sensu启动新的进程。它从事件数据中提取Graphite纯文本,然后可以使用套接字处理器将其转发。

幸运的是,InfluxDB和Telegraf都可以以Graphite纯文本格式摄取指标,所以这是一个可行的选项。InfluxDB或Telegraf可以负责在数据到达时转换指标,而Sensu可以继续执行Sensu的事情。

注意:在撰写此帖子时,我遇到了Telegraf的一个错误,该错误导致它拒绝包含换行符的包,这意味着它拒绝Sensu发送的数据。幸运的是,这是一个简单的修复(Pull Request在这里:#3684),并且更改已经包含在GitHub上的master分支中!它将在Telegraf的下一个版本中提供,或者您可以下载一个夜间的构建版本链接在仓库中以立即开始。

默认情况下,以Graphite纯文本格式发送到Telegraf或InfluxDB的指标将使用完整的Graphite路径作为测量名称存储,类似于Sensu InfluxDB插件所做的那样,但这两个应用程序也提供模板功能,该功能告诉InfluxDB或Telegraf如何将指标转换为InfluxDB格式。

可以为每个配置的监听器定义模板,并且具有与Graphite路径类似的格式,其中值由句点分隔。模板中值的位置决定了Graphite路径中的相同部分如何作为标签、测量或字段处理。您可以在模板文档中找到更多信息。

让我们再次看看我们的CPU百分比指标

sensu.cpu.user 0.50 1515534170
sensu.cpu.nice 0.00 1515534170
sensu.cpu.system 0.00 1515534170
...

每个指标具有相同的格式,因此我们可以使用单个模板来解析它们。它们在路径中有三个部分,第一个是主机,后两个是指标。我们希望将每个指标分解为测量和字段,以便我们可以有一个单一的cpu测量,其中包含usernicesystem等字段的测量。为了实现这一点,我们可以使用以下模板

host.measurement.field
注意:许多Sensu指标收集检查包括一个参数,--scheme,可用于自定义指标输出。对于CPU百分比检查,方案默认为#{Socket.gethostname}.cpu,这对我们来说已经足够好了。

由于InfluxDB和Telegraf都可以处理Graphite纯文本,因此您在哪里决定做这项工作取决于您的负载、基础设施和工具。如果您只收集少数类型的指标,您可以使用几个模板轻松处理它们,并且您的InfluxDB盒子上可用资源,您可能希望直接将指标发送到那里。

但是,如果您正在尝试从许多不同的服务收集指标,您可能会发现创建模板时遇到冲突,或者您在InfluxDB服务器上施加了不合理的大量负载。在这种情况下,在您的应用程序旁边放置Telegraf实例可能更有意义,这样您可以分散处理负载并最小化每个监听器所需的模板数量。这种方法更容易扩展,但需要额外的配置开销。

对于此示例,我们将安装Telegraf并与其一起发送Graphite纯文本到套接字。

Telegraf设置

首先,在您的Sensu主机上安装Telegraf。您可以在以下位置找到Telegraf在不同平台上的安装说明

接下来,我们将禁用Telegraf默认收集的CPU统计数据,因为这些数据与Sensu的指标收集检查重复。请确保从默认配置中注释掉[[inputs.cpu]][[inputs.disk]][[inputs.mem]][[inputs.network]]部分。

我们还需要配置一个输入,以便Sensu可以将指标发送到。我们将定义一个socket_listener,给它一个端口和数据格式,并指定我们的Graphite纯文本解析模板。

将此部分添加到Telegraf配置文件/etc/telegraf/telegraf.conf

[[inputs.socket_listener]]
  service_address = "udp://:8094"
  data_format = "graphite"
  templates = [
    "host.measurement.field"
  ]

使用sudo systemctl restart telegraf重启Telegraf以获取新的配置。

Sensu配置

在Sensu中配置一个UDP处理器,使用only_check_output突变体,将其添加到您的/etc/sensu/conf.d/handlers.json

{
  "handlers": {
    "telegraf-graphite-handler": {
      "type": "udp",
      "socket": {
        "host": "127.0.0.1",
        "port": 8094
      },
      "mutator": "only_check_output"
    }
  }
}

更新检查,使其使用新的处理器,编辑/etc/sensu/conf.d/cpu_percentage.json

{
  "checks": {
    "cpu_metrics": {
      "type": "metric",
      "command": "metrics-cpu-pcnt-usage.rb",
      "subscribers": [
        "legacy-hosts"
      ],
      "interval": 10,
      "handlers": [
        "debug",
        "telegraf-grafphite-handler"
      ]
    }
  }
}

最后,重启Sensu服务

$ sudo systemctl restart sensu-server sensu-api sensu-client

验证其是否正常工作

我们的指标以以下格式从Sensu输出

sensu.cpu.user 0.50 1515534170
sensu.cpu.nice 0.00 1515534170
sensu.cpu.system 0.00 1515534170
sensu.cpu.idle 99.50 1515534170
sensu.cpu.iowait 0.00 1515534170
sensu.cpu.irq 0.00 1515534170
sensu.cpu.softirq 0.00 1515534170
sensu.cpu.steal 0.00 1515534170
sensu.cpu.guest 0.00 1515534170

通过此模板运行

host.measurement.field

并最终生成一个具有多个字段的测量值cpu。让我们检查这是否是我们数据库中看到的内容。打开InfluxDB CLI,选择sensumetrics数据库,显示测量值并选择最后一分钟的数据,就像我们之前做的那样

> USE sensumetrics
Using database sensumetrics
> SHOW MEASUREMENTS
name
----
cpu
> SELECT * FROM cpu WHERE time < now() - 1m
name: cpu
time                 guest host  idle  iowait irq nice softirq steal system user
----                 ----- ----  ----  ------ --- ---- ------- ----- ------ ----
2018-01-09T20:32:09Z 0     sensu 98.51 0      0   0    0       0     0.5    1
2018-01-09T20:32:19Z 0     sensu 98.51 0      0   0    0       0     0.5    1
2018-01-09T20:32:29Z 0     sensu 98.51 0      0   0    0       0     0.5    1
2018-01-09T20:32:39Z 0     sensu 98.51 0      0   0    0       0     0.5    1
2018-01-09T20:32:49Z 0     sensu 98.51 0      0   0    0       0     0.5    1

下一步

我们还在做一些不必要的转换,将Graphite纯文本指标转换成;在某个时候,更新我们的检查以输出InfluxDB行协议数据,或者使用Telegraf从我们的应用程序直接收集和发送指标到InfluxDB可能是合理的。

下周我们将继续探索Sensu和InfluxDB的集成,通过创建一个基于我们捕获的数据的指标检查来继续。