αž€αžΆαžšαž€αžŸαžΆαž„αž…αž„αŸ’αž€αŸ„αž˜ PostgreSQL αžŠαŸ‚αž›αž˜αžΆαž“αž€αž˜αŸ’αžšαž·αžαžαŸ’αž–αžŸαŸ‹αžŠαŸ„αž™αž”αŸ’αžšαžΎ Patroni, etcd, HAProxy

αžœαžΆαž”αžΆαž“αž€αžΎαžαž‘αžΎαž„αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžαžΆ αž“αŸ…αž–αŸαž›αž˜αžΆαž“αž”αž‰αŸ’αž αžΆαž€αžΎαžαž‘αžΎαž„ αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αž˜αžΆαž“αž”αž‘αž–αž·αžŸαŸ„αž’αž“αŸαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αž—αž·αžœαžŒαŸ’αžαž“αŸ αž“αž·αž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž“αŸαŸ‡αžαŸ‚αž˜αŸ’αž“αžΆαž€αŸ‹αž―αž„αž“αŸ„αŸ‡αž‘αŸαŸ” αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžαŸ’αž‰αž»αŸ†αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ Google αŸ”

αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αžŠαžΉαž„αžαžΆαž€αžΆαžšαž…αžΆαž”αŸ‹αž“αŸ„αŸ‡αž‡αžΆαž’αŸ’αžœαžΈαž“αŸ„αŸ‡αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž›αžΎαž€αž‘αžΈαžŠαž”αŸ‹αž˜αž½αž™αžαŸ’αž‰αž»αŸ†αž”αŸ’αžšαžˆαž˜αž˜αž»αžαž“αžΉαž„αž€αžΆαžšαž–αž·αžαžŠαŸ‚αž›αžαžΆαž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαžαŸ’αž‰αž»αŸ†αž’αŸ’αžœαžΎαž’αŸ’αžœαžΈαŸ—αž‚αŸ’αžšαž”αŸ‹αž™αŸ‰αžΆαž„αž˜αž½αž™αž‡αŸ†αž αžΆαž“αž˜αŸ’αžαž„αŸ—αžŠαžΌαž…αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αŸαžšαŸ€αž“αž€αŸαžŠαŸ„αž™ αž€αŸαžšαŸ€αž”αž…αŸ†αž”αžšαž·αž™αžΆαž€αžΆαžŸαžŠαžΌαž…αž’αŸ’αž“αž€αž“αž·αž–αž“αŸ’αž’αžŠαŸ‚αžš αž“αŸ„αŸ‡αž‚αŸ’αž˜αžΆαž“αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž˜αžΆαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αž“αŸ„αŸ‡αž‘αŸαŸ” αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αžŠαžΉαž„αžαžΆαž˜αžΆαž“αžšαžΏαž„αž’αŸ’αžœαžΈαž“αŸ„αŸ‡αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αžαŸ’αž‰αž»αŸ†αž‡αž½αž”αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αž˜αŸ’αžαž„αž‘αŸ€αž αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαžαžΆαžαŸ’αž‰αž»αŸ†αž“αžΉαž„αžŸαžšαžŸαŸαžšαž€αžΆαžšαž”αž„αŸ’αžšαŸ€αž“αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ† αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αžœαžΈαŸ—αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ” αž˜αž½αž™αžŠαŸ‚αž›αž”αŸ’αžšαžΆαž€αžŠαž‡αžΆαž“αžΉαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ”

αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αž“αŸ…αž›αžΎαž’αŸŠαžΈαž“αž’αžΊαžŽαž·αž

αžœαžΆαž€αžΎαžαž‘αžΎαž„αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžαžΆαž’αŸŠαžΈαž“αž’αžΊαžŽαž·αžαž˜αž·αž“αž‘αž‘αž½αž›αžšαž„αž–αžΈαž€αžΆαžšαžαŸ’αžœαŸ‡αžαžΆαžαž“αŸƒαž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αž•αŸ’αžŸαŸαž„αŸ— αž€αžΆαžšαž”αž„αŸ’αžšαŸ€αž“ αž‡αŸ†αž αžΆαž“αžŠαŸ„αž™αž‡αŸ†αž αžΆαž“ αž“αž·αž„αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαŸ” αžœαžΆαž”αžΆαž“αž€αžΎαžαž‘αžΎαž„αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžαžΆαžαŸ’αž‰αž»αŸ†αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαž‚αž›αŸ‹αž—αžΆαžšαž€αž·αž…αŸ’αž…αž±αŸ’αž™αž”αž„αŸ’αž€αžΎαžαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž› αž“αž·αž„αž”αž„αŸ’αž€αžΎαžαž…αž„αŸ’αž€αŸ„αž˜ PostgreSQL αžŠαŸ‚αž›αž”αžšαžΆαž‡αŸαž™ αžŠαŸ‚αž›αž‡αžΆαžαž˜αŸ’αžšαžΌαžœαž€αžΆαžšαž…αž˜αŸ’αž”αž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž•αŸ’αžŸαžΆαž™αž…αž˜αŸ’αž›αž„αž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž‘αŸ…αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž…αž˜αŸ’αž›αž„αž‘αžΆαŸ†αž„αž’αžŸαŸ‹ αž“αž·αž„αž€αžΆαžšαž•αŸ’αžαž›αŸ‹αž‘αž»αž“αž”αŸ†αžšαž»αž„αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž“αŸ…αž€αŸ’αž“αž»αž„αž–αŸ’αžšαžΉαžαŸ’αžαž·αž€αžΆαžšαžŽαŸαž“αŸƒαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž˜αŸαŸ” αž”αžšαžΆαž‡αŸαž™αŸ”

αž“αŸ…αžŠαŸ†αžŽαžΆαž€αŸ‹αž€αžΆαž›αž“αŸαŸ‡αž‡αž„αŸ‹αž“αŸƒαž”αž…αŸ’αž…αŸαž€αžœαž·αž‘αŸ’αž™αžΆαžŠαŸ‚αž›αž”αžΆαž“αž”αŸ’αžšαžΎαžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹:

  • PostgreSQL αž‡αžΆ DBMS
  • αž”αŸ‰αžΆαžαžΌαž“αžΈ αž‡αžΆαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž…αž„αŸ’αž€αŸ„αž˜
  • etcd αž‡αžΆαž€αžΆαžšαž•αŸ’αž‘αž»αž€αž…αŸ‚αž€αž…αžΆαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ Patroni
  • HAproxy αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžšαŸ€αž”αž…αŸ†αž…αŸ†αžŽαž»αž…αž…αžΌαž›αžαŸ‚αž˜αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ„αž™αž”αŸ’αžšαžΎαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ - αž€αžΆαžšαž€αžŸαžΆαž„αž…αž„αŸ’αž€αŸ„αž˜ PostgreSQL αžŠαŸ‚αž›αž˜αžΆαž“αž€αž˜αŸ’αžšαž·αžαžαŸ’αž–αžŸαŸ‹αžŠαŸ„αž™αž”αŸ’αžšαžΎ Patroni, etcd, HAProxy αŸ”

αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αžαž‡αžΆαž˜αž½αž™αž“αžΉαž„ Debian 10 OS αžŠαŸ‚αž›αž”αžΆαž“αžŠαŸ†αž‘αžΎαž„αŸ”

αž›

αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αžŽαŸ‚αž“αžΆαŸ†αž±αŸ’αž™αžŠαŸ†αž‘αžΎαž„ etcd αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžŠαžΌαž…αž‚αŸ’αž“αžΆαžŠαŸ‚αž› patroni αž“αž·αž„ postgresql αž“αžΉαž„αž˜αžΆαž“αž‘αžΈαžαžΆαŸ†αž„αž‘αŸ αž–αŸ’αžšαŸ„αŸ‡αž€αžΆαžšαž•αŸ’αž‘αž»αž€αžαžΆαžŸαž˜αžΆαž“αžŸαžΆαžšαŸˆαžŸαŸ†αžαžΆαž“αŸ‹αžαŸ’αž›αžΆαŸ†αž„αžŽαžΆαžŸαŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ etcd αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹β€‹αž‚αŸ„αž›β€‹αž”αŸ†αžŽαž„β€‹αž’αž”αŸ‹αžšαŸ† αž™αžΎαž„β€‹αž“αžΉαž„β€‹αž’αŸ’αžœαžΎβ€‹αž”αŸ‚αž”β€‹αž“αŸ„αŸ‡αŸ”
αžαŸ„αŸ‡αžŠαŸ†αž‘αžΎαž„ αž›αŸ”

#!/bin/bash
apt-get update
apt-get install etcd

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžΆαžαž·αž€αžΆαž‘αŸ…αž―αž€αžŸαžΆαžš /etc/default/etcd

[αžŸαž˜αžΆαž‡αž·αž€]

ETCD_NAME=datanode1 # αžˆαŸ’αž˜αŸ„αŸ‡αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αŸƒαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”
ETCD_DATA_DIR=”/var/lib/etcd/default.etcd”

αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ IP αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž‚αž½αžšαžαŸ‚αž˜αžΆαž“αžŸαž»αž–αž›αž—αžΆαž–αŸ” LISTER PEER, Client αž‡αžΆαžŠαžΎαž˜ αž‚αž½αžšαžαŸ‚αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αž‘αŸ…αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ IP αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“

ETCD_LISTEN_PEER_URLS="http://192.168.0.143:2380Β» # αž’αžΆαžŸαŸαž™αžŠαŸ’αž‹αžΆαž“αž‘αžΆαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”
ETCD_LISTEN_CLIENT_URLS="http://192.168.0.143:2379,http://127.0.0.1:2379Β» # αž’αžΆαžŸαŸαž™αžŠαŸ’αž‹αžΆαž“αž‘αžΆαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

[αž…αž„αŸ’αž€αŸ„αž˜]

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.0.143:2380Β» # αž’αžΆαžŸαŸαž™αžŠαŸ’αž‹αžΆαž“αž‘αžΆαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”
ETCD_INITIAL_CLUSTER=Β»datanode1=http://192.168.0.143:2380,datanode2=http://192.168.0.144:2380,datanode3=http://192.168.0.145:2380Β» # αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜ etcd
ETCD_INITIAL_CLUSTER_STATE="αžαŸ’αž˜αžΈ"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-1β€³
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.0.143:2379Β» # αž’αžΆαžŸαŸαž™αžŠαŸ’αž‹αžΆαž“αž‘αžΆαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ

systemctl restart etcd

PostgreSQL 9.6 + patroni

αžšαžΏαž„αžŠαŸ†αž”αžΌαž„αžŠαŸ‚αž›αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎαž‚αžΊαžŠαŸ†αž‘αžΎαž„αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αž·αž˜αŸ’αž˜αž·αžαž…αŸ†αž“αž½αž“αž”αžΈαžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ†αž‘αžΎαž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž…αžΆαŸ†αž”αžΆαž…αŸ‹αž“αŸ…αž›αžΎαž–αž½αž€αžœαžΆαŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαžŠαŸ†αž‘αžΎαž„αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž αžΎαž™ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž’αŸ’αžœαžΎαžαžΆαž˜αž€αžΆαžšαž”αž„αŸ’αžšαŸ€αž“αžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ† αž’αŸ’αž“αž€αž’αžΆαž…αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž“αŸαŸ‡αžŠαŸ‚αž›αž“αžΉαž„ (αžŸαŸ’αž‘αžΎαžšαžαŸ‚) αž’αŸ’αžœαžΎαž’αŸ’αžœαžΈαŸ—αž‚αŸ’αžšαž”αŸ‹αž™αŸ‰αžΆαž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αŸ” αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‡αžΆ root αŸ”

αžŸαžΌαž˜αž…αŸ†αžŽαžΆαŸ†αžαžΆαžŸαŸ’αž‚αŸ’αžšαžΈαž”αž”αŸ’αžšαžΎ PostgreSQL αž€αŸ†αžŽαŸ‚ 9.6 αž“αŸαŸ‡αž‚αžΊαžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αžαž˜αŸ’αžšαžΌαžœαž€αžΆαžšαž•αŸ’αž‘αŸƒαž€αŸ’αž“αž»αž„αžšαž”αžŸαŸ‹αž€αŸ’αžšαž»αž˜αž αŸŠαž»αž“αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžΆαž€αž›αŸ’αž”αž„αž›αžΎαž€αŸ†αžŽαŸ‚αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸƒ PostgreSQL αž‘αŸαŸ”

#!/bin/bash
apt-get install gnupg -y
echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main" >> /etc/apt/sources.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
apt-get update
apt-get install postgresql-9.6 python3-pip python3-dev libpq-dev -y
systemctl stop postgresql
pip3 install --upgrade pip
pip install psycopg2
pip install patroni[etcd]
echo "
[Unit]
Description=Runners to orchestrate a high-availability PostgreSQL
After=syslog.target network.target

[Service]
Type=simple

User=postgres
Group=postgres

ExecStart=/usr/local/bin/patroni /etc/patroni.yml

KillMode=process

TimeoutSec=30

Restart=no

[Install]
WantedBy=multi-user.targ
" > /etc/systemd/system/patroni.service
mkdir -p /data/patroni
chown postgres:postgres /data/patroni
chmod 700 /data/patroniΠΏΠΎ
touch /etc/patroni.yml

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš /etc/patroni.yml αžŠαŸ‚αž›αž’αŸ’αž“αž€αž‘αžΎαž”αžαŸ‚αž”αž„αŸ’αž€αžΎαž αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžŠαžΆαž€αŸ‹αž˜αžΆαžαž·αž€αžΆαžαžΆαž„αž€αŸ’αžšαŸ„αž˜ αž‡αžΆαž€αžΆαžšαž–αž·αžαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“ IP αž“αŸ…αž‚αŸ’αžšαž”αŸ‹αž€αž“αŸ’αž›αŸ‚αž„αž‘αŸ…αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαŸ”
αž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αž…αŸ†αž–αŸ„αŸ‡αž˜αžαž·αž™αŸ„αž”αž›αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„ yaml αž“αŸαŸ‡αŸ” αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž‘αŸ…αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž“αžΈαž˜αž½αž™αŸ—αž“αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜αŸ”

/etc/patroni.yml

scope: pgsql # Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ Π½Π° всСх Π½ΠΎΠ΄Π°Ρ…
namespace: /cluster/ # Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ Π½Π° всСх Π½ΠΎΠ΄Π°Ρ…
name: postgres1 # Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π·Π½Ρ‹ΠΌ Π½Π° всСх Π½ΠΎΠ΄Π°Ρ…

restapi:
    listen: 192.168.0.143:8008 # адрСс Ρ‚ΠΎΠΉ Π½ΠΎΠ΄Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ находится этот Ρ„Π°ΠΉΠ»
    connect_address: 192.168.0.143:8008 # адрСс Ρ‚ΠΎΠΉ Π½ΠΎΠ΄Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ находится этот Ρ„Π°ΠΉΠ»

etcd:
    hosts: 192.168.0.143:2379,192.168.0.144:2379,192.168.0.145:2379 # пСрСчислитС здСсь всС ваши Π½ΠΎΠ΄Ρ‹, Π² случаС Ссли Π²Ρ‹ устанавливаСтС etcd Π½Π° Π½ΠΈΡ… ΠΆΠ΅

# this section (bootstrap) will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
# and all other cluster members will use it as a `global configuration`
bootstrap:
    dcs:
        ttl: 100
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 1048576
        postgresql:
            use_pg_rewind: true
            use_slots: true
            parameters:
                    wal_level: replica
                    hot_standby: "on"
                    wal_keep_segments: 5120
                    max_wal_senders: 5
                    max_replication_slots: 5
                    checkpoint_timeout: 30

    initdb:
    - encoding: UTF8
    - data-checksums
    - locale: en_US.UTF8
    # init pg_hba.conf Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ адрСса Π’Π‘Π•Π₯ машин, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… Π² кластСрС
    pg_hba:
    - host replication postgres ::1/128 md5
    - host replication postgres 127.0.0.1/8 md5
    - host replication postgres 192.168.0.143/24 md5
    - host replication postgres 192.168.0.144/24 md5
    - host replication postgres 192.168.0.145/24 md5
    - host all all 0.0.0.0/0 md5

    users:
        admin:
            password: admin
            options:
                - createrole
                - createdb

postgresql:
    listen: 192.168.0.143:5432 # адрСс Ρ‚ΠΎΠΉ Π½ΠΎΠ΄Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ находится этот Ρ„Π°ΠΉΠ»
    connect_address: 192.168.0.143:5432 # адрСс Ρ‚ΠΎΠΉ Π½ΠΎΠ΄Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ находится этот Ρ„Π°ΠΉΠ»
    data_dir: /data/patroni # эту Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ создаст скрипт, описанный Π²Ρ‹ΡˆΠ΅ ΠΈ установит Π½ΡƒΠΆΠ½Ρ‹Π΅ ΠΏΡ€Π°Π²Π°
    bin_dir:  /usr/lib/postgresql/9.6/bin # ΡƒΠΊΠ°ΠΆΠΈΡ‚Π΅ ΠΏΡƒΡ‚ΡŒ Π΄ΠΎ вашСй Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ с postgresql
    pgpass: /tmp/pgpass
    authentication:
        replication:
            username: postgres
            password: postgres
        superuser:
            username: postgres
            password: postgres
    create_replica_methods:
        basebackup:
            checkpoint: 'fast'
    parameters:
        unix_socket_directories: '.'

tags:
    nofailover: false
    noloadbalance: false
    clonefrom: false
    nosync: false

αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžαŸ’αžšαžΌαžœαžαŸ‚αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž‘αžΆαŸ†αž„αž”αžΈαž“αŸƒαž…αž„αŸ’αž€αŸ„αž˜ αž αžΎαž™αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αžαžΆαž„αž›αžΎαž€αŸαžαŸ’αžšαžΌαžœαžαŸ‚αžŠαžΆαž€αŸ‹αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš /etc/patroni.yml αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ”

αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αžΆαž“αž”αž‰αŸ’αž…αž”αŸ‹αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž‘αžΆαŸ†αž„αž“αŸαŸ‡αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜ αžŸαžΌαž˜αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž“αŸ…αž›αžΎαž–αž½αž€αžœαžΆαžŽαžΆαž˜αž½αž™αŸ”

systemctl start patroni
systemctl start postgresql

αžšαž„αŸ‹αž…αžΆαŸ†αž”αŸ’αžšαž αŸ‚αž› 30 αžœαž·αž“αžΆαž‘αžΈ αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαž“αŸαŸ‡αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžŠαŸ‚αž›αž“αŸ…αžŸαž›αŸ‹αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜αŸ”

HAproxy

αž™αžΎαž„αž”αŸ’αžšαžΎ HAproxy αžŠαŸαž’αžŸαŸ’αž…αžΆαžšαŸ’αž™αžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αžαž›αŸ‹αž“αžΌαžœαž…αŸ†αžŽαž»αž…αž…αžΌαž›αžαŸ‚αž˜αž½αž™αŸ” αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž˜αŸαž“αžΉαž„αžαŸ‚αž„αžαŸ‚αž˜αžΆαž“αž“αŸ…αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžŠαŸ‚αž› HAproxy αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αŸ”

αžŠαžΎαž˜αŸ’αž”αžΈαž€αž»αŸ†αž±αŸ’αž™αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž‡αžΆαž˜αž½αž™ HAproxy αž€αŸ’αž›αžΆαž™αž‡αžΆαž…αŸ†αžŽαž»αž…αž”αžšαžΆαž‡αŸαž™αžαŸ‚αž˜αž½αž™ αž™αžΎαž„αž“αžΉαž„αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„ Docker container αž αžΎαž™αž“αŸ…αž–αŸαž›αž’αž“αžΆαž‚αž αžœαžΆαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαžΆαž€αŸ‹αž±αŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αŸ…αž€αŸ’αž“αž»αž„αž…αž„αŸ’αž€αŸ„αž˜αžšαž”αžŸαŸ‹ K8 αž“αž·αž„αž’αŸ’αžœαžΎαž±αŸ’αž™ cluster αž”αžšαžΆαž‡αŸαž™αžšαž”αžŸαŸ‹αž™αžΎαž„αž€αžΆαž“αŸ‹αžαŸ‚αž‚αž½αžšαž±αŸ’αž™αž‘αž»αž€αž…αž·αžαŸ’αžαŸ”

αž”αž„αŸ’αž€αžΎαžαžαžαž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž―αž€αžŸαžΆαžšαž–αžΈαžš - Dockerfile αž“αž·αž„ haproxy.cfg αŸ” αž‘αŸ…αžœαžΆαŸ”

Dockerfile

FROM ubuntu:latest

RUN apt-get update 
    && apt-get install -y haproxy rsyslog 
    && rm -rf /var/lib/apt/lists/*

RUN mkdir /run/haproxy

COPY haproxy.cfg /etc/haproxy/haproxy.cfg

CMD haproxy -f /etc/haproxy/haproxy.cfg && tail -F /var/log/haproxy.log

αžŸαžΌαž˜αž”αŸ’αžšαž™αŸαžαŸ’αž“ αž”αž“αŸ’αž‘αžΆαžαŸ‹αž”αžΈαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸƒαž―αž€αžŸαžΆαžš haproxy.cfg αž‚αž½αžšαžαŸ‚αžšαžΆαž™αž”αž‰αŸ’αž‡αžΈαž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž“αŸƒαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ” HAproxy αž“αžΉαž„αž‘αžΆαž€αŸ‹αž‘αž„ Patroni αž“αŸ…αž€αŸ’αž“αž»αž„αž”αž‹αž˜αž€αžαžΆ HTTP αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž“αžΉαž„αžαŸ‚αž„αžαŸ‚αžαŸ’αžšαž‘αž”αŸ‹ 200 αž αžΎαž™αž€αžΆαžšαž…αž˜αŸ’αž›αž„αž“αžΉαž„αžαŸ‚αž„αžαŸ‚αžαŸ’αžšαž‘αž”αŸ‹ 503 αŸ”

haproxy.cfg

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 postgresql1 192.168.0.143:5432 maxconn 100 check port 8008
    server postgresql2 192.168.0.144:5432 maxconn 100 check port 8008
    server postgresql3 192.168.0.145:5432 maxconn 100 check port 8008

αžŠαŸ„αž™αžŸαŸ’αžαž·αžαž“αŸ…αž€αŸ’αž“αž»αž„αžαžαž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž―αž€αžŸαžΆαžšαž‘αžΆαŸ†αž„αž–αžΈαžšαžšαž”αžŸαŸ‹αž™αžΎαž„ "αž€αž»αž αž€" αžŸαžΌαž˜αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αžαžΆαž˜αž›αŸ†αžŠαžΆαž”αŸ‹αž›αŸ†αžŠαŸ„αž™αž“αžΌαžœαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžœαŸαž…αžαŸ’αž…αž”αŸ‹αž€αž»αž„αžαžΊαž“αŸαžš αž€αŸαžŠαžΌαž…αž‡αžΆαž€αžΆαžšαž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžœαžΆαž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž”αž“αŸ’αžαž…αŸ’αžšαž€αž…αžΆαŸ†αž”αžΆαž…αŸ‹αŸ–

docker build -t my-haproxy .
docker run -d -p5000:5000 -p7000:7000 my-haproxy 

αž₯αž‘αžΌαžœαž“αŸαŸ‡ αžŠαŸ„αž™αž”αžΎαž€αž’αžΆαžŸαž™αžŠαŸ’αž‹αžΆαž“αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž‡αžΆαž˜αž½αž™ HAproxy αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€ αž αžΎαž™αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž…αŸ’αžšαž€ 7000 αž’αŸ’αž“αž€αž“αžΉαž„αžƒαžΎαž‰αžŸαŸ’αžαž·αžαž·αž“αŸ…αž›αžΎαž…αž„αŸ’αž€αŸ„αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαžŠαŸ‚αž›αž‡αžΆαž˜αŸαž“αžΉαž„αžŸαŸ’αžαž·αžαž€αŸ’αž“αž»αž„αžŸαŸ’αžαžΆαž“αž—αžΆαž– UP αž αžΎαž™αž€αžΆαžšαž…αž˜αŸ’αž›αž„αž“αžΉαž„αžŸαŸ’αžαž·αžαž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ’αžαžΆαž“αž—αžΆαž–αž…αž»αŸ‡αž€αŸ’αžšαŸ„αž˜αŸ” αž“αŸαŸ‡αž‡αžΆαžšαžΏαž„αž’αž˜αŸ’αž˜αžαžΆαž‘αŸ αžαžΆαž˜αž–αž·αžαž–αž½αž€αž‚αŸαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž–αž½αž€αžœαžΆαž›αŸαž…αž‘αžΎαž„αžαžΆαž˜αžšαž”αŸ€αž”αž“αŸαŸ‡ αžŠαŸ„αž™αžŸαžΆαžšαž–αž½αž€αž‚αŸαžαŸ’αžšαž‘αž”αŸ‹ 503 αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ†αžŽαžΎαž–αžΈ HAproxy αŸ” αž“αŸαŸ‡αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž™αžΎαž„αžŠαžΉαž„αž‡αžΆαž“αž·αž…αŸ’αž…αžαžΆ αžαžΎαž˜αž½αž™αžŽαžΆαž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž‘αžΆαŸ†αž„αž”αžΈαž‡αžΆαž˜αŸαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“

αž’αŸ’αž“αž€β€‹αž‚αžΊβ€‹αžŸαŸ’αžšαžŸαŸ‹β€‹αžŸαŸ’αž’αžΆαžβ€‹! αž€αŸ’αž“αž»αž„αžšαž™αŸˆαž–αŸαž›αžαŸ’αžšαžΉαž˜αžαŸ‚ 30 αž“αžΆαž‘αžΈαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡ αž’αŸ’αž“αž€αž”αžΆαž“αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž“αžΌαžœαž…αž„αŸ’αž€αŸ„αž˜αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ‚αž›αž’αž“αŸ‹αž‘αŸ’αžšαžΆαŸ†αž“αžΉαž„αž€αŸ†αž αž»αžŸ αž“αž·αž„αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αžαŸ’αž–αžŸαŸ‹αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž…αž˜αŸ’αž›αž„αžŸαŸ’αž‘αŸ’αžšαžΈαž˜ αž“αž·αž„αž€αžΆαžšαžαž™αž€αŸ’αžšαŸ„αž™αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αžΆαž“αž‚αž˜αŸ’αžšαŸ„αž„αž”αŸ’αžšαžΎαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž“αŸαŸ‡ αžŸαžΌαž˜αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž› αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž―αž€αžŸαžΆαžšαž•αŸ’αž›αžΌαžœαž€αžΆαžšαžšαž”αžŸαŸ‹ Patroniαž αžΎαž™αž‡αžΆαž–αž·αžŸαŸαžŸαž‡αžΆαž˜αž½αž™αž“αžΉαž„αž•αŸ’αž“αŸ‚αž€αžšαž”αžŸαŸ‹αžœαžΆαž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ patronictl αžŠαŸ‚αž›αž•αŸ’αžαž›αŸ‹αž“αžΌαžœαž—αžΆαž–αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž€αŸ’αž“αž»αž„αž€αžΆαžšαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž…αž„αŸ’αž€αŸ„αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αž’αž”αž’αžšαžŸαžΆαž‘αžš!

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹