PatroniRESTAPI

Patroniには、リーダーレース中にPatroni自分自身が使用する豊富なRESTAPIがあります。、そしてもちろんモニタリングにも使用できます。以下に、PatroniRESTAPIエンドポイントのリストを示します。

ヘルスチェックエンドポイント

すべてのヘルスチェック GET リクエストについて、Patroniは、ノードのステータスとHTTPステータスコードを含むJSONドキュメントを返します。JSONドキュメントが必要ない、または必要ない場合は、 GET の代わりに HEAD または OPTIONS メソッドの使用を検討してください。

  • PatroniRESTAPIへの次の要求は、Patroniノードがリーダーロックでプライマリとして実行されている場合にのみ、HTTPステータスコード 200 を返します。

    • GET /

    • GET /primary

    • GET /read-write

  • GET /standby-leader :Patroniノードが GET /standby-leader リーダーとして実行されている場合にのみ、HTTPステータスコード GET /standby-leader を返します。

  • GET /leader :Patroniノードがリーダーロックを持っている場合、HTTPステータスコード GET /leader を返します。以前の2つのエンドポイントとの主な違いは、PostgreSQLが primary または standby_leader として実行されているかどうかを考慮しないことです。

  • GET /replica :レプリカヘルスチェックエンドポイント。Patroniノードの状態が running 、ロールが replica 、 noloadbalance タグが設定されていない場合にのみ、HTTPステータスコード GET /replica を返します。

  • GET /replica?lag=<max-lag> :レプリカチェックエンドポイント。 replica からのチェックに加えて、レプリケーションレイテンシーもチェックし、指定された値を下回る場合にのみステータスコード GET /replica?lag=<max-lag> を返します。DCSのキーcluster.last_leader_operationは、パフォーマンス上の理由から、リーダーウォールの位置とレプリカでのレイテンシーの計算に使用されます。max-lagは、バイト(整数)または人間が読める値で指定できます。例16kB、64MB、1GB。

    • GET /replica?lag=1048576

    • GET /replica?lag=1024kB

    • GET /replica?lag=10MB

    • GET /replica?lag=1GB

  • GET /replica?tag_key1=value1&tag_key2=value2 :レプリカチェックエンドポイント。さらに、ユーザー定義タグ key1 および key2 、およびyaml構成管理の GET /replica?tag_key1=value1&tag_key2=value2 セクション内のそれぞれの値もチェックします。インスタンスに対してタグが定義されていない場合、またはyaml構成の値がクエリ値と一致しない場合、HTTPステータスコード503が返されます。

    以下のリクエストでは、リーダーまたはスタンバイリーダーのステータスを確認しているため、Patroniはユーザ定義のタグを適用せず、無視されます。

    • GET /?tag_key1=value1&tag_key2=value2

    • GET /leader?tag_key1=value1&tag_key2=value2

    • GET /primary?tag_key1=value1&tag_key2=value2

    • GET /read-write?tag_key1=value1&tag_key2=value2

    • GET /standby_leader?tag_key1=value1&tag_key2=value2

    • GET /standby-leader?tag_key1=value1&tag_key2=value2

  • GET /read-only :上記のエンドポイントに似ていますが、プライマリも含まれます。

  • GET /synchronous または GET /sync :Patroniノードが同期スタンバイとして実行されている場合にのみ、HTTPステータスコード GET /synchronous を返します。

  • GET /read-only-sync :上記のエンドポイントに似ていますが、プライマリも含まれます。

  • GET /asynchronous または GET /async :Patroniノードが非同期スタンバイとして実行されている場合にのみ、HTTPステータスコード GET /asynchronous を返します。

  • GET /asynchronous?lag=<max-lag> または GET /async?lag=<max-lag> :非同期スタンバイチェックエンドポイント。 asynchronous または async からのチェックに加えて、レプリケーションレイテンシーもチェックし、指定された値を下回る場合にのみステータスコード GET /asynchronous?lag=<max-lag> を返します。DCSのキーcluster.last_leader_operationは、パフォーマンス上の理由から、リーダーウォールの位置とレプリカでのレイテンシーの計算に使用されます。max-lagは、バイト(整数)または人間が読める値で指定できます。例16kB、64MB、1GB。

    • GET /async?lag=1048576

    • GET /async?lag=1024kB

    • GET /async?lag=10MB

    • GET /async?lag=1GB

  • GET /health :PostgreSQLが稼働している場合にのみHTTPステータスコード GET /health を返します。

  • GET /liveness :Patroniハートビートループが適切に実行されている場合はHTTPステータスコード GET /liveness を返し、最後の実行がプライマリで ttl 秒以上前であった場合は GET /liveness 、レプリカで 2*ttl を返します。 livenessProbe に使用できます。

  • GET /readiness :Patroniノードがリーダーとして実行されている場合、またはPostgreSQLが起動して実行されている場合、HTTPステータスコード GET /readiness を返します。リーダー選挙(OpenShift)にKubernetesエンドポイントを使用できない場合、エンドポイントを readinessProbe に使用できます。

readiness および liveness エンドポイントは両方とも非常に軽量で、SQLを実行しません。リーダーキーの有効期限が切れる頃に失敗し始めるように、プローブを構成する必要があります。 30s の例である ttl のデフォルト値を使用すると、プローブは次のようになります。

readinessProbe:
  httpGet:
    scheme: HTTP
    path: /readiness
    port: 8008
  initialDelaySeconds: 3
  periodSeconds: 10
  timeoutSeconds: 5
  successThreshold: 1
  failureThreshold: 3
livenessProbe:
  httpGet:
    scheme: HTTP
    path: /liveness
    port: 8008
  initialDelaySeconds: 3
  periodSeconds: 10
  timeoutSeconds: 5
  successThreshold: 1
  failureThreshold: 3

モニタリングエンドポイント

GET /patroni は、リーダーレース中にパトローニが使用します。また、監視システムで使用することもできます。このエンドポイントによって生成されるJSONドキュメントは、ヘルスチェックエンドポイントによって生成されるJSONと同じ構造を持っています。

Example: 健全なクラスター

$ curl -s http://localhost:8008/patroni | jq .
{
  "state": "running",
  "postmaster_start_time": "2023-08-18 11:03:37.966359+00:00",
  "role": "master",
  "server_version": 150004,
  "xlog": {
    "location": 67395656
  },
  "timeline": 1,
  "replication": [
    {
      "usename": "replicator",
      "application_name": "patroni2",
      "client_addr": "10.89.0.6",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    },
    {
      "usename": "replicator",
      "application_name": "patroni3",
      "client_addr": "10.89.0.2",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    }
  ],
  "dcs_last_seen": 1692356718,
  "tags": {
    "clonefrom": true
  },
  "database_system_identifier": "7268616322854375442",
  "patroni": {
    "version": "3.1.0",
    "scope": "demo"
  }
}

Example: ロック解除されたクラスター

$ curl -s http://localhost:8008/patroni  | jq .
{
  "state": "running",
  "postmaster_start_time": "2023-08-18 11:09:08.615242+00:00",
  "role": "replica",
  "server_version": 150004,
  "xlog": {
    "received_location": 67419744,
    "replayed_location": 67419744,
    "replayed_timestamp": null,
    "paused": false
  },
  "timeline": 1,
  "replication": [
    {
      "usename": "replicator",
      "application_name": "patroni2",
      "client_addr": "10.89.0.6",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    },
    {
      "usename": "replicator",
      "application_name": "patroni3",
      "client_addr": "10.89.0.2",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    }
  ],
  "cluster_unlocked": true,
  "dcs_last_seen": 1692356928,
  "tags": {
    "clonefrom": true
  },
  "database_system_identifier": "7268616322854375442",
  "patroni": {
    "version": "3.1.0",
    "scope": "demo"
  }
}

Example: Example: が有効になっているロック解除されたクラスター

$ curl -s http://localhost:8008/patroni  | jq .
{
  "state": "running",
  "postmaster_start_time": "2023-08-18 11:09:08.615242+00:00",
  "role": "replica",
  "server_version": 150004,
  "xlog": {
    "location": 67420024
  },
  "timeline": 1,
  "replication": [
    {
      "usename": "replicator",
      "application_name": "patroni2",
      "client_addr": "10.89.0.6",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    },
    {
      "usename": "replicator",
      "application_name": "patroni3",
      "client_addr": "10.89.0.2",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    }
  ],
  "cluster_unlocked": true,
  "failsafe_mode_is_active": true,
  "dcs_last_seen": 1692356928,
  "tags": {
    "clonefrom": true
  },
  "database_system_identifier": "7268616322854375442",
  "patroni": {
    "version": "3.1.0",
    "scope": "demo"
  }
}

Example: Example: が有効になっているクラスター

$ curl -s http://localhost:8008/patroni  | jq .
{
  "state": "running",
  "postmaster_start_time": "2023-08-18 11:09:08.615242+00:00",
  "role": "replica",
  "server_version": 150004,
  "xlog": {
    "location": 67420024
  },
  "timeline": 1,
  "replication": [
    {
      "usename": "replicator",
      "application_name": "patroni2",
      "client_addr": "10.89.0.6",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    },
    {
      "usename": "replicator",
      "application_name": "patroni3",
      "client_addr": "10.89.0.2",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    }
  ],
  "pause": true,
  "dcs_last_seen": 1692356928,
  "tags": {
    "clonefrom": true
  },
  "database_system_identifier": "7268616322854375442",
  "patroni": {
    "version": "3.1.0",
    "scope": "demo"
  }
}

GET /metrics エンドポイントを介して、Prometheus形式でPatroniメトリックを取得します。

$ curl http://localhost:8008/metrics

# HELP patroni_version Patroni semver without periods. \
# TYPE patroni_version gauge
patroni_version{scope="batman"} 020103
# HELP patroni_postgres_running Value is 1 if Postgres is running, 0 otherwise.
# TYPE patroni_postgres_running gauge
patroni_postgres_running{scope="batman"} 1
# HELP patroni_postmaster_start_time Epoch seconds since Postgres started.
# TYPE patroni_postmaster_start_time gauge
patroni_postmaster_start_time{scope="batman"} 1657656955.179243
# HELP patroni_master Value is 1 if this node is the leader, 0 otherwise.
# TYPE patroni_master gauge
patroni_master{scope="batman"} 1
# HELP patroni_primary Value is 1 if this node is the leader, 0 otherwise.
# TYPE patroni_primary gauge
patroni_primary{scope="batman"} 1
# HELP patroni_xlog_location Current location of the Postgres transaction log, 0 if this node is not the leader.
# TYPE patroni_xlog_location counter
patroni_xlog_location{scope="batman"} 22320573386952
# HELP patroni_standby_leader Value is 1 if this node is the standby_leader, 0 otherwise.
# TYPE patroni_standby_leader gauge
patroni_standby_leader{scope="batman"} 0
# HELP patroni_replica Value is 1 if this node is a replica, 0 otherwise.
# TYPE patroni_replica gauge
patroni_replica{scope="batman"} 0
# HELP patroni_sync_standby Value is 1 if this node is a sync standby replica, 0 otherwise.
# TYPE patroni_sync_standby gauge
patroni_sync_standby{scope="batman"} 0
# HELP patroni_xlog_received_location Current location of the received Postgres transaction log, 0 if this node is not a replica.
# TYPE patroni_xlog_received_location counter
patroni_xlog_received_location{scope="batman"} 0
# HELP patroni_xlog_replayed_location Current location of the replayed Postgres transaction log, 0 if this node is not a replica.
# TYPE patroni_xlog_replayed_location counter
patroni_xlog_replayed_location{scope="batman"} 0
# HELP patroni_xlog_replayed_timestamp Current timestamp of the replayed Postgres transaction log, 0 if null.
# TYPE patroni_xlog_replayed_timestamp gauge
patroni_xlog_replayed_timestamp{scope="batman"} 0
# HELP patroni_xlog_paused Value is 1 if the Postgres xlog is paused, 0 otherwise.
# TYPE patroni_xlog_paused gauge
patroni_xlog_paused{scope="batman"} 0
# HELP patroni_postgres_streaming Value is 1 if Postgres is streaming, 0 otherwise.
# TYPE patroni_postgres_streaming gauge
patroni_postgres_streaming{scope="batman"} 1
# HELP patroni_postgres_in_archive_recovery Value is 1 if Postgres is replicating from archive, 0 otherwise.
# TYPE patroni_postgres_in_archive_recovery gauge
patroni_postgres_in_archive_recovery{scope="batman"} 0
# HELP patroni_postgres_server_version Version of Postgres (if running), 0 otherwise.
# TYPE patroni_postgres_server_version gauge
patroni_postgres_server_version {scope="batman"} 140004
# HELP patroni_cluster_unlocked Value is 1 if the cluster is unlocked, 0 if locked.
# TYPE patroni_cluster_unlocked gauge
patroni_cluster_unlocked{scope="batman"} 0
# HELP patroni_postgres_timeline Postgres timeline of this node (if running), 0 otherwise.
# TYPE patroni_postgres_timeline counter
patroni_failsafe_mode_is_active{scope="batman"} 0
# HELP patroni_postgres_timeline Postgres timeline of this node (if running), 0 otherwise.
# TYPE patroni_postgres_timeline counter
patroni_postgres_timeline{scope="batman"} 24
# HELP patroni_dcs_last_seen Epoch timestamp when DCS was last contacted successfully by Patroni.
# TYPE patroni_dcs_last_seen gauge
patroni_dcs_last_seen{scope="batman"} 1677658321
# HELP patroni_pending_restart Value is 1 if the node needs a restart, 0 otherwise.
# TYPE patroni_pending_restart gauge
patroni_pending_restart{scope="batman"} 1
# HELP patroni_is_paused Value is 1 if auto failover is disabled, 0 otherwise.
# TYPE patroni_is_paused gauge
patroni_is_paused{scope="batman"} 1

クラスターステータスエンドポイント

  • GET /cluster エンドポイントは、現在のクラスターのトポロジと状態を説明するJSONドキュメントを生成します。

$ curl -s http://localhost:8008/cluster | jq .
{
  "members": [
    {
      "name": "patroni1",
      "role": "leader",
      "state": "running",
      "api_url": "http://10.89.0.4:8008/patroni",
      "host": "10.89.0.4",
      "port": 5432,
      "timeline": 5,
      "tags": {
        "clonefrom": true
      }
    },
    {
      "name": "patroni2",
      "role": "replica",
      "state": "streaming",
      "api_url": "http://10.89.0.6:8008/patroni",
      "host": "10.89.0.6",
      "port": 5433,
      "timeline": 5,
      "tags": {
        "clonefrom": true
      },
      "lag": 0
    }
  ],
  "scheduled_switchover": {
    "at": "2023-09-24T10:36:00+02:00",
    "from": "patroni1",
    "to": "patroni3"
  }
}
  • GET /history エンドポイントは、クラスターのスイッチオーバー/フェイルオーバーの履歴に関するビューを提供します。形式は、 pg_wal ディレクトリ内の履歴ファイルの内容と非常によく似ています。唯一の違いは、新しいタイムラインが作成された日時を示すタイムスタンプフィールドです。

$ curl -s http://localhost:8008/history | jq .
[
  [
    1,
    25623960,
    "no recovery target specified",
    "2019-09-23T16:57:57+02:00"
  ],
  [
    2,
    25624344,
    "no recovery target specified",
    "2019-09-24T09:22:33+02:00"
  ],
  [
    3,
    25624752,
    "no recovery target specified",
    "2019-09-24T09:26:15+02:00"
  ],
  [
    4,
    50331856,
    "no recovery target specified",
    "2019-09-24T09:35:52+02:00"
  ]
]

構成エンドポイント

GET /config :動的構成の現在のバージョンを取得します。

$ curl -s http://localhost:8008/config | jq .
{
  "ttl": 30,
  "loop_wait": 10,
  "retry_timeout": 10,
  "maximum_lag_on_failover": 1048576,
  "postgresql": {
    "use_slots": true,
    "use_pg_rewind": true,
    "parameters": {
      "hot_standby": "on",
      "wal_level": "hot_standby",
      "max_wal_senders": 5,
      "max_replication_slots": 5,
      "max_connections": "100"
    }
  }
}

PATCH /config :既存の構成を変更します。

$ curl -s -XPATCH -d \
        '{"loop_wait":5,"ttl":20,"postgresql":{"parameters":{"max_connections":"101"}}}' \
        http://localhost:8008/config | jq .
{
  "ttl": 20,
  "loop_wait": 5,
  "maximum_lag_on_failover": 1048576,
  "retry_timeout": 10,
  "postgresql": {
    "use_slots": true,
    "use_pg_rewind": true,
    "parameters": {
      "hot_standby": "on",
      "wal_level": "hot_standby",
      "max_wal_senders": 5,
      "max_replication_slots": 5,
      "max_connections": "101"
    }
  }
}

上記のRESTAPI呼び出しは、既存の構成にパッチを適用し、新しい構成を返します。

ノードがこの構成を処理したことを確認しましょう。まず、5秒ごとにログ行の印刷を開始する必要があります(loop_wait=5)。/"max_connections/"の変更には再起動が必要なため、/"pending_restart/"フラグを公開する必要があります。

$ curl -s http://localhost:8008/patroni | jq .
{
  "pending_restart": true,
  "database_system_identifier": "6287881213849985952",
  "postmaster_start_time": "2016-06-13 13:13:05.211 CEST",
  "xlog": {
    "location": 2197818976
  },
  "patroni": {
    "scope": "batman",
    "version": "1.0"
  },
  "state": "running",
  "role": "master",
  "server_version": 90503
}

パラメータの削除:

いくつかの設定を削除(リセット)したい場合は、 null パッチを当てるだけです:

$ curl -s -XPATCH -d \
        '{"postgresql":{"parameters":{"max_connections":null}}}' \
        http://localhost:8008/config | jq .
{
  "ttl": 20,
  "loop_wait": 5,
  "retry_timeout": 10,
  "maximum_lag_on_failover": 1048576,
  "postgresql": {
    "use_slots": true,
    "use_pg_rewind": true,
    "parameters": {
      "hot_standby": "on",
      "unix_socket_directories": ".",
      "wal_level": "hot_standby",
      "max_wal_senders": 5,
      "max_replication_slots": 5
    }
  }
}

上記の呼び出しは、動的構成から postgresql.parameters.max_connections を削除します。

PUT /config :既存の動的構成の完全な書き換えを無条件に実行することもできます。

$ curl -s -XPUT -d \
        '{"maximum_lag_on_failover":1048576,"retry_timeout":10,"postgresql":{"use_slots":true,"use_pg_rewind":true,"parameters":{"hot_standby":"on","wal_level":"hot_standby","unix_socket_directories":".","max_wal_senders":5}},"loop_wait":3,"ttl":20}' \
        http://localhost:8008/config | jq .
{
  "ttl": 20,
  "maximum_lag_on_failover": 1048576,
  "retry_timeout": 10,
  "postgresql": {
    "use_slots": true,
    "parameters": {
      "hot_standby": "on",
      "unix_socket_directories": ".",
      "wal_level": "hot_standby",
      "max_wal_senders": 5
    },
    "use_pg_rewind": true
  },
  "loop_wait": 3
}

スイッチオーバーとフェイルオーバーのエンドポイント

POST /switchover または POST /failover 。これらのエンドポイントは互いに非常に似ています。ただし、いくつかの小さな違いがあります。

  1. フェールオーバーエンドポイントを使用すると、正常なノードがない場合に手動フェールオーバーを実行できますが、同時にスイッチオーバーをスケジュールすることはできません。

  2. スイッチオーバーエンドポイントは反対です。クラスターが正常な場合(リーダーがあります)にのみ機能し、特定の時刻にスイッチオーバーをスケジュールできます。

POST リクエストのJSON本体では、特定の時刻にスイッチオーバーをスケジュールする場合は、少なくとも leader または candidate フィールド、およびオプションで scheduled_at フィールドを指定する必要があります。

例:特定のノードへのフェイルオーバーを実行します。

$ curl -s http://localhost:8009/failover -XPOST -d '{"candidate":"postgresql1"}'
Successfully failed over to "postgresql1"

例:特定の時刻にリーダーからクラスター内の他の正常なレプリカへのスイッチオーバーをスケジュールします。

$ curl -s http://localhost:8008/switchover -XPOST -d \
        '{"leader":"postgresql0","scheduled_at":"2019-09-24T12:00+00"}'
Switchover scheduled

状況に応じて、リクエストは異なるHTTPステータスコードとボディで終了する場合があります。スイッチオーバーまたはフェイルオーバーが正常に完了すると、ステータスコード 200 が返されます。スイッチオーバーが正常にスケジュールされた場合、PatroniはHTTPステータスコード 200 を返します。何かがうまくいかなかった場合、エラーステータスコード( 200 、 200 または 200 のいずれか)が応答本文にいくつかの詳細とともに返されます。詳細については、 patroni/api.py:do_POST_failover() メソッドのソースコードを確認してください。

  • DELETE /switchover :スケジュールされたスイッチオーバーを削除します

POST /switchover および POST failover エンドポイントは、それぞれ patronictl switchover および patronictl failover によって使用されます。 DELETE /switchover は patronictl flush <cluster-name> switchover によって使用されます。

エンドポイントをリスタート

  • POST /restart : POST /restart 呼び出しを実行することにより、特定のノードでPostgresを再起動できます。 POST リクエストのJSON本文では、オプションでいくつかのリスタート条件を指定できます。

    • restart_pending :ブール値、 true に設定されている場合Patroniは、PostgreSQL構成のいくつかの変更を適用するために、再起動が保留中の場合にのみPostgreSQLを再起動します。

    • role :ノードの現在のロールがPOST要求からのロールと一致する場合にのみ再起動を実行します。

    • postgres_version :postgresの現在のバージョンがPOSTリクエストで指定されたものよりも小さい場合にのみ再起動を実行します。

    • timeout :PostgreSQLが接続の受け入れを開始するまでに待機する時間。 primary_start_timeout をオーバーライドします。

    • schedule :タイムゾーン付きのタイムスタンプ、将来のどこかで再起動をスケジュールします。

  • DELETE /restart :スケジュールされた再起動を削除します

POST /restart および DELETE /restart エンドポイントは、それぞれ patronictl restart および patronictl flush <cluster-name> restart によって使用されます。

エンドポイントをリロード

POST /reload 呼び出しは、Patroniに構成ファイルを再読み取りして適用するように指示します。これは、 SIGHUP シグナルをPatroniプロセスに送信することと同じです。再起動が必要なPostgresパラメーターの一部( POST /reload など)を変更した場合、 POST /restart エンドポイントを呼び出すか、 patronictl restart の助けを借りて、Postgresの再起動を明示的に行う必要があります。

リロードエンドポイントは patronictl reload によって使用されます。

エンドポイントを再初期化する

POST /reinitialize :指定されたノードのPostgreSQLデータディレクトリを再初期化します。レプリカでのみ実行が許可されます。呼び出されると、データディレクトリを削除し、 pg_basebackup または代替の POST /reinitialize を起動します。

Patroniがループ内にあり、障害が発生したPostgresを回復(再起動)しようとしている場合、呼び出しは失敗する可能性があります。この問題を克服するために、リクエストボディで {/"force/":true} を指定できます。

再初期化エンドポイントは、 patronictl reinit によって使用されます。