ラベル Prometheus の投稿を表示しています。 すべての投稿を表示
ラベル Prometheus の投稿を表示しています。 すべての投稿を表示

2024年11月1日金曜日

mtail を使って nginx にアクセスが来ているかを Prometheus で監視する方法

mtail を使って nginx にアクセスが来ているかを Prometheus で監視する方法

概要

mtail指定したログの行数を Promethues 用のメトリックスとして返してくれる exporter です
今回は nginx と連携して nginx のログを監視する compose を紹介します

環境

  • Ubuntu 24.04
  • docker 27.3.1
  • mtail 3.0.8

compose.yaml

nginx を起動しアクセスログをホスト側でマウントします
mtail 側ではホスト側のマウントした nginx のログを更にコンテナ側にマウントします

mtail の公式イメージは dockerhub で公開されていないので Dockerfile.mtail を作成し自分でビルドしてイメージを作成します

あとは mtail の設定を作成します

services:
  nginx:
    image: nginx:latest
    container_name: nginx_server
    ports:
      - "8080:80"
    volumes:
      - ./nginx/log:/var/log/nginx
    networks:
      - monitoring_net

  mtail:
    container_name: mtail_monitor
    build:
      context: .
      dockerfile: Dockerfile.mtail
    ports:
      - "3903:3903"
    volumes:
      - ./nginx/log:/var/log/nginx:ro
      - ./mtail/progs:/mtail/progs:ro
    networks:
      - monitoring_net
    command: >
      -logtostderr
      -logs /var/log/nginx/access.log
      -progs /mtail/progs

networks:
  monitoring_net:
    driver: bridge

Dockerfile.mtail

golang は執筆時の最新を使っています
mtail 自体のインストールはバイナリまたは自分でソースビルドするしかないので今回はバイナリファイルを使います

また mtail でメトリックスを取得するためのポートを expose します

FROM golang:1.23.2

RUN wget https://github.com/google/mtail/releases/download/v3.0.8/mtail_3.0.8_linux_amd64.tar.gz
RUN tar zvxf mtail_3.0.8_linux_amd64.tar.gz
RUN mv mtail /go/bin

EXPOSE 3903

ENTRYPOINT ["/go/bin/mtail"]

mtail/progs/log.mtail

mtail 用の設定ファイルを作成します
アクセスがきたときにカウントする変数を用意します
今回は nginx のどのパスにアクセスが来てもカウントをプラス1するようにします

counter nginx_requests_total

/^.*$/ {
  nginx_requests_total++
}

動作確認

  • docker compose up -d

で各種コンテナを作成しましょう

  • curl localhost:3903/metrics

にアクセスするとメトリックスが確認できます
更に

  • curl localhost:8080

にアクセスし再度メトリックスを確認するとカウンタが1進んでいるのが確認できると思います

おまけ: 特定のパスのみカウントする方法

  • vim nginx/nginx.conf
events {}

http {
    server {
        listen 80;
        
        location /status {
            default_type application/json;
            return 200 '{"status":"ok"}';
        }

        # 他のリクエストをデフォルトの404にする場合
        location / {
            return 404;
        }
    }
}
  • vim compose.yaml
services:
  nginx:
    image: nginx:latest
    container_name: nginx_server
    ports:
      - "8080:80"
    volumes:
      - ./nginx/log:/var/log/nginx
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    networks:
      - monitoring_net

  mtail:
    container_name: mtail_monitor
    build:
      context: .
      dockerfile: Dockerfile.mtail
    ports:
      - "3903:3903"
    volumes:
      - ./nginx/log:/var/log/nginx:ro
      - ./mtail/progs:/mtail/progs:ro
    networks:
      - monitoring_net
    command: >
      -logtostderr
      -logs /var/log/nginx/access.log
      -progs /mtail/progs

networks:
  monitoring_net:
    driver: bridge
  • vim mtail/progs/log.mtail
counter nginx_requests_total

/status/ {
  nginx_requests_total++
}

最後に

mtail を使ってログの行数を Promethues のメトリックス形式で取得する方法を紹介しました
mtail 側からログファイルにアクセスできればどんなファイルでも監視することができます

ファイルは単純なテキストファイルなどでも良いです

2024年7月5日金曜日

Prometheus を nginx 配下で動作させる方法

Prometheus を nginx 配下で動作させる方法

概要

ポイントは --web.router-prefix は何も設定しない点です

環境

  • Ubuntu 22.04
  • Promethues 2.52.0
  • nginx 1.27.0

Prometheus の起動オプション変更

--web.external-url=http://localhost:9090/prometheus/ を追加します
localhost の部分は listen したいホスト名や IP に変更してください

nginx.conf

/prometheus で受けれるようにします

upstream prometheus {
    server 192.168.1.100:9090;
}

server {
    listen 8080;
    server_name host01;

    location = /prometheus {
        return 302 /prometheus/;
    }

    location /prometheus/ {
        proxy_set_header Host $host;
        proxy_pass http://prometheus;
    }
}

動作確認

:8080/prometheus にアクセスして問題なく動作することを確認しましょう

また Prometheus のエンドポイントにアクセスしているツール (grafana や sdk など) がある場合はそちらのエンドポイントも修正する必要があります

最後に

次回は Alertmanager を動作させます

参考サイト

2023年12月18日月曜日

Prometheus の query_range で最大プロット可能なステップ数を計算する方法

Prometheus の query_range で最大プロット可能なステップ数を計算する方法

概要

前回 query_range をコールする方法を紹介しました
その際にプロット数の最大値が 11,000 個ということを紹介しました
指定した範囲に応じて最大ステップ数が変わるので今回はそれを考慮したコードを紹介します

環境

  • Python 3.11.3
  • requests 2.31.0

サンプルコード

ポイントは step = int(range / 11000) + 1 の部分です
レンジ内における最大プロット数に収まる step 数を計算します

from datetime import datetime, timedelta, timezone

import requests

proxies = {"http": "192.168.100.2:3128"}
end = datetime.now(timezone.utc)
start = end - timedelta(hours=60)
end_s = end.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
start_s = start.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
# 60時間の範囲で指定可能な最大ステップ数を計算する
# query_range のプロット数が11,000を超えないようにする
range = (end - start).total_seconds()
# 1秒分加算することで指定可能なstep数の最大値になる
step = int(range / 11000) + 1
params = {
    "query": 'instance:node_filesystem_avail:ratio{mountpoint="/var/opt/gitlab"}',
    "start": start_s,
    "end": end_s,
    "step": f"{step}s",
}
schema = "http"
hostname = "192.168.100.1"
port = "9090"
path = "/api/v1/query_range"
url = f"{schema}://{hostname}:{port}{path}"

res = requests.get(url, params=params, proxies=proxies)

# ステップ数とレンジによりプロット数が11,000を超えていないことを確認
# print(res.json())
print(f"step -> {step}s")
print(f"range -> {range}")
print(len(res.json()["data"]["result"][0]["values"]))

注意事項

上記場合一つ考慮が足りない点があります
例えば上記の場合 60 時間分のレンジ内で 11,000 プロット取れるステップ数 (20s) を計算していますがもし 60 時間分のデータがまだない場合にはもっと細かいステップ数を指定することができます

例えば 30 時間分のデータしかない場合には単純に倍のステップ数を指定することができます (10s)
これを考慮する場合には指定のレンジ内で取得したデータの実際のレンジ情報を取得しその実際のレンジ情報からステップ数を計算する必要があるので 2 回 API をコールする必要が出てきます
正確に出したい場合にはその方法が必要になるかなと思います

また scrape_interval が 30s などになっている場合はそもそもデータが 30 秒おきに格納されていることになるので step=30s 以下を指定しても結果的には step=30s と同じデータになるはずです

最後に

Promethues の UI でネットワークを見ると実際に query_range をコールしているクエリが見えるのでそれを参考にしてもいいかもしれません

2023年12月14日木曜日

Promethues の API を requests でコールする

Promethues の API を requests でコールする

概要

過去にライブラリを使った方法を紹介しました
今回は requests だけでコールしてみました

環境

  • Python 3.11.3
  • requests 2.31.0

サンプルコード

API は query_range を使います

from datetime import datetime, timedelta, timezone

import requests

proxies = {"http": "192.168.100.2:3128"}
# 30分前から現在時刻まで取得
now = datetime.now(timezone.utc)
end = now.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
start = (now - timedelta(minutes=30)).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
params = {
    "query": 'instance:node_filesystem_avail:ratio{mountpoint="/var/opt/gitlab"}',
    "start": start,
    "end": end,
    "step": "60s",
}
schema = "http"
hostname = "192.168.100.1"
port = "9090"
path = "/api/v1/query_range"
url = f"{schema}://{hostname}:{port}{path}"

res = requests.get(url, params=params, proxies=proxies)
print(res.json())

注意事項

step=60s にしていますが query_range API の場合、取得できる最大プロットの数が 11,000 になるのでそれを超えなければ更に短い時間でも OK です
query API であれば制限はないようです
一週間取得する場合には 60s からでないと取得できません
また Prometheus はデフォルトだと 15 日間しかデータを保存していません

最後に

メトリックを取得するだけならかなり簡単にコールできるので専用のライブラリはいらないかもです

参考サイト

2023年12月7日木曜日

Gitlab の Promethues を使って死活監視をするときに使えそうなメトリックス

Gitlab の Promethues を使って死活監視をするときに使えそうなメトリックス

概要

Gitlab 内蔵の Promethues を使って Gitlab 自体の死活監視をする方法を紹介します
使えそうなメトリックスとダメそうなメトリックスがあったのでそれも紹介します

環境

  • Gitlab 16.3.6
  • Prometheus 2.46.0

使えそうなメトリックス

  • gitlab_sli:gitlab_component_errors:rate{job="gitlab-workhorse"} > 0

が一番いいかなと思います
gitlab に定期的にアクセスして 500 が帰ってきたときの割合を返してくれるメトリックスです

これは gitlab が提供してくれる recording alert で実際の中身は sum(rate(http_request_duration_seconds_count{job="gitlab-rails",status=~"5.."}[1m])) になっています

使えなさそうなメトリック

  • avg_over_time(up[5m]) * 100 < 50

これも gitlab が提供してくれるアラートルールなのですが up を使っています
up だと各プロセスではなく Promethues が使用している targets つまり exporter のプロセス監視をしているだけなので実際の redis や postgres, rails (puma) がダウンしても exporter に影響がないためアラートがあがりません

なのでこの ServiceDown というアラートを死活監視として使うことはおすすめしません

実際にプロセス監視ができそうなのが redis_up というクエリだけで他のプロセスに関しては死活監視できそうなクエリはデフォルトの gitlab のメトリックはありませんでした

最後に

自分で blackbox_exporter を追加しても OK です
が面倒なのでデフォルトの gitlab + Promethues で死活監視できる方法を紹介しました

あとは自作の exporter を作ってもいいですがそれも面倒かなと思います

参考サイト

2023年12月1日金曜日

Promethues + Alertmanager + node_exporter の最小構成 docker compose

Promethues + Alertmanager + node_exporter の最小構成 docker compose

概要

メモがてら残しておきます

環境

  • Ubuntu 22.04
  • docker 24.0.4

compose.yml

  • vim compose.yml
services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
    ports:
      - 9090:9090
    restart: unless-stopped
    volumes:
      - ./prometheus:/etc/prometheus
      - prom_data:/prometheus
  node_exporter:
    image: quay.io/prometheus/node-exporter:latest
    container_name: node_exporter
    command:
      - '--path.rootfs=/host'
    network_mode: host
    pid: host
    restart: unless-stopped
    volumes:
      - '/:/host:ro,rslave'
  alertmanager:
    image: prom/alertmanager
    container_name: alertmanager
    volumes:
      - ./alertmanager:/etc/alertmanager
    command: "--config.file=/etc/alertmanager/alertmanager.yml"
    ports:
      - 9093:9093
    restart: unless-stopped
volumes:
  prom_data:

Promethues

  • vim promethues/prometheus.yml
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alertmanager:9093

rule_files:
- '/etc/prometheus/*.rules'

scrape_configs:
- job_name: 'node_exporter'
  static_configs:
  - targets:
    - '192.168.100.1:9100'
  • vim prometheus/node.rules
groups:
- name: Node
  rules:
  - record: instance:node_cpus:count
    expr: count without(cpu, mode) (node_cpu{mode="idle"})

Alertmanager

  • vim alertmanager/alertmanager.yml
oute:
  receiver: default-receiver
  routes:
  - receiver: email
    matchers:
    - alertname=""
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 4h
receivers:
- name: default-receiver
- name: email
  email_configs:
  - send_resolved: true
    to: your_mail_address@here
    from: your_from_address@here
    hello: localhost
    smarthost: smtp.ess.nifcloud.com:465
    auth_username: xxx
    auth_password: xxx
    headers:
      Subject: '{{ template "my.email.text.subject" . }}'
    text: '{{ template "my.email.text.body" . }}'
    require_tls: false
templates:
- /etc/alertmanager/*.tmpl
  • vim alertmanager/my_email_text.tmpl
{{ define "my.email.text.body" }}
{{ range .Alerts.Firing }}
{{ range .Annotations.SortedPairs }}
- {{ .Name }} = {{ .Value }}
{{ end }}
{{ end }}
{{ end }}

{{ define "my.email.text.subject" }}
{{ $alerts := "" }}
{{ $instance_id := (index .Alerts 0).Labels.instance_id }}
{{ range .Alerts }}
{{ $alerts = (printf "%v %v" $alerts .Labels.alertname) }}
{{ end }}
[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] ({{ $instance_id }} ->{{ $alerts }})
{{ end }}

動作確認

  • docker compose up -d
  • docker compose ps
NAME                IMAGE                                     COMMAND                  SERVICE             CREATED             STATUS                    PORTS
alertmanager        prom/alertmanager                         "/bin/alertmanager -…"   alertmanager        13 minutes ago      Up 13 minutes             0.0.0.0:9093->9093/tcp, :::9093->9093/tcp
node_exporter       quay.io/prometheus/node-exporter:latest   "/bin/node_exporter …"   node_exporter       13 minutes ago      Up 13 minutes
prometheus          prom/prometheus                           "/bin/prometheus --c…"   prometheus          13 minutes ago      Up 13 minutes             0.0.0.0:9090->9090/tcp, :::9090->9090/tcp

最後に

あとは必要に応じて node.rules ファイルや prometheus.yml でメトリックスの取得先を変更すれば OK です

my_email_text.tmpl を変更すればテキストメールのテンプレートも変更できます

2023年11月24日金曜日

Gitlab の Promethues に独自のルールを設定する方法

Gitlab の Promethues に独自のルールを設定する方法

概要

rules ファイルを作成してコンテナ側にマウントすれば OK です
今回は簡単な独自ルールを作成して設定してみました

環境

  • Gitlab 16.3.6

custom.rules

groups:
- name: MyCustomRule
  rules:
  - alert: CpuHighUsage
    expr: instance:node_cpu_utilization:ratio > 0.5
    for: 30m
    annotations:
      description: Current cpu usage is {{ $value }}.
      summary: CPU usage exceeded 50%.

instance:node_cpu_utilization:ratio は Gitlab のルールでデフォルトで提供されている Recoding rule の一つで CPU の使用率を取得することができる値です

コンテナ内の /var/opt/gitlab/prometheus/rules/ に配置

  • cp custom.rules /mnt/opt/gitlab/prometheus/rules

ローカル領域のマウントでもボリュームのマウントでも OK です

Omnibus Gitlab のデフォルトでは /var/opt/gitlab/prometheus/rules/ 配下のルールを見るのでそこに配置しましょう

gitlab.rb

もし別の場所に rules ファイルを配置する場合は配列に追加しましょう

prometheus['rules_files'] = ['/var/opt/gitlab/prometheus/rules/*.rules']

動作確認

  • docker-compose down
  • docker-compose up -d

であとは Promethues の rules の設定を確認して追加されていることを確認しましょう

参考サイト

2023年3月15日水曜日

Promethues の Basic 認証を追加する方法

Promethues の Basic 認証を追加する方法

概要

タイトルの通りです
web.yml に認証情報を記載して Prometheus を起動させるだけです
今回は docker コンテナで Promethues は動作させます

環境

  • Ubuntu 18.04
  • docker 20.10.7
  • Python 3.10.2
  • bcrypt 4.0.1

bcrypt パスワードの生成

ベーシック認証用のパスワードは bcrypt で暗号化された文字列が必要です

公式にもありますが bcrypt は Python のライブラリを使って生成しました

  • pip install bcrypt
  • python -c 'import bcrypt; hashed_password=bcrypt.hashpw("passw0rd!".encode("utf-8"), bcrypt.gensalt()); print(hashed_password)'

上記の平文パスワードの部分を適宜変更すれば OK です

web.yml の作成

パスワード情報は web.yml に記載します

  • vim web.yml
basic_auth_users:
    admin: $2b$12$BB48JzIK5bfRo44g4GOAPe3/q6sTaLW3pbvugPlUZVuYg8LOW4sOK

起動する

作成した web.yml を使って起動します
web.yml を指定するオプションは web.config.file です

  • docker run -d -p 9090:9090 -v $(pwd):/prometheus-data prom/prometheus --config.file=/prometheus-data/prometheus.yml --web.config.file=/prometheus-data/web.yml

prometheus.yml は必須なので適当にこちらから作成してください (ノードエクスポータなどの内容は仮で大丈夫です)

動作確認

localhost:9090 にアクセスするとブラウザのベーシック認証が発動するのが確認できると思います

API をコールするときもベーシック認証が必要になっていることを CLI で確認しましょう

  • curl --head -u admin http://localhost:9090/graph

最後に

今回は紹介しませんが Alertmanager でも同じ歩法でベーシック認証を付与することができます

参考サイト

2022年4月15日金曜日

docker-compose で node_exporter を起動する方法

docker-compose で node_exporter を起動する方法

環境

  • Ubuntu 18.04
  • docker 20.10.7
  • node-exporter 1.3.1

docker-compose

version: '3.8'

services:
  node_exporter:
    image: quay.io/prometheus/node-exporter:latest
    container_name: node_exporter
    command:
      - '--path.rootfs=/host'
    network_mode: host
    pid: host
    restart: unless-stopped
    volumes:
      - '/:/host:ro,rslave'

上記は host ネットワークで起動します
ports を使う場合は以下の通り

version: '3.8'

services:
  node_exporter:
    image: quay.io/prometheus/node-exporter:latest
    container_name: node_exporter
    command:
      - '--path.rootfs=/host'
    ports:
      - '9100:9100'
    restart: unless-stopped
    volumes:
      - '/:/host:ro,rslave'

ただ ports を使う場合はネットワークのメトリックが node_exporter のコンテナのメトリックになるので注意してください

ちゃんとホストのネットワークインタフェースを監視したい場合は network_mode: host を使用します

参考サイト

2021年12月16日木曜日

VictoriaMetrics 超入門

VictoriaMetrics 超入門

概要

VictoriaMetrics はサーバなどのメトリックデータを収集し時系列データとして可視化することができる監視ツールです

Prometheus のメトリックデータも収集することができます
今回は VictoriaMetrics を構築し簡単なメトリックの収集までやってみました

環境

  • macOS 11.6.1
  • docker 20.10.11
  • VictoriaMetrics 20211202-133618-tags-v1.70.0-0-g7f2f26b25

node_exporter の起動

テストなので mac 上で起動します

prometheus.yml の準備

VictoriaMetorics は prometheus.yml をそのまま使うことができます

先程準備した node_exporter を scrape 先として設定します

  • mkdir config
  • vim config/prometheus.yml
global:
  scrape_interval:     15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'node_exporter_on_mac'
    static_configs:
    - targets: ['192.168.1.2:9100']

VictoriaMetorics の起動

今回は docker で構築します
公式のイメージが dockerhub で公開されているのでそれを使います

  • mkdir data
  • docker run -d -v $(pwd)/data:/victoria-metrics-data -p 8428:8428 victoriametrics/victoria-metrics

これで http://localhost:8428 にアクセスすると管理画面が表示されます
ここで WebUI にアクセスしたり scrape 先の設定できます

http://localhost:8428/targets を確認するとちゃんと先程起動した node_export がターゲットに入っていることが確認できます

オプション確認

各種オプションは以下のコマンドで確認できます

  • docker run --rm victoriametrics/victoria-metrics --help

動作確認

Promethues の API 互換でもあるので API を使います

  • curl 'http://localhost:8428/api/v1/query?query=up'

これで以下の結果が取得できればちゃんとメトリックデータが VictoriaMetrics に格納されていることが確認できます

{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"up","instance":"192.168.1.2:9100","job":"node_exporter_on_mac"},"value":[1639445877,"1"]}]}}

PromQL も使えます
http://localhost:8428/vmui にアクセスすると VictoriaMetrics 専用の PromQL をコールできる UI が表示されるのでここで PromQL を発行しましょう

up{job="node_exporter_on_mac"}

と入力して実行すると以下のようにメトリックがグラフで確認できるはずです

最後に

今回はシングルノードでしたが VictoriaMetrics はクラスタ構成も組めるので大量のメトリックデータを管理保管することができます

Prometheus 互換でもあるので Prometheus の代替としても使えます
node_exporter などのエクスポータのデータも簡単に取り込めました

参考サイト

2021年10月11日月曜日

Prometheus で CPU 使用率が高くなったら Slack に通知するサンプル

Prometheus で CPU 使用率が高くなったら Slack に通知するサンプル

概要

Prometheus + Alertmanager + Node Export でノードの CPU 使用率を見て一定以上になったら Slack に通知するサンプルです

よく使う形式なので雛形として残しておきます

環境

  • Ubuntu 18.04
  • docker 20.10.7
  • Prometheus 2.30.3
  • Alertmanager 0.23.0
  • Node export 1.2.2

Node export 起動

  • docker run -d --net="host" --pid="host" -v "/:/host:ro,rslave" quay.io/prometheus/node-exporter:latest --path.rootfs=/host

:9100 ポートで起動します

Alertmanager 起動

  • mkdir data
  • vim alertmanager.yml
route:
  receiver: 'slack'
receivers:
- name: 'slack'
  slack_configs:
    - api_url: 'https://hooks.slack.com/services/xxx/xxx/xxx'
      channel: '#private'
      text: "{{ .CommonAnnotations.summary }}"
      send_resolved: true
  • docker run -d -p 9093:9093 --name alertmanager -v $(pwd):/alertmanager prom/alertmanager --config.file=/alertmanager/alertmanager.yml

:9093 ポートで起動します

Prometheus 起動

  • vim prometheus.yml
global:
  scrape_interval:     15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - 192.168.100.10:9093

rule_files:
  - 'alerts.rule'

scrape_configs:
  - job_name: 'node1'
    static_configs:
    - targets: ['192.168.100.10:9100']
  • vim alerts.rule
groups:
  - name: 'Node1 cpu monitoring'
    rules:
    - alert: 'Node1 cpu usage alert'
      expr: avg without(cpu) (rate(node_cpu_seconds_total{ job="node1",mode!="idle"}[1m])) >= 0.4
      for: 5s
      annotations:
        summary: 'Node1 cpu usage over 40%'
  • docker run -d -p 9090:9090 --name prometheus -v $(pwd):/prometheus-data prom/prometheus --config.file=/prometheus-data/prometheus.yml

:9090 ポートで起動します

動作確認

CPU に負荷テストします

  • stress-ng -c 2 -l 100

-c オプションは CPU のコア数です
各自の環境に合わせて変更してください

これで Slack に通知が来れば OK です

最後に

必要最低限な設定としてセットで覚えちゃってもいいかもしれません

stress-ng で 100% 負荷なのに Prometheus 的には 40% ほぼの負荷にしかなっていなかったのは CPU のモードごとに Prometheus が管理しているだと思います

stress-ng 実行後に top コマンドでコアごとの使用率を見ると 100% だったので top と同じ値を監視したい場合は監視ルールを少し変更する必要がありそうです

2021年5月1日土曜日

Promethues を helm chart で構築してみた

Promethues を helm chart で構築してみた

概要

Promethues を helm を使ってインストールしてみました

環境

  • kubernetes 1.20.4
  • helm 3.5.2
  • Grafana helm chart 13.8.0

事前準備

何でもいいので pv を用意しましょう
local を使う方法はこちら
default の storageClass を用意しても OK です
nfs で default の storageClass を作成する方法はこちら

リポジトリインストール

  • helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  • helm repo add kube-state-metrics https://kubernetes.github.io/kube-state-metrics
  • helm repo update

とりあえず使ってみる

  • helm install promethues prometheus-community/prometheus
  • kubectl get pod
NAME                                                  READY   STATUS    RESTARTS   AGE
nfs-subdir-external-provisioner-78cc5b4979-tnnnj      1/1     Running   0          17d
promethues-kube-state-metrics-55c795cd7f-mgg9b        1/1     Running   0          19m
promethues-prometheus-alertmanager-6b68776f64-7xlcq   2/2     Running   0          19m
promethues-prometheus-node-exporter-65j44             1/1     Running   0          19m
promethues-prometheus-node-exporter-j8hx8             1/1     Running   0          19m
promethues-prometheus-node-exporter-wb9bf             1/1     Running   0          19m
promethues-prometheus-pushgateway-844488b78d-k72vt    1/1     Running   0          19m
promethues-prometheus-server-d47764bc7-s5zjv          2/2     Running   0          19m

デフォルトだと nodeexporter や pushgateway, alertmanager なども同時にインストールされるようです
nodeexporter は各ノードにインストールされます

NodePort でアクセスできるようにする

公式のヘルプだと port-forward を使ってローカルからアクセスする方法が表示されます
それだといろいろと面倒なので NodePort でアクセスできるようにします

  • helm upgrade promethues prometheus-community/prometheus --set server.service.type=NodePort --set server.service.nodePort=32090
  • kubectl get svc
NAME                                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                            ClusterIP   10.96.0.1        <none>        443/TCP        17d
promethues-kube-state-metrics         ClusterIP   10.97.206.173    <none>        8080/TCP       26m
promethues-prometheus-alertmanager    ClusterIP   10.106.111.197   <none>        80/TCP         26m
promethues-prometheus-node-exporter   ClusterIP   None             <none>        9100/TCP       26m
promethues-prometheus-pushgateway     ClusterIP   10.98.175.145    <none>        9091/TCP       26m
promethues-prometheus-server          NodePort    10.110.171.176   <none>        80:32090/TCP   26m

これで http://node:32090 で Prometheus サーバにアクセスできます

監視先を追加する方法

extraScrapeConfigs という values が用意されているのでこれを使います
scrape_configs を直接変更することもできますがデフォルトの k8s の管理 Pod の監視設定などを上書きしてしまうので、extraScrapeConfigs で追記するようにしましょう

- job_name: site_exporter
  scheme: https
  metrics_path: /metrics
  static_configs:
  - targets:
    - kaka-request-dumper.herokuapp.com
  • helm upgrade promethues prometheus-community/prometheus --set rbac.create=true --set server.service.type=NodePort --set server.service.nodePort=32090 --set-file extraScrapeConfigs=my_values.yml

設定がうまく反映されていないようであれば Pod を再起動しましょう

  • kubectl rollout restart deploy promethues-prometheus-server

おまけ: values の取得

  • helm get values promethues -a > promethues_values.yml

参考サイト

2021年3月10日水曜日

alertmanager で起動する URI を変更する方法

概要

デフォルトだと / で受けますが nginx 配下で別の URI で受けたい場合には Alertmanager 側の URI も変更しましょう

環境

  • Alertmanager 0.21.0

web.external-url を指定する

  • docker run -d -p 9093:9093 --name alertmanager -v $(pwd):/alertmanager prom/alertmanager --config.file=/alertmanager/alertmanager.yml --web.external-url=http://localhost:9093/am

k8s で指定する場合は

deployments あたりで args を使いましょう

...
    spec:
      securityContext:
        fsGroup: 0
      containers:
        - args:
            - --config.file=/home/alertmanager.yml
            - --web.external-url=http://alertmanager:9093/am
          image: prom/alertmanager:v0.21.0
          name: alertmanager
...

2021年2月16日火曜日

Alertmanager で通知を一時的にオフにする方法

概要

メンテナンスなどのときに使えます
Alertmanager の Silence を使います

環境

  • Promethues 2.24.1
  • Alertmanager 0.21.0

Alertmanager の起動

192.168.100.10:9093 で起動します

  • mkdir -p alertmanager/data
  • cd alertmanager
  • vim alertmanager.yml
route:
  receiver: 'containers_notification'
receivers:
- name: 'slack'
  slack_configs:
    - api_url: 'https://hooks.slack.com/services/xxxxxx/xxxxxx/xxxxxxxxx'
      channel: '#general'
      text: "{{ .CommonAnnotations.summary }}"
      send_resolved: true
  • docker run -d -p 9093:9093 --name alertmanager -v $(pwd):/alertmanager prom/alertmanager --config.file=/alertmanager/alertmanager.yml

Promethues の起動

192.168.100.11:9090 で起動します

  • mkdir promethues
  • cd prometheus
  • vim promethues.yml
global:
  scrape_interval:     15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - 192.168.100.10:9093

rule_files:
  - 'alerts.rule'

scrape_configs:
  - job_name: node
    static_configs:
      - targets:
        - 192.168.100.12:9100

192.168.100.12:9100 が監視するノードで node_exporter を起動しておきます

  • vim alerts.rule
groups:
  - name: 'Test monitoring'
    rules:
    - alert: 'cpu idel alert'
      expr: node_cpu_seconds_total{cpu="0", instance="192.168.100.12:9100", job="node", mode="idle"} > 1
      for: 5s
      annotations:
        summary: 'instance: {{ $labels.instance }}, value: {{ $value }}'
  • docker run -d -p 9090:9090 --name promethues -v $(pwd):/prometheus-data prom/prometheus --config.file=/prometheus-data/prometheus.yml

とりあえず通知が来ることを確認する

idel が 1 以上なので必ず通知が来ると思います
slack に通知が来ることを確認しましょう

一旦アラートを解消する

  • vim alerts.rule
groups:
  - name: 'Test monitoring'
    rules:
    - alert: 'cpu idel alert'
      expr: node_cpu_seconds_total{cpu="0", instance="192.168.100.12:9100", job="node", mode="idle"} < 1
      for: 5s
      annotations:
        summary: 'instance: {{ $labels.instance }}, value: {{ $value }}'
  • docker restart promethues

Slack にアラート解除の通知が来ることを確認します

Silences を登録する

UI から登録できます
開始時間から終了時間の間にアラートしないようにできます

http://192.168.100.10:9093/#/silences

右上に Silence を登録できるボタンがあるのでクリックして作成します
デフォルトだと現在時刻から 2 時間が設定されています
Matchers にマッチしたアラートを無視するようになるので無視したいアラートのマッチ情報を記載しましょう
あとは User と Comment を適当に記載すれば OK です

Matchers はアラートに表示される key/value の値を設定します

登録が完了すると以下のようになります

動作確認

Silence 登録後に再度 alerts.rules を変更してアラートを発泡してみます
すると今度は Slack に通知が来ないのが確認できると思います
Alertmanager の Silence の項目を見るとちゃんと無視しているアラートとしても確認できます

ちなみにアラートが解消されていない状態で Silence が Expire になるとアラートが飛んで来るのでちゃんと解消されていることを確認してから Expire にしましょう

おまけ: API で Silence を登録する

curl http://localhost:9093/api/v1/silences -d '{
  "matchers": [
    {
      "name": "alername",
      "value": "cpu idel alert",
      "isRegex": false
    }
  ],
  "startsAt": "2021-02-15T04:00:00.000000000Z",
  "endsAt": "2021-02-15T05:00:00.000000000Z",
  "createdBy": "api",
  "comment": "test silence",
  "status": {
    "state": "active"
  }
}'

参考サイト

2021年2月15日月曜日

Gitlab で外部の Prometheus と連携する方法

概要

Omnibus Gitlab は内部で Prometheus のプロセスを管理しています
今回は Prometheus サーバを構築しその Prometheus サーバと Gitlab を連携する方法を紹介します

環境

  • Ubuntu 18.04
  • Omnibus Install Gitlab-ee 13.8.0
  • Prometheus 2.24.1

Gitlab 側の exporter の設定

まずは gitlab.rb を編集します
Omnibus Install した Gitlab の場合いろいろな場所に exporter が設置されています
それらすべての exporter を外部に設置する Prometheus からアクセスできるようにします
exporter によって設定する項目がかなりことなるので注意が必要です
192.168.100.10 は外部に設置する Prometheus の IP アドレスになります

  • vim /etc/gitlab/gitlab.rb
prometheus['enable'] = false

# for gitlab_workhorse_exporter (9229/metrics)
gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229"

# for gitaly_exporter (9236/metrics)
gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"

# for node_exporter (9100/metrics)
node_exporter['listen_address'] = '0.0.0.0:9100'

# for gitlab_exporter (9168/database, 9168/metrics, 9168/sidekiq)
gitlab_exporter['listen_address'] = '0.0.0.0'
gitlab_exporter['listen_port'] = '9168'

# for redis_exporter (9121/metrics)
# redis_exporter['listen_address'] = '0.0.0.0:9121'

# for postgres_exporter (9187/metrics)
postgres_exporter['listen_address'] = '0.0.0.0:9187'

# for gitlab-sidekiq, gitlab-rails exporter (8082/metrics, 8080/-/metrics)
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.100.10']
gitlab_rails['prometheus_address'] = '192.168.100.10:9090'
puma['listen'] = '0.0.0.0'
puma['port'] = 8080
sidekiq['listen_address'] = '0.0.0.0'

# for nginx exporter (8060/metrics)
nginx['status']['options'] = {
  "server_tokens" => "off",
  "access_log" => "off",
  "allow" => "192.168.100.10",
  "deny" => "all",
}

設定変更したら reconfigure しましょう

  • gitlab-ctl reconfigure

ちなみに今回は redis-server はすでに外部に移行しており外部のサーバに exporter を設置していないためコメントアウトしています
もし外部に移行した他のコンポーネントがありかつそこに exporter が設置してある場合は後述する promethues.yml にそこのエンドポイントを記載しましょう

Prometheus サーバの構築

次に Prometheus サーバを構築します
ポイントは外部に公開した Omnibus Gitlab の exporter にちゃんとアクセスできることです
192.168.100.11 は各種 exporter が起動している Omnibus Gitlab の IP になります
もし redis のようにすでに別のインスタンスに移行しておりそこに exporter がある場合はそのエンドポイントを記載しましょう

  • vim prometheus.yml
global:
  scrape_interval:     15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

rule_files:

scrape_configs:
  - job_name: nginx
    static_configs:
      - targets:
        - 192.168.100.11:8060
  - job_name: postgres
    static_configs:
      - targets:
        - 192.168.100.11:9187
  - job_name: node
    static_configs:
      - targets:
        - 192.168.100.11:9100
  - job_name: gitlab-workhorse
    static_configs:
      - targets:
        - 192.168.100.11:9229
  - job_name: gitlab-rails
    metrics_path: "/-/metrics"
    static_configs:
      - targets:
        - 192.168.100.11:8080
  - job_name: gitlab-sidekiq
    static_configs:
      - targets:
        - 192.168.100.11:8082
  - job_name: gitlab_exporter_database
    metrics_path: "/database"
    static_configs:
      - targets:
        - 192.168.100.11:9168
  - job_name: gitlab_exporter_sidekiq
    metrics_path: "/sidekiq"
    static_configs:
      - targets:
        - 192.168.100.11:9168
  - job_name: gitlab_exporter_metrics
    metrics_path: "/metrics"
    static_configs:
      - targets:
        - 192.168.100.11:9168
  - job_name: gitaly
    static_configs:
      - targets:
        - 192.168.100.11:9236

あとは Prometheus サーバを起動します
今回はコンテナで起動していますがプロセスで起動しても OK です

  • docker run -d -p 9090:9090 -v $(pwd):/prometheus-data prom/prometheus --config.file=/prometheus-data/prometheus.yml

動作確認

Promethues の管理画面にアクセスして Status -> Targets を確認しましょう
すべてのステータスがグリーンになっていれば OK です

Grafana 連携

今回の場合 Promethues は外部に移行しましたが Grafana は相変わらず Omnibus Gitlab と同じ場所にあります
その場合 Grafana は Promethues が同じ場所にあると思って動作し続けるのでうまく動作しません
なので Grafana のデータソースなどを修正する必要があります
なおこの作業は Grafana の admin 権限が必要になるので Omnibus Gitlab の Grafana で admin ログインできるようにしておきましょう (参考)

まずデータソースを新規で作成します
URL には Promethues のエンドポイントを入力しましょう

次に既存のダッシュボードをコピーします
以下では Gitaly のダッシュボードをコピーしています
コピーする理由はデフォルトで用意されている Grafana のダッシュボードは readonly になっているためデータソースなどが変更できないためです
(デフォルトの設定はファイルに記載されているので直接そのファイルを編集してデータソースを変更しても OK かなと思います)

コピーしたダッシュボードのデータソースを変更します

あとはダッシュボード内にあるペインのデータソースも変更します
ダッシュボードのデータソースを変更してもペイン側は自動で書き換わらないので手動でそれぞれのペインのデータソースも変更します

こんな感じでデータが見えるようになれば OK です

BadGateway が出る場合はデータソースが正しく追加されていない可能性があります
Garafana から Promethues のエンドポイントにうまく疎通できているか確認してから再度データソースを追加してみてください

参考サイト

2021年1月27日水曜日

Prometheus の blackbox_exporter を使ってみた

概要

blackbox_exporter はインスタンスの死活監視を行うためのエクスポータです
今回はインストール方法と簡単な使い方について紹介します

環境

  • Ubuntu 18.04
  • docker 20.10.2
  • Prometheus 2.24.1

nginx 起動

動作確認用の nginx を起動します
192.168.100.11 という IP のインスタンスで起動しています

  • sudo systemctl start nginx

blackbox.yml の作成

使用するモジュールやルールを設定します
実際に監視を行うサイトなどの情報は prometheus.yml 側に記載します
今回は Ping チェックとターゲットのサイトから 200 番系のレスポンスが返却されるかのチェックをします
ただこちらにはターゲットのサイトなどは記載しません

  • vim blackbox.yml
modules:
  icmp:
    prober: icmp
    timeout: 5s
  http_2xx:
    prober: http
    timeout: 5s
    http:
      valid_status_codes: []
      method: GET
      preferred_ip_protocol: "ip4"

blackbox_exporter の起動

先程作成した blackbox.yml を使ってコンテナを起動します
blackbox_exporter は 192.168.100.10 で起動しています

  • docker run --rm -d -p 9115:9115 --name blackbox_exporter -vpwd:/config prom/blackbox-exporter:master --config.file=/config/blackbox.yml

prometheus.yml の作成

次に prometheus.yml を定義します
blackbox_exporter の場所と実際に死活監視するターゲットサイトの情報はこちらに記載します

  • vim prometheus.yml
global:
  scrape_interval:     15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'nginx_check'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - http://192.168.100.11 # nginx が起動しているインスタンス
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 192.168.100.10:9115 # blackbox_exporter が起動しているインスタンス

Prometheus の起動

prometheus.yml を使って起動します

  • docker run -d -p 9090:9090 -v $(pwd):/prometheus-data prom/prometheus --config.file=/prometheus-data/prometheus.yml

動作確認

まず blackbox_exporter が起動しているノードにアクセスするとチェック結果が確認できます
今回であれば http://192.168.100.10:9115/ にアクセスすると以下のような結果が確認できます

また Prometheus にアクセスすると probe から始まるメトリックが取得できているのが確認できます

nginx を停止して probe_success の値が 0 になることを確認しましょう

おまけ: Ping チェックをする場合の prometheus.yml

job_name を追加すれば OK です
あとは Prometheus コンテナを再起動しましょう
メトリックは probe_icmp_duration_seconds あたりが追加になっています
probe_success に job="icmp_check" も追加になっているのでそれを見ても OK です

global:
  scrape_interval:     15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'nginx_check'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - http://192.168.100.10
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 192.168.100.10:9115
  - job_name: 'icmp_check'
    metrics_path: /probe
    params:
      module: [icmp]
    static_configs:
      - targets:
        - 192.168.100.11
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 192.168.100.10:9115

最後に

blackbox_exporter を試してみました
ターゲットのサイトは prometheus.yml に書きますが実際にターゲットのサイトにアクセスしているのは blackbox_exporter のはずなのでネットワークのリーチャビリティなどには注意しましょう

参考サイト

2020年10月19日月曜日

Python から Prometheus のメトリックを取得してみる

概要

前回 Ruby から Prometheus のメトリックを取得してみました
今回は Python から取得してみたいと思います

環境

  • macOS 10.15.7
  • Python 3.8.5
    • prometheus-api-client

インストール

  • pipenv install prometheus-api-client

すべてのメトリックのクエリを取得

取得可能なメトリックの一覧を取得してみます
配列でメトリック名が取得できます
このメトリック名と時間を使って特定の期間のメトリックを取得できます

  • vim app.py
from prometheus_api_client import PrometheusConnect

prom = PrometheusConnect(url ="http://192.168.100.10:9090", disable_ssl=True)
print(prom.all_metrics())
  • pipenv run python app.py

特定のメトリック情報を取得する

例えば redis_memory_used_bytes を取得してみます
最新の 10 分間だけ取得する場合には get_metric_range_data を使います
label_config には特定のメトリックを取得ために設定されているキーバリューのラベルを設定します
あとは metric_name にメトリック名を指定すれば OK です

import datetime
from prometheus_api_client import PrometheusConnect

prom = PrometheusConnect(url ="http://192.168.100.10:9090", disable_ssl=True)
label_config = {'instance': 'localhost:9121', 'job': 'redis'}
metric_data = prom.get_metric_range_data(metric_name='redis_memory_used_bytes', label_config=label_config)
print(metric_data)

t = metric_data[0].get('values')[-1][0]
v = metric_data[0].get('values')[-1][1]
print(datetime.datetime.fromtimestamp(t))
print(int(v) / (1000 * 1000))

values という配列にメトリックデータが入っています
-1 で参照しているのは配列の最後に最新のデータが入っているためです
時刻は unix time なので変換し値はバイト単位なのでメガバイトに変換しています

時間を指定して取得する

10 分間ではないレンジを指定したい場合は get_metric_range_data を使います
時間の指定は prometheus_api_client が用意してくれている parse_datetime が使えます
chunk_size は取得できるメトリック数をいくつかのチャンクに分けて取得してくれます
例えば以下のサンプルのように 30 分間のメトリックを取得する際に chunk_size=6mins などにすると 5 分間隔のメトリックデータに分割して取得してくれます

import datetime
from prometheus_api_client import PrometheusConnect
from prometheus_api_client.utils import parse_datetime

prom = PrometheusConnect(url ="http://192.168.100.10:9090", disable_ssl=True)
label_config = {'instance': 'localhost:9121', 'job': 'redis'}
start_time = parse_datetime("30min")
end_time = parse_datetime("now")
chunk_size = datetime.timedelta(minutes=30)

metric_data = prom.get_metric_range_data(
    'redis_memory_used_bytes{instance="localhost:9121",job="redis"}',
    start_time=start_time,
    end_time=end_time,
    chunk_size=chunk_size,
)
print(metric_data)
print(len(metric_data[0].get('values')))

t = metric_data[0].get('values')[-1][0]
v = metric_data[0].get('values')[-1][1]
print(datetime.datetime.fromtimestamp(t))
print(int(v) / (1000 * 1000))

最後に

Python から Prometheus のメトリックを取得してみました
基本は Ruby と同じでメトリック名+ラベル+時間のレンジを指定することでメトリック情報を取得することができます
時間や値の変換方法が言語で異なる他、データ取得のためのヘルパーメソッドが用意されているかいないかが違いかなと思います

参考サイト