我试着让Google Home Mini说出来来自Prometheus的警报

首先

聽說從前有個前輩,以前他用進擊的巨人阿斯卡的聲音說話的智能音箱,所以我想嘗試用 Google Home Mini 製造出類似的裝置。
這次我們會監控家中的網絡設備界面,當連接狀態改變時會請它說話。

构成

我决定在Prometheus上进行监控。
因为我从未接触过它,这是个不错的机会。

topo.jpeg

我会为每个组件创建一个Docker容器。
我们决定从主机上挂载每个配置文件(和源代码)。
我会创建Dockerfile和配置文件,并使用docker-compose进行整合。

建造

验证环境
– macOS Sierra 10.12.6
– Mac上的Docker:Docker社区版17.09.1-ce-mac42

监视对象
– Cisco 891FJ:千兆以太网0-7

SNMP导出器

Prometheus会从每个导出者中获取监视对象的信息。
由于本次是通过SNMP轮询进行监视,所以我们将使用SNMP Exporter。
为了描述Prometheus的警报规则,我们先定义了指标。

我决定使用基于CentOS的容器。
由于Prometheus的组件可以通过下载二进制文件并运行来构建,所以非常方便。
现在我们要下载对应的二进制文件。
然后只需解压并运行即可。(版本将使用最新版本。)

FROM centos

RUN yum -y update
RUN yum -y install wget
RUN wget https://github.com/prometheus/snmp_exporter/releases/download/v0.8.0/snmp_exporter-0.8.0.linux-amd64.tar.gz
RUN tar xvf snmp_exporter-0.8.0.linux-amd64.tar.gz

WORKDIR /snmp_exporter-0.8.0.linux-amd64

CMD ./snmp_exporter

在SNMP Exporter的二进制文件的相同目录中,继续写入snmpwalk和metric的信息到配置文件(snmp.yml)中。

要监视IOS接口的上/下状态,可以使用以下的MIB对象:
1.3.6.1.2.1.2.1.8
尝试执行snmpwalk命令。

~ ❯❯❯ snmpwalk -v 2c -c public Cisco891FJ 1.3.6.1.2.1.2.2.1.8
(省略)
IF-MIB::ifOperStatus.6 = INTEGER: up(1)
IF-MIB::ifOperStatus.7 = INTEGER: down(2)
(省略)

顺便提一下,末尾的数字与界面名称的对应关系可以在以下获取到。

~ ❯❯❯ snmpwalk -v 2c -c public Cisco891FJ 1.3.6.1.2.1.2.2.1.2
(省略)
IF-MIB::ifDescr.6 = STRING: GigabitEthernet0
IF-MIB::ifDescr.7 = STRING: GigabitEthernet1
(省略)

只要能够访问到1.3.6.1.2.1.2.2.1.8.6 – 1.3.6.1.2.1.2.2.1.8.13对象,就没有问题来监视GigabitEthernet0-7。

SNMP Exporter通过模块单元的方式描述snmpwalk的信息和度量定义,而监视的目标信息则在Prometheus的配置中进行描述。

interface:
  version: 2
  auth:
    community: public
  walk:
  - 1.3.6.1.2.1.2.2.1.8
  metrics:
  - name: ifOperStatus
    oid: 1.3.6.1.2.1.2.2.1.8
    type: gauge
    indexes:
      - labelname: ifNumber
        type: Integer32
    help: The current operational status of the interfaces. - 1.3.6.1.2.1.2.2.1.8
スクリーンショット 2018-01-01 0.17.26.png

普罗米修斯

因为已经准备好了容器,所以我使用了它。因此不需要Dockerfile。

将Prometheus的配置文件和警报规则定义文件放置在容器的/etc/prometheus/目录下。
我们修改了官方示例并进行了创建。
指定Alertmanager和rule_files,以及定义snmp job。

# my global config
global:
  scrape_interval:     1s
  evaluation_interval: 1s

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alert_manager:9093 # alert managerのIPアドレス : 待ち受けポート

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  - "alert.rules.yml" # alertのruleを記述したファイルの指定


# A scrape configuration containing exactly one endpoint to scrape:
scrape_configs:
  - job_name: 'snmp'
    static_configs:
      - targets:
        - x.x.x.x  # SNMPの監視対象のIPアドレス
    metrics_path: /snmp
    params:
      module: [interface]
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: snmp_exporter:9116  # snmp exporterのIPアドレス : 待ち受けポート

警报规则使用delta()函数来计算状态在10秒(起点和终点)内的差异,如果不为0,则认为状态已转换。
我选择了10秒的时间间隔,只是个人偏好。

groups:
- name: interface
  rules:
  - alert: Interface_Down
    expr: delta(ifOperStatus{ifNumber="6"}[10s]) > 0
    for: 1s
    annotations:
      summary: 891fj/インターフェース/0/ダウン
  - alert: Interface_Down
    expr: delta(ifOperStatus{ifNumber="7"}[10s]) > 0
    for: 1s
    annotations:
      summary: 891fj/インターフェース/1/ダウン
  - alert: Interface_Down
  (省略)

我在省略部分写下了每个接口规则的说明。
对于”Up”情况来说,delta(ifOperStatus{ifNumber=”x”}[10s]) < 0。
(是否有一种可编程的描述方式呢?)

以下是将摘要内容转化为Google Home Mini语音输出内容的选项(“/”用于表示语音间的分隔符)。

报警管理器

只需从这里下载Alertmanager二进制文件并运行。
使用与SNMP Exporter相同的方法,快速编写Dockerfile。
可以从这里找到二进制文件。

FROM centos

RUN yum -y update
RUN yum -y install wget
RUN wget https://github.com/prometheus/alertmanager/releases/download/v0.12.0/alertmanager-0.12.0.linux-amd64.tar.gz
RUN tar xvf alertmanager-0.12.0.linux-amd64.tar.gz

WORKDIR /alertmanager-0.12.0.linux-amd64

CMD ./alertmanager

將設定檔案放置在二進制文件的同一目錄下。
將配置描述為對Google Home通知器發送POST請求的JSON。

global:

route:
  receiver: 'webhook'
  group_by: ['alertname', 'cluster', 'service']
  group_wait: 1s
  group_interval: 5s
  repeat_interval: 5s

receivers:
- name: 'webhook'
  webhook_configs:
  - send_resolved: false
    url: 'http://notifier:8091/google-home-notifier'

虽然警报应该持续10秒钟,但在Slack通知中,需要大约7秒钟的时间,而实际上只发送了3秒钟(3次)的通知。
根据此参考,将与同一警报通知相关的repeat_interval设置为5秒。
group_interval也设置为5秒。
由于本次所有警报都属于同一组,例如,在GigabitEthernet 0上升后的2秒后,GigabitEthernet 1上升,仍然会有5秒的通知间隔。
(对于同一警报通知,它将属于同一组,只有经过两个间隔才会触发通知。repeat_interval的时间应不小于group_interval,否则没有意义。

谷歌智能助手通知器

Google Home Notifier是一个基于Node.js的库。
我使用了该库来命名组件。
我会编写一个Dockerfile以便执行名为”app.js”的源代码。
因为对Node.js不太熟悉,所以准备环境也费了一番功夫。
总之,很高兴成功让它正常运行了。

FROM node

RUN apt-get update
RUN apt-get install -y avahi-daemon avahi-discover libnss-mdns libavahi-compat-libdnssd-dev
RUN cat /etc/avahi/avahi-daemon.conf | grep -v rlimit-nproc > temp.conf
RUN mv -f temp.conf /etc/avahi/avahi-daemon.conf
RUN git clone https://github.com/noelportugal/google-home-notifier
RUN cd google-home-notifier && npm install

WORKDIR google-home-notifier

CMD service dbus start && service avahi-daemon start && node app.js

app.js在很大程度上重用了example.js。
附加的内容是:
– 接收JSON数据
– 将摘要赋值给文本

这就是这样。


var express = require('express');
var googlehome = require('./google-home-notifier');
var ngrok = require('ngrok');
var bodyParser = require('body-parser');
var app = express();
const serverPort = 8091; // default port

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var deviceName = 'Google Home';
var ip = 'x.x.x.x'; // Google Home IP address

var urlencodedParser = bodyParser.urlencoded({ extended: false });

app.post('/google-home-notifier', urlencodedParser, function (req, res) {

  var text = req.body.commonAnnotations.summary;

  if (!req.body) return res.sendStatus(400)
  console.log(text);

   if (req.query.ip) {
     ip = req.query.ip;
  }

  var language = 'ja'; // default language code
  if (req.query.language) {
    language;
  }

  googlehome.ip(ip, language);
  googlehome.device(deviceName,language)

  if (text){
    try {
      if (text.startsWith('http')){
        var mp3_url = text;
        googlehome.play(mp3_url, function(notifyRes) {
          console.log(notifyRes);
          res.send(deviceName + ' will play sound from url: ' + mp3_url + '\n');
        });
      } else {
        googlehome.notify(text, function(notifyRes) {
          console.log(notifyRes);
          res.send(deviceName + ' will say: ' + text + '\n');
        });
      }
    } catch(err) {
      console.log(err);
      res.sendStatus(500);
      res.send(err);
    }
  }else{
    res.send('Please GET "text=Hello Google Home"');
  }
})


app.listen(serverPort, function () {
  ngrok.connect(serverPort, function (err, url) {
    console.log('Start Notifier');
  });
})

docker-compose
Docker-compose

使用创建好的Dockerfile和配置文件等,在docker-compose中进行部署。

.
├── docker-compose.yml
├── dockerfile
│   ├── dockerfile_alert
│   ├── dockerfile_notifier
│   └── dockerfile_snmp
├── google-home-notifier
│   └── app.js
└── yml
    ├── alert.rules.yml
    ├── alertmanager.yml
    ├── prometheus.yml
    └── snmp.yml
version: '2'
services:
  prometheus:
    image: prom/prometheus
    ports:
      - 9090:9090
    links:
      - snmp_exporter
      - alert_manager
    volumes:
      - ./yml/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./yml/alert.rules.yml:/etc/prometheus/alert.rules.yml
  snmp_exporter:
    build:
      context: .
      dockerfile: "./dockerfile/dockerfile_snmp"
    ports:
      - 9116:9116
    volumes:
      - ./yml/snmp.yml:/snmp_exporter-0.8.0.linux-amd64/snmp.yml
  alert_manager:
    build:
      context: .
      dockerfile: "./dockerfile/dockerfile_alert"
    links:
      - notifier
    volumes:
      - ./yml/alertmanager.yml:/alertmanager-0.12.0.linux-amd64/alertmanager.yml
  notifier:
    build:
      context: .
      dockerfile: "./dockerfile/dockerfile_notifier"
    volumes:
      - ./google-home-notifier/app.js:/google-home-notifier/app.js
スクリーンショット 2018-01-01 0.56.23.png

让警报器发声

那么,让我们来测试接口的上下状态。

让Google Home Mini说出Up/Down的界面(口述)

她/他/它说得很清楚,感觉很好。

因为据说这个指定的mp3也可以流播放,所以我根据这篇文章的参考创建了一个可以返回mp3的web服务器。

    帰宅したらGoogleHomeから好きな音声で「おかえり」って言ってもらいます

在警报的摘要中记下MP3的地址,可以实现这样的功能。
音源是从効果音ラボ借来的。

使用语音数据让Google Home Mini的界面说出Up/Down。

(ノ゚∀゚)ノ 你好亢奋啊!

结束

(Translation: End)

我试着让Google Home Mini说出Prometheus的警报。
出乎意料地,非常有乐趣。
Google Home不仅可以与它交谈,还可以有效地利用它说话的功能。

广告
将在 10 秒后关闭
bannerAds