👻

PostgresqlのMultiple Primariesを検知してアラートする

2022/09/20に公開

はじめに

PostgresqlをKubernetesにデプロイして利用しているのですが、一つやっかいな問題があります。それは、複数レプリカ存在するPostgresqlにおいて、通常ではPostgresqlが何らかの不具合でKubernetesのヘルスチェックに失敗したときに、Primaryのノードの場合はクラスターから切り離され、スタンバイのノードがプライマリーに昇格します。このフェイルオーバーが正しく動かず、複数のPrimaryがクラスター内に存在し、データの整合性が取れなかったりする原因になります。
これは、使用しているPostgresqlのHelmチャートのレポジトリでも複数回問題が報告されていますが、現在でも修正されてはいません。
https://github.com/bitnami/charts/issues/2610
https://github.com/bitnami/charts/issues/5589
https://github.com/bitnami/charts/issues/12263

上記問題の対処法としては、本来スタンバイであるはずがPrimaryとして動作しているPodを削除する。というのが挙げられます。が、しかしこの現象がいつ起こるのかは不明のため、Prometheusのメトリクスなどを利用して発生した段階でわかるようなアラートが必要になってきます。今回そのダッシュボードとアラートを作成したので、紹介しようと思います。
全体のソースコードは以下レポジトリに格納しています。
https://github.com/shohta-tera/postgres-with-dashboard

環境

  • WSL2: Ubuntu 20.04
  • Docker: 4.10.1
  • kind: kind v0.11.1 go1.16.4 linux/amd64

Postgresqlのインストール

PostgresqlのインストールにはHelmチャートを利用します。
https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha

ローカルのKindにインストールするために必要な設定をvalues.yamlとして保存します。

---
global:
  storageClass: 'local-path'
  postgresql:
    postgresqlPassword: postgres
postgresql:
  priorityClassName: ''
  username: test
  password: test
  repmgrUsername: repmgr
  repmgrPassword: repmgr!
  repmgrDatabase: repmgr

pgpool:
  adminUsername: admin
  adminPassword: admin
  configuration: |
    failover_on_backend_error = 'on'
    failover_command = '/opt/bitnami/pgpool/etc/failover.sh %d %P %H %R'
volumePermissions:
  enabled: true

metrics:
  enabled: true
  customMetrics:
  pg_replication:
    master: true
    query: |
      SELECT
      CASE
      WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() THEN 0
      ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())::INTEGER
      END
      AS lag,
      CASE WHEN pg_is_in_recovery() THEN 1 ELSE 0 END as is_replica;
    metrics:
    - lag:
        usage: "GAUGE"
    - is_replica:
        usage: "GAUGE"

persistance:
  enabled: true
  size: 100Mi

その次に実際に、Postgresqlをインストールしていきます。

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update bitnami
kubectl create namespace database
helm upgrade postgres bitnami/postgresql-ha \
  --install \
  --namespace database \
  --values=./values.yaml

カスタムメトリクスの作成

values.yamlに以下の項目を記載することでpostgres-exporterにはない独自メトリクスを追加することができます。

metrics:
  customMetrics:
    pg_replication:
      master: true
      query: |
        SELECT
        CASE
        WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() THEN 0
        ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())::INTEGER
        END
        AS lag,
        CASE WHEN pg_is_in_recovery() THEN 1 ELSE 0 END as is_replica;
      metrics:
        - lag:
          usage: "GAUGE"
        - is_replica:
          usage: "GAUGE"

作成されたメトリクス名としては、pg_replication_is_replicaにて検索することが可能です。

Grafanaのダッシュボードを作成する

今回使用するpostgres-exporterには、複数GrafanaのダッシュボードがGrafanaのサイトに登録されているので、基本的なメトリクスについてはそれを使うことにします。ただ、今回追加したカスタムメトリクスについてはダッシュボードが提供されているわけではないので、Grafanaで作成していきます。
https://github.com/prometheus-community/postgres_exporter

Multiple Primariesを検知してアラートを出すダッシュボードを作成する

pg_replication_is_replicaで検索すると、各PodごとのReplicaのステータスが確認できます。

この情報をもとに、ダッシュボードを作っていきます。といっても、複雑なことは特にせず、値が0(Primary)のメトリクスの数を数えるだけです。

保存した後に、アラートを作成していきます。こちらもシンプルで、ダッシュボードで表示している値が5分以上連続して2以上の時に通知するものを作成します。

最後に

PrometheusのメトリクスとGrafanaのダッシュボードを使うことで、当初の問題であったPostgresqlの複数のPrimaryを検知し、アラート通知することができました。本来であれば、自動的に検知して修復まで出来れば運用の負荷としては減るのでそこまで作れればよかったのですが、現状だと通知までの実装になっています。PostgresqlのOperatorを導入できれば、そこまで実現できそうな気がするので、次回はそちらに挑戦してみようと思います。
https://github.com/CrunchyData/postgres-operator
https://github.com/zalando/postgres-operator

認識違いや不正確な点などあれば、コメント等で指摘してもらえると非常に助かります。
それでは、今回はここまで。

GitHubで編集を提案

Discussion