このページでは、論理フェイルオーバー スロットを使用して Cloud SQL for PostgreSQL の 論理レプリケーションを構成し、 高度な障害復旧(DR) オペレーション( Cloud SQL Enterprise Plus エディションのインスタンスでのスイッチオーバーとレプリカ フェイルオーバー)とシームレスに連携させる方法について説明します。
Cloud SQL の高度な障害復旧(DR)機能により、堅牢な障害復旧機能が実現します。PostgreSQL の論理レプリケーションと組み合わせる場合は、スイッチオーバーまたはレプリカ フェイルオーバーの後もレプリケーション ストリームが途切れないようにすることが重要です。
PostgreSQL の論理レプリケーションで高度な障害復旧(DR)を使用すると、論理サブスクライバーでデータ損失が発生せず、障害復旧イベント後に新しいプライマリ インスタンスに自動的に再接続できるため、ビジネス継続性を確保できます。
この機能は、次の構成の Cloud SQL インスタンスで使用できます。
- PostgreSQL バージョン 17 以降
- Cloud SQL Enterprise Plus エディション
プライベート サービス アクセス
論理サブスクライバーの自動再接続を有効にするには、プライベート サービス アクセス ドメイン名サービス(DNS)書き込みエンドポイントを使用することをおすすめします。
始める前に
-
バージョン 502.0.0 以降を使用する必要があります。Google Cloud SDK のバージョンを確認するには、
gcloud --versionを実行します。Google Cloud SDK を更新するには、gcloud components updateを実行します。 プロジェクトを作成するか、既存のプロジェクトを選択します。 Cloud de Confiance by S3NS
必要な Identity and Access Management(IAM)のロールと権限を付与します。
プロジェクトを作成するには: プロジェクト作成者(
roles/resourcemanager.projectCreator)Cloud SQL インスタンスを作成して管理するには: Cloud SQL 管理者 (
roles/cloudsql.admin)Compute Engine VM を作成して管理するには: Compute インスタンス管理者(v1)(
roles/compute.instanceAdmin.v1)と Compute 閲覧者(roles/compute.networkViewer)VPC ネットワークを作成するには: ネットワーク管理者(
roles/compute.networkAdmin)
詳細については、 ロールと権限をご覧ください。
IAM ロールと権限を付与する方法については、 プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。
論理レプリケーションで高度な障害復旧(DR)を設定する
PostgreSQL の論理レプリケーションで高度な障害復旧(DR)を設定する手順は、次のとおりです。
- 環境変数と踏み台 VM を設定します。
- プライマリ インスタンスを作成して設定します。
- DR レプリカを作成して指定します。
- 論理サブスクライバー インスタンスを作成して設定します。
- 論理レプリケーション サブスクリプションを作成します。
- スイッチオーバーまたはレプリカ フェイルオーバーを実行します。
- レプリケーションを検証します。
- 新しいレプリカで孤立したレプリケーション スロットをクリーンアップします。
- 省略可: スイッチバックを実行します。
環境変数と踏み台 VM を設定する
次の環境変数を設定します。
# Project export PROJECT="PROJECT_ID" # Instance names export PRIMARY_INSTANCE_NAME="PRIMARY_INSTANCE" export DR_REPLICA_NAME="DR_REPLICA" export SUBSCRIBER_INSTANCE_NAME="SUBSCRIBER_INSTANCE" export BASTION_VM_NAME="BASTION_VM" # Regions and zones export PRIMARY_REGION="PRIMARY_REGION" export REPLICA_REGION="REPLICA_REGION" export SUBSCRIBER_REGION="SUBSCRIBER_REGION" export VM_ZONE="VM_ZONE" # Network export NETWORK_NAME="NETWORK" # Credentials export POSTGRES_PASSWORD="PASSWORD" # Set gcloud project gcloud config set project PROJECT_ID次のように置き換えます。
- PROJECT_ID: 実際のプロジェクトの ID。
- PRIMARY_INSTANCE: プライマリ Cloud SQL インスタンスの名前。
- DR_REPLICA: レプリカの名前。
- SUBSCRIBER_INSTANCE: サブスクライバー インスタンスの名前。
- BASTION_VM: 踏み台 VM の名前。
- PRIMARY_REGION: プライマリ インスタンスが配置されているリージョン。
- REPLICA_REGION: レプリカが配置されているリージョン。レプリカは、プライマリ インスタンスとは異なるリージョンに配置する必要があります。
- SUBSCRIBER_REGION: サブスクライバーが配置されているリージョン。
- VM_ZONE: 踏み台 VM が配置されているゾーン。
- NETWORK: VPC ネットワークの名前。
- PASSWORD:
postgresユーザーのパスワード。
Compute Engine 踏み台 VM を作成します。
Cloud SQL インスタンスはプライベート IP を使用します。そのため、VPC ネットワークに Compute Engine 踏み台インスタンス VM を作成します。
gcloud compute instances create $BASTION_VM_NAME \ --zone=$VM_ZONE \ --machine-type=e2-small \ --network=projects/$PROJECT_ID/global/networks/$NETWORK_NAME \ --image-project=debian-cloud \ --image-family=debian-11 \ --project=$PROJECT踏み台 VM に接続します。
gcloud compute ssh $BASTION_VM_NAME \ --zone=$VM_ZONE \ --project=$PROJECT踏み台 VM に PostgreSQL クライアントをインストールします。
sudo apt-get update sudo apt-get install -y postgresql-client exit
以降の手順の PostgreSQL コマンドは、踏み台 VM から実行します。
プライマリ インスタンスを作成して設定する
プライマリ Cloud SQL インスタンスを作成します。
gcloud sql instances create $PRIMARY_INSTANCE_NAME \ --database-version=POSTGRES_17 \ --edition=ENTERPRISE_PLUS \ --region=$PRIMARY_REGION \ --tier=db-perf-optimized-N-2 \ --no-assign-ip \ --network=projects/$PROJECT/global/networks/$NETWORK_NAME \ --project=$PROJECT論理デコードを有効にします。
gcloud sql instances patch $PRIMARY_INSTANCE_NAME \ --database-flags=cloudsql.logical_decoding=on \ --project=$PROJECTプライマリで
postgresユーザーのパスワードを設定します。gcloud sql users set-password postgres \ --instance=$PRIMARY_INSTANCE_NAME \ --password="$POSTGRES_PASSWORD" \ --project=$PROJECT踏み台 VM からプライマリ インスタンスに接続します。
プライマリ インスタンスのプライベート IP アドレスを取得します。
gcloud sql instances describe $PRIMARY_INSTANCE_NAME \ --format="value(ipAddresses[0].ipAddress)" \ --project=$PROJECTプライマリ インスタンスのプライベート IP アドレスをコピーして保存します。
踏み台 VM に SSH で接続します。
gcloud compute ssh $BASTION_VM_NAME --zone=$VM_ZONE --project=$PROJECT踏み台 VM からプライマリ インスタンスに接続します。
psql -h PRIMARY_PRIVATE_IP -U postgresPRIMARY_PRIVATE_IP は、この手順のステップ 4.a で取得した プライマリ インスタンスのプライベート IP に置き換えます。
パスワードの入力を求められたら、変数
$POSTGRES_PASSWORDを入力します。これで、踏み台 VM が PostgreSQL を介してプライマリ インスタンスに接続されました。
権限を付与してパブリケーションを作成します。
postgresユーザーにREPLICATION権限を付与します。ALTER USER postgres WITH REPLICATION;public スキーマとテーブルに必要な権限を付与します。
GRANT SELECT ON ALL TABLES IN SCHEMA public TO postgres;すべてのテーブルのパブリケーションを作成します。
CREATE PUBLICATION my_publication FOR ALL TABLES;exitと入力して PostgreSQL を終了し、もう一度exitと入力して踏み台 VM の SSH セッションを閉じます。
障害復旧レプリカ(DR レプリカ)を作成して指定する
DR レプリカを作成します。
gcloud sql instances create $DR_REPLICA_NAME \ --master-instance-name=$PRIMARY_INSTANCE_NAME \ --edition=ENTERPRISE_PLUS \ --tier=db-perf-optimized-N-2 \ --region=$REPLICA_REGION \ --no-assign-ip \ --network=projects/$PROJECT/global/networks/$NETWORK_NAME \ --project=$PROJECTこのレプリカを DR レプリカとして指定します。
gcloud sql instances patch $PRIMARY_INSTANCE_NAME \ --failover-dr-replica-name=$DR_REPLICA_NAME \ --project=$PROJECT論理スロットの同期用に DR レプリカを構成します。
gcloud sql instances patch $DR_REPLICA_NAME \ --database-flags="^:^cloudsql.logical_decoding=on:hot_standby_feedback=on:sync_replication_slots=on:cloudsql.logical_slot_sync_dbname=postgres" \ --project=$PROJECTプライマリ インスタンスと DR レプリカ間の同期レプリケーションを構成します。
プライマリ インスタンスが突然停止し、その後にレプリカ フェイルオーバーが発生した場合に、論理サブスクライバーでデータが失われる可能性を防ぐため、プライマリ インスタンスと DR レプリカ間の同期レプリケーションを構成することをおすすめします。
プライマリ インスタンスで
cloudsql.synchronized_standby_replicasを設定すると、プライマリ インスタンスの論理レプリケーション先行書き込みログ(WAL)送信者は、DR レプリカが特定のトランザクションの WAL を受信してフラッシュするまで待機してから、そのトランザクションを論理サブスクライバーに送信します。これにより、DR レプリカの状態が常に論理サブスクライバーの状態以上になります。gcloud sql instances patch $PRIMARY_INSTANCE_NAME \ --database-flags="^:^cloudsql.logical_decoding=on:cloudsql.synchronized_standby_replicas=$DR_REPLICA_NAME" \ --project=$PROJECT
論理サブスクライバー インスタンスを作成して設定する
サブスクライバー インスタンスを作成します。
gcloud sql instances create $SUBSCRIBER_INSTANCE_NAME \ --database-version=POSTGRES_17 \ --tier=db-perf-optimized-N-2 \ --region=$SUBSCRIBER_REGION \ --no-assign-ip \ --network=projects/$PROJECT/global/networks/$NETWORK_NAME \ --project=$PROJECTサブスクライバーで論理デコードを有効にします。
gcloud sql instances patch $SUBSCRIBER_INSTANCE_NAME \ --database-flags=cloudsql.logical_decoding=on \ --project=$PROJECT
論理レプリケーション サブスクリプションを作成する
プライマリ インスタンスのプライベート サービス アクセス書き込みエンドポイントを取得します。
gcloud sql instances describe $PRIMARY_INSTANCE_NAME \ --format="value(replicationCluster.psaWriteEndpoint)" \ --project=$PROJECT書き込みエンドポイントをコピーして保存します。
サブスクライバー インスタンスに接続します。
サブスクライバー インスタンスの
postgresユーザーのパスワードを更新します。gcloud sql users set-password postgres \ --instance=$SUBSCRIBER_INSTANCE_NAME \ --password="$POSTGRES_PASSWORD" \ --project=$PROJECTサブスクライバー インスタンスのプライベート IP アドレスを取得します。
gcloud sql instances describe $SUBSCRIBER_INSTANCE_NAME \ --format="value(ipAddresses[0].ipAddress)" \ --project=$PROJECTプライベート IP アドレスをコピーして保存します。
踏み台 VM に SSH で接続します。
gcloud compute ssh $BASTION_VM_NAME \ --zone=$VM_ZONE \ --project=$PROJECT踏み台 VM から PostgreSQL を介してサブスクライバー インスタンスに接続します。
psql -h SUBSCRIBER_PRIVATE_IP -U postgresSUBSCRIBER_PRIVATE_IP は、 この手順のステップ 2.b でコピーしたサブスクライバー インスタンスのプライベート IP に置き換えます。
パスワードの入力を求められたら、変数
$POSTGRES_PASSWORDを入力します。
サブスクリプションを作成します。
CREATE SUBSCRIPTION my_subscription CONNECTION 'host=DR_CLUSTER_PSA_DNS_WRITE_ENDPOINT port=5432 dbname=postgres user=postgres password=PASSWORD' PUBLICATION my_publication WITH (failover = true);次のように置き換えます。
- DR_CLUSTER_PSA_DNS_WRITE_ENDPOINT: この手順のステップ 1でコピーしたプライベート サービス アクセス書き込みエンドポイント。
- PASSWORD:変数
${POSTGRES_PASSWORD}の値。
PostgreSQL と踏み台 VM の SSH セッションを終了します。
省略可。DR レプリカのスロットの永続性を確認します。
この永続的な移行(
temporary = false)は通常、迅速に行われます。プライマリのアクティビティが少ない場合は、数秒で完了します。プライマリに書き込み負荷が高い場合、このプロセスには時間がかかることがあります(通常は約 1 分)。 これらの手動コマンドが完了すると、スロットは永続的になります。DR レプリカのプライベート IP アドレスを取得します。
gcloud sql instances describe $DR_REPLICA_NAME \ --format="value(ipAddresses[0].ipAddress)" \ --project=$PROJECTDR レプリカのプライベート IP アドレスをコピーして保存します。
踏み台 VM に SSH で接続します。
gcloud compute ssh $BASTION_VM_NAME \ --zone=$VM_ZONE \ --project=$PROJECT踏み台 VM から DR レプリカに接続します。
psql -h DR_REPLICA_PRIVATE_IP -U postgresDR_REPLICA_PRIVATE_IP は、この手順のステップ 5.a で取得した DR レプリカのプライベート IP アドレスに置き換えます。
パスワードの入力を求められたら、変数
$POSTGRES_PASSWORDを入力します。スロットのステータスを確認します。
SELECT slot_name, slot_type, temporary, failover, synced FROM pg_replication_slots WHERE slot_type = 'logical' AND failover = true;temporary列がfになるまで待ちます。通常は 1 分未満で完了します。PostgreSQL と踏み台 VM の SSH セッションを終了します。
スイッチオーバーまたはレプリカ フェイルオーバーを実行する
シナリオに応じて、実行するオペレーションを選択します。
スイッチオーバー(計画されたロールの反転): 計画されたメンテナンス、 障害復旧テスト、またはプライマリ インスタンスが オンラインで正常な場合にロールを切り替える場合に選択します。このオペレーションにより、物理レプリケーションでデータ損失が発生しません。
gcloud sql instances switchover $DR_REPLICA_NAME \ --project=$PROJECTレプリカ フェイルオーバー(障害復旧): プライマリ インスタンス が使用できない場合、または応答しない場合に選択します。このオペレーションにより、DR レプリカがプライマリに昇格します。論理サブスクライバーのデータ損失のリスクを最小限に抑えるため、プライマリ インスタンスに
cloudsql.synchronized_standby_replicasが設定されていることを 確認してください。これは、障害復旧レプリカ(DR レプリカ)を作成して指定するで推奨されています。gcloud sql instances promote-replica $DR_REPLICA_NAME \ --failover \ --project=$PROJECT$DR_REPLICA_NAMEの昇格は迅速に行われます。ただし、元のプライマリ インスタンス($PRIMARY_INSTANCE_NAME)は、オンラインに戻ったときにのみ、新しいプライマリのレプリカとして再構成されます。これを確認するには、オペレーション ログで$PRIMARY_INSTANCE_NAMEのRECONFIGURE_OLD_PRIMARYオペレーションが完了しているかどうかを確認します。次のコマンドを実行します。gcloud sql operations list --instance=$PRIMARY_INSTANCE_NAME --project=$PROJECT --limit=10`このフェーズが完了すると、障害復旧の設定が完全に復元されます。
どちらのオペレーションの後も、サブスクライバーはプライベート サービス アクセス書き込みエンドポイントを介して新しいプライマリ $DR_REPLICA_NAME に自動的に再接続します。
フラグの管理
Cloud SQL のワークフローは、スイッチオーバー オペレーションとレプリカ フェイルオーバー オペレーション中およびオペレーション後に、障害復旧クラスタ内の両方のインスタンスで必要なデータベース フラグを自動的に管理します。これには次のものがあります。
- 新しいレプリカになるインスタンスで、論理スロットの同期フラグ(
cloudsql.logical_decoding、hot_standby_feedback、sync_replication_slots、cloudsql.logical_slot_sync_dbname) が正しいことを確認します。 - 新しいプライマリになるインスタンスの
cloudsql.synchronized_standby_replicasフラグは、新しい DR レプリカの名前に自動的に更新されます。
スイッチオーバー オペレーションまたはレプリカ フェイルオーバー オペレーションの後に、これらのフラグを手動で再適用または変更する必要はありません。Cloud SQL は、プライマリ ロールとレプリカ ロールの正しい構成を維持します。
レプリケーションを検証する
サブスクライバーのステータスを確認します。
踏み台 VM から、次のコマンドを実行します。
psql -h SUBSCRIBER_PRIVATE_IP -U postgresSUBSCRIBER_PRIVATE_IP は、サブスクライバー インスタンスのプライベート IP アドレスに置き換えます。
サブスクライバー インスタンスで、次のコマンドを実行します。
SELECT subname, pid IS NOT NULL AS is_active FROM pg_stat_subscription;ステータスは
streamingになります。
新しいプライマリのレプリケーション スロットのステータスを確認します。新しいプライマリは、以前の DR レプリカ(
$DR_REPLICA_NAME)です。新しいプライマリのプライベート IP アドレスを取得します。
gcloud sql instances describe $DR_REPLICA_NAME \ --project=$PROJECT --format="value(ipAddresses[0].ipAddress)"新しいプライマリのプライベート IP アドレスをコピーして保存します。
踏み台 VM に SSH で接続します。
psql -h NEW_PRIMARY_PRIVATE_IP -U postgresNEW_PRIMARY_PRIVATE_IP は、前の手順でコピーした新しいプライマリのプライベート IP アドレスに置き換えます。
新しいプライマリ インスタンスで、次のコマンドを実行します。
SELECT slot_name, slot_type, active, synced, active_pid, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS replication_lag FROM pg_replication_slots WHERE slot_type = 'logical';スロット(
my_subscriptionなど)はactive = tになります。SELECT application_name, state FROM pg_stat_replication;pg_stat_replicationに、サブスクライバーが接続されていることが表示されます。
新しいレプリカで孤立したレプリケーション スロットをクリーンアップする
スイッチオーバー オペレーションとフェイルオーバー オペレーションが完了すると、元のプライマリ インスタンス($PRIMARY_INSTANCE_NAME)はレプリカになります。この新しいレプリカ インスタンスは、ディスクに my_subscription という名前の元の論理レプリケーション スロットを保持しています。サブスクライバーはプライベート サービス アクセス書き込みエンドポイントを介して新しいプライマリ($DR_REPLICA_NAME)に接続することが想定されているため、この my_subscription スロットは孤立しています。
Cloud SQL は、この孤立したスロットを新しいレプリカから自動的に削除しません。これは、Cloud SQL が、サブスクライバーがプライベート サービス アクセス書き込みエンドポイントではなくインスタンスの IP アドレスを使用するように構成されているかどうかを判断できないためです。サブスクリプションが手動で変更されるまで、サブスクライバーが新しいレプリカの古いスロットに接続しようとする可能性があります。 スロットを自動的に削除すると、このような構成が破損する可能性があります。
新しいレプリカ($PRIMARY_INSTANCE_NAME)にこの孤立したスロットが存在すると、このインスタンスの slotsync
ワーカー プロセスでログにエラーが生成されます。新しいレプリカの postgres.log に次のようなエラー メッセージが表示されることがあります。slotsync
ワーカーが試行を続けるため、このエラーは繰り返されます。
ERROR: exiting from slot synchronization because same name slot "my_subscription" already exists on the standby
このようなエラーを防ぎ、slotsync ワーカーがこのレプリカで my_subscription
スロットの新しい同期バージョンを正しく確立できるようにするには、孤立したスロットを手動で削除する必要があります。これにより、今後スイッチバックを行う場合に、このインスタンスを適切に準備できます。
新しいレプリカ(
$PRIMARY_INSTANCE_NAME)のプライベート IP アドレスを取得します。gcloud sql instances describe $PRIMARY_INSTANCE_NAME \ --project=$PROJECT --format="value(ipAddresses[0].ipAddress)"新しいレプリカのプライベート IP アドレスをコピーして保存します。
踏み台 VM に SSH で接続します。
gcloud compute ssh $BASTION_VM_NAME \ --zone=$VM_ZONE \ --project=$PROJECT踏み台 VM から新しいレプリカに接続します。
psql -h NEW_REPLICA_IP -U postgresNEW_REPLICA_IP は、この手順のステップ 1 でコピーした新しい レプリカの IP アドレスに置き換えます。
パスワードの入力を求められたら、変数
$POSTGRES_PASSWORDを入力します。新しいレプリカ(
$PRIMARY_INSTANCE_NAME)で、孤立したスロットを削除します。SELECT slot_name, slot_type, temporary, failover, synced, active FROM pg_replication_slots WHERE slot_name = 'my_subscription';synced = falseとactive = falseでスロットが存在することを確認し、削除します。SELECT pg_drop_replication_slot('my_subscription');孤立したスロットが削除されます。
スロットの自動再同期
孤立したスロットが削除されると、新しいレプリカ($PRIMARY_INSTANCE_NAME)の slotsync
ワーカーは、次のサイクルで新しいプライマリ($DR_REPLICA_NAME)に自動的に接続します。新しいプライマリのアクティブ スロットと同期された新しいローカル my_subscription スロットが作成されます。
新しいレプリカの postgres.log に、次のような成功を示すメッセージが表示されます。
LOG: newly created slot "my_subscription" is sync-ready now
新しい同期スロットには failover=true が設定され、最終的に永続的(temporary=false)になります。これにより、後でスイッチバックする場合に、このインスタンスを準備できます。
省略可: スイッチバックを実行する
スイッチバックして、
$PRIMARY_INSTANCE_NAMEを再びプライマリ インスタンスにします。gcloud sql instances switchover $PRIMARY_INSTANCE_NAME \ --project=$PROJECTスイッチバック後に検証を行います。
サブスクライバー インスタンスのステータスを確認します。
SELECT subname, pid IS NOT NULL AS is_active FROM pg_stat_subscription;サブスクリプションはアクティブのままにする必要があります(
is_active = t)。新しいプライマリ(
$PRIMARY_INSTANCE_NAME)のスロットのステータスを確認します。SELECT slot_name, active FROM pg_replication_slots WHERE slot_type = 'logical'; SELECT * FROM pg_stat_replication;スロットはアクティブで、サブスクライバーが接続されている必要があります。