Amazon-AWS IaaS環境でフェイルセーフ(HA)PostgreSQLデータベースクラスターをセットアップする主なポイントを説明することにしました。
ネイティブレプリケーションを使用する9番目のバージョンの公開以降、このバンドルのセットアップについて多くの記事が既に書かれているため、PostgreSQLとpgpoolの詳細なセットアップについては説明しません。 指定された設定は、単純なコピーアンドペーストには適していません;いずれにしても、設定を開いて必要なパラメーターを編集する必要があります。 コピーと貼り付けの構成プロセスを奨励したくありません。
用語:
ストリーミング複製-postgresノードがマスター自体から更新をプルすることを意味します。 追加のアーカイブ機能は必要ありません。
ホットスタンバイ-スレーブサーバーがクライアントリクエストを処理せず、ウィザードから現在のベースを常に更新するウォームスタンバイとは異なり、スレーブノードはロードバランシングのためのREADリクエストを処理できます。 また、複製は同期および非同期(同期または非同期)にすることができます。
私の例では、通常のマスター-スレーブデータベースサーバーの束が使用されます。同期レプリケーションでは使用できません。同期レプリケーションでは、マスターがレプリカをスレーブに送信できなかったため、単に要求を満たさず、スレーブを待ってハングし、そのようなスキームのすべての意味が失われます。
入力データ:
作成される構成には、単一障害点がないようにする必要があります。 pgpoolレベルでは、ネイティブウォッチドッグ機能を使用して、ノードのいずれかの落下を追跡し、クライアントアプリケーションが接続するIPをドラッグできるようにします。 postgresqlレベルでは、ストリーミングレプリケーションとホットスタンバイを使用します。 マスターが陥落した場合、スレーブはすぐにその役割を引き継ぎ、スレーブは$ PGDATAにトリガーファイルを作成してpgpoolをマスターに変えます。 スレーブクラッシュが発生した場合、手動で蘇らせます。 データベースを使用した自動操作は適切に行われず、いずれの場合でもノードドロップの不測の事態に注意する必要があります。 説明されているすべてのクラッシュの場合、クライアントアプリケーションは最小限のダウンタイムで機能し続ける必要があります。
4つの仮想マシンがAWSクラウド(Amazon Web Services)に作成されました:pgpool-1(IP:10.0.3.11)、pgpool-2(IP:10.0.3.12)、db-1(IP:10.0.3.21)、db-2( IP:10.0.3.22)。 マシンは、プライベートアドレスを割り当てることができるようにVPCですぐに作成され、再起動インスタンス間で保存されます。 インスタンスを作成するときに、Ubuntuのami-8e987ef9イメージを使用しました。 ただし、イメージを選択する機会がある場合は、Amazon Linuxを使用してください。なぜそうなのか、テキストでわかると思います。
構成:
1. db-1-バンドルを起動する段階のマスター
...
wal_level = hot_standby
#次のパラメータはマスターサーバーでは無視されますが、マスターとスレーブは場所を変更できるため、master'a configに含めます
hot_standby = on
...
ニーズに応じて、次の値を調整します
checkpoint_segments、max_wal_senders、wal_keep_segments
レプリケーションを開始するには、デフォルトでそれらをそのままにして、最初にwiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Serverを読んでそれらを強化できます。
pg_hba.confでレプリケーションへのアクセスを設定します。パスワードを使用できます。 VPCクラウド内のすべてが回転しており、外部から直接アクセスすることはできません。信頼を登録しました。
ホスト複製postgres 10.0.3.0/24信頼
2. db-2-束の開始時のスレーブ
...
wal_level = hot_standby
hot_standby = on
...
スレーブのスタンバイ動作は、$ PGDATAにあるrecovery.confファイルによって制御されます。
私の場合、それはディレクトリ/var/lib/postgresql/9.3/mainでした
recovery.conf:
standby_mode = 'on'
primary_conninfo = 'ホスト= 10.0.3.21ポート= 5432ユーザー= postgres'
trigger_file = '/var/lib/postgresql/9.3/main/postgresql.trigger'
pg_hba.confへのアクセスの設定を忘れないでください
3. pgpool-1
pgpool.conf:
...
backend_hostname0 = '10 .0.3.21 '
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/var/lib/postgresql/9.3/main'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_hostname1 = '10 .0.3.22 '
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/var/lib/postgresql/9.3/main'
backend_flag1 = 'ALLOW_TO_FAILOVER'
#T.K。 ホットスタンバイがあります。
load_balance_mode = on
#ストリーミングレプリケーションが機能します
master_slave_mode = on
master_slave_sub_mode = 'stream'
sr_check_period = 10
sr_check_user = 'postgres'
sr_check_password = ''
delay_threshold = 100
#スレーブ> 1の場合に意味があります
follow_master_command = ''
#ノードが消えたときの対処:
failover_command = '/etc/pgpool2/failover.sh% d%P%H%R'
#倒れたノードが戻ったときの対処:
failback_command = ''
#バックエンドに接続できないときにフェイルオーバーを実行する
fail_over_on_backend_error = on
search_primary_node_timeout = 10
どのユーザーの下でオンライン回復を行うか
recovery_user = 'postgres'
recovery_password = ''
#第一段階では、pgpoolはクライアントからの接続と要求を受け入れ続けますが、第二段階では受け入れません。
#実行中のスクリプトは$ PGDATAにある必要があります
recovery_1st_stage_command = 'basebackup.sh'
recovery_2nd_stage_command = ''
#ノードの復元を待機している秒数
recovery_timeout = 90
#ウォッチドッグを使用してpgpoolの状態を監視します
use_watchdog = on
wd_hostname = 'pgpool-1'
wd_port = 9000
wd_authkey = ''
#クライアントアプリケーションが接続する仮想アドレス:
delegate_IP = '10 .0.3.10 '
#インターフェイス管理スクリプトは次の場所にあります。
ifconfig_path = '/ opt / AWS'
#コマンドを実行して、ノードに仮想IPを割り当てます
if_up_cmd = 'if.sh up $ _IP_ $'
#コマンドを実行して、ノードから仮想IPを削除します
if_down_cmd = 'if.sh down $ _IP_ $'
#Pgpoolは、ARPキャッシュを更新するために仮想インターフェイスを自分自身にドラッグしている間にarpを実行します
arping_cmd = ''
#隣接するpgpoolノードの活性をどのように確認しますか:
#heartbeatまたはそれを介してデータベースリクエストを送信しよう
wd_lifecheck_method = 'heartbeat'
#チェック間の間隔(秒):
wd_interval = 4
#ヘルメットが装着されているポート:
wd_heartbeat_port = 9694
#キープアライブパケットマンドレル間の間隔
wd_heartbeat_keepalive = 2
#サイレントノードの削除が検討されるまでの時間:
wd_heartbeat_deadtime = 15
#隣接ノードのアドレス:
heartbeat_destination0 = 'pgpool-2'
heartbeat_destination_port0 = 9694
#ハートビートが機能するインターフェイスを指定できます
heartbeat_device0 = ''
#別のノードのパラメーターについて説明します。
other_pgpool_hostname0 = 'pgpool-2'
other_pgpool_port0 = 9999
other_wd_port0 = 9000
...
4. pgpool-2
構成はpgpool-1と同じです。隣接ノードの説明はpgpool-2からpgpool-1に変更されます。
両方のノードの/ etc / hostsで、名前バインディングをipに設定します。
10.0.3.11 pgpool-1
10.0.3.12 pgpool-2
10.0.3.21 db-1
10.0.3.22 db-2
5.データベースと連携するためのpgpoolの統合
pgpool-1とpgpool-2の部分では、failover_commandパラメーターからスクリプトを作成します。これは、ノードが落ちたときに実行されます(マスターノードが落ちたときにのみ自動アクションがあります)。 ノードが落ちているかどうか、およびマスターがスレーブ上でトリガーファイルを作成する場合、彼が行うすべてが実際にマスターによってチェックされ、スレーブが自動的に読み取り/書き込みモードになります。 彼をマスターにします:
#!/bin/bash -x FALLING_NODE=$1 # %d OLDPRIMARY_NODE=$2 # %P NEW_PRIMARY=$3 # %H PGDATA=$4 # %R KEY_PATH="/var/lib/postgresql/.ssh/id_rsa" if [ $FALLING_NODE = $OLDPRIMARY_NODE ]; then if [ $UID -eq 0 ] then sudo -u postgres ssh -T -i $KEY_PATH postgres@$NEW_PRIMARY "touch $PGDATA/postgresql.trigger" exit 0; fi ssh -T -i $KEY_PATH postgres@$NEW_PRIMARY "touch $PGDATA/postgresql.trigger" fi; exit 0;
db-1およびdb-2側から、作業用にpgpoolスキームをインストールします。
sudo -u postgres psql -f /usr/share/postgresql/9.3/extension/pgpool-recovery.sql template1
隣接ノードでpostgresqlを起動するpgpool_remote_startスクリプトを$ PGDATAに作成します[使用するpostgresqlのバージョンによっては、ノードの$ PGDATAディレクトリを指すpgpoolによって渡される2番目のパラメーターが必要な場合があります]:
#! /bin/sh DEST=$1 PGCTL=/usr/bin/pg_ctlcluster KEY_PATH="/var/lib/postgresql/.ssh/id_rsa" ssh -T -i $KEY_PATH postgres@$DEST "$PGCTL 9.3 main stop --force;$PGCTL 9.3 main restart"
また、新しいスレーブの現在のマスターと同期するrecovery_1st_stage_commandパラメーターからのスクリプト(pgpool_remote_startの隣の$ PGDATAにもあります):
#! /bin/sh datadir=$1 desthost=$2 destdir=$3 KEY_PATH="/var/lib/postgresql/.ssh/id_rsa" PGCTL="/usr/bin/pg_ctlcluster" ssh -T -i $KEY_PATH postgres@$desthost "$PGCTL 9.3 main stop --force" psql -c "SELECT pg_start_backup('Streaming Replication', true)" postgres rsync -C -a -c --delete -e ssh --exclude postgresql.conf --exclude postmaster.pid \ --exclude postmaster.opts --exclude pg_log \ --exclude recovery.conf --exclude recovery.done \ --exclude pg_xlog $datadir/ $desthost:$destdir/ ssh -T -i $KEY_PATH postgres@$desthost "cp $destdir/../recovery.done $destdir/recovery.conf;rm $destdir/postgresql.trigger" psql -c "SELECT pg_stop_backup()" postgres
5.リモートホスト上のサービスの再起動とデータのコピーに関連するコマンドを実行できるようにするには、パスワードなしのアクセスを構成する必要があります。
pgpool-1-> db-1、db-2ホストベースのsshを使用でき、sshキーを生成してauthorized_keysで有効にできます。
pgpool-2-> db-1、db-2
db-1-> db-2
db-2-> db-1
アクセスを設定した後、pgpool中にスクリプトを実行するユーザーに代わってチェックする必要があります。私はpostgresを持っています:
pgpool-1ホストから、次を実行します。
sudo -u postgres ssh -i /path_to_key -T postgres@db-1 id
したがって、必要なすべてのホストについて、アクセスを確認し、sshのknown_hostsファイルを更新します。
この段階では、AWS環境ではない通常の作業のために、4つのノードの房がすでに開始されている可能性があります。
- マスターホスト(db-1)を起動します
- スレーブを同期します(postgresqlはまだ実行されていません)、$ PGDATAディレクトリを介して、以下を実行します。
mv main main.bak && sudo -u postgres pg_basebackup -h 10.0.3.21 -D /var/lib/postgresql/9.3/main -U postgres -v -P && cp recovery.done main/recovery.conf && chown postgres:postgres main/recovery.conf
- スレーブでpostgresqlを実行します。
sudo service postgresql restart
- 「select * from pg_stat_replication」でレプリケーションの状態を確認すると、次のように表示されます。
application_name | ウォルレシーバー
または、db-1およびdb-2ホスト上のプロセスのリストでwal sender / receiverの存在を確認してください。
client_addr | 10.0.3.22
状態| ストリーミング
sent_location | 1 / 2A000848
write_location | 1 / 2A000848
flush_location | 1 / 2A000848
replay_location | 1 / 2A000848
sync_priority | 0
sync_state | 非同期
起動後、最初に起動するpgpoolは、if_up_cmdパラメーターからコマンドを実行することにより、delegate_IPパラメーターから仮想アドレスをそれ自体にプルします(デフォルトでは単にifconfigがあります)。
ログエントリ:
wd_escalation:マスターpgpoolに正常にエスカレートしましたしばらくして、ログで2番目のpgpoolを実行すると、隣接するpgpoolノードが正常に認識され、リンクが機能したことがわかります。
find_primary_node:プライマリノードIDは0プールのステータスは、pcp_ *コマンド-pcp_pool_status、pcp_node_infoのいずれか、またはpgpoolノードに「show pool_nodes;」、「show pool_pools;」を要求することで表示できます。
これらのすべてのコマンド、およびプール内のノードのステータスは、 pgpoolのドキュメント( www.pgpool.net/docs/pgpool-II-3.3.2/doc/pgpool-en.html)で非常に詳しく説明されています。
最初のpgpoolを切断すると、2番目のpgpoolは、if_up_cmdパラメーターからのコマンドを使用して、delegate_ipを自身にプルします。
db-1またはdb-2バックエンドがクラッシュすると、failover_commandパラメーターからのコマンドが実行されます。
pcp_attach_nodeおよびpcp_recovery_nodeコマンドは、バックエンドをプールに戻すために使用されます。
AWSスタッフ:
それでは、AWS環境で何が起こるのでしょうか? [ネットワークインターフェイス]メニューの[セカンダリプライベートアドレスの割り当て]設定を使用して、ネットワークインターフェイスにIPアドレスを事前に割り当てる必要があることを除き、すべて同じです。 先ほど書いたAmazon Linuxの場合、このアドレスを作業中のインスタンスに自動的に割り当て、必要に応じてpgpool-1とpgpool-2の間でクロールすることができます(私は個人的にAmazon linuxをテストしませんでした。 ) AWSに適合していないイメージの場合、 ec2-api-tools setから追加のスクリプトを使用する必要があります 。
api-toolsの最新バージョンは、 amazonからダウンロードするのが最適です。
ec2-api-toolsを使用するには、Javaが必要です。インストール-apt-get install default-jre
aws / binの解凍されたapi-toolsアーカイブには、コンソールを介してawsを管理するためのスクリプトが含まれます。
ただし、Amazon APIを使用するには認証キーが必要です。
認証データを取得するプロセスは、アマゾンで詳細に説明されています-docs.aws.amazon.com/IAM/latest/UserGuide/ManagingCredentials.htmlおよびこちらdocs.aws.amazon.com/IAM/latest/UserGuide/ManagingUserCerts.html
最初のリンクを使用して、キーを持つユーザーを作成し、IAMメニュー( console.aws.amazon.com/iam/home?#usersを使用して必要なグループを割り当てる方法を学習します。 -別のものを生成する必要があります)。 Amazonは、キーを初めて作成するときに、AWS管理アカウントでキーを作成するのではなく、これらの目的でIAMメニューに別のユーザーを作成することを強くお勧めします。
2番目のリンクでは、証明書を作成して同じAWS IAMメニューにすべて登録する方法を学習します。
openssl genrsa 1024> private-key.pem
openssl pkcs8 -topk8 -nocrypt -inform PEM -in private-key.pem -out private-key-in-PCKS8-format.pem
openssl req -new -x509 -nodes -sha1 -days 3650 -key private-key.pem -outform PEM> certificate.pem
certificate.pemの内容は、IAMでAWSに注がれます。 証明書管理は、IAM Security Credentialsメニューから実行できます。
![](https://habrastorage.org/getpro/habr/post_images/3fa/6a8/89d/3fa6a889d04633b4afc6ee570bd26633.jpg)
これらすべての操作の後、次のことができます。
パラメーターEC2_CERTのcertificate.pem
EC2_PRIVATE_KEY、AWS_ACCESS_KEY、およびAWS_SECRET_KEYのprivate-key-in-PCKS8-format.pem。
ec2-api-toolsの使用を開始できます。
これを行うために、pgpoolsのdelegate_IPをインスタンス間でドラッグするif.shスクリプトを作成しました。 パラメーターとしてのスクリプトは、インターフェース(up / down)およびインターフェースに必要なIPアドレスで実行する必要があるアクションを受け取ります。 次に、スクリプトは入力されたIPのサブネットを計算します(私は/ 24を使用し、最後のオクテットを切り捨てるので、マスクが/ 24でない人はスクリプトを終了する必要があります)。 私はサブネットを インスタンスで2つのインターフェイスが使用されます-プライマリと管理。どちらを使用してセカンダリIPをハングアップする必要があるかを理解します。
if.shスクリプト:
#!/bin/sh if test $# -eq 0 then echo "This scripts adds and removes ip to subinterfaces and to AWS VPC configuration." echo "Don't forget to set variables inside this script." echo echo Usage: $0' [up|down] IP_ADDRESS' echo exit 1 fi #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #CORRECT VALUES MUST BE SET PRIOR TO RUN THIS SCRIPT #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #Proxy if used: export EC2_JVM_ARGS='-Dhttp.proxySet=true -Dhttps.proxySet=true -Dhttp.proxyHost=xxxx -Dhttp.proxyPort=3128 -Dhttps.proxyHost=xxxx -Dhttps.proxyPort=3128' #Path to unpacked ec2-api from http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip export EC2_HOME=/opt #Path to java export JAVA_HOME=/usr #Path to generated private key & cert (READ http://docs.aws.amazon.com/IAM/latest/UserGuide/ManagingUserCerts.html) export EC2_PRIVATE_KEY=/opt/private-key-in-PCKS8-format.pem export EC2_CERT=/opt/certificate.pem #User access & secret key (READ http://docs.aws.amazon.com/IAM/latest/UserGuide/ManagingCredentials.html) export AWS_ACCESS_KEY=YOUR_ACCESS_KEY export AWS_SECRET_KEY=YOUR_SECRET_KEY #Region for this EC2 instance REGION=YOUR_REGION #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! AWS_PATH=$EC2_HOME VIP=$2 subnet () { SUB=`echo $VIP | awk '{ split($0,a,"."); print a[1]"."a[2]"."a[3]"."; }'` SUBNET=`$AWS_PATH/bin/ec2-describe-subnets --region $REGION | grep -F $SUB | awk '{print $2}'` echo Subnet-id: $SUBNET if [ -z "$SUBNET" ]; then echo "Wrong subnet!" exit 1; fi Instance_ID=`/usr/bin/curl --silent http://169.254.169.254/latest/meta-data/instance-id` echo Instance_ID=$Instance_ID ENI_ID=`$AWS_PATH/bin/ec2-describe-instances $Instance_ID --region $REGION | cut -f 2,3 | grep $SUBNET | awk '{print $1}'` echo ENI_ID=$ENI_ID } if_up () { subnet /usr/bin/sudo /sbin/ifconfig eth1:0 inet $VIP netmask 255.255.255.255 $AWS_PATH/bin/ec2-assign-private-ip-addresses -n $ENI_ID --secondary-private-ip-address $VIP --allow-reassignment --region $REGION } if_down (){ subnet /usr/bin/sudo /sbin/ifconfig eth1:0 down $AWS_PATH/bin/ec2-unassign-private-ip-addresses -n $ENI_ID --secondary-private-ip-address $VIP --region $REGION } case $1 in [uU][pP]) if_up break ;; [dD][oO][wW][nN]) if_down break ;; *) echo "Up/Down command missed!" exit 1 esac /usr/sbin/service networking restart > /dev/null 2>&1
ec2-associate-addressおよびec2-unassign-private-ip-addressesを使用して、実際のエラスティックIPを管理できます。
実際には、AWSを使用してAmazon Linuxインスタンスでは機能しないpgpoolを友達にするために、これらのジェスチャーを実行する必要がありました。