Chuyển đến nội dung chính

レッスン 24: アップグレード戦略

PostgreSQL メジャー バージョン、Patroni バージョン、ゼロ ダウンタイム アップグレード手法、ロールバック手順、ラボの PG 17 から 18 へのアップグレード。

🔒 DevSecOps — レッスン 24 レッスン 24: アップグレード戦略__HTMLTAG_53___

Patroni と PostgreSQL の高可用性etcd

パート 5: セキュリティと上級_

xdev.asia_

目標

このレッスンの後、次のことを行います:

  • PostgreSQL メジャー バージョンのアップグレードを計画および実行
  • ダウンタイムなしで Patroni をアップグレード
  • インプレースで pg_upgrade を使用するアップグレード
  • アップグレード用の論理レプリケーションを実装
  • 失敗したアップグレードを安全にロールバック

1。アップグレード計画

1.1。アップグレード前チェックリスト

☐ Review PostgreSQL release notes
☐ Check extension compatibility
☐ Test upgrade in staging environment
☐ Backup all data (full + WAL archive)
☐ Document current versions
☐ Schedule maintenance window
☐ Notify stakeholders
☐ Prepare rollback plan
☐ Verify disk space (need 2x current data size)
☐ Check for deprecated features in new version
☐ Update monitoring/alerting
☐ Prepare downtime communication

1.2。バージョン互換性マトリックス

___HTMLTAG_97 ___リスク
From → To方法ダウンタイム
17 → 18pg_upgrade分___HTMLTAG _108___低
15 → 18pg_upgrade分___HTMLTAG_ 118___中
12 → 18論理的レプリケーションなし中
9.6 → 18ダンプ/復元時間高

1.3.現在の状態

# PostgreSQL version
psql -c "SELECT version();"

Installed extensions

psql -c "\dx"

Database sizes

psql -c "SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database;"

Patroni version

patronictl version

etcd version

etcdctl version

2 を文書化します。 PostgreSQL マイナー バージョン アップグレード

2.1。マイナー アップグレード プロセス (例: 18.0 → 18.1)

# Minor upgrades are easy - just update packages

On each node (one at a time):

1. Update packages

sudo apt-get update sudo apt-get install --only-upgrade postgresql-18

2. Restart Patroni (will restart PostgreSQL)

sudo systemctl restart patroni

3. Verify new version

psql -c "SELECT version();"

Patroni handles failover automatically during restart

2.2。ローリング マイナー アップグレード_

# Upgrade replicas first
for node in node2 node3; do
echo "Upgrading $node..."
ssh $node "sudo apt-get update && sudo apt-get install -y --only-upgrade postgresql-18"
ssh $node "sudo systemctl restart patroni"
sleep 30  # Wait for replica to catch up
done

Switchover to upgraded replica

patronictl switchover postgres-cluster --leader node1 --candidate node2

Upgrade old leader (now replica)

ssh node1 "sudo apt-get update && sudo apt-get install -y --only-upgrade postgresql-18" ssh node1 "sudo systemctl restart patroni"

3。 pg_upgrade

3.1 による PostgreSQL メジャー バージョン アップグレード。アーキテクチャ_

Before (PostgreSQL 17):
node1 (17, Leader)
node2 (17, Replica)
node3 (17, Replica)

During upgrade: node1 (17, Leader) ← Still serving traffic node2 (18, NEW) ← Upgrading node3 (17, Replica)

After upgrade: node1 (18, Leader) ← Upgraded node2 (18, Replica) node3 (18, Replica)

3.2。新しい PostgreSQL バージョン

# Install PostgreSQL 18 alongside 17
sudo apt-get install -y postgresql-18 postgresql-18-contrib

Both versions now installed:

/usr/lib/postgresql/17/

/usr/lib/postgresql/18/

3.3 をインストールします。アップグレードの準備をします (ノード 2 - 最初のレプリカ)

# 1. Stop Patroni on node2
sudo systemctl stop patroni

2. Create new data directory for v18

sudo mkdir -p /var/lib/postgresql/18/data sudo chown postgres:postgres /var/lib/postgresql/18/data

3. Initialize new cluster

sudo -u postgres /usr/lib/postgresql/18/bin/initdb
-D /var/lib/postgresql/18/data
--encoding=UTF8
--data-checksums

4. Run pg_upgrade

sudo -u postgres /usr/lib/postgresql/18/bin/pg_upgrade
--old-datadir=/var/lib/postgresql/17/data
--new-datadir=/var/lib/postgresql/18/data
--old-bindir=/usr/lib/postgresql/17/bin
--new-bindir=/usr/lib/postgresql/18/bin
--check # Dry run first!

If check passes, run actual upgrade:

sudo -u postgres /usr/lib/postgresql/18/bin/pg_upgrade
--old-datadir=/var/lib/postgresql/17/data
--new-datadir=/var/lib/postgresql/18/data
--old-bindir=/usr/lib/postgresql/17/bin
--new-bindir=/usr/lib/postgresql/18/bin
--link # Use hard links (faster)

Expected output:

Performing Consistency Checks

-----------------------------

...

Upgrade Complete

----------------

3.4。 v18

# /etc/patroni/patroni.yml
postgresql:
bin_dir: /usr/lib/postgresql/18/bin  # Changed from 17
data_dir: /var/lib/postgresql/18/data  # Changed from 17

... rest of config

# Start Patroni with new version
sudo systemctl start patroni

Verify node2 is now running v18

psql -h node2 -U postgres -c "SELECT version();"

3.5 の Patroni 設定を更新します。残りのノード_

# Repeat process for node3
ssh node3 "sudo systemctl stop patroni"
ssh node3 "# ... same pg_upgrade steps ..."
ssh node3 "sudo systemctl start patroni"

Finally, upgrade node1 (current leader)

Switchover to node2 first

patronictl switchover postgres-cluster --leader node1 --candidate node2

Now upgrade node1

ssh node1 "sudo systemctl stop patroni" ssh node1 "# ... same pg_upgrade steps ..." ssh node1 "sudo systemctl start patroni"

All nodes now on v18!

patronictl list

3.6 をアップグレードします。アップグレード後のタスク_

# Run generated optimize scripts
sudo -u postgres ./analyze_new_cluster.sh
sudo -u postgres ./reindex_hash.sh  # If upgrading from < 10

Update extensions

psql -c "ALTER EXTENSION pg_stat_statements UPDATE;"

Vacuum analyze all databases

vacuumdb --all --analyze-in-stages

Remove old cluster (after verifying everything works!)

sudo -u postgres ./delete_old_cluster.sh

4。論理レプリケーションによるダウンタイムゼロのアップグレード_

4.1。アーキテクチャ_

Production (v17):
node1 (v17, Leader) ← Serving traffic
↓ Logical replication
New cluster (v18):
node4 (v18, Leader) ← Receiving changes
node5 (v18, Replica)

After cutover: Application → node4 (v18) ← New primary

4.2。新しい v18 クラスター_

# Install PostgreSQL 18 on new servers

Setup Patroni cluster (node4, node5, node6)

See previous lessons for installation

Verify new cluster

patronictl -c /etc/patroni/patroni-v18.yml list

4.3 をセットアップします。 v17 (ソース)

-- On node1 (v17 leader)
CREATE PUBLICATION pg17_to_pg18 FOR ALL TABLES;

-- Or specific tables: -- CREATE PUBLICATION pg17_to_pg18 FOR TABLE users, orders, products;

-- Verify SELECT * FROM pg_publication;

4.4 でパブリケーションを作成します。 v18 (ターゲット)

-- On node4 (v18 leader)
CREATE SUBSCRIPTION pg18_from_pg17
CONNECTION 'host=node1 port=5432 dbname=myapp user=replicator password=rep_pass'
PUBLICATION pg17_to_pg18
WITH (copy_data = true, create_slot = true);

-- Monitor initial sync SELECT * FROM pg_stat_subscription;

-- Wait for initial data copy to complete -- subname | pg18_from_pg17 -- received_lsn | 0/3000000 -- ...

4.5 でサブスクリプションを作成します。レプリケーションの遅延_

-- On v17 (source)
SELECT slot_name, active, restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots
WHERE slot_name LIKE '%pg18%';

-- On v18 (target) SELECT subname, received_lsn, latest_end_lsn, pg_size_pretty(pg_wal_lsn_diff(latest_end_lsn, received_lsn)) AS lag FROM pg_stat_subscription;

4.6を監視します。カットオーバー手順_

# 1. Stop writes to v17 (put app in maintenance mode)

Or set database to read-only:

psql -h node1 -U postgres -c "ALTER SYSTEM SET default_transaction_read_only = on;" psql -h node1 -U postgres -c "SELECT pg_reload_conf();"

2. Wait for replication to catch up

psql -h node4 -U postgres -c "SELECT pg_size_pretty(pg_wal_lsn_diff(latest_end_lsn, received_lsn)) FROM pg_stat_subscription;"

Should be 0 bytes

3. Disable subscription on v18

psql -h node4 -U postgres -c "ALTER SUBSCRIPTION pg18_from_pg17 DISABLE;"

4. Drop subscription (optional, after confirming everything works)

psql -h node4 -U postgres -c "DROP SUBSCRIPTION pg18_from_pg17;"

5. Update application connection strings to point to node4

6. Enable writes on v18

psql -h node4 -U postgres -c "ALTER SYSTEM SET default_transaction_read_only = off;" psql -h node4 -U postgres -c "SELECT pg_reload_conf();"

7. Verify application works on v18

8. Keep v17 cluster running for rollback (1-2 weeks)

5。 Patroni バージョン アップグレード

5.1。互換性を確認してください_

# Check current Patroni version
patronictl version

Check PostgreSQL compatibility

Patroni 3.2.0+ supports PostgreSQL 18

See: https://github.com/zalando/patroni/releases

5.2。 Patroni のアップグレード (Python パッケージ)

# On each node:

1. Upgrade via pip

sudo pip3 install --upgrade patroni[etcd]

Or specific version:

sudo pip3 install patroni[etcd]==3.2.2

2. Verify new version

patronictl version

3. Restart Patroni service

sudo systemctl restart patroni

No downtime - Patroni handles failover automatically

5.3。ローリング パトローニのアップグレード_

# Upgrade replicas first
for node in node2 node3; do
echo "Upgrading Patroni on $node..."
ssh $node "sudo pip3 install --upgrade patroni[etcd]"
ssh $node "sudo systemctl restart patroni"
sleep 10
done

Switchover to upgraded replica

patronictl switchover postgres-cluster --leader node1 --candidate node2

Upgrade old leader

ssh node1 "sudo pip3 install --upgrade patroni[etcd]" ssh node1 "sudo systemctl restart patroni"

6。 etcd のアップグレード_

6.1。 etcd のマイナー アップグレード

# On each etcd node:
sudo systemctl stop etcd
sudo apt-get update
sudo apt-get install --only-upgrade etcd
sudo systemctl start etcd

Verify cluster health

etcdctl endpoint health

6.2。 etcd メジャー アップグレード (例: 3.4 → 3.5)

# Follow official etcd upgrade guide

https://etcd.io/docs/latest/upgrades/

Key steps:

1. Backup etcd data

etcdctl snapshot save backup.db

2. Upgrade one member at a time

3. Verify cluster health after each upgrade

4. Update Patroni to use new etcd API version

7。ロールバック戦略

7.1。 pg_upgrade

# Before deleting old cluster, you can rollback

1. Stop Patroni

sudo systemctl stop patroni

2. Restore old configuration

/etc/patroni/patroni.yml

postgresql: bin_dir: /usr/lib/postgresql/17/bin # Back to 17 data_dir: /var/lib/postgresql/17/data

3. Start Patroni

sudo systemctl start patroni

Old cluster resumes operation

7.2 をロールバックします。論理レプリケーションをロールバック

# If cutover to v18 fails, rollback to v17

1. Stop application

2. Set v17 to read-write

psql -h node1 -U postgres -c "ALTER SYSTEM SET default_transaction_read_only = off;" psql -h node1 -U postgres -c "SELECT pg_reload_conf();"

3. Update application connection strings to v17

4. Resume normal operations

Note: Any writes to v18 during cutover will be LOST!

Consider setting up reverse replication v18 → v17 if needed

7.3。 Patroni のアップグレード

# Downgrade Patroni if upgrade causes issues

sudo pip3 install patroni[etcd]==3.1.2 # Previous version sudo systemctl restart patroni

8 をロールバックします。アップグレードのテスト_

8.1。ステージング環境テスト

# 1. Clone production to staging
pg_basebackup -h prod-leader -D /var/lib/postgresql/staging -X stream

2. Perform upgrade in staging

... follow upgrade procedures ...

3. Run application tests

... smoke tests, integration tests ...

4. Benchmark performance

pgbench -i -s 100 myapp pgbench -c 10 -j 2 -t 1000 myapp

5. Document issues and timings

8.2。アップグレードのリハーサル

# Practice upgrade multiple times

Time each step

Identify bottlenecks

Refine procedures

Example timing log:

Step 1: Stop Patroni - 5 seconds

Step 2: pg_upgrade --check - 30 seconds

Step 3: pg_upgrade - 10 minutes

Step 4: Start Patroni - 15 seconds

Step 5: Replication catchup - 2 minutes

Total: ~13 minutes

9。ベスト プラクティス

✅ DO

  1. 最初にステージングでテスト - 複数回
  2. バックアップすべて_ - 完全バックアップ + WAL アーカイブ_
  3. pg_upgrade --check - 問題を早期に発見
  4. 文書化手順 -ステップバイステップのランブック_
  5. メンテナンス期間のスケジュール - オフピーク時間_
  6. 注意深く監視 - メンテナンス中およびメンテナンス後アップグレード
  7. 古いバージョンを保持 - 1~2 週間削除しないでください
  8. 論理レプリケーションを使用 -ゼロダウンタイム
  9. 拡張機能のアップグレード - PostgreSQL アップグレード後
  10. 真空分析 - メジャー後アップグレード

❌ 禁止

  1. バックアップをスキップしない - 重要なセーフティネット
  2. すべてをアップグレードしないでください一度に - ローリングアップグレード
  3. 古いクラスターをすぐに削除しないでください - ロールバックのために保持_
  4. リリースを無視しないでくださいメモ_ - 重大な変更
  5. テストをスキップしないでください - ステージングは不可欠_
  6. ピーク時間帯にはアップグレードしないでください - メンテナンスを計画してくださいウィンドウ_
  7. 拡張機能を忘れないでください_ - 更新が必要な場合があります

10。ラボ演習

ラボ 1: マイナー バージョン アップグレード

タスク:

  1. 現在の PostgreSQL バージョンを確認する
  2. パッケージを更新するレプリカ_
  3. レプリカで Patroni を再起動_
  4. アップグレードされたレプリカに切り替え_
  5. 古いリーダーをアップグレード

ラボ 2: pg_upgrade によるメジャー バージョン アップグレード

タスク:

  1. すべてに PostgreSQL 18 をインストールするノード_
  2. pg_upgrade を実行 -- レプリカでチェック
  3. レプリカで pg_upgrade を実行
  4. Patroni 構成を更新
  5. ローリングを完了アップグレード

ラボ 3: 論理レプリケーションによるダウンタイムゼロのアップグレード

タスク:

  1. 新しい v18 をセットアップするクラスター_
  2. v17 でパブリケーションを作成_
  3. v18 でサブスクリプションを作成
  4. レプリケーションラグを監視_
  5. カットオーバーを実行_
  6. アプリケーションを確認機能

ラボ 4: ロールバック手順

タスク:

  1. 失敗したアップグレードのシミュレーション
  2. 停止すべてのノードで Patroni_
  3. 古い構成を復元
  4. 古いクラスターを再起動_
  5. ロールバックが成功したことを確認_

11。概要____HTMLTAG_364__HTMLTAG_365___アップグレード方法の比較

__ _HTMLTAG_387___分___HTMLTAG_411__ _時間
方法ダウンタイム_ __HTMLTAG_374___複雑さリスク使用ケース_
pg_upgrade低低_マイナーバージョンのジャンプ
論理的レプリケーションなし高中ゼロダウンタイム必須
ダンプ/復元低低古代バージョン_
pg_upgrade --link秒MediumMedium_同じサーバーアップグレード

一般的なタイムライン___HTMLTAG_436__CODEBLOCK_27___

アップグレード チェックリスト_

Pre-upgrade:
☐ Full backup completed
☐ Staging test successful
☐ Release notes reviewed
☐ Maintenance window scheduled
☐ Rollback plan documented
☐ Stakeholders notified

During upgrade: ☐ Backups verified ☐ pg_upgrade --check passed ☐ Upgrade completed ☐ Replication working ☐ Application connectivity verified

Post-upgrade: ☐ Extensions updated ☐ Vacuum analyze completed ☐ Performance validated ☐ Monitoring updated ☐ Documentation updated

次のステップ_

レッスン 25 では実際のケースについて説明します研究_:

  • 運用アーキテクチャの例
  • 1000 クエリ/秒以上に拡張
  • コストの最適化テクニック
  • 失敗から学んだ教訓
  • 業界固有の実装