LoginSignup
1
0

More than 1 year has passed since last update.

[Prometheus] Postgres Exporter with Docker

Last updated at Posted at 2021-06-08

関連

概要

Prometheusでの、PostgreSQLのメトリクス収集用のPostgres ExporterのDocker環境構築手順。

前提条件

以下の手順でPrometheus環境を構築していることを前提とする。
https://qiita.com/Esfahan/items/0feaedfd771f49ac7ee4

Postgres exporter

こちらを利用する。
https://github.com/prometheus-community/postgres_exporter

環境

  • postgres_exporter v0.9.0
  • PostgreSQL 9.6

監視対象のPostgresの設定

pg_stat_statementsの有効化

以下を参考にpg_stat_statementsを有効化する。
参考:https://qiita.com/Esfahan/items/2f0c5ad85671d435f209

もしpg_stat_statementsを有効化しない場合は、次項の「メトリクス収集用ユーザーの作成」で、CREATE OR REPLACE VIEW postgres_exporter.pg_stat_statementsの箇所を実行せずにskipする。

メトリクス収集用ユーザーの作成

defaultでは like pg_stat_statements や pg_stat_activity はsuperuser以外では参照できない。もしsuperuser以外でメトリクス収集する場合は、以下を実行する。

以下の例ではpostgres_exporterという名前のメトリクス収集用のユーザーを作成する。
パスワードは、ALTER USER postgres_exporter WITH PASSWORD 'password';で設定しているので、パスワード値を適宜変更する。

参考:https://github.com/prometheus-community/postgres_exporter#running-as-non-superuser

-- To use IF statements, hence to be able to check if the user exists before
-- attempting creation, we need to switch to procedural SQL (PL/pgSQL)
-- instead of standard SQL.
-- More: https://www.postgresql.org/docs/9.3/plpgsql-overview.html
-- To preserve compatibility with <9.0, DO blocks are not used; instead,
-- a function is created and dropped.
CREATE OR REPLACE FUNCTION __tmp_create_user() returns void as $$
BEGIN
  IF NOT EXISTS (
          SELECT                       -- SELECT list can stay empty for this
          FROM   pg_catalog.pg_user
          WHERE  usename = 'postgres_exporter') THEN
    CREATE USER postgres_exporter;
  END IF;
END;
$$ language plpgsql;

SELECT __tmp_create_user();
DROP FUNCTION __tmp_create_user();

-- passwordを適宜変更
ALTER USER postgres_exporter WITH PASSWORD 'password';
ALTER USER postgres_exporter SET SEARCH_PATH TO postgres_exporter,pg_catalog;

-- If deploying as non-superuser (for example in AWS RDS), uncomment the GRANT
-- line below and replace <MASTER_USER> with your root user.
-- GRANT postgres_exporter TO <MASTER_USER>;
CREATE SCHEMA IF NOT EXISTS postgres_exporter;
GRANT USAGE ON SCHEMA postgres_exporter TO postgres_exporter;
GRANT CONNECT ON DATABASE postgres TO postgres_exporter;

CREATE OR REPLACE FUNCTION get_pg_stat_activity() RETURNS SETOF pg_stat_activity AS
$$ SELECT * FROM pg_catalog.pg_stat_activity; $$
LANGUAGE sql
VOLATILE
SECURITY DEFINER;

CREATE OR REPLACE VIEW postgres_exporter.pg_stat_activity
AS
  SELECT * from get_pg_stat_activity();

GRANT SELECT ON postgres_exporter.pg_stat_activity TO postgres_exporter;

CREATE OR REPLACE FUNCTION get_pg_stat_replication() RETURNS SETOF pg_stat_replication AS
$$ SELECT * FROM pg_catalog.pg_stat_replication; $$
LANGUAGE sql
VOLATILE
SECURITY DEFINER;

CREATE OR REPLACE VIEW postgres_exporter.pg_stat_replication
AS
  SELECT * FROM get_pg_stat_replication();

GRANT SELECT ON postgres_exporter.pg_stat_replication TO postgres_exporter;

CREATE OR REPLACE FUNCTION get_pg_stat_statements() RETURNS SETOF pg_stat_statements AS
$$ SELECT * FROM public.pg_stat_statements; $$
LANGUAGE sql
VOLATILE
SECURITY DEFINER;

-- pg_stat_statementsを利用しない場合は以降は実行しない
CREATE OR REPLACE VIEW postgres_exporter.pg_stat_statements
AS
  SELECT * FROM get_pg_stat_statements();

GRANT SELECT ON postgres_exporter.pg_stat_statements TO postgres_exporter;

作成されたものなど確認

psql -U postgres_exporter -W -d postgres
postgres=# \l
                                    List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |      Access privileges
-----------+----------+----------+------------+------------+------------------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =Tc/postgres                +
           |          |          |            |            | postgres=CTc/postgres       +
           |          |          |            |            | postgres_exporter=c/postgres
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres                 +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres                 +
           |          |          |            |            | postgres=CTc/postgres
(3 rows)

postgres=# \dn
       List of schemas
       Name        |  Owner
-------------------+----------
 postgres_exporter | postgres
 public            | postgres
(2 rows)

postgres=# \du
                                       List of roles
     Role name     |                         Attributes                         | Member of
-------------------+------------------------------------------------------------+-----------
 postgres          | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 postgres_exporter |                                                            | {}

postgres=> \d
                     List of relations
      Schema       |        Name         | Type |  Owner
-------------------+---------------------+------+----------
 postgres_exporter | pg_stat_activity    | view | postgres
 postgres_exporter | pg_stat_replication | view | postgres
 postgres_exporter | pg_stat_statements  | view | postgres
(3 rows)

Postgres Exporterの環境構築

docker-compose.yaml
version: '3'

services:
  postgres-exporter:
    container_name: postgres-exporter
    image: quay.io/prometheuscommunity/postgres-exporter
    hostname: postgres-exporter
    env_file:
      - .env
    ports:
      - 9187:9187
    networks:
      - sample-network
networks:
    sample-network:
        external: true
.env
DATA_SOURCE_NAME=postgresql://postgres_exporter:password@sample-postgres:5432/postgres?sslmode=disable

DATA_SOURCE_NAMEは、"'などクォーテーションを付けるとpostgres-exporterでパースされなかったので付けないこと。

$ docker-compose up -d --build

Prometheusの設定

こちらの記事で構築したPrometheus環境の設定ファイルを編集する。

監視対象を追加

prometheus.yamlに以下を追記。

prometheus/prometheus.yaml
# 前略
scrape_configs:
+  - job_name: postgres
+    metrics_path: /postgres_exporter/metrics
+    static_configs:
+      - targets:
+        - your-postgres-exporter-hostname:9187
+        labels:
+          env: development

設定を反映

$ sudo docker-compose restart prometheus

ルールを追加

/etc/prometheus/alert.rules
groups:
  - name: sample001
    rules:
      # Postgres用のルールを追記
      - alert: Postgres_down
        # Postgresが起動しているかのPromQL。
        expr: pg_up == 0
        # 5分間応答がなければアラートを飛ばす
        for: 5m
        labels:
          severity: critical
        # エラー文言
        annotations:
          firing_text: "[{{ $labels.env }}] {{ $labels.instance }} PostgreSQL has been down for more than 5 minutes."
          resolved_text: "[{{ $labels.env }}] {{ $labels.instance }} PostgreSQL has recoverd."

UI確認

http://your_prometeus.com:9090/graph
pg_up == 1であればpostgresが正常に起動しているということ。0が異常状態。
Screen Shot 2021-06-13 at 16.04.31.png

その他

Error: function pg_current_wal_lsn() does not exist

pg_current_wal_lsn() はpostgres 10以降に実装された関数なので、9系ではエラーが出る。

$ docker logs -f postgres-exporter
time="2021-06-07T17:51:16Z" level=info msg="Error running query on database \"sample-postgres:5432\": pg_replication_slots pq: function pg_current_wal_lsn() does not exist" source="postgres_exporter.go:1503"

2021/03/04にIssueが上がっており、対応してくれそうなので待ち。
https://github.com/prometheus-community/postgres_exporter/issues/495

DockerのexporterからホストOSのpostgresにアクセスする場合

ホストOSのpostgresがpg_hba.confでアクセス制限を厳密にやっている時の対策方法。

docker-compose.yaml

以下の様にnetworksの設定でコンテナのIPアドレスを固定する。

docker-compose.yaml
version: '3'

services:
  postgres-exporter:
    container_name: postgres-exporter
    image: quay.io/prometheuscommunity/postgres-exporter
    hostname: postgres-exporter
    extra_hosts:
      # コンテナ内からホストOSのlocalhostへアクセスするための設定
      # ホストOSのdocker0のIPアドレスが渡される
      - "host.docker.internal:host-gateway"
    env_file:
      - ./postgres-exporter/.env
    ports:
      - 127.0.0.1:9187:9187
    restart: always
    networks:
      exporter-network:
        # このコンテナのIPアドレスを以下に固定
        ipv4_address: 192.168.200.1

networks:
  exporter-network:
    ipam:
      driver: default
      config:
        # 16個確保
        - subnet: 192.168.200.0/28

pg_hba.conf

pg_hba.confで、先程固定したexporterのコンテナIPアドレスからの接続許可設定をする。

host dbname postgres_exporter 192.168.200.1/32 md5

postgresql.conf

postgresql.confのlistenを書き換える

-listen_addresses = '127.0.0.1'
+listen_addresses = '*'

接続確認

exporterからではなくホストOS上からコマンドで接続確認する方法。これで接続確認できれば、おそらくDockerコンテナからも接続できる。

docker0のIPアドレスを確認

以下のコマンドでdocker0のIPアドレスを確認。
ここでは、192.168.249.1だったとする

$ /sbin/ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.249.1  netmask 255.255.255.0  broadcast 192.168.249.255

psqlで確認

docker0のIPアドレスをホストに指定して接続。

$ psql dbname -p 5432 -U postgres_exporter -h 192.168.249.1 -W

関連記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0