我试着让Google Home Mini说出来来自Prometheus的警报
首先
聽說從前有個前輩,以前他用進擊的巨人阿斯卡的聲音說話的智能音箱,所以我想嘗試用 Google Home Mini 製造出類似的裝置。
這次我們會監控家中的網絡設備界面,當連接狀態改變時會請它說話。
构成
我决定在Prometheus上进行监控。
因为我从未接触过它,这是个不错的机会。
我会为每个组件创建一个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
普罗米修斯
因为已经准备好了容器,所以我使用了它。因此不需要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
让警报器发声
那么,让我们来测试接口的上下状态。
让Google Home Mini说出Up/Down的界面(口述)
她/他/它说得很清楚,感觉很好。
因为据说这个指定的mp3也可以流播放,所以我根据这篇文章的参考创建了一个可以返回mp3的web服务器。
- 帰宅したらGoogleHomeから好きな音声で「おかえり」って言ってもらいます
在警报的摘要中记下MP3的地址,可以实现这样的功能。
音源是从効果音ラボ借来的。
使用语音数据让Google Home Mini的界面说出Up/Down。
(ノ゚∀゚)ノ 你好亢奋啊!
结束
(Translation: End)
我试着让Google Home Mini说出Prometheus的警报。
出乎意料地,非常有乐趣。
Google Home不仅可以与它交谈,还可以有效地利用它说话的功能。