Prometheusで本番環境の監視をして3か月経ちました

初めに

Prometheusで本番環境の監視を始めて3か月程度経過しました。

今回は

  • Prometheus 導入に関してハマったところ
  • 現在のPrometheus活用状況

といった所を紹介したいと思います。

「Prometheusって何?」という方はこちらをご覧ください。

tech.willgate.co.jp

Prometheus導入でハマったところ

紹介するところ以外でも色んなところでハマったのですが、代表的なところを紹介します。

メール送信設定

Alertmanagerからメールを送信しようとしたのですが送信できずログを見てみると、証明書のチェックでエラーが出ているようでした。

事象としては以下のissueに近いです。

github.com

送信に使っていたメールサーバは自分で構築したものではなく、他社VPSのメールサービスを使っていたのですが、そこの証明書がメール送信で使っているドメインと異なっていたのが原因だったようです。

Alertmanager の email_configs に以下の記述をして、証明書チェック時に出る警告を無視するようにしました。

  email_configs:
  - to: 'alert-error@example.com'
    tls_config:
      insecure_skip_verify: true
    send_resolved: true

send_resolved は障害から復旧した時に、復旧通知を自動で送るための設定です。

Rプロキシ経由にする

巷の運用監視ツールとは異なり、Prometheus本体は管理画面への認証機能を持っていません、ユーザという定義すらありません。

prometheus.io

なのでリバースプロキシ+LDAPサーバ等を使って認証機能を持たせるのが推奨されており、以下のようなディレクトリ構造を考えていました。

ところがリバースプロキシの設定だけではうまくいかず四苦八苦し、結局リバースプロキシのnginxのconfigとprometheusの起動時オプションで、公開URL(web.external-url)とディレクトリのパス(web.route-prefix)の設定をすることで解決しました。

nginx側の設定。LDAPサーバの認証も入ってます。

upstream prometheus {
    server <prometheusのIPアドレス>:9090;
}

server {

    server_name example.com;
    listen 80;

    location /prometheus {

        auth_ldap "Forbidden";
        auth_ldap_servers <LDAPサーバ>;

        proxy_redirect          off;
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://prometheus$request_uri;

prometheus側の設定。docker-composeを使っています。

command:
  - '--web.external-url=http://example.com/prometheus/'
  - '--web.route-prefix=/prometheus'

公式にも書いてある手順です。Alertmanagerでも同様の手順で公開できます。

prometheus.io

現在のPrometheus活用状況

現在の構成

すべてVPS上のコンテナとして動かして、docker-composeでまとめています。

各コンテナイメージのバージョンは以下の通りです。

  • grafana:6.2.5
  • prometheus:v2.11.1
  • alertmanager:v0.18.0
  • blackbox-exporter:v0.14.0

VPSのスペックは以下の通りです。

  • CPU: 6core
  • MEM: 8GB
  • SSD: 500GB

上記構成でメトリクス保存期間6か月、200弱のVM監視を行っていますが、パフォーマンスの問題が出たことはありません。

ECインスタンスの監視

Prometheusはkubernetesやコンテナ監視のイメージが強いかもしれませんが、VMの監視でも十分な力を発揮してくれます。

弊社はAWSのEC2を使ってサービスを構築することが多いのですが、Prometheusのサービスディスカバリ機能を使えば、IAMユーザに紐づくEC2インスタンスを探してメタデータを取得してくれます。

例えば以下は、EC2インスタンスを探してnode_exporter での監視対象とする設定です。

「relabel_configs」というので、<ec2のパブリック IP:9100>をPrometheusでの監視対象とし、ec2のメタデータに登録されているEC2インスタンス名前([__meta_ec2_tag_Name])を、nameというラベルに付け替えてあげて、Prometheusで監視するときのサーバ名としています。

  - job_name: 'aws.ec2'
    ec2_sd_configs:
      - region: ap-northeast-1
        access_key: <ACCESS_KEY>
        secret_key: <SECRET_KEY>
        port: 9100
    relabel_configs:
      - source_labels: [__meta_ec2_public_ip]
        regex:  '(.*)'
        target_label: __address__
        replacement: '${1}:9100'
      - source_labels: [__meta_ec2_tag_Name]
        target_label: name

あとはEC2インスタンスnode_exporterを入れれば監視が始まります。Ansibleを使ってコード化すると非常に楽です。

またGrafanaを使うのであれば、CloudWatchをDataSourceとして扱うことができます。node_exporterを入れることができないRDSやAuroraはその方法で監視しています。

設定のバージョン管理

Prometheusは設定をyamlファイルで定義できます。弊社の場合はdocker-composeのyamlファイルと合わせてGit+Bitbucketでバージョン管理をしています。これで構成管理と可搬性の担保をしています。

種類豊富なexporter

Prometheusはexporterという、エージェントのようなものからメトリクスを取得します。サーバの基本な情報を取得するnode_exporterMySQLの情報を取得するmysqld_exporterなど、公式サイトで紹介されているだけでも相当な数になっています。

prometheus.io

ただ、exporterはそれぞれに待ち受けるPort番号が異なり、exporterを追加/削除するたびにPortの開閉をするのが非常に面倒だったのですが、exporter_proxyの登場で全てが一変しました。

github.com

これはexporterのproxyとして動作するもので、1つのportで複数のexporterとの通信が可能になります。

非常に、非常に便利です。

柔軟なPromQL

Prometheusは取得したメトリクスに対してPromQLというクエリを発行して、値を見ることができます。

正直とっつきにくいのですが、慣れれば軽快かつパワフルに動いてくれます。

例えば最近だと、Linuxカーネルに以下のような脆弱性が発覚し、カーネルの更新が必要となりました。

JVNVU#93800789: Linux および FreeBSD カーネルにおけるサービス運用妨害 (DoS) の脆弱性

VMカーネルのバージョンを取得し、状況を把握する必要がありました。

まずはnode_exporter から取得できる『node_uname_info』というメトリクスを使って、unameコマンドの戻り値のような値を取得します。フィルタリングしないと以下のような値を取得できます。

以下は取得例です。

node_uname_info{instance="192.0.2.1:9100",job="aws.ec2",machine="x86_64",name="example",release="3.10.0-957.21.3.el7.x86_64",sysname="Linux",version="#1 SMP Tue Jun 18 16:35:19 UTC 2019"}

そして下記のようなクエリを発行することで、特定のバージョン以外のカーネルを持つVMを抽出できます。

node_uname_info{release!~"4.14.123-86.*|3.10.0-957.21.*|2.6.32-754.*"}

解説するとこれは正規表現を使って、2系、3系、4系それぞれの指定したバージョン以外のVMを抽出するクエリとなります。

!~ で以降の正規表現パターンにマッチしない、=~ で以降の正規表現パターンにマッチするという意味になります。

Grafanaのpanelを使うとcsvにexportできるので、スプレッドシートに直して対応状況の一覧シートも簡単に作成できます。

f:id:kobayashi-ryotaro:20190711174316p:plain
export_csv

Grafanaとの組み合わせ

先にも述べたようにGrafanaとPromQLで様々な情報を取得したりグラフ化できるようになります。GrafanaにはPrometheus本体より親切なPromQL補完機能があるので助かるのですが、取得できる情報があまりにも多いので、最初は困惑しました。

なのでおすすめは、とりあえず公開されているGrafanaのダッシュボードをimportして、動かしてみることです。

grafana.com

かなりの数が公開されいます。私はnode_exporter用のNode Exporter Full dashboardData for Grafana | Grafana LabsをGrafanaにimportして、中に書かれているPromQLを参考にしてダッシュボードを作っていきました。以下はあるサービスの全体を俯瞰できるダッシュボードです。

f:id:kobayashi-ryotaro:20190711175146p:plain
dashboard

まとめ

CPU使用率、Topページのレスポンスなど、観点によって監視対象は様々です。PrometheusとGrafanaで様々シーンに対応した見やすいダッシュボードを作ることができるようになりました。

今回は少ししか紹介しませんでしたが、Alertmanagerを使うことで簡単にSlackやメールに障害情報を通知できるようになります。

若いプロダクトゆえに日本語情報が少ないので、『入門 Prometheus』という本にはかなり助けられています。

www.oreilly.co.jp

ウィルゲートとしても使うだけではなく、今後も情報を発信していきたいと考えています。

お読みいただきありがとうございました。