因为1.0版本发布了,所以尝试入门Prometheus

大约3周前,一个罕见的监测工具Prometheus 1.0以Pull型架构发布了。最近在日本也举办了Prometheus Casual Talk并增加了一些应用案例,因此我考虑将来可能会引入并尝试使用。

特征

在我所见范围内,引起我的兴趣的特点包括以下几点。

    • Go製

 

    • アラート機能が無償で利用可能(例えばELKスタック使う場合、Watcherがありますが、利用には有償契約が必要)

 

    • 扱えるのは数値のみ(ログ等で文字列を扱う場合は別のツール等が必要)

 

    • Pull型

 

    監視ツールはPush型(監視対象側が監視ツールに情報を送る)のものが多いと思いますが、PrometheusはPull型(Prometheusが監視対象の情報を取得する)です。理由はここに書いてありますが、ラップトップ等で気軽に監視ツールを実行できること、ターゲットが落ちている場合の判断が楽なこと(Push型だとターゲットがエラーで落ちたのかメンテで落ちたのかの判断が監視ツールにはできない)、ターゲットの状態をブラウザ等から確認できる、といった点が上げられています。ただし、PrometheusにもPushgatewayという機能があり、Pushすることも可能です。(バッチ処理の結果送信等限られた用途でのみ使うことが推奨されています)

试着使用

我想要逐一确认功能。
上一篇文章中,我尝试了使用Docker 1.12新增的swarm模式,因此这次也选择了swarm模式进行构建,但我觉得这个例子并不太合适。(由于与Prometheus本身无关,原因将在最后说明)

如果要使用swarm,只要安装了docker-machine和docker,就可以进行搭建,不需要阅读上述的文章。但如果想了解每个命令的含义,可以参考上一篇文章。
如果不使用swarm,建议根据需要将其替换为docker run等。

我会使用DigitalOcean云计算平台。如果您能从这里注册,我们双方都会很高兴。

普罗米修斯的建设和自身的监控

首先创建一个Swarm的管理器。

# manager用のホストを作成
$ docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "512mb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} manager
(結果略)

# managerのIPをメモる
$ docker-machine ls
NAME           ACTIVE   DRIVER         STATE     URL                          SWARM   DOCKER    ERRORS
manager        *        digitalocean   Running   tcp://104.131.149.142:2376           v1.12.0

# swarmモードを初期化
$ eval $(docker-machine env manager)
$ docker swarm init --advertise-addr 104.131.149.142

# 以下のような出力が得られるのでworkerを追加するコマンド(1個目)を控えておく
To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-12wn17zowr4ysj089mb4s0zijbwexx6w3oucz77k87uwkmxlsu-e9lv6z80x48hx42mxz50t0l6g \
    104.131.149.142:2377

To add a manager to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-12wn17zowr4ysj089mb4s0zijbwexx6w3oucz77k87uwkmxlsu-en1rtjwtlujupv16qqjja9xda \
    104.131.149.142:2377

接下来,我们要为Prometheus创建一个Docker主机。

# Prometheus用のホストを作成
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "2gb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} prometheus
(結果略)

# prometheusノードをswarmクラスタに追加
$ eval $(docker-machine env prometheus)
$ docker swarm join \
--token SWMTKN-1-12wn17zowr4ysj089mb4s0zijbwexx6w3oucz77k87uwkmxlsu-e9lv6z80x48hx42mxz50t0l6g \
104.131.149.142:2377

我会创建一个最小配置,用于监控自己如下所述。

mkdir prometheus
vi prometheus/prometheus.yml
global:
  scrape_interval:     15s
  external_labels:
    monitor: 'codelab-monitor'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']

我认为您可以从标签上知道正在设置什么,但是如果您查看官方网页,可以了解详细信息。

一旦启动Prometheus。

# 設定ファイルディレクトリをDockerホストにコピー
docker-machine scp -r prometheus prometheus:/opt/

# managerでdockerコマンドを実行するように指定
eval $(docker-machine env manager)

# prometheusサービスをprometheusホストでのみ起動するよう作成
docker service create \
  --replicas 1 \
  --name prometheus \
  --publish 9090:9090 \
  --mount type=volume,source=/opt/prometheus,target=/etc/prometheus \
  --constraint node.hostname==prometheus \
  prom/prometheus

当您访问http://:9090/metrics时,将出现以下指标列表。
请通过运行docker-machine ls等命令查找Prometheus的IP。

Screenshot from 2016-08-03 17-54-57.png

从 http://:9090/graph 选择Graph选项卡或Console选项卡,分别显示图形和控制台。

首先,在控制台选取“控制台”标签,并从/metrics列表中随机选择一个指标名称进行输入和执行。关于指标类型和查询语法等内容稍后会详细介绍,但这次我们试试使用go_goroutines这个指标。

Screenshot from 2016-08-03 22-14-33.png

打开图表标签后,看起来是这样的。

Screenshot from 2016-08-03 22-16-57.png

可以调整时间轴等。

增加其他的监视对象

因为目前只能获取到Prometheus的指标,所以我想要添加其他监控对象。

出口商

要获取操作系统本身的指标或现有软件的指标,可以使用exporter。MySQL、HAProxy等知名exporter可以使用官方或第三方提供的版本。需要注意的是,kubernetes、etcd等默认会向Prometheus暴露指标,因此无需使用exporter即可获取指标。

这次我们将尝试使用node exporter来获取系统的度量指标作为示例。


# hostネットワークを使うため、swarmではなく通常のdockerコマンドで実行
# manager上で実行
eval $(docker-machine env manager)
docker run -d -p 9100:9100 --net="host" prom/node-exporter

# prometheusノードでも実行
eval $(docker-machine env prometheus)
docker run -d -p 9100:9100 --net="host" prom/node-exporter

当您访问http://<目标节点的IP>:9100/metrics时,您可以看到与先前相同的各种指标和节点导出器指标。

Screenshot from 2016-08-04 18-24-09.png

为了使Prometheus能够监视,将配置文件按以下方式进行修改。

global:
  scrape_interval:     15s
  external_labels:
    monitor: 'codelab-monitor'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']
  - job_name:       'node'
    scrape_interval: 5s
    static_configs:
      - targets: ['manager_host_ip:9100']
        labels:
          group: 'manager'
      - targets: ['prometheus_ip:9100']
        labels:
          group: 'worker'

当你修改config文件时,可以通过向Prometheus进程发送SIGHUP信号或发送以下请求来重新加载。顺便一提,虽然是POST请求,但不能直接传递config文件本身。(规格)。

# configファイルをホストに送信
docker-machine scp -r prometheus prometheus:/opt/

# curlでリロード
curl -X POST http://prometheus_ip:9090/-/reload

因为应该已经被添加到监视对象中,所以我们可以从http://:9090/graph的“Console”选项卡中尝试查看名为node_cpu的度量指标。

Screenshot from 2016-08-04 20-08-53.png

查询的方法

我将试图简要介绍查询的方法。
如上所示,当执行node_cpu命令时,可以看到在Element列中显示了带有不同标签的node_cpu值(例如,node_cpu{cpu=”cpu0″,group=”worker”,instance=”192.241.200.47:9100″,job=”node”,mode=”idle”})。
此格式可直接用于查询,例如执行node_cpu{cpu=”cpu0″,group=”manager”,mode=”user”}将只获取相应的数据。

Screenshot from 2016-08-04 20-20-31.png

顺便提一下,”job”和”group”这两个标签是在上述的yml文件中指定的。

使用通配符进行模糊匹配,以及语法操作符进行逻辑运算等等,都可以增强查询的灵活性和准确性。

node_cpu {cpu=~”cpu+”, group=”worker”, mode=~”user|system”} 可以用以下方式进行释义:

只需一种选项,在中文中释义下列内容:显示最近5分钟的数据

在中国的母语中,将以下内容进行重述,只需要一种选择:
node_cpu{cpu=~”cpu.+”,group=”worker”,mode=~”user|system”}[5m]

过去的5分钟内,属于”worker”组的节点中的CPU使用情况(只包括”cpu.+”命名方式的CPU)的模式为”user”或者”system”。

显示最近5分的平均值。

计算在过去5分钟内,属于”worker”组且模式为”user”或”system”的节点CPU使用率。

显示用户和系统的总数

将以下内容在中文中进行本地化释义,只需要给出一个选项:
五分钟内的`node_cpu{cpu=”cpu0″,group=”worker”,mode=~”user|system”}`的平均值。

我有很多选择。

如果您打开图表选项卡,相应数据的图表将会显示。

Screenshot from 2016-08-04 20-51-45.png

当然,exporter也可以自己编写。
https://prometheus.io/docs/instrumenting/writing_exporters/

写客户消息

如果想要从应用程序、工具等中获取指标,您无需编写出口器即可使用客户端库公开指标。
https://prometheus.io/docs/instrumenting/clientlibs/

可以使用Go以外的语言进行编写。

这次只是试验,我制作了下面这个没有意义的Counter示例。除了Counter之外,还有Gauge、Summary和Histogram这几种类型的指标。

顺便提一下,因为已经在这里发布了,所以下面的程序和Dockerfile不需要再制作了,可以省略。

package main

import (
    "math/rand"
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus"
)

func main() {
    pushCounter := prometheus.NewCounter(prometheus.CounterOpts{
        Name: "sample_counter",
        Help: "just a simple counter",
    })
    prometheus.MustRegister(pushCounter)

    go func() {
        for {
            pushCounter.Inc()
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
        }
    }()

    http.Handle("/metrics", prometheus.Handler())
    http.ListenAndServe(":9111", nil)
}

由于我要在Alpine上运行,所以我会用以下方式进行构建。

CGO_ENABLED=0的条件下使用go build。

我会创建一个类似这样的Dockerfile。

FROM alpine:latest
ADD prometheus /
CMD /prometheus

我們將創建一個執行此任務的服務。

docker service create \
  --replicas 1 \
  --name sample-client \
  --publish 9111:9111 \
  daikikohara/prometheus-client:v1

当访问swarm节点的任意IP地址:9111/metrics时,除了默认的指标外,还会显示一个名为”sample_counter”的附加指标。

Screenshot from 2016-08-05 00-45-03.png

要将其添加为Prometheus的监控目标,可以添加以下类似的部分:

  - job_name:       'sample'
    scrape_interval: 5s
    static_configs:
      - targets: ['sample-clientが動いているノードのIP:9111']

我会重新加载。

docker-machine scp -r prometheus prometheus:/opt/
curl -X POST http://prometheus_ip:9090/-/reload

从WebUI上也可以显示图表。

Screenshot from 2016-08-05 15-32-23.png

记录规则

使用Recording rule可以将常用查询的结果等作为其他度量标准获取。这比每次执行原始查询更高效,特别是在频繁执行的仪表盘等情况下非常有利。

为了试用,我们将在本地创建一个名为prometheus/prometheus.rules的文件,内容如下。

sample_rule:node_cpu_user:avg_rate5m = avg(rate(node_cpu{mode="user"}[5m])) by (instance, cpu)

通过以下工具可以检查规则书写是否正确。

$ go get github.com/prometheus/prometheus/cmd/promtool
$ promtool check-rules ./prometheus.rules
Checking ./prometheus.rules
  SUCCESS: 1 rules found

将prometheus.yml文件进行如下修改。新增了evaluation_interval和rule_files两个选项。其中evaluation_interval选项用于每15秒评估一次规则。

global:
  scrape_interval:     15s
  evaluation_interval: 15s
  external_labels:
    monitor: 'codelab-monitor'
rule_files:
  - 'prometheus.rules'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['localhost:9090']
  - job_name:       'node'
    scrape_interval: 5s
    static_configs:
      - targets: ['manager_ip:9100']
        labels:
          group: 'manager'
      - targets: ['prometheus_ip:9100']
        labels:
          group: 'worker'
  - job_name:       'sample'
    scrape_interval: 5s
    scrape_timeout: 3s
    static_configs:
      - targets: ['prometheus_ip:9111']

将规则和配置文件发送到Prometheus主机以重新加载。

docker-machine scp -r prometheus prometheus:/opt/
curl -X POST http://prometheus_ip:9090/-/reload

在指定的规则名称下,可以获取到图表。

Screenshot from 2016-08-05 18-45-55.png

警报管理器

使用Alertmanager可以根据不同的条件发送警报。
Alertmanager是与Prometheus分离的一个进程,在Prometheus上设置规则并向Alertmanager发送警报,Alertmanager根据条件将收到的警报发送到不同的通知目标等进行处理。

发送地址可以是电子邮件,也可以是Slack等各种方式。

在官方网页上可以看到,规则可以根据需求进行多种设置。其中,有Grouping(例如,当数据库出现故障时只需要从一个实例接收错误等信息,因此可以将相同类型的警报进行合并), Inhibition(如果某个组的警报已经发生,就不会再出现其他警报),以及Silence(在一定时间内不发出特定的警报)等类型的规则。

我目前正在尝试使用官方页面上提供的实例,测试当实例宕机时的警报。我已尝试将警报发送到Slack。

首先,在本地创建一个用于Alertmanager的目录,并创建配置文件。

mkdir alertmanager
vi alertmanager/config.yml
global:
route:
  receiver: main
  group_by: ['alertname', 'instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 1h
receivers:
- name: 'main'
  slack_configs:
  - api_url: 'https://hooks.slack.com/services/your_api_token'
    channel: '#channel_name'

接下来启动Alertmanager。

# alertmaanger用のホストを作成
docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "2gb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} alertmanager

# swarmクラスタに追加
eval $(docker-machine env alertmanager)
docker swarm join \
--token SWMTKN-1-12wn17zowr4ysj089mb4s0zijbwexx6w3oucz77k87uwkmxlsu-e9lv6z80x48hx42mxz50t0l6g \
104.131.149.142:2377

# 設定ファイルをalertmanagerのホストに送信
docker-machine scp -r alertmanager alertmanager:/opt/

# Alertmanager用のサービスの作成
eval $(docker-machine env manager)
docker service create \
  --replicas 1 \
  --name alertmanager \
  --publish 9093:9093 \
  --mount type=volume,source=/opt/alertmanager,target=/etc/alertmanager \
  --constraint node.hostname==alertmanager \
  prom/alertmanager:latest

当你通过浏览器访问Alertmanager节点的IP:9093,并看到以下屏幕时,一切正常。

Screenshot from 2016-08-05 20-37-23.png

接下来我们在 Prometheus 一侧添加警报规则。在 prometheus 目录下创建一个类似以下内容的文件。

ALERT InstanceDown
  IF up == 0
  FOR 1m
  LABELS { severity = "page" }
  ANNOTATIONS {
    summary = "Instance {{ $labels.instance }} down",
    description = "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.",
  }

从prometheus.yml文件中引用上述文件。

rule_files:
  - 'prometheus.rules'
  - 'alert.rules'

需要修改Prometheus容器的配置,但官方Docker镜像无法连接到Alertmanager,因此我创建了以下的Dockerfile并放置在此。

FROM prom/prometheus
ENTRYPOINT [ "sh" ]
CMD [ "-c", \
      "/bin/prometheus \
      -config.file=/etc/prometheus/prometheus.yml \
      -storage.local.path=/prometheus \
      -alertmanager.url=${ALERTMANAGER}" ]

一旦关闭原始的Prometheus服务后,我们将使用以上提及的镜像来运行Prometheus服务。

# サービスを削除
$ docker service rm prometheus

# 設定ファイルをホストに送信
$ docker-machine scp -r prometheus prometheus:/opt/

# サービスを再作成
$ docker service create \
  --replicas 1 \
  --name prometheus \
  --publish 9090:9090 \
  --mount type=volume,source=/opt/prometheus,target=/etc/prometheus \
  --env ALERTMANAGER="http://alertmanager_ip:9093" \
  --constraint node.hostname==prometheus \
  daikikohara/prometheus:v1

我会突然将一个被监视的容器关闭。

# manager上のdockerプロセスを確認
$ docker ps
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS               NAMES
57aa0d720403        prom/node-exporter                 "/bin/node_exporter"     2 hours ago         Up 2 hours                              suspicious_keller
9687d44ae859        daikikohara/prometheus-client:v1   "/bin/sh -c /promethe"   7 hours ago         Up 7 hours                              sample-client.1.2zkn3wtvw37f8fiy6xqfhui4n

# node_exporterのプロセスを停止
$ docker stop suspicious_keller
suspicious_keller

在这里通过Alert标签确认,状态显示为PENDING。

Screenshot from 2016-08-05 23-23-42.png

经过1分钟以上的时间,再次确认时,状态变为FIRING。

Screenshot from 2016-08-05 23-28-41.png

Alertmanager也会收到通知。

(忘了截图)

通过Alertmanager向Slack发送了通知。

Screenshot from 2016-08-08 00-38-02.png

Grafana与其他系统的整合

根据我们之前所看到的,Prometheus本身也具备图形功能,但相对而言不太强大,因此官方推荐与Grafana集成。Grafana是一种可视化各种指标的工具,除了与Prometheus集成外,还支持与InfluxDB、CloudWatch等各种数据源的连接。

首先创建用于Grafana的机器和服务。

# Grafana用のホストを作成
$ docker-machine create -d digitalocean --digitalocean-image "ubuntu-16-04-x64" --digitalocean-region "sfo1" --digitalocean-size "2gb" --digitalocean-access-token ${DIGITALOCEAN_API_TOKEN} grafana

# grafanaノードをswarmクラスタに追加
$ eval $(docker-machine env grafana)
$ docker swarm join \
--token SWMTKN-1-12wn17zowr4ysj089mb4s0zijbwexx6w3oucz77k87uwkmxlsu-e9lv6z80x48hx42mxz50t0l6g \
104.131.149.142:2377

# Grafana用のサービスを作成
$ docker service create \
  --replicas 1 \
  --name grafana \
  --publish 3000:3000 \
  --constraint node.hostname==grafana \
  grafana/grafana

当您访问Grafana节点的IP地址:3000时,将出现登录界面。

Screenshot from 2016-08-08 12-01-14.png

这次我们使用默认设置,使用admin/admin进行登录。

要添加Prometheus数据源,

    • logoクリック

 

    • Data Sourcesクリック

 

    • Add data sourceをクリック

 

    • Nameに適当な名前を入力

 

    • Defaultにチェック(オプショナル)

 

    • Type をPrometheusに変更

 

    • UrlをPrometheusのURLに変更

 

    • AccessをDirectに変更

 

    Addをクリック

可以进行额外添加。

Screenshot from 2016-08-08 12-57-37.png

要创建图表,首先需要

    • 左上のlogoクリック

 

    • DashboardsからNewを選択

 

    • 左端のメニューからAdd Panel、Graphを選択

 

    Queryに適当にグラフにしたいクエリを入力

可以通过这样做来创建。

Screenshot from 2016-08-08 12-59-59.png

在Prometheus控制台上可以直接输入已输入的内容。当从补全或指标查找的地方输入时也可以起作用。

先制创建一个以任意指标为基准的图表,然后进行保存,之后只需从列表中选择即可访问该图表。

我认为其他有关图表创建的详细信息属于Grafana本身的功能,所以建议您在Grafana的官方网页上查看。

其他

我对以下内容很感兴趣,但由于尚未尝试,所以如果以后有机会尝试,我会附加说明。

    • Pushgateway

 

    • 最初に書きましたがPushgatewayを使うとPullではなくPushもできるようになります。

Consul連携
Consulと連携することでConsulから監視対象を取得できるようなので監視対象の増減に伴う設定ファイルの書き換えが不要になりそうなので試してみたいと思っています。

Federation
Federationを使うと他のPrometheusのインスタンスからメトリクスの取得ができるようです。スケールさせる場合等に使うようですが、今のところそこまでの規模が必要になることは無さそうなので試すことは無いかもしれません。。。

最后

所以我简单地看了一下 Prometheus 的使用方法。
因为它看起来相当有趣,所以如果有机会的话,我打算尝试实际应用。

顺便提一句,我使用了Docker的Swarm模式,但是我希望监视工具在固定节点上运行,并且如果将监视目标作为服务创建,那么当它崩溃时将无法察觉到(因为会从另一个节点通过路由网格接收响应),所以作为Swarm模式的示例,我觉得非常不合适。因此,如果要实际创建,我认为最好使用常规的compose之类来建立。

bannerAds