kun432's blog

技術ネタ、読書記録、など。2015年から人生をやり直し中です。

Prometheusを理解する

Kubernetesの監視はPrometheusがデファクトスタンダードになっており、インストールもk8sクラスタ上に行うのが一般的です。が、今回はPrometheusをざっくり理解するために普通のサーバに入れてみようという、今更だけど自分用メモです。

Prometheusとは

ちゃんとした解説は世の中に色々転がっていると思うので、そちらを見てください。自分的には

  • Prometheus server/Prometheus Web UI/Alertmanager/Push Gateway/Exporter/Grafanaなど複数のコンポーネントで構成
  • 構造がシンプルでバイナリ+設定ファイルだけで動く
  • DockerやKubernetesとの連携も可能

というイメージです。

コンポーネントが細かく別れていることと、UIがコンポーネントごとに別だったり、他の外部UIコンポーネント(grafanaとか)も現実的に必要になったり、ということで全貌が見えにくい印象があります。が、Promethes本体はあくまでも各監視対象のメトリクスを保存しておく単なる時系列データベースであり、周辺ツールがここにアクセスすることで一つの監視システムを構成していると考えています。

なので、各コンポーネントが何をしているのか、というところからまず整理します。

  • Prometheus Server
    • 本体。時系列データベース、それにアクセスするためのAPI、監視対象からメトリクスを収集
  • Exporter
    • いわゆるエージェント。監視対象システム上でメトリクスを収集、Prometheus Serverからの取得要求に答える
  • Push Gateway
    • 監視対象側からメトリクスをpushしたい場合に待ち受けている。Prometheus Serverはここをポーリングしてメトリクスを拾うので、pushとpullの中間層的なイメージ。
  • AlertManager
    • Promethes本体は通知機能を持たない。AlertManagerにpushして通知を行う。そのためのWeb UIも持つ。
  • Prometheus web UI/Grafana
    • Prometheus ServerのAPIにアクセスして、メトリクスの抽出、視覚化を行う。PromQLというクエリ言語でアクセスする。

ま、ざっとこんな感じかなと。このあたりをアーキテクチャ図と見比べると理解しやすいかと思います。他にもサービスディスカバリ等でkubernetesと連携したりしますが、そこはちょっと置いときましょう。

Prometheusのインストール

では早速やっていきましょう。Prometheusサーバと監視対象サーバの2台のサーバを用意してやってみます。

  • Prometheusサーバ
    • OS: ubuntu 18.04
    • IP: 10.240.0.31
  • 監視対象サーバ
    • OS: ubuntu 18.04
    • IP: 10.240.0.32

インストール方法は色々あるようですが、ubuntuなので素直にパッケージ使いたいと思います。

Prometheusサーバ

インストール

$ sudo apt-get install -y prometheus

設定ファイルは/etc/prometheus/prometheus.yaml

# Sample config for Prometheus.

global:
  scrape_interval:     15s # By default, scrape targets every 15 seconds.
  evaluation_interval: 15s # By default, scrape targets every 15 seconds.
  # scrape_timeout is set to the global default (10s).

  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
      monitor: 'example'

# Load and evaluate rules in this file every 'evaluation_interval' seconds.
rule_files:
  # - "first.rules"
  # - "second.rules"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # Override the global default and scrape targets from this job every 5 seconds.
    scrape_interval: 5s
    scrape_timeout: 5s

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ['localhost:9090']

  - job_name: node
    # If prometheus-node-exporter is installed, grab stats about the local
    # machine by default.
    static_configs:
      - targets: ['localhost:9100']
  • 15秒間隔で監視対象からデータを引っ張る
  • 15秒間隔で引っ張ったデータとルールの比較を行う
  • アラートルールの設定はなし
  • scrape_configs.[].job_nameで監視対象の設定を行う。デフォルトでは以下が含まれている。
    • ローカルのprometheusサーバ自身
    • ローカルのnode-exporter(prometheusのインストールで自動で入る)

とりあえずこのままでも動きそうなので起動します。node-exporterも起動しておきましょう。

$ sudo systemsctl start prometheus
$ sudo systemsctl start prometheus-node-exporter

では、ブラウザでprometheusサーバの9090版ポートにアクセスします。

f:id:kun432:20200629175812p:plain

はい、prometheusの管理画面が表示されていますね。ではメトリクスを表示してみます。ドロップダウンリストから適当なメトリクスを選択して"Execute"をクリックします。今回は「node_cpu」を選択してみます。

f:id:kun432:20200629180352p:plain

こんな感じでメトリクスが表示されます。次に、Graphタブをクリックしてみてください。

f:id:kun432:20200629180547p:plain

時系列でメトリクスが時系列でグラフ表示されます。つまり先程数値で表示されていたのは最新のメトリクスということですね。

f:id:kun432:20200629180736p:plain

監視対象サーバ

こちらはprometheus-node-exporterをインストールしてプロセスを上げておくだけです。

$ sudo apt-get install -y prometheus-node-exporter
$ sudo systemctl start prometheus-node-exporter

で、あとはprometheusサーバ側で監視対象に追加してあげます。/etc/prometheus/prometheus.yamlに以下を追加します。

... snip ...

scrape_configs:
... snip ...

  - job_name: prometheus-client
    static_configs:
      - targets: ['10.240.0.41:9100']

反映します。

$ sudo systemctl restart prometheus

先ほどと同じように「node_cpu」のグラフを見てみましょう。新しく追加した監視対象サーバが下の方に追加されているのが見えるでしょうか?

f:id:kun432:20200629183414p:plain

ここまでがprometheusの基本になります。

AlertManagerのインストール

上でも述べたとおり、Prometheus自体は通知の機能を持たず、通知はAlertManagerの仕事になります。ということでAlertManagerをPrometheusサーバ上にインストールします。

$ apt-get install -y prometheus-alertmanager

アラートの条件やしきい値はPrometheus Server側で設定します(なのでAlertManagerはほんと通知だけですね。)/etc/prometheus/prometheus.yaml に以下を追加します。別ファイルで切り出している形です。

... snip ...

rule_files:
  - "/etc/prometheus/alert.rules"

... snip ...

/etc/prometheus/alert.rulesを記載します。で、prometheusのアラートルールを色々紹介しているサイトがあるみたいなので、そこからルールを持ってたいと思います。

groups:
  - name: prometheus-client
    rules:
    - alert: PrometheusTargetMissing
      expr: up == 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Prometheus Target missing (instance {{ $labels.instance }})"
        description: "A Prometheus Target has disappeared\n  VALUE = {{ $value }}\n  LABELS: {{ $labels }}"
    - alert: HostHighCpuLoad
      expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Host high CPU load (instance {{ $labels.instance }})"
        description: "CPU load is > 80%\n  VALUE = {{ $value }}\n  LABELS: {{ $labels }}"

ノードが死んだ場合とcpuが80%を超えた場合を試しに設定してみました。

反映します。

sudo systemctl restart prometheus

prometheusの管理画面にあるAlertメニューを開くと追加したルールが表示されていますね。

f:id:kun432:20200629210258p:plain

では試しに監視対象サーバを落としてみましょう。Prometheusのalertを開くと、ちゃんと状態が変化していることを検出できています。

f:id:kun432:20200629210822p:plain

この状態でしばらく待つと、さらに状態が変わり「FIRING」となります。これがalertmanagerにpushされる状態です。

f:id:kun432:20200629211221p:plain

では、通知の設定を行います。色々通知の方法はありますが、今回はSlackに投げてみましょう。/etc/prometheus/alertmanager.ymlを以下のように修正します。

global:
  slack_api_url: "https://hooks.slack.com/services/XXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXX"

route:
  receiver: 'slack-notification'

receivers:
- name: 'slack-notification'
  slack_configs:
  - channel: '#general'
    text: "<!channel> \nsummary: {{ .CommonAnnotations.summary }}\ndescription: {{ .CommonAnnotations.description }}"

シンプルにslackだけに投げてます。グループは使ってません。あとはテキストにアラート設定側のannotationsを含めるようにしてます。通知のテンプレは以下も参考にしてください。

そして、Prometheus serverからalert manager似pushするように設定します。/etc/prometheus/prometheus.yaml に以下を追加します。

alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - localhost:9093

でAlert Managerを起動、Prometheus Serverも再起動して反映しましょう。

$ sudo systemctl start prometheus-alertmanager
$ sudo systemctl restart prometheus-alertmanager

AlertManagerのWeb画面を見てみるとこちらでも検出しています。

f:id:kun432:20200629223406p:plain

そしてslackにも通知が来ました!

f:id:kun432:20200629223133p:plain

まとめ

とりあえず一通り動きました。あとはgrafana入れればよくあるprometheus構成になると思いますが、ちょっとそこは割愛します。次回はこれをkubernetesでやってみたいと思います。