HTTPロードバランシングレイヤーをスケーリングするための鍵は、最初に下位レベル(IPまたはTCP)ロードバランシングの別のレイヤーを追加することです。このレイヤーは完全にオープンソースソフトウェアで構築できますが、最新のルーターを使用すればより良い結果が得られます。
フロー(TCPセッション)は、送信元/宛先IPやTCPポートなどのヘッダーを使用してハッシュし、どのフロントエンドに移動するかを決定する必要があります。また、フロントエンドが停止したときに、フロントエンドが使用されなくなることを確認するメカニズムも必要です。
さまざまな戦略がありますが、何百万人ものユーザーにサービスを提供するサイトで本番で使用したカップルの概要を説明します。すべてを詳細に説明するのは長すぎますが、この回答があなたが始めるのに十分な情報/ポインターを提供することを願っています。これらのソリューションを実装するには、ネットワークについて本当に知識のある人が必要になります。
確かに、ここで説明していることは、他の回答で説明されているものよりも実装がはるかに困難ですが、99.9%を超える大きなスケーラビリティの問題と可用性の要件を備えたトラフィックの多いWebサイトがある場合、これは本当に最先端です。既にネットワークエンジニアを搭載している場合は、ロードバランサーアプライアンスよりもセットアップと実行(capexとopexの両方)にかかる費用が少なく、追加費用をほとんどかけずにさらに拡張できます(新規購入など)現在のモデルよりも大きくなった場合の高価なアプライアンス)。
最初の戦略:ファイアウォールを使用する
おそらく、ISPアップリンクが接続されている2つのルーターがあります。ISPは2つのリンクを提供します(VRRPを使用したアクティブ/パッシブ)。ルーターでは、VRRPも使用し、パブリックネットワークに向かうトラフィックをファイアウォールにルーティングします。ファイアウォールは、(FW 1
およびFW 2
下記)もまた、アクティブ/パッシブであり、(あなたのHTTPロードバランサを、トラフィックをフィルタリングし、健康的なフロントエンドサーバーへの各フローを送信するFE 1
と、FE 2
下記)。
+ -------------- + + -------------- +
| ISPルーターA | | ISPルーターB |
+ -------------- + + -------------- +
| |
==#======================#==(パブリックネットワーク)
| |
+ --------------- + + --------------- +
| ルーターA | | ルーターB |
+ --------------- + + --------------- +
| |
==#=====#==========#=====#==(RFC 1918プライベートネットワーク)
| | | |
+ ------ + + ------ + + ------ + + ------ +
| FW 1 | | FE 1 | | FE 2 | | FW 2 |
+ ------ + + ------ + + ------ + + ------ +
目標は、フローを次のようにすることです。
- ISPはIPに向かうトラフィックをアクティブルーターにルーティングします。
- ルーターは、RFC 1918アドレスを使用するVIPにトラフィックをルーティングします。このVIPは、VRRPによく似たアクティブファイアウォールによって所有されています。ファイアウォールのニーズにOpenBSDを使用している場合は、VRRP / HSRPに代わる特許フリーのCARPを使用できます。
- ファイアウォールがフィルターを適用します(たとえば、「この特定のIPアドレスへの80 / tcpおよび443 / tcpの送信のみを許可する」)。
- ファイアウォールはルーターとしても機能し、正常なフロントエンドにパケットを転送します。
- フロントエンドはTCP接続を終了します。
これで、ステップ4と5で魔法が発生するので、それらの機能の詳細を見てみましょう。
ファイアウォールは、フロントエンド(FE 1
およびFE 2
)のリストを認識しており、フローの特定の側面に基づいてそれらの1つを選択します(たとえば、ヘッダーの中でソースIPとポートをハッシュすることにより)。ただし、トラフィックが正常なフロントエンドに転送されるようにする必要もあります。そうしないと、トラフィックがブラックホールになります。たとえば、OpenBSDを使用している場合は、を使用できますrelayd
。何relayd
簡単です:すべてのフロントエンドのヘルスチェックを行い(たとえば、プローブHTTPリクエストを送信することにより)、フロントエンドが正常な場合は常に、特定のフローのパケットの次ホップを選択するためにファイアウォールが使用するテーブルに追加します。フロントエンドがヘルスチェックに失敗すると、テーブルから削除され、パケットは送信されなくなります。パケットをフロントエンドに転送する場合、ファイアウォールは、パケットの宛先MACアドレスを、選択したフロントエンドの宛先MACアドレスに交換するだけです。
ステップ5では、ユーザーからのパケットがロードバランサーによって受信されます(Varnish、nginxなど)。この時点では、パケットはまだパブリックIPアドレスに向けられているため、ループバックインターフェイスでVIPをエイリアスする必要があります。これはDSR(Direct Server Return)と呼ばれます。フロントエンドがTCP接続を終了し、その間のファイアウォールがシンプレックストラフィックのみを受信する(着信パケットのみ)ためです。ルーターは、発信パケットをISPのルーターに直接ルーティングします。要求は応答よりも小さくなる傾向があるため、HTTPトラフィックには特に適しています。明確にするために:これはOpenBSD固有のものではなく、トラフィックの多いWebサイトで広く使用されています。
落とし穴:
- DSRを使用するため、エンドユーザーはフロントエンドサーバーに直接接続します。おそらく既にそうでしたが、そうでない場合は、適切に保護されていることを確認する必要があります。
- OpenBSDを使用する場合、シングルCPUコアのパフォーマンスによりファイアウォールのスループットが制限されるため、カーネルはシングルスレッドであることに注意してください。NICのタイプと表示されているパケットレートによっては問題になる場合があります。この問題を解決する方法があります(これについては以下で詳しく説明します)。
2番目の戦略:ファイアウォールなし
この戦略はより効率的ですが、使用しているルーターの特性により依存するため、セットアップが難しくなります。アイデアは、上記のファイアウォールをバイパスし、ファイアウォールが行っていたすべての作業をルーターに実行させることです。
ポートごとのL3 / L4 ACL、BGPとECMP、およびポリシーベースルーティング(PBR)をサポートするルーターが必要です。これらの機能をサポートするのはハイエンドルーターのみであり、多くの場合、BGPを使用するには追加のライセンス料がかかります。これは通常、ハードウェアロードバランサーよりも安価であり、スケーリングもはるかに簡単です。これらのハイエンドルーターの良い点は、ラインレートになる傾向があることです(たとえば、10GbEインターフェイスでも、ASICによってすべての決定がハードウェアで行われるため、常にリンクを最大限に使用できます)。
ISPアップリンクがあるポートで、ファイアウォールに使用されていたACLを適用します(たとえば、「この特定のIPアドレスへの80 / tcpおよび443 / tcpのみ許可」)。次に、各フロントエンドにルーターとのBGPセッションを維持させます。優れたOpenBGPD(フロントエンドがOpenBSD上にある場合)またはQuaggaを使用できます。ルーターは、BGPセッションを維持しているため、正常なフロントエンドへのトラフィックをECMPします。ルーターは、PBRを使用してトラフィックを適切にルーティングします。
絞り込み
- ファイアウォールペアソリューションでは、ファイアウォール間でTCP状態を同期できれば、1つのファイアウォールに障害が発生しても、すべてがスムーズに他のファイアウォールにフェイルオーバーできるようになります。これはで実現でき
pfsync
ます。
- 念頭に置いてベア
pfsync
通常、ファイアウォール上のパケットレートを倍増します。
- HTTPはステートレスプロトコルであるため、ファイアウォールフェールオーバー中にすべての接続をリセットしても、使用しないので世界の終わりではありません
pfsync
。
- 単一のファイアウォールを超える場合、ルーターでECMPを使用して、トラフィックを複数のファイアウォールペアにルーティングできます。
- ファイアウォールの複数のペアを使用する場合、それらをすべてアクティブ/アクティブにすることもできます。フロントエンドがファイアウォールなしの2番目の設計で1つを維持する必要があるのと同様に、ファイアウォールでルーターとのBGPセッションを維持することでこれを実現できます。
サンプルrelayd
設定
https://calomel.org/relayd.htmlの HOWTOも参照してください。
vip = "1.2.3.4"#パブリックIPアドレス
#(複数持つことができますが、必要はありません)
fe1 = "10.1.2.101"
fe2 = "10.1.2.102"
fe3 = "10.1.2.103"
fe4 = "10.1.2.104"#任意の数のフロントエンドを使用できます。
int_if = "em0"
テーブル<fe> {$ fe1再試行2、$ fe2再試行2、$ fe3再試行2、$ fe4再試行2}
テーブル<フォールバック> {127.0.0.1}
ウェブトラフィックのリダイレクト{
$ vipポート80でリッスンします
セッションタイムアウト60
<fe>へのルートhttp "/healthcheck.html"ダイジェストをチェックする "(healthcheck.htmlのsha1sum)"インターフェイス$ int_if
}