Mục tiêu
Sau bài học này, bạn sẽ:
- Cài đặt Python và các dependencies cần thiết
- Cài đặt Patroni qua pip
- Hiểu cấu trúc file
patroni.yml - Tạo systemd service cho Patroni
- Cài đặt Patroni trên 3 nodes
1. Giới thiệu
Patroni là một Python application, do đó cần Python runtime và các dependencies. Trong bài này, chúng ta sẽ:
- Cài đặt Python 3 và pip
- Cài đặt Patroni package
- Cấu hình Patroni
- Tạo systemd service để quản lý Patroni daemon
Kiến trúc mục tiêu:
┌──────────────────────────────────┐
│ etcd Cluster (3 nodes) │
│ ✅ RUNNING │
└──────────────────────────────────┘
│ │ │
┌────┴────┐ │ ┌─────┴─────┐
▼ ▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Patroni 1│ │Patroni 2│ │Patroni 3│ ← Installing now
│ + PG │ │ + PG │ │ + PG │
└─────────┘ └─────────┘ └─────────┘
2. Cài đặt Python Dependencies
2.1. Cài đặt Python trên Ubuntu/Debian
Thực hiện trên TẤT CẢ 3 nodes.
Bước 1: Cài đặt Python 3 và pip
# Update package list sudo apt updateCài Python 3, pip, và development tools
sudo apt install -y python3 python3-pip python3-dev python3-venv
Kiểm tra version
python3 --version
Output: Python 3.10.x (hoặc 3.11.x hoặc 3.12.x)
pip3 --version
Output: pip 22.x.x
Bước 2: Cài đặt system dependencies
# Cài các libraries cần thiết cho Patroni và PostgreSQL Python modules sudo apt install -y
libpq-dev
gcc
python3-psycopg2libpq-dev: PostgreSQL client library headers
gcc: Compiler cho building Python packages
python3-psycopg2: PostgreSQL adapter cho Python
2.2. Cài đặt Python trên CentOS/RHEL
# Python 3 thường đã có sẵn, nhưng cần pip và dev tools sudo dnf install -y python3 python3-pip python3-develSystem dependencies
sudo dnf install -y
postgresql18-devel
gcc
python3-psycopg2Kiểm tra
python3 --version pip3 --version
2.3. Upgrade pip (khuyến nghị)
# Upgrade pip to latest version sudo pip3 install --upgrade pipVerify
pip3 --version
3. Cài đặt Patroni qua pip
3.1. Cài đặt Patroni
Thực hiện trên TẤT CẢ 3 nodes.
# Cài Patroni với etcd support sudo pip3 install patroni[etcd]Hoặc specify version cụ thể
sudo pip3 install patroni[etcd]==3.2.0
Kiểm tra installation
patroni --version
Output: patroni 3.2.0
patronictl --version
Output: patronictl 3.2.0
Giải thích [etcd]:
- Patroni hỗ trợ nhiều DCS backends (etcd, consul, zookeeper)
[etcd]install thêmpython-etcdclient library- Có thể cài nhiều backends:
patroni[etcd,consul,zookeeper]
3.2. Các packages được cài đặt
# Liệt kê các packages liên quan pip3 list | grep -E "(patroni|etcd|psycopg)"Output:
patroni 3.2.0
python-etcd 0.4.5
psycopg2 2.9.x
psycopg2-binary 2.9.x
3.3. Verify Patroni commands
# Check patroni binary which patroniOutput: /usr/local/bin/patroni
Check patronictl binary
which patronictl
Output: /usr/local/bin/patronictl
List patronictl commands
patronictl --help
Output:
Usage: patronictl [OPTIONS] COMMAND [ARGS]...
Commands: list Show cluster members switchover Perform planned switchover failover Perform manual failover reinit Reinitialize cluster member restart Restart cluster member reload Reload cluster member configuration pause Disable auto-failover resume Enable auto-failover edit-config Edit cluster configuration ...
4. Cấu trúc file patroni.yml
4.1. Tổng quan về patroni.yml
File patroni.yml là file cấu hình chính của Patroni, bao gồm:
- Scope: Tên cluster
- Namespace: Prefix cho keys trong DCS
- Node information: Tên node, REST API config
- DCS connection: etcd endpoints
- Bootstrap: Initial cluster setup
- PostgreSQL: Database configuration
- Tags: Node metadata
- Watchdog: Optional hardware watchdog
4.2. Cấu trúc cơ bản
scope: postgres namespace: /service/ name: node1restapi: listen: 0.0.0.0:8008 connect_address: 10.0.1.11:8008
etcd: hosts: 10.0.1.11:2379,10.0.1.12:2379,10.0.1.13:2379
bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true parameters: wal_level: replica hot_standby: "on" max_wal_senders: 10 max_replication_slots: 10
initdb: - encoding: UTF8 - data-checksums
pg_hba: - host replication replicator 10.0.1.0/24 scram-sha-256 - host all all 0.0.0.0/0 scram-sha-256
postgresql: listen: 0.0.0.0:5432 connect_address: 10.0.1.11:5432 data_dir: /var/lib/postgresql/18/data bin_dir: /usr/lib/postgresql/18/bin authentication: replication: username: replicator password: replicator_password superuser: username: postgres password: postgres_password
tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
4.3. Giải thích các sections chính
Section: Global
scope: postgres # Cluster name (unique identifier)
namespace: /service/ # DCS key prefix
name: node1 # Unique node name trong cluster
Section: REST API
restapi: listen: 0.0.0.0:8008 # Listen trên tất cả interfaces connect_address: 10.0.1.11:8008 # Address để nodes khác connectauthentication: # Optional: Basic auth
username: admin
password: secret
REST API endpoints:
GET /: Cluster infoGET /health: Health check (200 = healthy)GET /primary: Check if node is primaryGET /replica: Check if node is replicaPOST /restart: Restart PostgreSQLPOST /reload: Reload configuration
Section: etcd (DCS)
etcd: hosts: 10.0.1.11:2379,10.0.1.12:2379,10.0.1.13:2379 # etcd endpointsprotocol: http # http hoặc https
username: user # Optional: etcd authentication
password: pass
Section: Bootstrap
bootstrap: dcs: ttl: 30 # Leader lock TTL (seconds) loop_wait: 10 # Check interval (seconds) retry_timeout: 10 # DCS operation timeout maximum_lag_on_failover: 1048576 # Max lag (bytes) để eligible for failover postgresql: use_pg_rewind: true # Enable pg_rewind for fast recovery parameters: # PostgreSQL parameters wal_level: replica hot_standby: "on" wal_keep_size: "1GB" max_wal_senders: 10 max_replication_slots: 10 wal_log_hints: "on" # Required for pg_rewindinitdb: # pg_initdb options - encoding: UTF8 - data-checksums # Enable page checksums - locale: en_US.UTF-8
pg_hba: # pg_hba.conf entries - host replication replicator 10.0.1.0/24 scram-sha-256 - host all all 0.0.0.0/0 scram-sha-256
users: # Create users during bootstrap admin: password: admin_password options: - createrole - createdb
Lưu ý: Bootstrap section chỉ áp dụng khi khởi tạo cluster lần đầu.
Section: PostgreSQL
postgresql: listen: 0.0.0.0:5432 # PostgreSQL listen address connect_address: 10.0.1.11:5432 # Address để connect từ bên ngoài data_dir: /var/lib/postgresql/18/data # Data directory bin_dir: /usr/lib/postgresql/18/bin # PostgreSQL binaries pgpass: /tmp/pgpass # Optional: pgpass fileauthentication: replication: username: replicator password: replicator_password superuser: username: postgres password: postgres_password rewind: # Optional: dedicated user for pg_rewind username: rewind_user password: rewind_password
parameters: # PostgreSQL runtime parameters max_connections: 100 shared_buffers: 2GB effective_cache_size: 6GB maintenance_work_mem: 512MB checkpoint_completion_target: 0.9 wal_buffers: 16MB default_statistics_target: 100 random_page_cost: 1.1 effective_io_concurrency: 200 work_mem: 16MB min_wal_size: 1GB max_wal_size: 2GB
pg_hba: # Additional pg_hba.conf entries - host all all 10.0.2.0/24 scram-sha-256
callbacks: # Optional: callback scripts on_start: /etc/patroni/scripts/on_start.sh on_stop: /etc/patroni/scripts/on_stop.sh on_role_change: /etc/patroni/scripts/on_role_change.sh
Section: Tags
tags: nofailover: false # false = có thể become primary noloadbalance: false # false = có thể nhận read traffic clonefrom: false # false = có thể clone từ node này nosync: false # false = có thể become synchronous standbyCustom tags
datacenter: dc1 environment: production
Section: Watchdog (Optional)
watchdog:
mode: required # required, automatic, hoặc off
device: /dev/watchdog # Hardware watchdog device
safety_margin: 5 # Seconds before watchdog triggers
5. Tạo Patroni configuration files
5.1. Tạo thư mục cấu hình
Trên TẤT CẢ 3 nodes:
# Tạo directory cho Patroni config sudo mkdir -p /etc/patroniTạo directory cho callback scripts (optional)
sudo mkdir -p /etc/patroni/scripts
Set ownership
sudo chown -R postgres:postgres /etc/patroni
5.2. Node 1 - /etc/patroni/patroni.yml
scope: postgres namespace: /service/ name: node1restapi: listen: 0.0.0.0:8008 connect_address: 10.0.1.11:8008
etcd: hosts: 10.0.1.11:2379,10.0.1.12:2379,10.0.1.13:2379
bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true parameters: wal_level: replica hot_standby: "on" wal_keep_size: "1GB" max_wal_senders: 10 max_replication_slots: 10 wal_log_hints: "on"
initdb: - encoding: UTF8 - data-checksums
pg_hba: - host replication replicator 10.0.1.11/32 scram-sha-256 - host replication replicator 10.0.1.12/32 scram-sha-256 - host replication replicator 10.0.1.13/32 scram-sha-256 - host all all 10.0.1.0/24 scram-sha-256 - host all all 0.0.0.0/0 md5
users: admin: password: admin123 options: - createrole - createdb
postgresql: listen: 0.0.0.0:5432 connect_address: 10.0.1.11:5432 data_dir: /var/lib/postgresql/18/data bin_dir: /usr/lib/postgresql/18/bin authentication: replication: username: replicator password: replicator_password superuser: username: postgres password: postgres_password parameters: max_connections: 100 shared_buffers: 2GB effective_cache_size: 6GB maintenance_work_mem: 512MB checkpoint_completion_target: 0.9
tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
5.3. Node 2 - /etc/patroni/patroni.yml
scope: postgres namespace: /service/ name: node2restapi: listen: 0.0.0.0:8008 connect_address: 10.0.1.12:8008
etcd: hosts: 10.0.1.11:2379,10.0.1.12:2379,10.0.1.13:2379
bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true parameters: wal_level: replica hot_standby: "on" wal_keep_size: "1GB" max_wal_senders: 10 max_replication_slots: 10 wal_log_hints: "on"
initdb: - encoding: UTF8 - data-checksums
pg_hba: - host replication replicator 10.0.1.11/32 scram-sha-256 - host replication replicator 10.0.1.12/32 scram-sha-256 - host replication replicator 10.0.1.13/32 scram-sha-256 - host all all 10.0.1.0/24 scram-sha-256 - host all all 0.0.0.0/0 md5
users: admin: password: admin123 options: - createrole - createdb
postgresql: listen: 0.0.0.0:5432 connect_address: 10.0.1.12:5432 data_dir: /var/lib/postgresql/18/data bin_dir: /usr/lib/postgresql/18/bin authentication: replication: username: replicator password: replicator_password superuser: username: postgres password: postgres_password parameters: max_connections: 100 shared_buffers: 2GB effective_cache_size: 6GB maintenance_work_mem: 512MB checkpoint_completion_target: 0.9
tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
5.4. Node 3 - /etc/patroni/patroni.yml
scope: postgres namespace: /service/ name: node3restapi: listen: 0.0.0.0:8008 connect_address: 10.0.1.13:8008
etcd: hosts: 10.0.1.11:2379,10.0.1.12:2379,10.0.1.13:2379
bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true parameters: wal_level: replica hot_standby: "on" wal_keep_size: "1GB" max_wal_senders: 10 max_replication_slots: 10 wal_log_hints: "on"
initdb: - encoding: UTF8 - data-checksums
pg_hba: - host replication replicator 10.0.1.11/32 scram-sha-256 - host replication replicator 10.0.1.12/32 scram-sha-256 - host replication replicator 10.0.1.13/32 scram-sha-256 - host all all 10.0.1.0/24 scram-sha-256 - host all all 0.0.0.0/0 md5
users: admin: password: admin123 options: - createrole - createdb
postgresql: listen: 0.0.0.0:5432 connect_address: 10.0.1.13:5432 data_dir: /var/lib/postgresql/18/data bin_dir: /usr/lib/postgresql/18/bin authentication: replication: username: replicator password: replicator_password superuser: username: postgres password: postgres_password parameters: max_connections: 100 shared_buffers: 2GB effective_cache_size: 6GB maintenance_work_mem: 512MB checkpoint_completion_target: 0.9
tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
5.5. Set permissions
Trên TẤT CẢ 3 nodes:
# Set ownership sudo chown postgres:postgres /etc/patroni/patroni.ymlSecure permissions (file chứa passwords)
sudo chmod 600 /etc/patroni/patroni.yml
Verify
ls -l /etc/patroni/patroni.yml
Output: -rw------- 1 postgres postgres ... patroni.yml
6. Tạo systemd service cho Patroni
6.1. Tạo systemd unit file
Tạo file /etc/systemd/system/patroni.service trên TẤT CẢ 3 nodes:
[Unit] Description=Patroni PostgreSQL HA manager Documentation=https://patroni.readthedocs.io/ After=syslog.target network.target etcd.service[Service] Type=simple User=postgres Group=postgres
Start Patroni
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml
Reload configuration
ExecReload=/bin/kill -HUP $MAINPID
Restart behavior
Restart=on-failure RestartSec=5
Limits
LimitNOFILE=65536 LimitNPROC=65536
Logging
StandardOutput=journal StandardError=journal
Working directory
WorkingDirectory=/var/lib/postgresql
Environment
Environment=PATH=/usr/lib/postgresql/18/bin:/usr/local/bin:/usr/bin:/bin
[Install] WantedBy=multi-user.target
6.2. Giải thích systemd unit file
| Directive | Giải thích |
|---|---|
After=etcd.service | Khởi động sau khi etcd đã sẵn sàng |
Type=simple | Process chạy foreground |
User=postgres | Chạy với user postgres |
ExecStart | Command để start Patroni |
ExecReload | Send HUP signal để reload config |
Restart=on-failure | Auto restart nếu fail |
RestartSec=5 | Đợi 5 giây trước khi restart |
LimitNOFILE=65536 | Max open files |
StandardOutput=journal | Log vào systemd journal |
6.3. Enable và verify service
Trên TẤT CẢ 3 nodes:
# Reload systemd sudo systemctl daemon-reloadEnable Patroni service (auto-start on boot)
sudo systemctl enable patroni
Verify service file
systemctl cat patroni
Check status (should be inactive/dead - not started yet)
systemctl status patroni
7. Verify installation
7.1. Check Patroni installation
Trên TẤT CẢ 3 nodes:
# Check Patroni version patroni --versionCheck patronictl
patronictl --help
Verify config file
sudo -u postgres cat /etc/patroni/patroni.yml
Validate YAML syntax
python3 -c "import yaml; yaml.safe_load(open('/etc/patroni/patroni.yml'))"
No output = valid YAML
7.2. Check etcd connectivity
# Test etcd từ mỗi node etcdctl endpoint health --clusterShould see all 3 etcd nodes healthy
7.3. Pre-flight checklist
Trước khi khởi động Patroni, verify:
# ✅ PostgreSQL installed nhưng NOT running systemctl status postgresqlShould be: inactive (dead)
✅ etcd cluster healthy
etcdctl endpoint health --cluster
✅ Patroni config file exists và có permissions đúng
ls -l /etc/patroni/patroni.yml
✅ Data directory có ownership đúng
ls -ld /var/lib/postgresql/18/data
Owner: postgres:postgres
✅ systemd service enabled
systemctl is-enabled patroni
Output: enabled
✅ Firewall rules (nếu có firewall)
sudo ufw status | grep -E "(5432|8008)"
Hoặc
sudo firewall-cmd --list-ports | grep -E "(5432|8008)"
8. Troubleshooting
8.1. Issue: pip install fails
# Error: "No module named 'setuptools'"Solution:
sudo apt install python3-setuptools
Or upgrade pip
sudo pip3 install --upgrade pip setuptools
8.2. Issue: Cannot find PostgreSQL binaries
# Error: "could not find postgres binary"Solution: Check bin_dir in patroni.yml
Find PostgreSQL bin directory
which postgres
Output: /usr/lib/postgresql/18/bin/postgres
Update patroni.yml
postgresql: bin_dir: /usr/lib/postgresql/18/bin
8.3. Issue: Permission denied on data directory
# Error: "FATAL: data directory ... has wrong ownership"Solution:
sudo chown -R postgres:postgres /var/lib/postgresql/18/data sudo chmod 700 /var/lib/postgresql/18/data
8.4. Issue: YAML syntax error
# 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
- Duplicate keys
9. Tổng kết
Key Takeaways
✅ Patroni: Python application, cài qua pip
✅ Dependencies: Python 3, pip, psycopg2, python-etcd
✅ Configuration: patroni.yml chứa tất cả settings
✅ systemd service: Quản lý Patroni daemon
✅ Security: File config có permissions 600 (chứa passwords)
Checklist sau Lab
- Python 3 và pip đã cài trên cả 3 nodes
- Patroni 3.2.0+ đã cài trên cả 3 nodes
- File
/etc/patroni/patroni.ymlđã tạo trên mỗi node với config riêng - systemd service
patroni.serviceđã tạo và enabled - Permissions đúng cho config file (600, owner postgres)
- etcd cluster đang running và healthy
Kiến trúc hiện tại
✅ 3 VMs prepared (Bài 4) ✅ PostgreSQL 18 installed (Bài 5) ✅ etcd cluster running (Bài 6) ✅ Patroni installed and configured (Bài 7)
Next: Bootstrap cluster lần đầu
Chuẩn bị cho Bài 8
Bài 8 sẽ đi sâu vào cấu hình Patroni chi tiết:
- Phân tích từng section trong
patroni.yml - Bootstrap configuration options
- PostgreSQL parameters tuning
- Authentication setup
- Tags và constraints
Bài 9: Bootstrap cluster
Sau khi Patroni đã cài và cấu hình xong, Bài 9 sẽ hướng dẫn:
- Khởi động Patroni lần đầu
- Quá trình bootstrap tự động
- Kiểm tra cluster status
- Troubleshootin