Panduan ini memberikan panduan komprehensif untuk men-deploy stack PostgreSQL yang sangat tersedia di tiga zona dalam lingkungan terisolasi Google Distributed Cloud (GDC). Anda akan mempelajari cara menyiapkan artefak software yang diperlukan, mem-bootstrap VM target, dan menggunakan Autobase untuk mengotomatiskan seluruh proses penyediaan. Di seluruh panduan ini, Patroni digunakan sebagai lapisan pengelolaan utama untuk mengatur siklus proses PostgreSQL dan menangani failover otomatis.
Arsitektur
Arsitektur ini terdiri dari lingkungan tiga VM yang didistribusikan di tiga zona ketersediaan.

Setiap VM identik dan menjalankan stack layanan yang ditempatkan bersama:
- PostgreSQL 17: Mesin database relasional inti.
- Patroni: Pengelola Ketersediaan Tinggi. Pengelola ini menangani siklus proses proses PostgreSQL dan melakukan failover otomatis. Pengelola ini mengekspos HTTPS REST API di port
8008(endpoint/primary) yang digunakan oleh load balancer untuk mengidentifikasi pemimpin saat ini. - etcd: Penyimpanan Konfigurasi Terdistribusi (DCS). Penyimpanan ini menyediakan lapisan konsensus untuk pemilihan pemimpin dan menyimpan konfigurasi Patroni.
- PgBouncer: Pooler koneksi yang berada di depan PostgreSQL untuk menstabilkan overhead koneksi. Pooler ini menyediakan titik entri yang direkomendasikan untuk traffic aplikasi di port
6432.
Stack ini juga mencakup Load Balancer L4 Global GDC dengan air gap, yang merupakan layanan terkelola platform yang menyediakan IP Virtual (VIP) yang stabil. Aplikasi terhubung ke VIP stabil di port 6432, yang dirutekan oleh load balancer ke PgBouncer di VM pemimpin saat ini. PgBouncer kemudian memproxy permintaan ke instance PostgreSQL lokal. Untuk mengelola alur traffic, load balancer terus melakukan polling endpoint HTTPS Patroni sebagai health check.
Health check di VM pemimpin menampilkan HTTP 200 OK untuk memberi sinyal bahwa VM siap untuk traffic, sedangkan health check di VM replika menampilkan HTTP 503 Service Unavailable untuk memberi sinyal kepada load balancer agar melewatinya. Jika pemimpin gagal, pemimpin baru akan dipilih dan instance Patroni-nya mulai menampilkan HTTP 200 OK, sehingga load balancer otomatis mengalihkan traffic ke port PgBouncer VM baru.
Untuk memastikan ketersediaan tinggi dan mencegah kehilangan data, stack mengandalkan konsep kuorum. Dengan 3 VM, sistem memerlukan mayoritas minimal dua anggota yang responsif dan berkomunikasi untuk memilih pemimpin dan tetap beroperasi. Konsensus berbasis mayoritas ini, yang dikelola oleh etcd dan Patroni, memungkinkan stack secara otomatis mentoleransi kegagalan total dari satu VM atau zona.
Pertimbangan performa
Saat merencanakan deployment, pertimbangkan faktor konkret berikut untuk mengoptimalkan performa dan keandalan:
- Ukuran Hardware: Meskipun persyaratan bervariasi menurut workload, gunakan profil standar ini sebagai titik awal untuk setiap VM:
- Pengembangan/Proof-of-Concept: 2 vCPU, RAM 8 GB (Minimum untuk operasi yang stabil).
- Produksi Kecil: 4 vCPU, RAM 16 GB. Cocok untuk alat internal dengan konkurensi sedang.
- Produksi Standar: 8 vCPU, RAM 32 GB. Baseline yang direkomendasikan untuk aplikasi penting.
- Throughput Tinggi: 16+ vCPU, RAM 64 GB+. Untuk workload yang memerlukan caching data yang luas dalam memori (buffer bersama PostgreSQL).
- Performa Penyimpanan: Penyimpanan berperforma tinggi sangat penting. Disk SSD sangat direkomendasikan untuk stabilitas etcd. etcd sangat sensitif terhadap latensi penulisan disk; panduan hardware etcd resmi merekomendasikan latensi fdatasync WAL disk p99 < 10 md.
- Latensi Jaringan: Latensi antara VM secara langsung memengaruhi performa replikasi:
- Kuorum etcd: Waktu round-trip (RTT) rata-rata harus < 50 md (ideal < 10 md) untuk mencegah waktu tunggu pemilihan dan ketidakstabilan cluster.
- Replikasi Sinkron: Jika dikonfigurasi, setiap transaksi tulis harus menunggu konfirmasi replika. Latensi antar-zona di GDC dengan air gap biasanya < 1 md, yang sangat baik untuk menjaga overhead tulis tetap minimal (biasanya 10-30%).
- Peran PgBouncer: PostgreSQL membuat proses OS baru untuk setiap koneksi, yang menggunakan ~10 MB RAM dan menimbulkan biaya pengalihan konteks CPU. PgBouncer mengurangi overhead ini dengan mempertahankan kumpulan koneksi persisten, sehingga database dapat menangani ribuan koneksi aplikasi dengan proses backend yang jauh lebih sedikit.
- Komponen Sidecar: Patroni dan etcd ringan, tetapi memerlukan ketersediaan CPU yang konsisten. Dalam skenario beban tinggi, pastikan VM tidak terlalu banyak berlangganan di tingkat hypervisor untuk menghindari "pencurian" siklus CPU yang diperlukan untuk heartbeat dan pemeliharaan pemimpin.
- Penyesuaian Kernel: Otomatisasi Autobase secara otomatis menerapkan pengoptimalan
yang bermanfaat untuk PostgreSQL, seperti mengonfigurasi
sysctl
parameter (misalnya,
vm.swappiness,net.core.somaxconn) dan menonaktifkan Transparent Huge Pages (THP). Perubahan ini mengurangi overhead pengelolaan memori dan meningkatkan throughput jaringan untuk instance database dengan traffic tinggi.
Sebelum memulai
Sebelum memulai deployment, Anda harus memastikan bahwa lingkungan Anda memenuhi persyaratan berikut.
Meninjau persyaratan VM
Untuk tujuan tutorial ini, Anda harus membuat tiga VM di project GDC dengan air gap. Anda harus mempertimbangkan poin dan persyaratan berikut untuk VM:
- Distribusi zona: Agar deployment ini benar-benar tahan terhadap kegagalan zona, Anda harus mendistribusikan VM di tiga zona ketersediaan yang berbeda. Namun, deployment tetap identik jika VM berada di dua zona atau bahkan satu zona. Yang paling penting adalah semua VM dapat berkomunikasi satu sama lain melalui jaringan dengan alamat IP internalnya.
- Sistem Operasi: Tutorial ini mengasumsikan Anda menggunakan image Ubuntu 22.04. Langkah-langkah lebih lanjut dalam panduan ini mungkin berbeda jika Anda menggunakan distribusi yang berbeda.
- Resource: Anda harus menyediakan minimal 2 CPU dan memori 8 GB per VM untuk tutorial ini. Dalam produksi, Anda harus menyediakan resource yang sesuai untuk workload tertentu (Lihat Pertimbangan performa).
- IP Jaringan: Anda harus mencatat alamat IP internal dan eksternal untuk setiap VM. Dalam panduan ini, Anda menggunakan IP eksternal untuk kontrol Ansible karena Anda menjalankan perintah dari workstation eksternal. IP internal digunakan untuk komunikasi dan binding antarlayanan. Jika Anda menyediakan VM bootstrapper di dalam jaringan, Anda hanya memerlukan IP internal.
- Akses: Akses sudo tanpa sandi untuk pengguna deployment diperlukan karena otomatisasi Ansible perlu melakukan tugas administratif (menginstal paket, mengubah konfigurasi sistem) tanpa diblokir oleh perintah sandi.
- SSH: Autentikasi berbasis kunci harus diaktifkan agar Ansible dapat terhubung ke VM target dengan aman dan non-interaktif.
Menyiapkan software workstation lokal
Untuk mengelola deployment dan menyiapkan artefak terisolasi, Anda memerlukan serangkaian alat otomatisasi dan containerization yang diinstal di workstation lokal.
- Ansible 2.17.0+: Mesin otomatisasi yang menjalankan playbook dan peran deployment.
- Docker: Digunakan untuk menarik dan mengemas dependensi OS dalam lingkungan yang identik dengan VM target (Ubuntu 22.04).
- Klien PostgreSQL (
psql): Diperlukan untuk menjalankan kueri pengujian dan memverifikasi replikasi data dari workstation lokal. Repositori Autobase:
- Clone repositori untuk mengakses playbook dan peran otomatisasi: https://github.com/vitabaks/autobase
Checkout rilis tertentu (panduan ini menggunakan versi 2.5.2):
git checkout 2.5.2Langkah-langkah lebih lanjut dalam panduan ini mungkin berbeda jika Anda menggunakan distribusi yang berbeda.
Untuk menjalankan playbook dalam panduan ini, Anda harus menginstal kode sumber
autobaselokal sebagai koleksi Ansible sehingga awalan peran dapat diselesaikan:cd autobase/automation ansible-galaxy collection install . --force
Membuat beberapa variabel lingkungan
Di seluruh panduan ini, Anda akan menggunakan variabel lingkungan berikut untuk menyederhanakan perintah. Variabel ini menyimpan parameter penting seperti project ID, zona ketersediaan untuk VM, nama host, dan label yang digunakan oleh load balancer untuk mengidentifikasi cluster Anda. Tetapkan variabel ini di sesi shell saat ini dengan nilai sebenarnya untuk lingkungan Anda (Pastikan zona dipisahkan dengan spasi).
Perhatikan bahwa meskipun Anda dapat menetapkan nama apa pun yang Anda inginkan untuk VM, panduan ini menggunakan postgres-vm-1, postgres-vm-2, dan postgres-vm-3 sebagai nama contoh arbitrer untuk node cluster:
export PROJECT_ID="your-project-id"
export ZONES="zone1 zone2 zone3"
export VM1_NAME="postgres-vm-1"
export VM2_NAME="postgres-vm-2"
export VM3_NAME="postgres-vm-3"
export VM_LABEL="app=my-postgres-cluster"
export CLUSTER_NAME="my-postgres-cluster"
Mengonfigurasi Ansible
Tentukan lingkungan VM Anda dalam file inventory.ini menggunakan template berikut:
[master]
postgres-vm-1 ansible_host=XX.XX.XX.XX hostname=postgres-vm-1 bind_address=XX.XX.XX.XX
[replica]
postgres-vm-2 ansible_host=XX.XX.XX.XX hostname=postgres-vm-2 bind_address=XX.XX.XX.XX
postgres-vm-3 ansible_host=XX.XX.XX.XX hostname=postgres-vm-3 bind_address=XX.XX.XX.XX
[postgres_cluster:children]
master
replica
[etcd_cluster]
postgres-vm-1
postgres-vm-2
postgres-vm-3
[all:vars]
ansible_user=...
ansible_ssh_private_key_file=~/.ssh/...
postgresql_version=17
with_haproxy_load_balancing=false
patroni_superuser_password=...
etcd_package_repo="file:///tmp/packages/etcd-v3.5.25-linux-amd64.tar.gz"
installation_method="packages"
install_postgresql_repo=false
install_timescale_repo=false
install_citus_repo=false
apt_repository=[]
yum_repository=[]
install_system_packages=false
patroni_installation_method=deb
Memahami konfigurasi:
[master]dan[replica]: Menentukan VM database utama dan sekunder. Pastikan Anda menggunakan nama VM sebenarnya yang ditetapkan dalam variabel lingkunganVM1_NAME,VM2_NAME, danVM3_NAME.[postgres_cluster:children]: Grup yang menggabungkan node master dan replika, sehingga Ansible dapat menargetkan seluruh cluster database dengan satu perintah.[etcd_cluster]: Menentukan node yang akan berpartisipasi dalam cluster konsensus etcd. Ini mencakup ketiga node database untuk memastikan ketersediaan tinggi.ansible_host: (Untuk setiap VM) IP masuk eksternal VM yang digunakan oleh Ansible untuk terhubung ke VM tersebut. GantiXX.XX.XX.XXdengan IP eksternal sebenarnya.bind_address: (Untuk setiap VM) Alamat IP internal VM. GantiXX.XX.XX.XXdengan IP internal sebenarnya.ansible_user: Pengguna jarak jauh yang digunakan Ansible untuk terhubung ke VM target dengan SSH. Ganti...dengan nama pengguna sebenarnya.ansible_ssh_private_key_file: Jalur lokal ke kunci SSH pribadi yang digunakan untuk autentikasi ke VM target. Ganti~/.ssh/...dengan jalur sebenarnya.patroni_superuser_password: Sandi untuk penggunapostgres. Pastikan Anda menggunakan sandi yang kuat dan aman di sini.with_haproxy_load_balancing=false: Menonaktifkan HAProxy lokal karena Anda menggunakan load balancer L4 native platform.etcd_package_repo: Menunjuk ke jalur lokal biner etcd di dalam direktori bootstrap VM.installation_method="packages": Menginstruksikan otomatisasi untuk menginstal komponen dengan paket OS, bukan mengompilasi dari sumber atau menggunakan pip Python.install_..._repo=falsedan_repository=[]: Penggantian ini mencegah Ansible mencoba menjangkau internet untuk menambahkan repositori eksternal atau memperbarui daftar paket.install_system_packages=false: Mencegah otomatisasi mencoba mendownload dan menginstal paket yang telah Anda sediakan selama fase inisialisasi atau bootstrap.patroni_installation_method=deb: Secara khusus memberi tahu peran untuk menggunakan paket.debyang Anda instal.
Menginisialisasi VM
Stack database memerlukan beberapa paket dan library OS yang mungkin tidak disertakan dalam image Ubuntu dasar Anda. Karena VM berada di lingkungan terisolasi tanpa akses internet, VM tidak dapat mendownload dependensi ini sendiri.
Untuk mengatasi masalah ini, ikuti langkah-langkah berikut:
Gunakan container Docker di workstation lokal untuk mendownload semua file yang diperlukan. Perintah berikut menggunakan
apt-rdependsuntuk mengidentifikasi secara rekursif setiap library bersama dan dependensi yang diperlukan oleh aplikasi target. Perintah ini mengonfigurasi repositori PostgreSQL resmi dalam container untuk mengambil artefak versi 17, lalu melakukan iterasi melalui daftar dependensi untuk mendownload file.debindividual sambil memfilter library sistem inti (sepertilibc6atauhostname) untuk menghindari konflik versi pada VM target. Terakhir, perintah ini mengambil biner etcd mandiri langsung dari GitHub.Pertama, buat direktori untuk menyimpan paket:
mkdir -p ./packagesKemudian, jalankan perintah Docker untuk mendownload semua paket yang diperlukan dan biner etcd:
docker run --rm --platform linux/amd64 -v "$(pwd)/packages:/packages" \ ubuntu:22.04 bash -c " set -e apt-get update apt-get install -y ca-certificates curl gnupg apt-rdepends # Add PostgreSQL Repository curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | \ gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg echo 'deb http://apt.postgresql.org/pub/repos/apt jammy-pgdg main' > \ /etc/apt/sources.list.d/pgdg.list apt-get update # Define Application Targets + Explicit dependencies needed for air-gap TARGETS='unzip tar pgbouncer patroni netdata postgresql-17 \ postgresql-client-17 postgresql-contrib-17 \ postgresql-server-dev-17 postgresql-17-dbgsym \ python3-psycopg2 python3-click python3-yaml python3-prettytable \ python3-urllib3 python3-tz python3-pip python3-setuptools \ python3-cryptography moreutils vim jq acl zstd libjq1 \ libpython3.10-stdlib libexpat1-dev zlib1g-dev libipc-run-perl \ libtime-duration-perl libjson-perl libpython3-dev \ libjs-sphinxdoc python3-wheel' # Resolve all recursive dependencies ALL_DEPS=\$(apt-cache depends --recurse --no-recommends --no-suggests \ --no-conflicts --no-breaks --no-replaces --no-enhances \$TARGETS | \ grep '^\w' | sort -u) cd /packages for pkg in \$ALL_DEPS; do if apt-cache show \"\$pkg\" > /dev/null 2>&1; then # Filter system core to avoid VM conflicts/breaks # We exclude core OS libraries (libc, systemd, etc.) because these # often cause version conflicts if the VM's patch level differs # from the online container. FILTER='base-files|debianutils|coreutils|findutils|diffutils|sed' FILTER+='|grep|gzip|hostname|ncurses|perl-base|libc6|binutils' FILTER+='|linux-libc|libc-bin|libc-dev-bin|systemd|dpkg|init' if [[ ! \"\$pkg\" =~ \$FILTER ]]; then apt-get download \"\$pkg\" || echo \"Failed \$pkg\" fi fi done # Download etcd binary if [ ! -f etcd-v3.5.25-linux-amd64.tar.gz ]; then curl -L https://github.com/etcd-io/etcd/releases/download/v3.5.25/\ etcd-v3.5.25-linux-amd64.tar.gz -o etcd-v3.5.25-linux-amd64.tar.gz fi "Gunakan Ansible untuk mengupload arsip ke ketiga VM target secara bersamaan:
ansible all -i inventory.ini -m copy -a "src=packages.tar.gz dest=/tmp/" -bHapus data paket yang ada di VM dan ekstrak file tar baru:
ansible all -i inventory.ini -m shell -a "rm -rf /tmp/packages && \ mkdir -p /tmp/packages && tar -xzf /tmp/packages.tar.gz -C /tmp/packages" -bLakukan penginstalan non-interaktif dari semua paket
.debyang didownload. Untuk menghindari masalah dengan pra-dependensi tertentu di lingkungan terisolasi, gunakan flag--force-dependsyang diikuti olehapt-get install -fyuntuk menyelesaikan pohon dependensi secara lokal:ansible all -i inventory.ini -m shell -a "DEBIAN_FRONTEND=noninteractive \ NEEDRESTART_MODE=a dpkg -i --force-depends /tmp/packages/*.deb" -b ansible all -i inventory.ini -m shell -a "DEBIAN_FRONTEND=noninteractive \ NEEDRESTART_MODE=a apt-get install -fy" -bSegera hentikan semua layanan untuk mencegahnya dimulai dengan status default yang tidak dikonfigurasi sebelum otomatisasi siap:
ansible all -i inventory.ini -m shell -a \ "systemctl stop patroni etcd pgbouncer postgresql || true" -bTerakhir, hapus cluster PostgreSQL default dan data etcd yang ada untuk memungkinkan inisialisasi yang bersih:
ansible all -i inventory.ini -m shell -a \ "pg_dropcluster 17 main --stop || true" -b ansible all -i inventory.ini -m shell -a \ "rm -rf /var/lib/postgresql/17/main/* /var/lib/etcd/default.etcd/*" -b
Menyediakan infrastruktur database
Dengan VM yang di-bootstrap dan inventaris yang dikonfigurasi, Anda kini dapat menggunakan playbook otomatisasi Autobase dengan Ansible untuk men-deploy stack PostgreSQL yang sangat tersedia.
Pertama, jalankan pemeriksaan pra-penerbangan untuk memastikan lingkungan siap:
ansible-playbook vitabaks.autobase.deploy_pgcluster -i inventory.ini \
--tags pre_checks
Jika pemeriksaan lulus, lanjutkan dengan deployment penuh:
ansible-playbook vitabaks.autobase.deploy_pgcluster -i inventory.ini
Output yang diharapkan: Playbook harus selesai dengan "PLAY RECAP" yang berhasil dan menampilkan semua VM target sebagai tercapai dan diperbarui:
PLAY RECAP ********************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=254 rescued=0 ignored=0
postgres-vm-1 : ok=160 changed=53 unreachable=0 failed=0 skipped=514 rescued=0 ignored=2
postgres-vm-2 : ok=116 changed=40 unreachable=0 failed=0 skipped=505 rescued=0 ignored=2
postgres-vm-3 : ok=116 changed=40 unreachable=0 failed=0 skipped=505 rescued=0 ignored=2
Memverifikasi deployment
Setelah deployment selesai, Anda harus melakukan beberapa pemeriksaan untuk memastikan semua komponen berfungsi dengan benar.
Memeriksa status HA
Periksa status pengelola ketersediaan tinggi untuk melihat peran yang ditetapkan ke setiap VM:
ansible master -i inventory.ini -m shell -a "patronictl list" -b
Contoh output:
+ Cluster: postgres-cluster (7607933704953386478) ---+----+-------------+-----+------------+-----+
| Member | Host | Role | State | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
| postgres-vm-1 | 10.253.1.254 | Leader | running | 1 | | | | |
| postgres-vm-2 | 10.253.1.253 | Replica | streaming | 1 | 0/6000000 | 0 | 0/6000000 | 0 |
| postgres-vm-3 | 10.253.1.252 | Replica | streaming | 1 | 0/6000000 | 0 | 0/6000000 | 0 |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
Memverifikasi endpoint health check
Uji apakah Patroni mengidentifikasi pemimpin dan replika dengan benar menggunakan REST API-nya.
Health check VM pemimpin harus menampilkan 200 OK, sedangkan health check VM replika harus menampilkan 503 Service Unavailable:
ansible ${VM1_NAME} -i inventory.ini -m shell -a \
"curl -ks -o /dev/null -w '%{http_code}' https://localhost:8008/primary" -b
ansible ${VM2_NAME} -i inventory.ini -m shell -a \
"curl -ks -o /dev/null -w '%{http_code}' https://localhost:8008/primary" -b
ansible ${VM3_NAME} -i inventory.ini -m shell -a \
"curl -ks -o /dev/null -w '%{http_code}' https://localhost:8008/primary" -b
Memverifikasi kesehatan VM individual
Periksa kesiapan semua instance PostgreSQL:
ansible postgres_cluster -i inventory.ini -m shell -a "pg_isready -p 5432" -b
Contoh output:
postgres-vm-1 | CHANGED | rc=0 >>
/var/run/postgresql:5432 - accepting connections
postgres-vm-2 | CHANGED | rc=0 >>
/var/run/postgresql:5432 - accepting connections
postgres-vm-3 | CHANGED | rc=0 >>
/var/run/postgresql:5432 - accepting connections
Memverifikasi kesehatan etcd
Verifikasi kesehatan lapisan konsensus di semua VM menggunakan localhost sebagai endpoint:
ansible all -i inventory.ini -m shell -a "ETCDCTL_API=3 etcdctl \
--endpoints=https://localhost:2379 \
--cacert=/etc/etcd/tls/ca.crt \
--cert=/etc/etcd/tls/server.crt \
--key=/etc/etcd/tls/server.key \
endpoint health" -b
Contoh output:
postgres-vm-1 | CHANGED | rc=0 >>
https://localhost:2379 is healthy: successfully committed proposal: \
took = 28.78311ms
postgres-vm-2 | CHANGED | rc=0 >>
https://localhost:2379 is healthy: successfully committed proposal: \
took = 33.081265ms
postgres-vm-3 | CHANGED | rc=0 >>
https://localhost:2379 is healthy: successfully committed proposal: \
took = 24.414291ms
Mengonfigurasi load balancer global
Untuk menyediakan IP virtual (VIP) yang stabil untuk stack database, konfigurasikan Load Balancer L4 Global native platform menggunakan gdcloud CLI.
Prasyarat:
- Pastikan Anda memiliki peran
load-balancer-admindi project Anda. Terapkan label ke VM Anda sehingga load balancer dapat menargetkan instance yang perlu ditayangkan dengan benar (Ganti nilai parameter
kubeconfigdengan filekubeconfigAPI pengelolaan yang sesuai untuk setiap zona):kubectl --kubeconfig=ZONE_A_MANAGEMENT_API label VirtualMachine \ -n ${PROJECT_ID} \ ${VM1_NAME} \ ${VM_LABEL} kubectl --kubeconfig=ZONE_B_MANAGEMENT_API label VirtualMachine \ -n ${PROJECT_ID} \ ${VM2_NAME} \ ${VM_LABEL} kubectl --kubeconfig=ZONE_C_MANAGEMENT_API label VirtualMachine \ -n ${PROJECT_ID} \ ${VM3_NAME} \ ${VM_LABEL}
- Pastikan Anda memiliki peran
Tentukan tingkat akses load balancing. Tetapkan
EXTERNALjika Anda perlu terhubung dari luar jaringan project, atauINTERNALjika akses hanya diperlukan dari dalam VPC. Untuk tutorial ini, kita akan menggunakan penyiapan eksternal:export LB_SCHEME=EXTERNALBuat health check. Load balancer menggunakan REST API Patroni untuk mengidentifikasi pemimpin:
gdcloud compute health-checks create https ${CLUSTER_NAME}-hc \ --project=${PROJECT_ID} \ --port=8008 \ --request-path="/primary" \ --check-interval=10 \ --timeout=5 \ --healthy-threshold=2 \ --unhealthy-threshold=3 \ --globalBuat backend zonal terpisah untuk setiap zona tempat VM Anda berada:
for zone in $(echo $ZONES); do gdcloud compute backends create ${CLUSTER_NAME}-backend-${zone} \ --project=${PROJECT_ID} \ --zone=${zone} \ --labels="${VM_LABEL}" doneBuat layanan backend global:
gdcloud compute backend-services create ${CLUSTER_NAME}-bes \ --project=${PROJECT_ID} \ --health-check="${CLUSTER_NAME}-hc" \ --globalTambahkan backend zonal ke layanan global:
for zone in $(echo $ZONES); do gdcloud compute backend-services add-backend ${CLUSTER_NAME}-bes \ --project=${PROJECT_ID} \ --backend=${CLUSTER_NAME}-backend-${zone} \ --backend-zone=${zone} \ --global doneBuat aturan penerusan global (VIP). Aturan ini mengekspos database di Port
6432:gdcloud compute forwarding-rules create ${CLUSTER_NAME}-fr \ --project=${PROJECT_ID} \ --load-balancing-scheme=${LB_SCHEME} \ --backend-service=${CLUSTER_NAME}-bes \ --ip-protocol-port="TCP:6432" \ --globalAmbil alamat VIP:
LB_IP=$(gdcloud compute forwarding-rules describe ${CLUSTER_NAME}-fr \ --project=${PROJECT_ID} \ --load-balancing-scheme=${LB_SCHEME} \ --global \ --format=json \ | jq -r '.metadata.annotations["networking.gke.io/forwardingRuleCIDR"]' \ | cut -d '/' -f 1) echo "The load balancer IP is: ${LB_IP}"Buat
ProjectNetworkPolicy(PNP) untuk mengizinkan traffic masuk ke port PgBouncer (Ganti nilai parameterkubeconfigdengan filekubeconfigAPI global lingkungan Anda yang sesuai).kubectl --kubeconfig=GLOBAL_API_KUBECONFIG apply -f - <<EOF apiVersion: networking.global.gdc.goog/v1 kind: ProjectNetworkPolicy metadata: name: allow-pgbouncer namespace: ${PROJECT_ID} spec: ingress: - ports: - port: 6432 protocol: TCP policyType: Ingress subject: subjectType: UserWorkload EOF
Memverifikasi replikasi data
Untuk mengonfirmasi bahwa stack ketersediaan tinggi berfungsi seperti yang diharapkan, Anda dapat membuat data sampel di pemimpin dan memverifikasi keberadaannya di replika.
Menyisipkan data sampel
Otomatisasi menghasilkan sandi acak untuk pengguna postgres selama deployment pertama jika tidak ada yang diberikan di inventory.ini. Anda dapat mengambilnya dari VM mana pun:
export PG_PASSWORD=$(ansible master -i inventory.ini -m shell -a \
"grep -A10 'authentication:' /etc/patroni/patroni.yml | \
grep -A3 'superuser' | grep 'password:' | awk '{ print \$2 }'" -b | \
tail -n 1)
echo $PG_PASSWORD
Hubungkan ke VIP load balancer di port PgBouncer (6432) dan buat tabel sampel:
PGPASSWORD="${PG_PASSWORD}" psql -h ${LB_IP} -p 6432 -U postgres -c "
CREATE TABLE employees (first_name TEXT, last_name TEXT);
INSERT INTO employees (first_name, last_name) VALUES ('John', 'Doe');
"
Output yang Diharapkan:
INSERT 0 1
Memverifikasi status replikasi
Jalankan kueri SELECT di semua VM untuk memastikan data telah direplikasi dari pemimpin ke semua replika:
ansible postgres_cluster -i inventory.ini -m shell -a "psql -U postgres -c \
'SELECT * FROM employees;'" -b
Contoh output:
postgres-vm-1 | CHANGED | rc=0 >>
first_name | last_name
------------+-----------
John | Doe
(1 row)
postgres-vm-2 | CHANGED | rc=0 >>
first_name | last_name
------------+-----------
John | Doe
(1 row)
postgres-vm-3 | CHANGED | rc=0 >>
first_name | last_name
------------+-----------
John | Doe
(1 row)
Menguji pengalihan manual
Pengalihan manual memungkinkan Anda memindahkan peran pemimpin ke VM kandidat tertentu dengan lancar. Hal ini biasanya dilakukan untuk pemeliharaan terencana, upgrade software, atau untuk menyeimbangkan penggunaan resource di seluruh zona.
Mengidentifikasi pemimpin saat ini
Verifikasi peran dan status VM saat ini:
ansible master -i inventory.ini -m shell -a "patronictl list" -b
Contoh output:
+ Cluster: postgres-cluster (7607933704953386478) ---+----+-------------+-----+------------+-----+
| Member | Host | Role | State | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
| postgres-vm-1 | 10.253.1.254 | Leader | running | 1 | | | | |
| postgres-vm-2 | 10.253.1.253 | Replica | streaming | 1 | 0/6000000 | 0 | 0/6000000 | 0 |
| postgres-vm-3 | 10.253.1.252 | Replica | streaming | 1 | 0/6000000 | 0 | 0/6000000 | 0 |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
Melakukan pengalihan
Picu pengalihan dari pemimpin saat ini ke VM lain (dalam hal ini masing-masing dari postgres-vm-1 ke postgres-vm-2). Perintah ini menggunakan --force untuk melewati perintah konfirmasi manual:
ansible master -i inventory.ini -m shell -a "patronictl switchover \
--leader ${VM1_NAME} --candidate ${VM2_NAME} --force" -b
Contoh output:
Successfully switched over to "postgres-vm-2"
+ Cluster: postgres-cluster (7607933704953386478) -+----+-------------+-----+------------+-----+
| Member | Host | Role | State | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------------+--------------+---------+---------+----+-------------+-----+------------+-----+
| postgres-vm-1 | 10.253.1.254 | Replica | stopped | | unknown | | unknown | |
| postgres-vm-2 | 10.253.1.253 | Leader | running | 1 | | | | |
| postgres-vm-3 | 10.253.1.252 | Replica | running | 1 | 0/70000A0 | 0 | 0/70000A0 | 0 |
+---------------+--------------+---------+---------+----+-------------+-----+------------+-----+
Memverifikasi pergeseran health check
Setelah pengalihan, verifikasi bahwa status health check telah beralih ke pemimpin baru:
ansible ${VM1_NAME} -i inventory.ini -m shell -a \
"curl -ks -o /dev/null -w '%{http_code}' https://localhost:8008/primary" -b
ansible ${VM2_NAME} -i inventory.ini -m shell -a \
"curl -ks -o /dev/null -w '%{http_code}' https://localhost:8008/primary" -b
Pemimpin lama (postgres-vm-1) harus menampilkan 503, sedangkan pemimpin baru (postgres-vm-2) harus menampilkan 200.
Menguji failover otomatis
Tidak seperti pengalihan manual, failover otomatis terjadi saat VM pemimpin tidak tersedia. Pengujian ini mengonfirmasi bahwa Patroni memilih pemimpin baru dan load balancer mengalihkan traffic tanpa intervensi manual. Asumsikan bahwa postgres-vm-2 adalah pemimpin saat ini setelah pengalihan manual yang dilakukan sebelumnya.
Mengidentifikasi pemimpin saat ini
Verifikasi peran dan status VM saat ini:
ansible master -i inventory.ini -m shell -a "patronictl list" -b
Contoh output:
+ Cluster: postgres-cluster (7607933704953386478) ---+----+-------------+-----+------------+-----+
| Member | Host | Role | State | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
| postgres-vm-1 | 10.253.1.254 | Replica | streaming | 2 | 0/8000000 | 0 | 0/8000000 | 0 |
| postgres-vm-2 | 10.253.1.253 | Leader | running | 2 | | | | |
| postgres-vm-3 | 10.253.1.252 | Replica | streaming | 2 | 0/8000000 | 0 | 0/8000000 | 0 |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
Menyimulasikan kegagalan VM
Hentikan layanan patroni di VM pemimpin untuk menyimulasikan error atau kegagalan yang parah:
ansible master -i inventory.ini -m shell -a "systemctl stop patroni" -b
Mengamati pemilihan baru
Tunggu 10-20 detik dan periksa status dari VM lain untuk melihat promosi pemimpin baru:
ansible replica -i inventory.ini -m shell -a "patronictl list" -b
Contoh output:
postgres-vm-3 | CHANGED | rc=0 >>
+ Cluster: postgres-cluster (7607933704953386478) ---+----+-------------+-----+------------+-----+
| Member | Host | Role | State | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
| postgres-vm-1 | 10.253.1.254 | Leader | running | 3 | | | | |
| postgres-vm-2 | 10.253.1.253 | Replica | stopped | | unknown | | unknown | |
| postgres-vm-3 | 10.253.1.252 | Replica | streaming | 3 | 0/90003F8 | 0 | 0/90003F8 | 0 |
+---------------+--------------+---------+-----------+----+-------------+-----+------------+-----+
Anda akan melihat bahwa salah satu VM lainnya (postgres-vm-1 atau postgres-vm-3) telah menjadi pemimpin dan pemimpin lama (postgres-vm-2) ditandai sebagai dihentikan.
Memverifikasi pergeseran health check
Konfirmasi bahwa health check load balancer kini akan mengidentifikasi pemimpin yang baru terpilih dengan benar:
ansible ${VM1_NAME} -i inventory.ini -m shell -a \
"curl -ks -o /dev/null -w '%{http_code}' https://localhost:8008/primary" -b
Pemimpin baru harus menampilkan 200 OK.
Memulihkan VM yang gagal
Mulai ulang layanan patroni di VM asli agar dapat bergabung kembali dengan stack sebagai replika dan mengejar data yang terlewat:
ansible ${VM2_NAME} -i inventory.ini -m shell -a \
"systemctl start patroni" -b