負荷分散のためのフェールオーバークラスター

水平スケーリングについて説明します。 プロジェクトが1台のサーバーが負荷に対応できないサイズまで成長し、リソースの垂直成長の機会がないとしましょう。







この場合、プロジェクトインフラストラクチャのさらなる開発は、通常、同じタイプのサーバーの数が増加し、それらの間で負荷が分散されるために発生します。 このアプローチにより、リソースの問題を解決できるだけでなく、プロジェクトの信頼性も向上します。1つまたは複数のコンポーネントに障害が発生しても、全体的なパフォーマンスが損なわれることはありません。







このスキームで大きな役割を果たしているのは、リクエスト/トラフィックを分散するシステムであるバランサーです。 設計段階では、次の重要な要件を満たすことが重要です。









実際、これはノードがサーバーのバランスを取っているクラスターの説明です。







この記事では、シンプルで控えめなリソース向けのクラスターのレシピを共有します。このコンセプトは、コントロールパネルのサーバー、内部DNSサーバー、 Galeraクラスター、さまざまなマイクロサービスへのリクエストのバランスをとるために独自のインフラストラクチャでうまく使用されています。







条件に同意します。



-クラスターを構成するサーバーは、ノードまたはバランサーと呼ばれます。

-最終サーバーは、トラフィックがクラスターを介してプロキシされるホストになります。

-仮想IPは、すべてのノード間で「浮動」するアドレスであり、DNSのサービス名が指すアドレスです。







必要なもの:



-クラスターを構成するには、それぞれに2つのネットワークインターフェイスを持つ少なくとも2つのサーバー(または仮想マシン)が必要です。

-最初のインターフェイスは、外部との通信に使用されます。 ここで、実際のIPアドレスと仮想IPアドレスが構成されます。

-2番目のインターフェイスは、サービストラフィック、相互の通信ノードに使用されます。 ここで、プライベート(「グレー」)ネットワーク172.16.0.0/24からのアドレスが設定されます。

各ノードの2番目のインターフェイスは、同じネットワークセグメントにある必要があります。







使用されるテクノロジー:



VRRP、仮想ルーター冗長プロトコル -この記事のコンテキストでは、クラスター内のノード間で浮動する仮想IPアドレスの実装。 ある時点で、そのようなアドレスは、MASTERと呼ばれる任意の1つのノードで発生させることができます。 2番目のノードはBACKUPと呼ばれます。 両方のノードは、常に特別なハートビートメッセージを交換します。 指定された間隔内でそのようなメッセージを受信または受信しないと、仮想IPを「ライブ」サーバーに再割り当てする根拠が与えられます。 プロトコルの詳細については、 こちらをご覧ください







LVS、Linux Virtual Server -IPVSモジュールとしてLinuxカーネルに組み込まれたトランスポート/セッションレベルバランサー。 LVS機能の詳細な説明は、 ここここにあります

作業の本質は、「IP +ポート」の特定のペアがあり、それが仮想サーバーであることを示すことです。 このペアには、リクエストの処理を担当する実サーバーのアドレスが割り当てられ、バランシングアルゴリズムが設定され、リクエスト転送モードが設定されます。







このシステムでは、トラフィックをプロキシする必要があるLVSとエンドサーバー間の中間としてNginxを使用します。 Nginxはすべてのノードに存在します。







VRRPの設定とIPVSとの対話には、Linux Virtual Serverプロジェクトの一部として作成されたKeepalivedデーモンを使用します。







コンセプト



システムは、LVSテクノロジーとVRRPプロトコルを使用してクラスターに結合された、互いに独立した2つの均等にバランスの取れたバランスノードです。







トラフィックのエントリポイントは、1つまたは2番目のノードで発生した仮想IPアドレスになります。







LVSは、受信リクエストを、実行中のNginxインスタンスの1つ(ローカルまたは隣接ノード)にリダイレクトします。 このアプローチにより、クラスターのすべてのノード間でリクエストを均等に分散できます。 各バランサーのリソースをより有効に活用します。











Nginxの仕事は、要求を宛先サーバーにプロキシすることです。 バージョン1.9.13以降、プロキシ機能はtcpおよびudpトランスポートプロトコルレベルで使用できます。







各vhost /ストリームは、近隣のバランサーからのサービスインターフェイスと仮想IPへの着信の両方の要求を受け入れるように構成されます。 また、仮想IPアドレスがこのバランサーで物理的に発生していない場合でも(KeepalivedはサーバーにBACKUPロールを割り当てました)。







したがって、バランサーの状態(MASTERまたはBACKUP)に応じたトラフィックパターンは次のようになります。







マスター:









バックアップ:









実装:



オペレーティングシステムとして、 バックポートリポジトリが接続されたDebian Jessieを使用します







各バランサーノードに、操作に必要なソフトウェアクラスターを含むパッケージをインストールし、いくつかのシステム全体の設定を行います。







apt-get update apt-get install -t jessie-backports nginx apt-get install keepalived ipvsadm
      
      





eth1



インターフェースで、グレーネットワーク172.16.0.0/24



からアドレスを構成します。







 allow-hotplug eth1 iface eth1 inet static address 172.16.0.1 #    -- 172.16.0.2 netmask 255.255.255.0
      
      





eth0



インターフェイスに仮想IPアドレスを登録する必要はありません。 これは維持されます。







/etc/sysctl.d/local.conf



ファイルに次のディレクティブを追加します。







 net.ipv4.ip_nonlocal_bind = 1 net.ipv4.vs.drop_entry = 1 net.nf_conntrack_max = 4194304
      
      





最初のものには、ローカルで発生しないIPをリッスンする機能が含まれます(これはNginxが機能するために必要です)。 2番目には、IPVSバランサーのレベルでのDDoSに対する自動保護が含まれます(セッションテーブルに十分なメモリがない場合、一部のレコードの自動クリーニングが開始されます)。 3番目は、conntrackテーブルのサイズを増やします。







/etc/modules



システムの起動時にIPVSモジュールのロードを有効にし/etc/modules









 ip_vs conn_tab_bits=18
      
      





conn_tab_bits



パラメーターは、接続を持つテーブルのサイズを決定します。 その値は2の累乗です。 最大許容値は20です。







ところで、Keepalivedの開始前にモジュールがロードされない場合、Keepalivedはsegfaltを開始します。







次に、両方のバランスノードを再起動します。 したがって、起動時に構成全体が正しく上昇することを確認します。










一般設定が完了しました。 次の2つのタスクのコンテキストでさらにアクションを実行します。









入力データ:









Nginxの設定から始めましょう。







ストリームセクションの説明を/etc/nginx/nginx.conf



追加し/etc/nginx/nginx.conf









 stream { include /etc/nginx/stream-enabled/*; }
      
      





そして、適切なディレクトリを作成します。







 mkdir /etc/nginx/stream-enabled
      
      





Webサーバーの設定をファイル/etc/nginx/sites-enabled/web_servers.conf



追加します







 upstream web_servers { server 192.168.0.101:80; server 192.168.0.102:80; server 192.168.0.103:80; } server { listen 172.16.0.1:80 default_server; #    -- 172.16.0.2 listen 192.168.0.100:80 default_server; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://web_servers; proxy_redirect default; } }
      
      





DNSサーバーの設定をファイル/etc/nginx/stream-enabled/dns_servers.conf



ます







 upstream dns_servers { server 192.168.0.201:53; server 192.168.0.202:53; } server { listen 172.16.0.1:53 udp reuseport; #    -- 172.16.0.2 listen 192.168.0.100:53 udp reuseport; proxy_pass dns_servers; }
      
      





その後、Keepalived(VRRP + LVS)を構成します。 バランシングノードがMASTER / BACKUP状態の間を移動するときに実行される特別なスクリプトを記述する必要があるため、これはもう少し複雑です。







すべての/etc/keepalived/keepalived.conf



設定は、1つのファイル/etc/keepalived/keepalived.conf



必要があります。 したがって、VRRPおよびLVS構成の次のブロックはすべて、このファイルに順番に保存する必要があります。







VRRP設定:







 vrrp_instance 192.168.0.100 { interface eth1 #      VRRP track_interface { #          eth0 #   ,     eth1 # FAULT, ..      IP  #   LVS } virtual_router_id 1 #      nopreempt #       BACKUP #          priority 102 # .      authentication { auth_type PASS auth_pass secret #      } virtual_ipaddress { 192.168.0.100/24 dev eth0 } notify /usr/local/bin/nat-switch }
      
      





上記のスクリプトは/usr/local/bin/nat-switch



です。 現在のVRRPインスタンスの状態が変わるたびに開始されます。 そのタスクは、BACKUP状態のバランサーが仮想IP宛てのパケットを正しく処理できるようにすることです。 この状況を解決するために、DNAT機能が使用されます。 つまり、次の形式のルール:







 -A PREROUTING -d 192.168.0.100/32 -i eth1 -j DNAT --to-destination ${IP_on_eth1}
      
      





MASTER状態に移行すると、スクリプトはこのルールを削除します。







ここでは、この例のために書かれたnat-switch



スクリプトのバリアントを見つけることができます。







WebサーバーのグループのLVS設定:







 virtual_server 192.168.0.100 80 { lb_algo wlc #   # wlc --       - #  . lb_kind DR #   . Direct routing protocol TCP delay_loop 6 #    healthchecker' real_server 172.16.0.1 80 { weight 1 TCP_CHECK { #     connect_timeout 2 #    Nginx } } real_server 172.16.0.2 80 { weight 1 TCP_CHECK { connect_timeout 2 } } }
      
      





DNSサーバーのグループのLVS設定:







 virtual_server 192.168.0.100 53 { lb_algo wlc lb_kind DR protocol UDP delay_loop 6 real_server 172.16.0.1 53 { weight 1 MISC_CHECK { connect_timeout 2 misc_path "/bin/nc -zn -u 172.16.0.1 53" } } real_server 172.16.0.2 53 { weight 1 MISC_CHECK { connect_timeout 2 misc_path "/bin/nc -zn -u 172.16.0.2 53" } } }
      
      





最後に、NginxとKeepalivedの構成を再読み込みします。







 nginx -s reload && /etc/init.d/keepalived reload
      
      





テスト:



バランサーがどのようにリクエストを宛先サーバーに配信するかを見てみましょう。 これを行うには、各Webサーバーで、簡単なコンテンツを含むindex.php



を作成します。







 <?php sleep(rand(2, 8)); echo("Hello from ".gethostname()." !"); ?>
      
      





そして、httpを介して仮想IP 192.168.0.100



いくつかのリクエストを行います。







 for i in $(seq 10); do printf 'GET / HTTP/1.0\n\n\n' | nc 192.168.0.100 80 | grep Hello done
      
      





結果:







 Hello from server-1 ! Hello from server-2 ! Hello from server-2 ! Hello from server-3 ! Hello from server-3 ! Hello from server-1 ! Hello from server-1 ! Hello from server-2 ! Hello from server-2 ! Hello from server-3 !
      
      





このサイクルの実行中に(MASTERノードでの)LVS操作の統計を見ると、次の図を見ることができます。







 ipvsadm -Ln
      
      





結果:







 IP Virtual Server version 1.2.1 (size=262144) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.100:80 wlc -> 172.16.0.1:80 Route 1 1 3 -> 172.16.0.2:80 Route 1 1 3 UDP 192.168.0.100:53 wlc -> 172.16.0.1:53 Route 1 0 0 -> 172.16.0.2:53 Route 1 0 0
      
      





ここでは、クラスターのノード間で要求がどのように分散されるかを確認できます。現在処理中のアクティブな接続が2つ、処理済みの接続が6つあります。







LVSを通過するすべての接続の統計は、次のように表示できます。







 ipvsadm -Lnc
      
      





結果:







 IPVS connection entries pro expire state source virtual destination TCP 14:57 ESTABLISHED 192.168.0.254:59474 192.168.0.100:80 172.16.0.1:80 TCP 01:49 FIN_WAIT 192.168.0.254:59464 192.168.0.100:80 172.16.0.1:80 TCP 01:43 FIN_WAIT 192.168.0.254:59462 192.168.0.100:80 172.16.0.1:80 TCP 14:59 ESTABLISHED 192.168.0.254:59476 192.168.0.100:80 172.16.0.2:80 TCP 01:56 FIN_WAIT 192.168.0.254:59468 192.168.0.100:80 172.16.0.1:80 TCP 01:57 FIN_WAIT 192.168.0.254:59472 192.168.0.100:80 172.16.0.2:80 TCP 01:50 FIN_WAIT 192.168.0.254:59466 192.168.0.100:80 172.16.0.2:80 TCP 01:43 FIN_WAIT 192.168.0.254:59460 192.168.0.100:80 172.16.0.2:80
      
      





ここでは、それぞれ同じことがわかります。2つのアクティブな接続と6つの非アクティブな接続です。







あとがき:



提案された構成は、独自の要件と機能を備えた特定のプロジェクトの特定のソリューションの設計の出発点として機能します。







記事について何か質問がある場合、または物議をかもしているように思われるものがある場合は、コメントを残してください。喜んで話し合います。








All Articles