前書き
高可用性はシステム設計の機能であり、障害が発生した場合にアプリケーションが自動的に再起動するか、作業を別の対応システムに再ルーティングできるようにします。 サーバーに関しては、可用性の高いシステムをセットアップするために必要なテクノロジーがいくつかあります。 作業をリダイレクトできるコンポーネントが必要です。また、障害を監視し、中断が検出された場合にシステムを移行するメカニズムが必要です。
keepalived
デーモンを使用して、サービスまたはシステムを監視し、問題が発生した場合にスタンバイに自動的にフェイルオーバーすることができます。 このガイドでは、keepalived
を使用してロードバランサーの高可用性を設定する方法を示します。 2つの対応するロードバランサー間で移動できるfloating IP addressを構成します。 これらはそれぞれ、2つのバックエンドWebサーバー間でトラフィックを分割するように構成されます。 プライマリロードバランサーがダウンすると、フローティングIPは自動的に2番目のロードバランサーに移動し、サービスを再開できます。
[.note]#Note:DigitalOcean Load Balancersは、フルマネージドで可用性の高い負荷分散サービスです。 ロードバランサーサービスは、ここで説明する手動の高可用性セットアップと同じ役割を果たすことができます。 そのオプションを評価したい場合は、guide on setting up Load Balancersに従ってください。
#
前提条件
このガイドを完了するには、DigitalOceanアカウントに4つのUbuntu 14.04サーバーを作成する必要があります。 すべてのサーバーは同じデータセンター内に配置する必要があり、プライベートネットワークを有効にする必要があります。
これらの各サーバーでは、sudo
アクセスで構成されたroot以外のユーザーが必要になります。 これらのユーザーを設定する方法については、Ubuntu 14.04 initial server setup guideをフォローしてください。
サーバーネットワーク情報の検索
インフラストラクチャコンポーネントの実際の構成を開始する前に、各サーバーに関する情報を収集することをお勧めします。
このガイドを完了するには、サーバーに関する次の情報が必要です。
-
web servers:プライベートIPアドレス
-
load balancersプライベートおよびアンカーIPアドレス
プライベートIPアドレスの検索
ドロップレットのプライベートIPアドレスを見つける最も簡単な方法は、curl
を使用してDigitalOceanメタデータサービスからプライベートIPアドレスを取得することです。 このコマンドは、ドロップレット内から実行する必要があります。 各ドロップレットで、次を入力します。
curl 169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo
ターミナルウィンドウに正しいIPアドレスを印刷する必要があります。
Output10.132.20.236
アンカーIPアドレスの検索
「アンカーIP」は、DigitalOceanサーバーに接続されたときにフローティングIPがバインドするローカルプライベートIPアドレスです。 これは、ハイパーバイザーレベルで実装された、通常のeth0
アドレスの単なるエイリアスです。
この値を取得する最も簡単でエラーの少ない方法は、DigitalOceanメタデータサービスから直接です。 curl
を使用すると、次のように入力して、各サーバー上のこのエンドポイントにアクセスできます。
curl 169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address && echo
アンカーIPは独自の行に印刷されます。
Output10.17.1.18
Webサーバーのインストールと構成
上記のデータを収集したら、サービスの構成に進むことができます。
Note
[.note]#このセットアップでは、Webサーバーレイヤー用に選択されたソフトウェアはかなり互換性があります。 このガイドは汎用であり、構成が簡単であるため、Nginxを使用します。 Apacheまたは(本番対応の)言語固有のWebサーバーに慣れている場合は、代わりに自由に使用してください。 HAProxyは、直接クライアント接続を処理するのと同じように要求を処理できるバックエンドWebサーバーにクライアント要求を渡すだけです。
#
最初に、バックエンドWebサーバーをセットアップします。 これらのサーバーは両方ともまったく同じコンテンツを提供します。 プライベートIPアドレスを介したWeb接続のみを受け入れます。 これにより、後で設定する2つのHAProxyサーバーのいずれかを経由してトラフィックが送信されるようになります。
ロードバランサーの背後にWebサーバーをセットアップすると、いくつかの同一のWebサーバー間で要求の負荷を分散できます。 トラフィックのニーズの変化に応じて、この層にWebサーバーを追加または削除することで、新しい需要に合わせて簡単に拡張できます。
Nginxのインストール
この機能を提供するために、WebサービングマシンにNginxをインストールします。
まず、sudo
ユーザーを使用して、Webサーバーとして使用する2台のマシンにログインします。 各Webサーバーのローカルパッケージインデックスを更新し、次のように入力してNginxをインストールします。
sudo apt-get update
sudo apt-get install nginx
ロードバランサーからのリクエストのみを許可するようにNginxを構成する
次に、Nginxインスタンスを構成します。 Nginxに、サーバーのプライベートIPアドレスでのみリクエストをリッスンするように指示します。 さらに、2つのロードバランサーのプライベートIPアドレスからのリクエストのみを処理します。
これらの変更を行うには、各WebサーバーでデフォルトのNginxサーバーブロックファイルを開きます。
sudo nano /etc/nginx/sites-available/default
まず、listen
ディレクティブを変更します。 listen
ディレクティブを変更して、ポート80で現在のweb server’s private IP addressをリッスンします。 余分なlisten
行を削除します。 これは次のようになります。
/etc/nginx/sites-available/default
server {
listen web_server_private_IP:80;
. . .
その後、2つのallow
ディレクティブを設定して、2つのロードバランサーのプライベートIPアドレスから発信されるトラフィックを許可します。 これをdeny all
ルールでフォローアップして、他のすべてのトラフィックを禁止します。
/etc/nginx/sites-available/default
server {
listen web_server_private_IP:80;
allow load_balancer_1_private_IP;
allow load_balancer_2_private_IP;
deny all;
. . .
完了したら、ファイルを保存して閉じます。
次のように入力して、行った変更が有効なNginx構文を表していることをテストします。
sudo nginx -t
問題が報告されていない場合は、次のように入力してNginxデーモンを再起動します。
sudo service nginx restart
変更のテスト
Webサーバーが正しく制限されていることをテストするために、さまざまな場所からcurl
を使用して要求を行うことができます。
Webサーバー自体で、次のように入力して、ローカルコンテンツの簡単な要求を試すことができます。
curl 127.0.0.1
Nginxサーバーブロックファイルに設定した制限のため、このリクエストは実際に拒否されます。
Outputcurl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused
これは予想されることであり、実装しようとした動作を反映しています。
これで、load balancersのいずれかから、WebサーバーのパブリックIPアドレスのいずれかを要求できます。
curl web_server_public_IP
繰り返しますが、これは失敗するはずです。 Webサーバーはパブリックインターフェイスをリッスンしておらず、さらにパブリックIPアドレスを使用している場合、Webサーバーはロードバランサーからのリクエストに許可されたプライベートIPアドレスを表示しません。
Outputcurl: (7) Failed to connect to web_server_public_IP port 80: Connection refused
ただし、Webサーバーのprivate IP addressを使用して要求を行うように呼び出しを変更すると、正しく機能するはずです。
curl web_server_private_IP
デフォルトのNginxindex.html
ページが返されます:
Output
Welcome to nginx!
. . .
これを両方のロードバランサーから両方のWebサーバーにテストします。 プライベートIPアドレスの各要求は成功する必要があり、パブリックアドレスに対する各要求は失敗するはずです。
上記の動作が実証されたら、次に進みます。 バックエンドWebサーバーの設定が完了しました。
HAProxyのインストールと構成
次に、HAProxyロードバランサーを設定します。 これらはそれぞれWebサーバーの前に配置され、2つのバックエンドサーバー間でリクエストを分割します。 これらのロードバランサーは完全に冗長です。 常に1つだけがトラフィックを受信します。
HAProxy構成は、両方のWebサーバーに要求を渡します。 ロードバランサーは、アンカーIPアドレスでリクエストをリッスンします。 前述したように、これは、ドロップレットに添付されたときにフローティングIPアドレスがバインドするIPアドレスです。 これにより、フローティングIPアドレスから発信されたトラフィックのみが転送されます。
HAProxyをインストールする
ロードバランサーで実行する必要がある最初のステップは、haproxy
パッケージをインストールすることです。 これはデフォルトのUbuntuリポジトリにあります。 ロードバランサーのローカルパッケージインデックスを更新し、次のように入力してHAProxyをインストールします。
sudo apt-get update
sudo apt-get install haproxy
HAProxyを構成する
HAProxyを処理するときに変更する必要がある最初の項目は、/etc/default/haproxy
ファイルです。 エディターでそのファイルを開きます。
sudo nano /etc/default/haproxy
このファイルは、起動時にHAProxyを開始するかどうかを決定します。 サーバーの電源を入れるたびにサービスを自動的に開始する必要があるため、ENABLED
の値を「1」に変更する必要があります。
/etc/default/haproxy
# Set ENABLED to 1 if you want the init script to start haproxy.
ENABLED=1
# Add extra flags here.
#EXTRAOPTS="-de -m 16"
上記の編集を行った後、ファイルを保存して閉じます。
次に、メインのHAProxy構成ファイルを開くことができます。
sudo nano /etc/haproxy/haproxy.cfg
調整する必要がある最初の項目は、HAProxyが動作するモードです。 TCP、またはレイヤー4の負荷分散を構成します。 これを行うには、default
セクションのmode
行を変更する必要があります。 また、ログを処理するオプションの直後にオプションを変更する必要があります。
/etc/haproxy/haproxy.cfg
. . .
defaults
log global
mode tcp
option tcplog
. . .
ファイルの最後で、フロントエンドの構成を定義する必要があります。 これにより、HAProxyが着信接続をリッスンする方法が決まります。 HAProxyをロードバランサーのアンカーIPアドレスにバインドします。 これにより、フローティングIPアドレスから発信されるトラフィックをリッスンできます。 簡単にするために、フロントエンドを「www」と呼びます。 また、トラフィックを渡すデフォルトのバックエンドも指定します(すぐに設定します)。
/etc/haproxy/haproxy.cfg
. . .
defaults
log global
mode tcp
option tcplog
. . .
frontend www
bind load_balancer_anchor_IP:80
default_backend nginx_pool
次に、バックエンドセクションを構成できます。 これにより、HAProxyが受信したトラフィックを渡すダウンストリームの場所が指定されます。 私たちの場合、これは設定した両方のNginx WebサーバーのプライベートIPアドレスになります。 従来のラウンドロビンバランシングを指定し、モードを再び「tcp」に設定します。
/etc/haproxy/haproxy.cfg
. . .
defaults
log global
mode tcp
option tcplog
. . .
frontend www
bind load_balancer_anchor_IP:80
default_backend nginx_pool
backend nginx_pool
balance roundrobin
mode tcp
server web1 web_server_1_private_IP:80 check
server web2 web_server_2_private_IP:80 check
上記の変更が完了したら、ファイルを保存して閉じます。
次のように入力して、行った構成変更が有効なHAProxy構文を表していることを確認します。
sudo haproxy -f /etc/haproxy/haproxy.cfg -c
エラーが報告されていない場合は、次を入力してサービスを再起動します。
sudo service haproxy restart
変更のテスト
curl
で再度テストすることにより、構成が有効であることを確認できます。
ロードバランサーサーバーから、ローカルホスト、ロードバランサー自身のパブリックIPアドレス、またはサーバー自身のプライベートIPアドレスをリクエストしてください:
curl 127.0.0.1
curl load_balancer_public_IP
curl load_balancer_private_IP
これらはすべて、次のようなメッセージで失敗します。
Outputcurl: (7) Failed to connect to address port 80: Connection refused
ただし、ロードバランサーのanchor IP addressにリクエストを送信すると、正常に完了するはずです。
curl load_balancer_anchor_IP
2つのバックエンドWebサーバーのいずれかからルーティングされたデフォルトのNginxindex.html
ページが表示されます。
Output
Welcome to nginx!
. . .
この動作がシステムの動作と一致する場合、ロードバランサーは正しく構成されています。
Keepalivedのビルドとインストール
現在、実際のサービスは稼働しています。 ただし、アクティブなロードバランサーで問題が発生した場合、トラフィックをリダイレクトする方法がないため、インフラストラクチャの可用性はまだ高くありません。 これを修正するために、ロードバランサーサーバーにkeepalived
デーモンをインストールします。 これは、アクティブなロードバランサーが利用できなくなった場合にフェールオーバー機能を提供するコンポーネントです。
Ubuntuのデフォルトリポジトリにはkeepalived
のバージョンがありますが、それは古く、構成が機能しなくなるいくつかのバグがあります。 代わりに、ソースから最新バージョンのkeepalived
をインストールします。
開始する前に、ソフトウェアのビルドに必要な依存関係を取得する必要があります。 build-essential
メタパッケージは必要なコンパイルツールを提供し、libssl-dev
パッケージにはkeepalived
が構築する必要のあるSSL開発ライブラリが含まれています。
sudo apt-get install build-essential libssl-dev
依存関係が設定されたら、keepalived
のtarballをダウンロードできます。 this pageにアクセスして、ソフトウェアの最新バージョンを見つけてください。 最新バージョンを右クリックして、リンクアドレスをコピーします。 サーバーに戻り、ホームディレクトリに移動し、wget
を使用してコピーしたリンクを取得します。
cd ~
wget http://www.keepalived.org/software/keepalived-1.2.19.tar.gz
tar
コマンドを使用して、アーカイブを展開します。 結果のディレクトリに移動します。
tar xzvf keepalived*
cd keepalived*
次を入力して、デーモンをビルドおよびインストールします。
./configure
make
sudo make install
これで、両方のロードバランサシステムにデーモンをインストールする必要があります。
Keepalived Upstartスクリプトを作成する
keepalived
のインストールにより、すべてのバイナリとサポートファイルがシステム上の所定の場所に移動しました。 ただし、Ubuntu 14.04システム用のUpstartスクリプトは含まれていませんでした。
keepalived
サービスを処理できる非常に単純なUpstartスクリプトを作成できます。 開始するには、/etc/init
ディレクトリ内のkeepalived.conf
というファイルを開きます。
sudo nano /etc/init/keepalived.conf
内部では、keepalived
が提供する機能の簡単な説明から始めることができます。 含まれているman
ページの説明を使用します。 次に、サービスを開始および停止するランレベルを指定します。 このサービスは、すべての通常の状態(ランレベル2〜5)でアクティブになり、他のすべてのランレベル(たとえば、再起動、電源オフ、シングルユーザーモードが開始されたとき)で停止します。
/etc/init/keepalived.conf
description "load-balancing and high-availability service"
start on runlevel [2345]
stop on runlevel [!2345]
このサービスはWebサービスを引き続き利用できるようにするために不可欠なので、障害が発生した場合にこのサービスを再起動する必要があります。 次に、サービスを開始する実際のexec
行を指定できます。 Upstartがpid
を正しく追跡できるように、--dont-fork
オプションを追加する必要があります。
/etc/init/keepalived.conf
description "load-balancing and high-availability service"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /usr/local/sbin/keepalived --dont-fork
完了したら、ファイルを保存して閉じます。
Keepalived構成ファイルを作成する
Upstartファイルを配置したら、keepalived
の構成に進むことができます。
サービスは、/etc/keepalived
ディレクトリで構成ファイルを探します。 両方のロードバランサーでこのディレクトリを作成します。
sudo mkdir -p /etc/keepalived
プライマリロードバランサーの構成の作成
次に、primaryサーバーとして使用するロードバランサーサーバーで、メインのkeepalived
構成ファイルを作成します。 デーモンは、/etc/keepalived
ディレクトリ内でkeepalived.conf
というファイルを探します。
sudo nano /etc/keepalived/keepalived.conf
内部では、vrrp_script
ブロックを開いて、HAProxyサービスのヘルスチェックを定義することから始めます。 これにより、keepalived
がロードバランサーの障害を監視できるようになり、プロセスがダウンしていることを通知して、対策の回復を開始できます。
チェックは非常に簡単です。 2秒ごとに、haproxy
というプロセスがまだpid
を要求していることを確認します。
プライマリサーバーの/etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}
次に、vrrp_instance
というブロックを開きます。 これは、keepalived
が高可用性を実装する方法を定義する主要な構成セクションです。
まず、keepalived
に、プライベートインターフェイスであるeth1
を介してピアと通信するように指示します。 プライマリサーバーを構成しているので、state
構成を「MASTER」に設定します。 これは、デーモンがピアに接続して選択を行うことができるまで、keepalived
が使用する初期値です。
選出中、priority
オプションを使用して、選出されるメンバーを決定します。 決定は、どのサーバーがこの設定の最大数を持っているかに基づいています。 プライマリサーバーには「200」を使用します。
プライマリサーバーの/etc/keepalived/keepalived.conf
vrrp_script chk_nginx {
script "pidof nginx"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
}
次に、両方のノードで共有されるこのクラスターグループにIDを割り当てます。 この例では「33」を使用します。 unicast_src_ip
をprimaryロードバランサーのプライベートIPアドレスに設定する必要があります。 unicast_peer
をsecondaryロードバランサーのプライベートIPアドレスに設定します。
プライマリサーバーの/etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
virtual_router_id 33
unicast_src_ip primary_private_IP
unicast_peer {
secondary_private_IP
}
}
次に、keepalived
デーモンが相互に通信するための簡単な認証を設定できます。 これは、連絡先のピアが正当であることを確認するための基本的な手段にすぎません。 authentication
サブブロックを作成します。 内部で、auth_type
を設定してパスワード認証を指定します。 auth_pass
パラメータには、両方のノードで使用される共有シークレットを設定します。 残念ながら、重要なのは最初の8文字のみです。
プライマリサーバーの/etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
virtual_router_id 33
unicast_src_ip primary_private_IP
unicast_peer {
secondary_private_IP
}
authentication {
auth_type PASS
auth_pass password
}
}
次に、ファイルの先頭に作成したchk_haproxy
というラベルの付いたチェックを使用して、ローカルシステムの状態を判断するようにkeepalived
に指示します。 最後に、このノードがペアの「マスター」になるたびに実行されるnotify_master
スクリプトを設定します。 このスクリプトは、フローティングIPアドレスの再割り当てをトリガーします。 このスクリプトを一時的に作成します。
プライマリサーバーの/etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state MASTER
priority 200
virtual_router_id 33
unicast_src_ip primary_private_IP
unicast_peer {
secondary_private_IP
}
authentication {
auth_type PASS
auth_pass password
}
track_script {
chk_haproxy
}
notify_master /etc/keepalived/master.sh
}
上記の情報を設定したら、ファイルを保存して閉じます。
セカンダリロードバランサーの構成の作成
次に、セカンダリロードバランサーでコンパニオンスクリプトを作成します。 セカンダリサーバーの/etc/keepalived/keepalived.conf
でファイルを開きます。
sudo nano /etc/keepalived/keepalived.conf
内部では、使用するスクリプトは主サーバーのスクリプトとほぼ同等です。 変更する必要がある項目は次のとおりです。
-
state
:選択が行われる前にノードがバックアップ状態に初期化されるように、これをセカンダリサーバーで「BACKUP」に変更する必要があります。 -
priority
:これはプライマリサーバーよりも低い値に設定する必要があります。 このガイドでは、値「100」を使用します。 -
unicast_src_ip
:これはsecondaryサーバーのプライベートIPアドレスである必要があります。 -
unicast_peer
:これにはprimaryサーバーのプライベートIPアドレスが含まれている必要があります。
これらの値を変更すると、セカンダリサーバーのスクリプトは次のようになります。
セカンダリサーバーの/etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
}
vrrp_instance VI_1 {
interface eth1
state BACKUP
priority 100
virtual_router_id 33
unicast_src_ip secondary_private_IP
unicast_peer {
primary_private_IP
}
authentication {
auth_type PASS
auth_pass password
}
track_script {
chk_haproxy
}
notify_master /etc/keepalived/master.sh
}
スクリプトを入力して適切な値を変更したら、ファイルを保存して閉じます。
フローティングIP移行スクリプトを作成する
次に、ローカルkeepalived
インスタンスがマスターサーバーになるたびに、フローティングIPアドレスを現在のドロップレットに再割り当てするために使用できるスクリプトのペアを作成する必要があります。
フローティングIP割り当てスクリプトをダウンロードする
まず、DigitalOcean APIを使用してフローティングIPアドレスをドロップレットに再割り当てするために使用できる汎用Pythonスクリプト(DigitalOcean community managerで記述)をダウンロードします。 このファイルを/usr/local/bin
ディレクトリにダウンロードする必要があります。
cd /usr/local/bin
sudo curl -LO http://do.co/assign-ip
このスクリプトを使用すると、次を実行して既存のフローティングIPを再割り当てできます。
python /usr/local/bin/assign-ip floating_ip droplet_ID
これは、DO_TOKEN
という環境変数がアカウントの有効なDigitalOceanAPIトークンに設定されている場合にのみ機能します。
DigitalOcean APIトークンを作成する
上記のスクリプトを使用するには、アカウントにDigitalOcean APIトークンを作成する必要があります。
コントロールパネルで、上部の[API]リンクをクリックします。 APIページの右側で、「新しいトークンを生成」をクリックします。
次のページで、トークンの名前を選択し、「トークンの生成」ボタンをクリックします。
APIページに、新しいトークンが表示されます:
トークンnowをコピーします。 セキュリティのため、このトークンを後で表示する方法はありません。 このトークンを紛失した場合、それを破棄して別のトークンを作成する必要があります。
インフラストラクチャにフローティングIPを構成する
次に、サーバーで使用するフローティングIPアドレスを作成して割り当てます。
DigitalOceanコントロールパネルで、「ネットワーク」タブをクリックし、「フローティングIP」ナビゲーション項目を選択します。 初期割り当てのメニューからプライマリロードバランサーを選択します。
アカウントに新しいフローティングIPアドレスが作成され、指定されたドロップレットに割り当てられます。
WebブラウザでフローティングIPにアクセスすると、バックエンドWebサーバーの1つから提供されるデフォルトのNginxページが表示されます。
フローティングIPアドレスをコピーします。 以下のスクリプトでこの値が必要になります。
ラッパースクリプトを作成する
これで、正しい資格情報を使用して/usr/local/bin/assign-ip
スクリプトを呼び出すラッパースクリプトを作成するために必要な項目ができました。
次のように入力して、ロードバランサーのbothにファイルを作成します。
sudo nano /etc/keepalived/master.sh
内部では、作成したAPIトークンを保持するDO_TOKEN
という変数を割り当ててエクスポートすることから始めます。 その下に、フローティングIPアドレスを保持するIP
という変数を割り当てることができます。
/etc/keepalived/master.sh
export DO_TOKEN='digitalocean_api_token'
IP='floating_ip_addr'
次に、curl
を使用して、現在使用しているサーバーのドロップレットIDをメタデータサービスに要求します。 これは、ID
という変数に割り当てられます。 また、このDropletに現在フローティングIPアドレスが割り当てられているかどうかを尋ねます。 そのリクエストの結果をHAS_FLOATING_IP
という変数に保存します。
/etc/keepalived/master.sh
export DO_TOKEN='digitalocean_api_token'
IP='floating_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_FLOATING_IP=$(curl -s http://169.254.169.254/metadata/v1/floating_ip/ipv4/active)
これで、上記の変数を使用してassign-ip
スクリプトを呼び出すことができます。 フローティングIPがドロップレットに関連付けられていない場合にのみ、スクリプトを呼び出します。 これにより、API呼び出しが最小限に抑えられ、マスターステータスがサーバー間で急速に切り替わる場合に、APIへの競合する要求が防止されます。
フローティングIPですでに進行中のイベントがある場合を処理するために、assign-ip
スクリプトを数回再試行します。 以下では、各呼び出しの間に3秒間隔で、スクリプトを10回実行しようとします。 フローティングIPの移動が成功すると、ループはすぐに終了します。
/etc/keepalived/master.sh
export DO_TOKEN='digitalocean_api_token'
IP='floating_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_FLOATING_IP=$(curl -s http://169.254.169.254/metadata/v1/floating_ip/ipv4/active)
if [ $HAS_FLOATING_IP = "false" ]; then
n=0
while [ $n -lt 10 ]
do
python /usr/local/bin/assign-ip $IP $ID && break
n=$((n+1))
sleep 3
done
fi
完了したら、ファイルを保存して閉じます。
ここで、keepalived
がスクリプトを呼び出せるように、スクリプトを実行可能にする必要があります。
sudo chmod +x /etc/keepalived/master.sh
Keepalivedサービスの起動とフェールオーバーのテスト
これで、keepalived
デーモンとそのすべてのコンパニオンスクリプトが完全に構成されます。 次のように入力して、両方のロードバランサーでサービスを開始できます。
sudo start keepalived
サービスは各サーバーで起動し、ピアに接続して、構成した共有シークレットで認証する必要があります。 各デーモンはローカルHAProxyプロセスを監視し、リモートkeepalived
プロセスからのシグナルをリッスンします。
現在、フローティングIPアドレスが割り当てられているプライマリロードバランサーは、リクエストを各バックエンドNginxサーバーに順番に送信します。 通常適用される単純なセッションスティッキがいくつかあり、Webブラウザーを介して要求を行うときに同じバックエンドを取得する可能性が高くなります。
プライマリロードバランサーでHAProxyをオフにするだけで、簡単な方法でフェールオーバーをテストできます。
sudo service haproxy stop
ブラウザでフローティングIPアドレスにアクセスすると、ページが見つからなかったことを示すエラーが一時的に表示される場合があります。
http://floating_IP_addr
ページを数回更新すると、すぐにデフォルトのNginxページが表示されます:
HAProxyサービスはプライマリロードバランサーでまだ停止しているため、セカンダリロードバランサーが引き継いだことを示しています。 keepalived
を使用して、セカンダリサーバーはサービスの中断が発生したことを判別できました。 その後、「マスター」状態に移行し、DigitalOcean APIを使用してフローティングIPを要求しました。
これで、プライマリロードバランサーでHAProxyを再び起動できます。
sudo service haproxy start
プライマリロードバランサーは、すぐにフローティングIPアドレスの制御を取り戻しますが、これはユーザーに対してかなり透過的でなければなりません。
遷移の視覚化
ロードバランサー間の移行をよりよく視覚化するために、移行中にサーバーログの一部を監視できます。
使用されているプロキシサーバーに関する情報はクライアントに返されないため、ログを表示するのに最適な場所は、実際のバックエンドWebサーバーからです。 これらの各サーバーは、どのクライアントがアセットを要求するかに関するログを保持する必要があります。 Nginxサービスの観点から見ると、クライアントは実際のクライアントに代わってリクエストを行うロードバランサーです。
Webサーバーでログを追跡する
各バックエンドWebサーバーで、/var/log/nginx/access.log
の場所をtail
にすることができます。 これにより、サーバーに対して行われた各リクエストが表示されます。 ロードバランサーはラウンドロビンローテーションを使用してトラフィックを均等に分割するため、各バックエンドWebサーバーは約半分のリクエストを確認する必要があります。
幸いなことに、クライアントアドレスはアクセスログの最初のフィールドです。 単純なawk
コマンドを使用して値を抽出できます。 Nginx Webサーバーのbothで以下を実行します。
sudo tail -f /var/log/nginx/access.log | awk '{print $1;}'
これらは、ほとんどの場合単一のアドレスを示します。
Output. . .
primary_lb_private_IP
primary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
サーバーのIPアドレスを参照すると、これらのほとんどがプライマリロードバランサーからのものであることがわかります。 実際の配布は、HAProxyが実装する単純なセッションスティッキ性により、少し異なる可能性が高いことに注意してください。
両方のWebサーバーでtail
コマンドを実行し続けます。
フローティングIPへのリクエストを自動化する
次に、ローカルマシンで、2秒ごとに1回、フローティングIPアドレスでWebコンテンツを要求します。 これにより、ロードバランサーの変更が簡単に確認できます。 ローカルターミナルで、次のように入力します(実際の応答は破棄されます。これは、どのロードバランサーが使用されているかに関係なく同じであるためです)。
while true; do curl -s -o /dev/null floating_IP; sleep 2; done
Webサーバーで、新しい要求が着信するのを確認する必要があります。 Webブラウザーを介して行われる要求とは異なり、単純なcurl
要求は、同じセッションのスティッキ性を示しません。 バックエンドWebサーバーへのリクエストがより均等に分割されるはずです。
プライマリロードバランサーでHAProxyサービスを中断する
これで、プライマリロードバランサーのHAProxyサービスを再びシャットダウンできます。
sudo service haproxy stop
数秒後、ウェブサーバーで、プライマリロードバランサーのプライベートIPアドレスからセカンダリロードバランサーのプライベートIPアドレスに移行するIPのリストが表示されます。
Output. . .
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
新しいリクエストはすべて、セカンダリロードバランサーから行われます。
次に、プライマリロードバランサーでHAProxyインスタンスを再度起動します。
sudo service haproxy start
クライアントリクエストが数秒以内にプライマリロードバランサーのプライベートIPアドレスに戻ることがわかります。
Output. . .
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
secondary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
primary_lb_private_IP
プライマリサーバーは、フローティングIPアドレスの制御を取り戻し、インフラストラクチャのメインロードバランサーとしてのジョブを再開しました。
実際のクライアントIPアドレスを記録するようにNginxを構成する
これまで見てきたように、Nginxアクセスログは、すべてのクライアントリクエストが、リクエストを最初に作成したクライアントの実際のIPアドレスではなく、現在のロードバランサーのプライベートIPアドレスからのものであることを示しています(つまり、 ローカルマシン)。 ロードバランサーサーバーではなく、元のクライアントのIPアドレスをログに記録しておくと便利です。 これは、すべてのバックエンドWebサーバーでNginx構成にいくつかの変更を加えることで簡単に実現できます。
両方のWebサーバーで、エディターでnginx.conf
ファイルを開きます。
sudo nano /etc/nginx/nginx.conf
「ログ設定」セクション(http
ブロック内)を見つけて、次の行を追加します。
/etc/nginx/nginx.confに追加します
log_format haproxy_log 'ProxyIP: $remote_addr - ClientIP: $http_x_forwarded_for - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';
保存して終了。 これは、haproxy_log
と呼ばれる新しいログ形式を指定します。これにより、$http_x_forwarded_for
値(元の要求を行ったクライアントのIPアドレス)がデフォルトのアクセスログエントリに追加されます。 リバースプロキシロードバランサーのIPアドレスである$remote_addr
も含まれています(つまり、 アクティブなロードバランサーサーバー)。
次に、この新しいログ形式を使用するには、デフォルトのサーバーブロックに行を追加する必要があります。
両方のWebサーバーで、default
サーバー構成を開きます。
sudo nano /etc/nginx/sites-available/default
server
ブロック内(listen
ディレクティブのすぐ下が適切な場所です)に、次の行を追加します。
/ etc / nginx / sites-available / defaultに追加します
access_log /var/log/nginx/access.log haproxy_log;
保存して終了。 これは、上記で作成したhaproxy_log
ログ形式を使用してアクセスログを書き込むようにNginxに指示します。
両方のWebサーバーで、Nginxを再起動して変更を有効にします。
sudo service nginx restart
これで、Nginxアクセスログには、リクエストを行っているクライアントの実際のIPアドレスが含まれているはずです。 前のセクションで行ったように、アプリサーバーのログを追跡することでこれを確認します。 ログエントリは次のようになります。
New Nginx access logs:. . .
ProxyIP: load_balancer_private_IP - ClientIP: local_machine_IP - - [05/Nov/2015:15:05:53 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0"
. . .
ログがよければ、設定は完了です!
結論
このガイドでは、可用性の高い、負荷分散されたインフラストラクチャをセットアップする完全なプロセスを説明しました。 アクティブなHAProxyサーバーがバックエンドのWebサーバーのプールに負荷を分散できるため、この構成はうまく機能します。 需要の増減に応じて、このプールを簡単に拡張できます。
フローティングIPとkeepalived
構成により、負荷分散レイヤーでの単一障害点が排除され、プライマリロードバランサーに完全な障害が発生した場合でもサービスが機能し続けることができます。 この構成はかなり柔軟であり、HAProxyサーバーの背後に好みのWebスタックをセットアップすることにより、独自のアプリケーション環境に適合させることができます。