Tutorial Lengkap Patroni PostgreSQL
Masih ingat tutorial saya tentang Patroni dahulu? Saya akan membuat tulisan lengkap dari nol sampai berjalan. Di akhir tutorial ini Anda bisa membuat kluster Patroni secara manual. Kalau Anda devops dan tertarik menulis resep untuk Ansible, Puppet, dan sejenisnya, saya harap artikel ini bisa menjadi acuan untuk mengerti Patroni.
Mesin-mesin yang Ada
Saya membagi setiap mesin yang digunakan dengan dua IP. Satu subnet IP internal yang digunakan untuk setiap mesin dalam kluster berkomunikasi dan satu subnet IP yang digunakan untuk akses luar. Implementasi fisik dengan menggunakan dua kartu jaringan (atau dua bonding fisik) yang berbeda. Perbedaan jaringan untuk komunikasi internal dan komunikasi dengan klien ini selain menyediakan keamanan dalam isolasi, juga membuat koneksi internal atau pun eksternal tidak saling mengganggu.
Untuk mengurangi kompleksitas tutorial ini, saya hanya menyediakan satu mesin HAProxy dan satu mesin etcd. Fokus tulisan ini adalah untuk ketersediaan PostgreSQL. Untuk membuat ketersediaan HAProxy dan etcd akan dibahas lain kali bila ada waktu [baca: kalau tidak malas].
Agar tidak membingungkan, saya selalu mempraktikkan penamaan kluster ditambah dengan prefiks nama aplikasi. Hal ini penting karena di perawanan yang sudah semakin terotomatisasi, kadang kita suka bingung kalau konfigurasi sudah tidak ada lagi.
Yak, intinya ada 5 mesin untuk tutorial kali ini. Saya menggunakan GNU/Linux Debian 9 karena itu standar sistem operasi UI. Untuk sistem operasi lain saya rasa tidak ada yang berbeda karena kali ini saya tidak menggunakan paket repositori.
Untuk memudahkan, pastikan kelima mesin ini memiliki berkas /etc/hosts yang berisi kelima host.
$ sudo tee -a /etc/hosts << EOF 192.168.100.1 haproxy0-nyata 192.168.100.2 etcd0-nyata 192.168.100.3 pg1-nyata 192.168.100.4 pg2-nyata 192.168.100.5 pg3-nyata EOF
Selanjutnya, akan dibuatkan etcd terlebih dahulu sebagai inti yang mengatur kluster.
ETCD
Aplikasi etcd adalah sebuah basisdata konfigurasi yang digunakan status. Aplikasi etcd tidak ada di repositori Debian 9. Saya mengunduh versi terbaru dari CoreOS dan memasang manual.
wget https://github.com/coreos/etcd/releases/download/v3.3.1/etcd-v3.3.1-linux-amd64.tar.gz tar xvfz etcd-v3.3.1-linux-amd64.tar.gz sudo cp etcd-v3.3.1-linux-amd64/etcd /usr/local/bin
Konfigurasi
Aplikasi etcd berisi satu binari. Untuk konfigurasi, buat manual.
$ sudo /etc/etcd.conf.yml << EOF # This is the configuration file for the etcd server. # Human-readable name for this member. name: 'etcd0-nyata' # Path to the data directory. data-dir: /var/lib/etcd/data # Path to the dedicated wal directory. wal-dir: /var/lib/etcd/wal # Number of committed transactions to trigger a snapshot to disk. snapshot-count: 10000 # Time (in milliseconds) of a heartbeat interval. heartbeat-interval: 100 # Time (in milliseconds) for an election to timeout. election-timeout: 1000 # Raise alarms when backend size exceeds the given quota. 0 means use the # default quota. quota-backend-bytes: 0 # List of comma separated URLs to listen on for peer traffic. listen-peer-urls: http://192.168.100.2:2380 # List of comma separated URLs to listen on for client traffic. listen-client-urls: http://localhost:2379,http://192.168.100.2:2379 # Maximum number of snapshot files to retain (0 is unlimited). max-snapshots: 5 # Maximum number of wal files to retain (0 is unlimited). max-wals: 5 # Comma-separated white list of origins for CORS (cross-origin resource sharing). cors: # List of this member's peer URLs to advertise to the rest of the cluster. # The URLs needed to be a comma-separated list. initial-advertise-peer-urls: http://192.168.100.2:2380 # List of this member's client URLs to advertise to the public. # The URLs needed to be a comma-separated list. advertise-client-urls: http://192.168.100.2:2379 # Discovery URL used to bootstrap the cluster. discovery: # Valid values include 'exit', 'proxy' discovery-fallback: 'proxy' # HTTP proxy to use for traffic to discovery service. discovery-proxy: # DNS domain used to bootstrap initial cluster. discovery-srv: # Initial cluster configuration for bootstrapping. initial-cluster: etcd0-scele=http://192.168.100.2:2380, # Initial cluster token for the etcd cluster during bootstrap. initial-cluster-token: 'etcd-nyata-cluster' # Initial cluster state ('new' or 'existing'). initial-cluster-state: 'new' # Reject reconfiguration requests that would cause quorum loss. strict-reconfig-check: false # Valid values include 'on', 'readonly', 'off' proxy: 'off' # Time (in milliseconds) an endpoint will be held in a failed state. proxy-failure-wait: 5000 # Time (in milliseconds) of the endpoints refresh interval. proxy-refresh-interval: 30000 # Time (in milliseconds) for a dial to timeout. proxy-dial-timeout: 1000 # Time (in milliseconds) for a write to timeout. proxy-write-timeout: 5000 # Time (in milliseconds) for a read to timeout. proxy-read-timeout: 0 # Enable debug-level logging for etcd. debug: false # Specify a particular log level for each etcd package (eg: 'etcdmain=CRITICAL,etcdserver=DEBUG'. log-package-levels: # Force to create a new one member cluster. force-new-cluster: true EOF
Layanan
Agar dapat dijalankan secara sistem, perlu dibuatkan layanan systemd secara manual.
$ sudo tee -a /etc/systemd/system/etcd.service << EOF [Unit] Description=etcd key-value store Documentation=https://github.com/coreos/etcd After=network.target [Service] User=etcd Group=etcd Type=notify ExecStart=/bin/bash --login -c "/usr/local/bin/etcd --config-file /etc/etcd.conf.yml" Restart=always RestartSec=10s LimitNOFILE=40000 [Install] WantedBy=multi-user.target EOF
Pengaktifan Layanan etcd
Perhatikan bahwa untuk contoh kali ini saya menggunakan akun etcd dan grup etcd. Praktik aman selalu jalankan layanan sebagai pengguna biasa, bukan root. Buat pengguna baru ini.
sudo adduser --system --home /var/lib/etcd --group etcd
Bagian terakhir dari etcd adalah mengaktifkan dan menjalankan layanan etcd.
sudo systemctl daemon-reload sudo systemctl enable etcd sudo systemctl start etcd
Baris daemon-reload adalah agar systemd membaca konfigurasi yang baru saja dibuat. Baris enable untuk mendaftarkan etcd sebagai layanan yang dijalankan otomatis saat mesin baru mulai. Baris terakhir untuk menjalankan layanan etcd.
PostgreSQL
Berbeda dengan tutorial yang lalu, saya akan membuat konfigurasi per mesin agar lebih menggambarkan apa yang terjadi. Sebelum memulai, saya asumsikan bahwa setiap mesin PostgreSQL pengguna root memiliki kunci SSH sehingga antar mesin bisa masuk tanpa kunci.
Cara paling gampang, di salah satu mesin buat kunci.
ssh-keygen -t ecdsa
Lalu, taruh kunci publik dan privat ke root. Saya asumsikan bahwa kita bekerja di mesin pg1-nyata.
# asumsi kerja di mesin pg1-nyata sudo mkdir /root/.ssh/ sudo cp ~/.ssh/id_ecdsa /root/.ssh/ cat ~/.ssh/id_ecdsa.pub | sudo tee -a /root/.ssh/authorized_keys # Transfer scp ~/.ssh/id_ecdsa ~/.ssh/id_ecdsa.pub pg2-nyata:/tmp scp ~/.ssh/id_ecdsa ~/.ssh/id_ecdsa.pub pg3-nyata:/tmp # ke mesin pg2-nyata ssh pg2-nyata sudo mkdir /root/.ssh/ sudo cp ~/.ssh/id_ecdsa /root/.ssh/ cat ~/.ssh/id_ecdsa.pub | sudo tee -a /root/.ssh/authorized_keys rm /tmp/id_ecdsa* exit # ke mesin pg3-nyata ssh pg3-nyata sudo mkdir /root/.ssh/ sudo cp ~/.ssh/id_ecdsa /root/.ssh/ cat ~/.ssh/id_ecdsa.pub | sudo tee -a /root/.ssh/authorized_keys rm /tmp/id_ecdsa* exit
Ini saya pasang secara manual. Biasanya untuk Vagrant, Proxmox, dan sejenisnya sudah menyediakan opsi pemasangan kunci SSH di konfigurasi/plugin mereka. Namun, untuk kelengkapan tutorial ini saya tuliskan saja manual. Saya sendiri sebenarnya hanya memasang satu mesin; memasang PostgreSQL; dan baru diklon menjadi dua mesin lainnya.
Pemasangan PostgreSQL
Saya kali ini menggunakan PostgreSQL yang saya kompilasi sendiri. Mengapa? Karena hasil kompilasi lebih irit dan saya mau ada variasi tulisan. Di blog saya ada kok cara-caranya untuk memasang versi repo.
Pemasangan PostgreSQL setiap mesin sama. Untuk memasang paket ketergantungan di setiap mesin jalankan:
sudo apt -y install build-essential libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt-dev libssl-dev pkg-config libsystemd-dev
Unduh PostgreSQL. Saya memakai versi stabil terbaru, 10.2. Kebetulan juga, saya ada peladen cermin di samping ruangan:
wget http://kambing.ui.ac.id/postgresql/source/v10.2/postgresql-10.2.tar.bz2 tar xvfj postgresql-10.2.tar.bz2 cd postgresql-10.2 sed -i '/DEFAULT_PGSOCKET_DIR/s@/tmp@/run/postgresql@' src/include/pg_config_manual.h ./configure --prefix=/usr --with-icu --with-openssl --with-systemd --enable-thread-safety --docdir=/usr/share/doc/postgresql-10.2 CFLAGS="-O3 -march=native -mtune=native -pipe" make -j$(nproc) sudo make install
Saya melakukan optimasi CFLAGS untuk kompilasi. Hal ini karena saya tahu bahwa peladen di tempat saya itu homogen. Tapi, kalau misalnya Anda memasang di penyedia awan, sebaiknya CFLAGS jangan disertakan.
Selanjutnya pemasangan Patroni.
Patroni
Patroni merupakan skrip Python. Untuk memasang Patroni, pastikan Python PIP dipasang. Saya memilih Python3. Namun, biasanya yang digunakan Python2. Saya memakai Python3 karena saya keren.
sudo apt install python3-pip sudo pip3 install --upgrade setuptools
Pasang Patroni dan plugin etcd-nya.
sudo pip3 install psycopg2-binary sudo -E pip3 install patroni[etcd]
Buat pengguna postgres
sudo adduser --system --home /var/lib/postgresql --group postgres
Buatkan layanan sistem.
$ sudo tee /etc/systemd/system/patroni.service << EOF [Unit] Description=Runners to orchestrate a high-availability PostgreSQL After=syslog.target network.target [Service] Type=simple User=postgres Group=postgres Environment="PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games" ExecStart=/usr/local/bin/patroni /etc/patroni.yml KillMode=process TimeoutSec=30 Restart=no [Install] WantedBy=multi-user.target EOF
Selanjutnya, buat konfigurasi per mesin.
Konfigurasi Per Mesin
Buat konfigurasi per mesin /etc/patroni.yml
scope: postgres namespace: /pg-nyata/ name: pg1-nyata restapi: listen: 192.168.100.3:8008 connect_address: 192.168.100.3:8008 etcd: host: 192.168.100.2:2379 bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true initdb: - encoding: UTF8 - data-checksums pg_hba: - host replication replicator 127.0.0.1/32 md5 - host replication replicator 192.168.100.3/0 md5 - host replication replicator 192.168.100.4/0 md5 - host replication replicator 192.168.100.5/0 md5 - host all all 0.0.0.0/0 md5 users: admin: password: aiwaQuaeHuojeuyai2fiemai6Reeneix options: - createrole - createdb postgresql: listen: 192.168.100.3:5432 connect_address: 192.168.100.3:5432 data_dir: /var/lib/postgresql/10.2-patroni pgpass: /tmp/pgpass authentication: replication: username: replicator password: zee0ohjisai5ohCohsaegho5gaeN8Xei superuser: username: postgres password: saichae9Aich0xeen2Otethaduphiepo parameters: unix_socket_directories: '.' tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
Contoh konfigurasi yang tertulis untuk mesin pg1-nyata. Untuk pg2-nyata dan pg3-nyata ubah baris ke-3 name dengan nama mesin, dan setiap baris listen dan connect_address dengan IP per mesin.
Contoh perbedaan pg1-nyata dan pg2-nyata.
$ diff pg{1,2}-nyata/etc/patroni.yml -u --- pg1-nyata/etc/patroni.yml 2018-03-08 10:03:26.502995392 +0700 +++ pg2-nyata/etc/patroni.yml 2018-03-08 10:08:35.869743378 +0700 @@ -1,14 +1,14 @@ scope: postgres namespace: /pg-nyata/ -name: pg1-nyata - +name: pg2-nyata + restapi: - listen: 192.168.100.3:8008 - connect_address: 192.168.100.3:8008 - + listen: 192.168.100.4:8008 + connect_address: 192.168.100.4:8008 + etcd: host: 192.168.100.2:2379 - + bootstrap: dcs: ttl: 30 @@ -17,28 +17,28 @@ maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true - + initdb: - encoding: UTF8 - data-checksums - + pg_hba: - host replication replicator 127.0.0.1/32 md5 - host replication replicator 192.168.100.3/0 md5 - host replication replicator 192.168.100.4/0 md5 - host replication replicator 192.168.100.5/0 md5 - host all all 0.0.0.0/0 md5 - + users: admin: password: aiwaQuaeHuojeuyai2fiemai6Reeneix options: - createrole - createdb - + postgresql: - listen: 192.168.100.3:5432 - connect_address: 192.168.100.3:5432 + listen: 192.168.100.4:5432 + connect_address: 192.168.100.4:5432 data_dir: /var/lib/postgresql/10.2-patroni pgpass: /tmp/pgpass authentication: @@ -50,7 +50,7 @@ password: saichae9Aich0xeen2Otethaduphiepo parameters: unix_socket_directories: '.' - + tags: nofailover: false noloadbalance: false
Semoga dengan ini tidak ada salah ganti atau terlewat.
Pengaktifan Layanan Patroni
Setelah konfigurasi dan unit layanan Patroni terpasang, layanan Patroni sudah bisa dijalankan. Untuk setiap mesin, jalankan:
sudo systemctl daemon-reload sudo systemctl enable patroni sudo systemctl start patroni
Satu langkah lagi.
HAProxy
Bagian yang paling mudah saya salin saja, ya, perintahnya.
sudo apt install haproxy
Konfigurasi:
$ sudo tee /etc/haproxy/haproxy.cfg << EOF global maxconn 100 defaults log global mode tcp retries 2 timeout client 30m timeout connect 4s timeout server 30m timeout check 5s listen stats mode http bind *:7000 stats enable stats uri / listen postgres bind *:5000 option httpchk http-check expect status 200 default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions server postgresql_192.168.100.3_5432 192.168.100.3:5432 maxconn 100 check port 8008 server postgresql_192.168.100.4_5432 192.168.100.4:5432 maxconn 100 check port 8008 server postgresql_192.168.100.5_5432 192.168.100.5:5432 maxconn 100 check port 8008 EOF
Lalu,
sudo systemctl restart haproxy
Selesai.
Tidak ada komentar:
Posting Komentar