Ubuntu 14.04でKeepalivedおよびフローティングIPを使用して高可用性HAProxyサーバーをセットアップする方法

前書き

高可用性はシステム設計の機能であり、障害が発生した場合にアプリケーションが自動的に再起動するか、作業を別の対応システムに再ルーティングできるようにします。 サーバーに関しては、可用性の高いシステムをセットアップするために必要なテクノロジーがいくつかあります。 作業をリダイレクトできるコンポーネントが必要です。また、障害を監視し、中断が検出された場合にシステムを移行するメカニズムが必要です。

keepalivedデーモンを使用して、サービスまたはシステムを監視し、問題が発生した場合にスタンバイに自動的にフェイルオーバーすることができます。 このガイドでは、keepalivedを使用してロードバランサーの高可用性を設定する方法を示します。 2つの対応するロードバランサー間で移動できるfloating IP addressを構成します。 これらはそれぞれ、2つのバックエンドWebサーバー間でトラフィックを分割するように構成されます。 プライマリロードバランサーがダウンすると、フローティングIPは自動的に2番目のロードバランサーに移動し、サービスを再開できます。

High Availability diagram

[.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_ipprimaryロードバランサーのプライベートIPアドレスに設定する必要があります。 unicast_peersecondaryロードバランサーのプライベート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ページの右側で、「新しいトークンを生成」をクリックします。

DigitalOcean generate API token

次のページで、トークンの名前を選択し、「トークンの生成」ボタンをクリックします。

DigitalOcean make new token

APIページに、新しいトークンが表示されます:

DigitalOcean token

トークンnowをコピーします。 セキュリティのため、このトークンを後で表示する方法はありません。 このトークンを紛失した場合、それを破棄して別のトークンを作成する必要があります。

インフラストラクチャにフローティングIPを構成する

次に、サーバーで使用するフローティングIPアドレスを作成して割り当てます。

DigitalOceanコントロールパネルで、「ネットワーク」タブをクリックし、「フローティングIP」ナビゲーション項目を選択します。 初期割り当てのメニューからプライマリロードバランサーを選択します。

DigitalOcean add floating IP

アカウントに新しいフローティングIPアドレスが作成され、指定されたドロップレットに割り当てられます。

DigitalOcean floating IP assigned

WebブラウザでフローティングIPにアクセスすると、バックエンドWebサーバーの1つから提供されるデフォルトのNginxページが表示されます。

DigitalOcean default index.html

フローティング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

DigitalOcean page not available

ページを数回更新すると、すぐにデフォルトのNginxページが表示されます:

DigitalOcean default index.html

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スタックをセットアップすることにより、独自のアプリケーション環境に適合させることができます。

Related