NGINX Plus R9 では、 UDP トラフィックのリバース プロキシと負荷分散の機能が導入され、NGINX Plus のレイヤー 4 負荷分散機能が大幅に強化されました。
このブログ投稿では、最新のアプリケーション インフラストラクチャで DNS サーバーを実行する際の課題を検討し、NGINX Open Source と NGINX Plus の両方が UDP トラフィックと TCP トラフィックの両方を効果的かつ効率的に負荷分散する方法を説明します。 (アプリケーション [アクティブ] ヘルスチェックは NGINX Plus 専用ですが、それ以外についてはこのブログの情報は NGINX Open Source にも同様に適用されます。簡潔にするために、この記事の残りの部分では NGINX Plus について言及します)。
[編集者注 – NGINX Plus R9 のすべての新機能の概要については、弊社ブログの「NGINX Plus R9 の発表」をご覧ください。]
TCP とは異なり、UDP は設計上、エンドツーエンドのデータ配信を保証しません。 これは伝書鳩でメッセージを送るのに似ています。メッセージが送信されたことは確かにわかりますが、届いたかどうかはわかりません。 この「コネクションレス」アプローチにはいくつかの利点がありますが、最も顕著なのは、UDP の個々のメッセージが小さいため帯域幅の使用が少なく、接続を確立するためのハンドシェイク プロセスがないため、TCP よりもレイテンシが低いことです。 UDP では、タイムアウトやその他のネットワーク レベルの問題を検出する問題はアプリケーション開発者に任されています。 しかし、これは DNS にとって何を意味するのでしょうか?
他のいくつかの UDP ベースのプロトコルと同様に、DNS は要求応答データ フローを使用します。 たとえば、DNS クライアントはホスト名に対応する IP アドレスを要求し、応答を受け取ります。 指定されたタイムアウト期間内に応答が届かない場合、DNS クライアントは同じ要求を「バックアップ」 DNS サーバーに送信します。 ただし、リクエストを再試行する前にタイムアウト期間を待つ必要があると、通常は非常に高速なプロセス (ミリ秒単位で測定) が非常に低速なプロセス (秒単位で測定) に変わってしまう可能性があります。
NGINX Plus を使用して DNS トラフィックをプロキシおよび負荷分散すると、クライアントでタイムアウトが発生する回数が減ります。 NGINX Plus ロード バランサーの背後に複数の DNS サーバーがある場合、クライアントと NGINX Plus の間にネットワーク パーティションがある場合にのみ、クライアントでタイムアウトが発生します。 NGINX Plus がアプリケーション ヘルス チェックを使用する場合、クライアントでは DNS サーバー自体の問題は発生しません。 NGINX Plus は、各サーバーの可用性と応答時間を監視することにより、正常でないサーバーにクライアント要求が送信されることを回避します。
DNS トラフィックの大部分は UDP 経由ですが、TCP を使用する一般的な DNS 操作もあります。 DNS は、小さなメッセージ (最大 512 バイト) には UDP を使用しますが、より大きなメッセージを必要とする (または必要になる可能性がある) 操作には TCP を使用します。 歴史的に、TCP は、権威あるプライマリ ネーム サーバーからセカンダリ ネーム サーバーへのゾーン転送にのみ DNS で使用されていました。 ただし、コンテナと不変のインフラストラクチャへの移行に伴い、 SRV
レコードの使用を通じて、DNS が主要なサービス検出メカニズムとしてますます使用されるようになっています。
DNS SRV
レコードは、もともとSIP を使用してサーバーを検出する Voice over IP (VoIP) 端末用に導入されましたが、あらゆるタイプのサービスに使用できます。 ただし、 SRV
レコードには、他のほとんどの DNS レコード タイプよりも多くの情報が含まれています。 その結果、標準の 512 バイトの UDP 応答には、約 30 個のA
レコードではなく、約 10 個のSRV
レコードしか収まりません。 DNS 応答が 512 バイトの制限を超えると、最初の 512 バイトが返されますが、応答には「切り捨て」のフラグが付けられます。 この時点で、DNS クライアントは、切り捨てられた応答を可能な限り処理するか、TCP を使用して同じ要求を再試行することができます。
つまり、最新のネットワーク インフラストラクチャで DNS サーバーを負荷分散する場合、NGINX Plus は UDP トラフィックと TCP トラフィックの混合を受信することが予想されます。
次の図は、2 つのロード バランサーを備えたマイクロサービス環境の簡略化されたビューを示しています。 フロントエンド ロード バランサーは、アプリケーションのパブリック クライアントからのリクエストをプロキシし、最適なマイクロサービス インスタンスを選択し、ここでは説明しない他の多くの機能を実行します。 ここでは、マイクロサービス環境と、マイクロサービスにサービス検出情報を提供する DNS サーバーの間に位置する DNS ロード バランサーに焦点を当てます。
NGINX Plus は、 Streamモジュールでレイヤー 4 ロード バランシングを実装しているため、次のスニペットに示すように、UDP および TCP ロード バランシングはストリーム
ブロックで構成されます。
警告: この構成スニペットを/etc/nginx/conf.dディレクトリに新しいファイルとして単純に追加することはできません。 デフォルトの NGINX Plus nginx.conf構成ファイルには、 http
ブロックのconf.dディレクトリ内のファイルの内容が含まれているため、検証エラーが発生します (「ここではストリーム ディレクティブは許可されていません」)。 最も簡単な解決策は、完全なストリーム
ブロックをnginx.confに直接含めることです。
ストリーム { アップストリーム dns_servers {
サーバー 192.168.136.130:53;
サーバー 192.168.136.131:53;
}
サーバー {
listen 53 udp;
listen 53; #tcp
proxy_pass dns_servers;
error_log /var/log/nginx/dns.log info;
}
}
まず、DNS サーバーの上流グループを定義します。 サーバー
ディレクティブは、アップストリーム サーバーがリッスンしているポート番号 53 (DNS の既知のポート) を指定します。
server{}
ブロックは、NGINX Plus が受信 DNS トラフィックを処理する方法を定義します。 2 つのlisten
ディレクティブは、NGINX Plus に、UDP と TCP トラフィックの両方をポート 53 でリッスンするように指示します。 TCP は Stream モジュールのデフォルトのレイヤー 4 プロトコルであるため、UDP の場合のようにパラメーターとして明示的に指定する必要はありません。
proxy_pass
ディレクティブは、NGINX Plus がリッスンしているトラフィックをどのように処理するかを指示します。 ここでは、このようなトラフィックをdns_serversアップストリーム グループにプロキシします。 NGINX Plus は、クライアントの UDP 要求をアップストリーム サーバーに転送するときに UDP を自動的に使用します (クライアントの TCP 要求の場合は TCP を使用します)。そのため、アップストリーム グループでレイヤー 4 プロトコルを明示的に指定する必要はありません。
NGINX Plus は TCP セグメントまたは UDP データグラムのペイロードを検査しないため (HTTP パケットの場合のように)、Stream モジュールにはaccess_log
ディレクティブはありません。 ただし、 error_log
ディレクティブのinfo
パラメータを使用して、接続処理とプロキシ イベントをログに記録できます。
[編集者注 – このブログが公開された後、NGINX Open Source 1.11.4 およびNGINX Plus R11では、 Stream モジュールでアクセス ログが有効になりました。]
DNS サーバーの可用性を向上させるために、さらにいくつかのディレクティブを追加し、アクティブな (アプリケーション) ヘルス チェックを構成できます。
最初の追加ディレクティブはproxy_responses
です。これは、プロキシされた各 UDP 要求に対して NGINX Plus が期待する応答の数を指定します。 私たちの場合、NGINX Plus は 1 つの応答を受信するとすぐにそれ以上の応答の待機を停止し、そのセッションに使用されていたメモリとソケットを解放します。
2 番目の追加ディレクティブproxy_timeout は
、NGINX Plus がサーバーからの応答を待機する時間を決定します (ここでは、デフォルトの 10 分を 1 秒に短縮します)。 NGINX Plus がこの期間内に応答を受信しない場合、アップストリーム グループ内の次のサーバーを試行し、応答のないアップストリーム サーバーを定義された期間 (デフォルトでは 10 秒) 使用不可としてマークします。これにより、その間に他のクライアントがタイムアウトによる遅延に悩まされることがなくなります。
サーバー { listen 53 udp; listen 53; #tcp proxy_pass dns_servers; error_log /var/log/nginx/dns.log info; proxy_responses 1 ; proxy_timeout 1s ; }
また、アップストリーム グループのserver
ディレクティブにfail_timeout
オプションを含めることで、サーバーが利用不可としてマークされる時間を変更することもできます。 次の設定では、NGINX Plus は障害が発生したアップストリーム サーバーを 60 秒間使用不可としてマークします。
アップストリーム dns_servers { サーバー 192.168.136.130:53 fail_timeout=60s ; サーバー 192.168.136.131:53 fail_timeout=60s ; }
これにより、DNS サーバーの 1 つに障害が発生した場合にクライアントが経験する遅延を制御できます。 ただし、障害が発生した DNS サーバーに TCP 要求が試行されると、TCP 固有のエラー チェックにより、NGINX Plus はそれを自動的に利用不可としてマークし、そのサーバーへの後続の TCP または UDP 要求を回避します。
NGINX Plus のアクティブ ヘルス チェック機能は、DNS を含むあらゆる負荷分散サービスの高可用性を実現するための、非常に価値のある追加のツールです。 DNS サーバーがダウンしているとマークする前に DNS クライアントからの実際の TCP 要求が失敗するのを待つのではなく、 server{}
ブロックにport=53
パラメータを指定したhealth_check
ディレクティブを含めることで、NGINX Plus がポート 53 で TCP 接続を定期的に試行し、DNS サーバーが起動していて正常に動作しているかどうかを確認します。 (NGINX Plus は、デフォルトではlisten
ディレクティブで指定されたポート (この場合は 53)) にヘルス チェックを送信します。 したがって、ここではパラメータを使用してデフォルトを明示的に構成していますが、DNS サーバーを変更してそのポートのトラフィックに応答するようにすれば、別のポートを指定することもできます。
UDP を使用すると、さらに一歩進んで、既知のレコードの実際の DNS 検索を実行するアクティブなヘルス チェックを構成できます。 たとえば、マイクロサービス環境内でのサービス検出に使用されるのと同じサブドメインのゾーン ファイルに次のCNAME
レコードを配置する場合があります。
healthcheck IN CNAME healthy.svcs.example.com。
UDP の軽量な性質により、ネットワーク トラフィックを監視し、DNS ルックアップを表すバイト文字列を簡単に抽出できます。 次に、その文字列を送信
ディレクティブのパラメータとして指定して、一致
構成ブロックを作成します。 expect
ディレクティブは、サーバーが正常であるとみなされるために返す必要がある応答を指定します。
match dns_lookup {
x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 を送信します...;
~* "healthy.svcs.example.com." を期待します;
}
この詳細なアプリケーション レベルのヘルス チェックの利点は、ネーム サーバーが稼働している場合でも、実稼働ドメインに対して実際の DNS ルックアップを実行すると、下流で問題を引き起こす可能性のある構成の問題やデータ破損が明らかになることです。
NGINX Plus サポート チームは、 DNS ルックアップやその他のプロトコルの UDP ヘルス チェックの準備をお手伝いします。
次のスニペットは、アクティブ ヘルス チェックに必要な追加のディレクティブを強調表示しています。
stream { アップストリーム dns_servers {ゾーン dns_mem 64k ; サーバー 192.168.136.130:53 fail_timeout=60s; サーバー 192.168.136.131:53 fail_timeout=60s; } match dns_lookup { send x00x01x00x00x00x01x00x00x00x00x00x00x06x68x65x61 ...; expect ~* "healthy.svcs.example.com."; }サーバー { listen 53 udp; listen 53; #tcp health_check match=dns_lookup interval=20 fails=2 passing=2 udp; health_check interval=20 fails=1 passing=2 port=53; #tcp proxy_pass dns_servers; error_log /var/log/nginx/dns.log デバッグ; proxy_responses 1; proxy_timeout 1s; } }
zone
ディレクティブは、 dns_memと呼ばれる共有メモリ ゾーンを定義します。これにより、ヘルス チェックの結果 (およびその他の状態情報) がすべての NGINX Plus ワーカー プロセスで利用できるようになります。
match
ディレクティブについては上記で説明しました。
health_check
ディレクティブには、環境に合わせて調整できるパラメーターがいくつかあります。 ここでは、UDP と TCP それぞれに個別のヘルス チェックを定義します。 UDP と TCP の違いにより、DNS サーバーを異常とマークする前に、UDP ヘルスチェックの失敗が 2 回連続して発生する必要がありますが、TCP の失敗は 1 回だけで済みます。 どちらのプロトコルでも、不安定な「フラッピング」サーバーにリクエストが送信されるのを避けるために、サーバーを再び正常としてマークする前に 2 つの正常な応答が必要です。
UDP トラフィックと TCP トラフィックの両方に対して単一のアップストリーム DNS サーバ グループを定義する利点は、どちらかのプロトコルのヘルス チェックに失敗すると、サーバが正常でないとマークされ、負荷分散プールから削除されることです。
バックエンド サーバーを 2 台だけ導入すると、効果的な高可用性ソリューションになりますが、NGINX Plus の負荷分散機能を使用すると、クライアントに知らせずにバックエンド サーバーを水平方向に拡張できます。
上記のサンプルのマイクロサービス環境では、バックエンド DNS サーバーのスケーリングが必要になることはほとんどありません。 ただし、すべての加入者に DNS サービスを提供する ISP では、一定の負荷と大きなスパイクが発生する可能性があるため、多数の DNS サーバーと、それら間でトラフィックの負荷を分散するフロントエンド プロキシが必要になります。
NGINX および NGINX Plus のすべての負荷分散アルゴリズムは、 HTTP だけでなく TCP と UDP でも使用できます。
(すべてのアルゴリズムに重みを設定して、効率をさらに高めることもできます。 詳細については、弊社のブログの「NGINX Plus ロードバランシング手法の選択」の重みに関するセクションを参照してください。
HTTP リクエストは、バックエンド サーバーにかかる負荷と処理要求の点で大きく異なる場合がありますが、DNS リクエストは通常、すべて同じ負荷を生成します。 このため、最小接続アルゴリズムと最小時間アルゴリズムがラウンドロビンよりも有利になる可能性は低くなります。 特に、Least Connections では、NGINX Plus がアップストリーム サーバーからの応答を待機している UDP 要求が接続数に含まれます。 proxy_responses
とproxy_timeout
の値が満たされていない限り、NGINX Plus は、すでに作業を完了している可能性のあるアップストリーム サーバーの接続をカウントし続けます。
多数のクライアントと、RADIUS チャレンジ レスポンス フローのようにクライアントとサーバー間で交換される複数のメッセージなど、多くの「ダイアログ」を実行するプロトコルがある場合、ソース IP ハッシュを使用すると、単一のバックエンド サーバーとのダイアログが可能になります。 つまり、セッションの永続性が確立され、NGINX Plus は特定のクライアントからのすべてのリクエストを同じサーバーに送信します。 次の例では、送信元(クライアント)IP アドレス( $remote_addr
変数によって取得)をキーとして使用して、RADIUS 認証サーバーのペアに対してハッシュ ロード バランシング アルゴリズムを設定します。
アップストリーム radius_servers { hash $remote_addr; # ソース IP ハッシュ
server 192.168.136.201:1812;
server 192.168.136.202:1812;
}
UDP および TCP 負荷分散の詳細については、次のリソースを参照してください。
アップストリーム
構成コンテキストNGINX Plus R9 のその他の優れた機能について詳しくは、ブログの「NGINX Plus R9 の発表」を参照し、オンデマンド ウェビナー「NGINX Plus R9 の新機能」をご覧ください。
NGINX Plus をお試しいただくには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、使用事例についてご相談ください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"