目標_
このレッスンの後、次のことを学びます:
- Patroni クラスターのブートストラップ プロセスを理解する_
- 3 ノードで初めて Patroni を起動_
- クラスターのステータスを確認するpatronictl
- レプリケーションがアクティブであることを確認__HTMLTAG_77___
- 一般的な問題のトラブルシューティング__HTMLTAG_79___
- 基本的なフェールオーバーをテスト
1。ブートストラップ前チェックリスト
1.1。前提条件の確認
Patroni を開始する前に、すべてのコンポーネントの準備ができていることを確認してください:
# ✅ etcd cluster healthy etcdctl endpoint health --clusterAll endpoints should be healthy
✅ PostgreSQL installed nhưng NOT running
systemctl status postgresql
Should be: inactive (dead)
✅ Patroni installed
patroni --version
Should show: patroni 3.2.0+
✅ Config file exists và valid
sudo -u postgres cat /etc/patroni/patroni.yml python3 -c "import yaml; yaml.safe_load(open('/etc/patroni/patroni.yml'))"
✅ Data directory exists với permissions đúng
ls -ld /var/lib/postgresql/18/data
Owner: postgres:postgres, Permissions: drwx------
✅ Firewall rules
sudo ufw status | grep -E "(5432|8008)"
Ports 5432, 8008 should be allowed
1.2。ネットワーク接続テスト
ノード間の接続を確認します:
# Test PostgreSQL port nc -zv 10.0.1.11 5432 nc -zv 10.0.1.12 5432 nc -zv 10.0.1.13 5432Test Patroni REST API port
nc -zv 10.0.1.11 8008 nc -zv 10.0.1.12 8008 nc -zv 10.0.1.13 8008
Test etcd port
nc -zv 10.0.1.11 2379 nc -zv 10.0.1.12 2379 nc -zv 10.0.1.13 2379
1.3。データ ディレクトリをクリーンアップ
データ ディレクトリが空でない場合は、削除して最初からやり直します:
# CẢNH BÁO: Chỉ làm khi bootstrap lần đầu
sudo systemctl stop patroni
sudo rm -rf /var/lib/postgresql/18/data/*
sudo chown postgres:postgres /var/lib/postgresql/18/data
2。ブートストラップ プロセスを理解する_
2.1。ブートストラップ フロー
Step 1: Start Patroni trên Node 1 ↓ Node 1 checks DCS: No cluster exists ↓ Node 1 acquires initialize key ↓ Node 1 runs pg_initdb ↓ Node 1 starts PostgreSQL as PRIMARY ↓ Node 1 creates replication user ↓ Node 1 stores cluster config in DCS ↓ Node 1 acquires leader lockStep 2: Start Patroni trên Node 2 ↓ Node 2 checks DCS: Cluster exists ↓ Node 2 sees Node 1 is leader ↓ Node 2 runs pg_basebackup from Node 1 ↓ Node 2 starts PostgreSQL as REPLICA ↓ Node 2 connects to Node 1 for replication
Step 3: Start Patroni trên Node 3 ↓ Node 3 checks DCS: Cluster exists ↓ Node 3 sees Node 1 is leader ↓ Node 3 runs pg_basebackup from Node 1 ↓ Node 3 starts PostgreSQL as REPLICA ↓ Node 3 connects to Node 1 for replication
Final State: ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Node 1 │────────→│ Node 2 │ │ Node 3 │ │ PRIMARY │ │ REPLICA │←────────│ REPLICA │ └─────────┘ └─────────┘ └─────────┘ Leader Streaming Streaming
2.2。競合状態の防止
Patroni は DCS を使用して、複数のノードがクラスターを初期化するのを防ぎます:
# In etcd
/service/postgres/initialize: "node1" # First node acquires this
/service/postgres/leader: {...} # Leader lock
2 つのノードが同時に開始する場合:
- 高速ノード
/initializekey - を取得します。他のノードはキーがすでに存在することを確認します。→待機して、リーダー
3からクローンを作成します。ブートストラップ クラスター - ステップバイステップ
3.1。ノード 1 で Patroni を開始
ノード 1 のターミナル:
# Start Patroni service sudo systemctl start patroniWatch logs
sudo journalctl -u patroni -f
予想通りログ:
INFO: No initialize key found in DCS
INFO: Trying to bootstrap a new cluster
INFO: Acquiring initialize key
INFO: Initializing a new cluster
INFO: Running initdb: /usr/lib/postgresql/18/bin/initdb ...
INFO: postmaster pid: 12345
INFO: PostgreSQL started
INFO: Running post_bootstrap script
INFO: Creating replication user
INFO: Lock owner: node1; I am node1
INFO: Leader election acquired
INFO: I am the leader with the lock
ノード 1 を確認:HTMLTAG_132__CODEBLOCK_7
3.2。 etcd_
# Check leader key etcdctl get /service/postgres/leader --print-value-only | jqOutput:
{
"role": "master",
"state": "running",
"conn_url": "postgres://10.0.1.11:5432/postgres",
"api_url": "http://10.0.1.11:8008/patroni",
"xlog_location": 50331648,
"timeline": 1
}
Check members
etcdctl get /service/postgres/members/ --prefix
Should show node1
3.3 で確認します。ノード 2 で Patroni を開始
ノード 2 でターミナル:
# Start Patroni sudo systemctl start patroniWatch logs
sudo journalctl -u patroni -f
予想通りログ:
INFO: Cluster already initialized
INFO: Found leader: node1
INFO: Trying to clone from leader
INFO: Running: pg_basebackup -D /var/lib/postgresql/18/data ...
INFO: Basebackup completed
INFO: Starting PostgreSQL
INFO: postmaster pid: 12346
INFO: Configuring standby mode
INFO: Following new leader: node1
INFO: Replication established
ノード 2 を確認:
# Check if it's REPLICA sudo -u postgres psql -c "SELECT pg_is_in_recovery();"pg_is_in_recovery
------------------
t ← true = REPLICA
Check replication status
sudo -u postgres psql -c "SELECT * FROM pg_stat_wal_receiver;" -x
3.4。ノード 3 で Patroni を開始
ノード 3 のターミナル:
# Start Patroni sudo systemctl start patroniWatch logs
sudo journalctl -u patroni -f
予想されるログ: ノードに類似2._
ノード 3:
# Check replica status sudo -u postgres psql -c "SELECT pg_is_in_recovery();"Should return: t (true)
4 を確認します。クラスターのステータス
4.1 を確認します。 patronictl の使用_
# List cluster members patronictl -c /etc/patroni/patroni.yml listOutput:
+ Cluster: postgres (7001234567890123456) ----+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+--------+---------------+---------+---------+----+-----------+
| node1 | 10.0.1.11:5432| Leader | running | 1 | |
| node2 | 10.0.1.12:5432| Replica | running | 1 | 0 |
| node3 | 10.0.1.13:5432| Replica | running | 1 | 0 |
+--------+---------------+---------+---------+----+-----------+
列の意味:
- メンバー: ノード名前_
- ホスト: 接続アドレス
- 役割: リーダー (プライマリ) またはレプリカ_
- 状態: 実行中、ストリーミング、アーカイブ回復中
- TL: タイムライン (すべて同じである必要があります)
- MB のラグ: レプリケーションラグ_
4.2。トポロジを確認
patronictl -c /etc/patroni/patroni.yml topology postgresOutput shows replication tree
4.3。 REST API
# Check node1 (primary) curl -s http://10.0.1.11:8008/ | jqOutput:
{
"state": "running",
"postmaster_start_time": "2024-11-24 10:30:15.123+00",
"role": "master",
"server_version": 180000,
"cluster_unlocked": false,
"xlog": {
"location": 50331648
},
"timeline": 1,
"database_system_identifier": "7001234567890123456"
}
Check node2 (replica)
curl -s http://10.0.1.12:8008/ | jq
Check node3 (replica)
curl -s http://10.0.1.13:8008/ | jq
4.4 の使用。 PostgreSQL からのレプリケーションを確認_
プライマリ (ノード 1) 上:
sudo -u postgres psql -c "SELECT * FROM pg_stat_replication;" -x
出力:
-[ RECORD 1 ]----+------------------------------ pid | 12350 usesysid | 16384 usename | replicator application_name | node2 client_addr | 10.0.1.12 client_hostname | client_port | 45678 backend_start | 2024-11-24 10:31:00.123+00 backend_xmin | state | streaming sent_lsn | 0/3000000 write_lsn | 0/3000000 flush_lsn | 0/3000000 replay_lsn | 0/3000000 write_lag | flush_lag | replay_lag | sync_state | async sync_priority | 0 reply_time | 2024-11-24 10:35:00.456+00
-[ RECORD 2 ]----+------------------------------ pid | 12351 usesysid | 16384 usename | replicator application_name | node3 ...
レプリカ上 (ノード 2、ノード3):
sudo -u postgres psql -c "SELECT status, received_lsn, latest_end_lsn FROM pg_stat_wal_receiver;" -x
4.5。レプリケーション ラグ
# On primary sudo -u postgres psql -c " SELECT application_name, client_addr, state, pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes, replay_lag FROM pg_stat_replication; "Output:
application_name | client_addr | state | lag_bytes | replay_lag
-----------------+-------------+-----------+-----------+------------
node2 | 10.0.1.12 | streaming | 0 |
node3 | 10.0.1.13 | streaming | 0 |
5 を確認します。基本操作
5.1 をテストします。テスト データベースとテーブルを作成します
プライマリで (任意のノードに接続すると、patronictl はプライマリにルーティングします):
# Create database sudo -u postgres psql -h 10.0.1.11 -c "CREATE DATABASE testdb;"Create table with data
sudo -u postgres psql -h 10.0.1.11 -d testdb << EOF CREATE TABLE test_table ( id SERIAL PRIMARY KEY, data TEXT, created_at TIMESTAMP DEFAULT NOW() );
INSERT INTO test_table (data) SELECT 'Test data ' || i FROM generate_series(1, 1000) AS i; EOF
5.2。レプリケーションを確認します
レプリケーション時 (ノード 2 またはノード 3):
# Check data replicated sudo -u postgres psql -h 10.0.1.12 -d testdb -c "SELECT COUNT(*) FROM test_table;"Should return: 1000
Try to write (should fail on replica)
sudo -u postgres psql -h 10.0.1.12 -d testdb -c "INSERT INTO test_table (data) VALUES ('test');"
ERROR: cannot execute INSERT in a read-only transaction
5.3。継続的レプリケーションのテスト
ターミナル 1 (プライマリ - ノード 1):
# Insert data continuously
while true; do
sudo -u postgres psql -h 10.0.1.11 -d testdb -c
"INSERT INTO test_table (data) VALUES ('Data at ' || NOW());"
sleep 1
done
ターミナル 2 (レプリカ -ノード 2):
# Watch count increase
watch -n 1 "sudo -u postgres psql -h 10.0.1.12 -d testdb -t -c 'SELECT COUNT(*) FROM test_table;'"
データは毎秒増加するはずです → レプリケーションは動作しています!
6。ブートストラップの一般的な問題_
6.1。問題: Patroni が起動しない
症状:
sudo systemctl status patroniFailed to start
確認してくださいログ_:
sudo journalctl -u patroni -n 50 --no-pager
一般的な原因と問題ソリューション:
A。構成ファイルの構文エラー
ERROR: Error parsing config file
解決策:
# Validate YAML python3 -c "import yaml; yaml.safe_load(open('/etc/patroni/patroni.yml'))"Common issues:
- Mixed tabs and spaces (use spaces only)
- Incorrect indentation
- Missing quotes around special characters
B。 etcd
ERROR: Failed to connect to etcd
Solution:
# Check etcd is running
etcdctl endpoint health
Check etcd endpoints in patroni.yml
grep "hosts:" /etc/patroni/patroni.yml
Test connectivity
C に接続できません。データ ディレクトリ_
ERROR: data directory has wrong ownership
Solution:
sudo chown -R postgres:postgres /var/lib/postgresql/18/data
sudo chmod 700 /var/lib/postgresql/18/data
D。ポートはすでに使用されています
ERROR: could not bind IPv4 address "0.0.0.0": Address already in use
解決策:_
# Check what's using port 5432 sudo lsof -i :5432Stop PostgreSQL if running
sudo systemctl stop postgresql
Kill process if needed
sudo pkill -9 postgres
6.2。問題: クラスターが初期化されません
症状: Patroni は起動しますが、クラスターが初期化されません。
Checkログ:
sudo journalctl -u patroni -f
一般的な原因:
A。データ ディレクトリが空ではありません_
INFO: Data directory is not empty
解決策:_
# Backup old data if needed sudo mv /var/lib/postgresql/18/data /var/lib/postgresql/18/data.bakCreate fresh directory
sudo mkdir -p /var/lib/postgresql/18/data sudo chown postgres:postgres /var/lib/postgresql/18/data sudo chmod 700 /var/lib/postgresql/18/data
Restart Patroni
sudo systemctl restart patroni
B。 etcd
INFO: Another node is initializing
Solutio でスタックしたキーを初期化しますn:
# Check initialize key etcdctl get /service/postgres/initializeIf stuck, delete it
etcdctl del /service/postgres/initialize
Restart Patroni
sudo systemctl restart patroni
6.3。問題: レプリカがプライマリからクローンを作成できない
症状: ノード 2 または 3 がベースバックアップを作成できません。
Checkログ:
sudo journalctl -u patroni -n 100 | grep -i basebackup
一般的な原因:
A。ネットワーク接続_
ERROR: could not connect to server
ソリューション:_
# Test connectivity telnet 10.0.1.11 5432Check firewall
sudo ufw status sudo ufw allow from 10.0.1.0/24 to any port 5432
B。認証に失敗しました
ERROR: FATAL: password authentication failed for user "replicator"
解決策:_
# Verify replication user exists on primary sudo -u postgres psql -h 10.0.1.11 -c "\du replicator"Check pg_hba.conf allows replication
sudo -u postgres psql -h 10.0.1.11 -c "SHOW hba_file;"
Then check the file
Verify password matches in patroni.yml
grep -A2 "replication:" /etc/patroni/patroni.yml
C。スペースが不十分です_
ERROR: No space left on device
解決策:_
# Check disk space df -h /var/lib/postgresqlClean up if needed
sudo du -sh /var/lib/postgresql/* | sort -h
6.4。問題: ノードのタイムラインが異なります
症状:
CODEBLOCK_4 7解決策:
# Reinitialize diverged node patronictl reinit postgres node2Or manually
sudo systemctl stop patroni sudo rm -rf /var/lib/postgresql/18/data/* sudo systemctl start patroni
7。ブート
# Enable Patroni service sudo systemctl enable patroniVerify
systemctl is-enabled patroni
Output: enabled
Test reboot (optional)
sudo reboot
After reboot, check cluster
patronictl list
8 時の自動起動を有効にします。基本的なクラスター管理_
8.1。ノード
# Graceful restart patronictl restart postgres node2Force restart
patronictl restart postgres node2 --force
8.2を再起動します。構成_
# Reload Patroni config (non-PostgreSQL settings) sudo systemctl reload patroniReload PostgreSQL config
patronictl reload postgres node1
8.3をリロードします。自動フェイルオーバーの一時停止/再開_
# Pause (disable auto-failover) patronictl pause postgresResume (enable auto-failover)
patronictl resume postgres
8.4。構成_
# Show current DCS configuration
patronictl show-config postgres
9を表示します。自動フェイルオーバーのテスト (オプション)
警告: 非運用環境でのみテストしてください!
9.1。一次障害_
# On node1 (current primary) sudo systemctl stop patroniOr kill PostgreSQL
sudo pkill -9 postgres
9.2 をシミュレートします。クラスターのフェイルオーバー
# On node2 hoặc node3 watch -n 1 "patronictl list"Timeline:
T+0s: node1 is Leader
T+10s: node1 not responding
T+30s: Leader lock expires
T+35s: node2 or node3 becomes Leader
T+40s: Cluster operational with new Leader
9.3 を監視します。新しいプライマリ
patronictl listNew output:
+ Cluster: postgres ----+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+--------+---------+---------+---------+----+-----------+
| node1 | 10.0.1.11| Replica | stopped | 1 | |
| node2 | 10.0.1.12| Leader | running | 2 | | ← New primary
| node3 | 10.0.1.13| Replica | running | 2 | 0 |
+--------+---------+---------+---------+----+-----------+
注: タイムラインが 1 → 2 に増加しました (フェールオーバーが発生したことを示します)。
9.4。古いプライマリ
# Start node1 again sudo systemctl start patroniPatroni auto-rewinds và rejoins as replica
patronictl list
Output:
| node1 | 10.0.1.11| Replica | running | 2 | 0 | ← Rejoined
| node2 | 10.0.1.12| Leader | running | 2 | |
| node3 | 10.0.1.13| Replica | running | 2 | 0 |
10に再参加します。ラボ演習_
ラボ 1: ブートストラップと検証
タスク: 1. ✅ 3 つのノードで Patroni を順番に起動します。 2. ✅patronictl でクラスタを検証します。リスト_ 3. ✅ レプリケーション ステータスを確認する 4. ✅ テスト データベースを作成し、データのレプリカを確認する_
ラボ 2: レプリケーション ラグをテスト
タスク: 1. プライマリに 10,000 行を挿入します。 2. レプリカのレプリケーション ラグを測定します。 3. 監視します。 pg_stat_replication_
ラボ 3: ノード障害のシミュレーション
タスク_: 1. プライマリ ノードを停止する 2. 自動フェイルオーバーを監視する 3. 新しいプライマリが適応していることを確認する 4. 古いプライマリに再参加する 5. すべてのノードを確認する健康_
11.概要
重要なポイント
✅ ブートストラップ: 最初のノードの初期化、その他クローン
✅ リーダー選出: 自動、DCS ベース
✅ レプリケーション: pg_basebackup による自動セットアップ__HTMLTAG_416___
✅ patronictl: プライマリ管理ツール
✅ モニタリング: patronictl、REST API、pg_stat_replication 経由でチェック
✅ フェイルオーバー: 自動プライマリが失敗した場合
後でチェックリストを作成ブートストラップ
-
patronictl リストHTMLTAG_434__ - 1 リーダー、2 に表示される 3 つのノードすべてレプリカ
- すべてのノードが同じタイムライン
- レプリケーションラグ = 0 MB_
- テストデータがすべてのノードに複製
- REST API が応答中すべてのノード_
- Patroni の自動起動が有効
- etcd クラスターが正常
現在のアーキテクチャ_
✅ 3 VMs prepared (Bài 4) ✅ PostgreSQL 18 installed (Bài 5) ✅ etcd cluster running (Bài 6) ✅ Patroni installed (Bài 7) ✅ Patroni configured (Bài 8) ✅ Cluster bootstrapped (Bài 9)
Next: Advanced replication management
レッスンの準備10_
レッスン 10 では、レプリケーション管理について詳しく説明します:
- 同期レプリケーションと非同期レプリケーション
- 同期モードの構成
- レプリケーションの監視ラグ_
- _レプリケーションの問題の処理