NGINXとNGINX PlusでDNSを使用したサービスディスカバリ

NGINX | 2016年4月27日

[編集者注 – 本記事は、初版で言及していた個別の動的構成モジュールに代わり、同モジュールを非推奨とするNGINX Plus APIを参照するよう更新されています。]

One of the great advantages of a マイクロサービスアーキテクチャの大きな利点の1つは、サービスインスタンスを迅速かつ容易にスケールできることです。複数のサービスインスタンスを使用する場合は、ロードバランサーに加え、利用可能なサービスインスタンス群の変更を迅速に通知する仕組みが必要です。これは「サービスディスカバリ」と呼ばれます。NGINX Plusでは、サービスディスカバリシステムとの統合方法として、NGINX Plus APIとドメインネームシステム(DNS)の再名前解決の2つを利用できます。このブログ記事では、後者について説明します。

仮想マシン(VM)やコンテナを追加または削除してサービスインスタンス(このブログ記事では「バックエンド」と呼びます)をスケーリングする場合、バックエンド構成の変更をすべて反映するように、ロードバランサーの設定を変更する必要があります。アプリケーションによっては、スケーリングが1日に複数回、1時間に複数回、さらには1分間に複数回行われることもあります。このように設定変更が頻繁に発生するため、自動化が必要です。その方法の1つが、DNSを介したサービスディスカバリです。

現在アプリケーションの実行に使用されている多くのプラットフォーム(Kubernetesなど)は、DNSを使用したサービスディスカバリをサポートしています。このブログ記事の末尾では、NGINX Plusを一般的なプラットフォームやDNSベースのサービスディスカバリツールと統合する方法を説明した記事へのリンクをご案内します。

DNSの主要機能を簡単におさらい

DNSを介したサービスディスカバリの設定方法を説明する前に、特に関連性が高く便利なDNSプロトコルの機能をいくつか簡単に確認します。

Time‑to‑Live

DNSクライアントが古い情報を使用しないように、DNSレコードにはTime-to-Live(TTL)フィールドが含まれており、クライアントがそのレコードを有効とみなせる期間を定義します。DNS標準に準拠するため、レコードのTTLが切れた場合、クライアントはDNSサーバーに更新を問い合わせる必要があります。NGINX PlusはデフォルトでTTLに従いますが、レコードの「有効期間」をより細かく制御することもできます。NGINX PlusでTTLを無視し、代わりに指定した頻度でレコードを更新するよう設定できます。(NGINX Open SourceでのTTLの処理については、この記事の後半で説明します。)

DNS over TCP

デフォルトでは、DNSクライアントとサーバーはUDPで通信します。ただし、ドメイン名から多数のバックエンドIPアドレスが解決される場合、応答全体が、512バイトに制限されている単一のUDPデータグラムに収まらないことがあります。この問題は、UDPの代わりにTCPを使用することで解決できます。すべてのレコードが1つのデータグラムに収まらない場合、サーバーは応答に切り捨てフラグを設定し、すべてのレコードを取得するためにTCPへ切り替えるようクライアントに通知します。DNS over TCPは、NGINXバージョン1.9.11以降およびNGINX Plus R9以降でサポートされています。詳細については、F5のブログ記事「NGINXとNGINX PlusによるDNSトラフィックの負荷分散」をご覧ください。

SRVレコード

DNSはホスト名をIPアドレスに解決しますが、ポート番号はどうでしょうか。たとえばDockerコンテナの負荷分散では、ポート番号が動的に割り当てられるため、ウェルノウンポート番号を利用できない場合があります。DNSには、ポート番号とその他いくつかのパラメーターを含む特殊なレコードタイプである「サービス(SRV)レコード」があります。R9以降のNGINX PlusはSRVレコードをサポートしており、レコードからポート情報を抽出できます。

編集者注:NGINX Plus R9のすべての新機能の概要については、F5のブログ記事「NGINX Plus R9の発表」をご覧ください。

NGINXおよびNGINX PlusでDNSを使用してサービスディスカバリを行う方法

ここでは、NGINXとNGINX PlusでDNSをサービスディスカバリに使用する5つの方法を、基本的なものから高度なものへ順に紹介します。最初の3つはNGINXとNGINX Plusの両方で利用でき、残りの2つはNGINX Plusでのみ利用できます。

このサービスディスカバリ手法の概要では、ゾーンexample.comに対してIPアドレス10.0.0.2の権威ネームサーバーがあるものとします。ドメイン名backends.example.comに対応するバックエンドサーバーは3台あり、以下のnslookupユーティリティの出力に示されています。ここで説明する最初の4つの方法では、NGINXとNGINX PlusはDNSに標準のAレコードを要求します。最後の方法では、NGINX Plusは代わりにSRVレコードを要求します。

$ nslookup backends.example.com 10.0.0.2Server:		10.0.0.2
Address:	10.0.0.2#53

Name:	backends.example.com
Address: 10.0.0.11
Name:	backends.example.com
Address: 10.0.0.10
Name:	backends.example.com
Address: 10.0.0.12

NGINXでDNSを使用したサービスディスカバリ

まず、DNSを使用する3つの方法をご紹介します。これらの方法は、NGINX Open Sourceだけでなく、前述のとおりNGINX Plusでも使用できます。

Using the Domain Name in the proxy_passディレクティブでのドメイン名の使用

アップストリームサーバー(バックエンド)のグループを定義する最も簡単な方法は、ドメイン名をproxy_passディレクティブのパラメーターとして指定することです。

server {    location / {
        proxy_pass http://backends.example.com:8080;
    }
}

NGINXは、起動時または設定の再読み込み時に、DNSサーバーへ問い合わせてbackends.example.comを名前解決します。DNSサーバーは前述の3つのバックエンドのリストを返し、NGINXはデフォルトのラウンドロビンアルゴリズムを使用して、それらのバックエンド間でリクエストの負荷を分散します。NGINXは、OSの設定ファイル/etc/resolv.confに基づいてDNSサーバーを選択します。

この方法は、サービスディスカバリの手法として最も柔軟性に乏しく、さらに次のような欠点があります。

  • ドメイン名を解決できない場合、NGINXは起動または設定の再読み込みに失敗します。
  • NGINXは、レコードのTTL値を無視し、次回の再起動または設定の再読み込みまでDNSレコードをキャッシュします。
  • 別の負荷分散アルゴリズムを指定することはできません。また、パッシブヘルスチェックや、次のセクションで説明するserverディレクティブのパラメーターで定義されるその他の機能も設定できません。

アップストリームサーバーグループでのドメイン名の使用

NGINXが提供する負荷分散オプションを活用するには、アップストリームサーバーのグループをupstream設定ブロックで定義できます。ただし、個々のサーバーをIPアドレスで指定する代わりに、ドメイン名をserverディレクティブのパラメーターとして使用します。

「最初の方法」と同様に、backends.example.comは、NGINXの起動時または設定の再読み込み時に3台のバックエンドサーバーへ名前解決されます。ただし、今回はより高度な負荷分散アルゴリズムである「最小接続数」を定義し、max_failsパラメーターを使用してパッシブヘルスチェックを有効にできます。これにより、リクエストが3回連続で失敗した場合に、NGINXがそのサーバーをダウンとしてマークするよう指定できます。

upstream backends {    least_conn;

    server backends.example.com:8080 max_fails=3;
}

server {
    location / {
        proxy_pass http://backends;
    }
}

この方法では、負荷分散アルゴリズムを選択してヘルスチェックを設定できますが、起動、再読み込み、TTLに関しては、前の方法と同じ欠点が残ります。

ドメイン名を変数に設定

この方法は、最初の方法のバリエーションですが、NGINXがドメイン名を再解決する頻度を制御できます。

resolver 10.0.0.2 valid=10s;
server {
    location / {
        set $backend_servers backends.example.com;
        proxy_pass http://$backend_servers:8080;
    }
}

変数を使用してproxy_passディレクティブにドメイン名を指定すると、NGINXはTTLの期限が切れた時点でドメイン名を再解決します。ネームサーバーを明示的に指定するには、resolverディレクティブを含める必要があります(NGINXは、最初の2つの方法とは異なり、/etc/resolv.confを参照しません)。validパラメーターをresolverディレクティブに含めることで、NGINXにTTLを無視させ、代わりに指定した頻度で名前を再解決させることができます。ここでは、10 秒ごとに名前を再解決するようNGINXに指定しています。

注: TCP/UDPロードバランシングでは、proxy_passディレクティブで変数を使用するこの方法は、NGINX 1.11.3以降およびNGINX Plus R10以降でサポートされています。

この方法では、ドメイン名を解決できない場合でもNGINXの起動や再読み込みが失敗せず、NGINXが名前を再解決する頻度も制御できるため、最初の方法にある2つの欠点を解消できます。ただし、アップストリームグループを使用しないため、serverディレクティブにロードバランシングアルゴリズムやその他のパラメーターを指定することはできません(2番目の方法では指定できました)。

NGINX PlusでDNSを使用したサービスディスカバリ

ここでは、NGINX Plus独自のDNSを使用した2つのサービスディスカバリ方法について説明します。

NGINX PlusでのAレコードの使用

NGINX Plusでは、DNS名を必要な頻度で再解決でき、前述した最初の3つの方法のような欠点もありません。この機能を使用するには、次の手順を実行します。

  • 前の方法と同様に、ネームサーバーを指定するためにresolverディレクティブを含めます。
  • 共有メモリゾーンを割り当てるには、zoneディレクティブをupstream設定ブロックに含めます。
  • ドメイン名を使用するresolveパラメーターをserverディレクティブに追加します。

次の例を考えてみます。

resolver 10.0.0.2 valid=10s;
upstream backends {
    zone backends 64k;
    server backends.example.com:8080 resolve;
}

server {
    location / {
        proxy_pass http://backends;
    }
}

デフォルトでは、NGINX PlusはTTLに従い、レコードの有効期限が切れると名前を再解決します。代わりに、指定した頻度で名前を再解決するには、validパラメーターをresolverディレクティブに含めます。

このスニペットでは、NGINX Plusが10秒ごとに10.0.0.2のネームサーバーへ問い合わせ、backends.example.comを名前解決します。名前を解決できない場合でも、起動時、設定の再読み込み時、実行時のいずれにおいてもNGINX Plusは異常終了しません。代わりに、クライアントには標準の502エラーページが表示されます。

NGINX Plusでの「SRV」レコードの使用

NGINX Plus R9以降は、DNSのSRVレコードをサポートしています。これにより、NGINX PlusはネームサーバーからIPアドレスだけでなく、ポート番号、重み、優先度も取得できます。これは、サービスのポート番号が動的に割り当てられることの多いマイクロサービス環境では極めて重要です。

編集者注:NGINX Plus R9のすべての新機能の概要については、ブログ記事「NGINX Plus R9の発表」をご覧ください。

SRVレコードは、サービス名、サービスとの通信に使用するプロトコル、ドメイン名の3要素で定義されます。ネームサーバーに問い合わせる際は、この3つをすべて指定する必要があります。10.0.0.2のネームサーバーには、サービス名がSRVのレコードが3つあり、その3要素はサービス名がhttp、プロトコルがtcp、ドメイン名がbackends.example.comです。以下のnslookupユーティリティの出力に示します。

$ nslookup -query=SRV _http._tcp.backends.example.com 10.0.0.2Server:		10.0.0.2
Address:	10.0.0.2#53

_http._tcp.backends.example.com	service = 0 2 8090 backend-0.example.com.
_http._tcp.backends.example.com	service = 0 1 8091 backend-1.example.com.
_http._tcp.backends.example.com	service = 10 1 8092 backend-2.example.com.

各SRVレコードのホスト名を照会すると、そのIPアドレスを取得できます。

$ nslookup backend-0.example.com 10.0.0.2...
Name:	backend-0.example.com
Address: 10.0.0.10

$ nslookup backend-1.example.com 10.0.0.2
...
Name:	backend-1.example.com
Address: 10.0.0.11

$ nslookup backend-2.example.com 10.0.0.2
...
Name:	backend-2.example.com
Address: 10.0.0.12

最初のSRVレコード(最初のnslookupコマンドで返されたもの)の情報を詳しく見てみましょう。

_http._tcp.backends.example.com	service = 0 2 8090 backend-0.example.com.
  • _http._tcp. – SRVレコードの名前とプロトコルです。これは、NGINX Plus構成ファイルのserverディレクティブにあるserviceパラメーターの値として指定します(以下を参照)。
  • 0 – 優先度。値が小さいほど、優先度が高くなります。NGINX Plusは、優先度が最も高いサーバーをプライマリサーバーに、それ以外のサーバーをバックアップサーバーに指定します。このレコードの値はすべてのレコードの中で最も小さい(優先度が最も高い)ため、NGINX Plusは対応するバックエンドをプライマリサーバーに指定します。
  • 2 – 重み。NGINX Plusは、バックエンドをアップストリームグループに追加する際に、そのバックエンドの重みをこの値に設定します(weightディレクティブのserverパラメーターに相当)。
  • 8090 – ポート番号。NGINX Plusは、バックエンドをアップストリームグループに追加する際に、そのポートをこの値に設定します。
  • backend‑0.example.com – バックエンドサーバーのホスト名。NGINX Plusはこの名前を解決し、対応するバックエンドをアップストリームグループに追加します。名前解決の結果、複数のレコードが返された場合、NGINX Plusは複数のサーバーを追加します。

次に、NGINX PlusでSRVレコードを使用するための設定方法を見ていきます。以下に設定ファイルの例を示します。

resolver 10.0.0.2 valid=10s;

upstream backends {
    zone backends 64k;
    server backends.example.com service=_http._tcp resolve;
}

server {
    location / {
        proxy_pass http://backends;
    }
}

Using the serverディレクティブのserviceパラメーターを使用して、名前解決するSRVレコードの名前とプロトコルを指定します。この例では、それぞれ_httpと_tcpです。serviceパラメーターを使用する点とポートを指定しない点を除けば、前のセクションの設定例と同じです。

このセクションの最初の「nslookup」コマンドから返された値に基づき、NGINX Plusには3台のバックエンドサーバーが設定されます。

  • 10.0.0.10 – ポート8090、重み2のプライマリサーバー。
  • 10.0.0.11 – ポート8091、重み1のプライマリサーバー。
  • 10.0.0.12 – ポート8092、重み1のバックアップサーバー。

NGINX Plusでライブアクティビティモニタリングを設定すると、組み込みのダッシュボードでこれらのバックエンドを確認できます。

ライブアクティビティ監視ダッシュボード。NGINX Plusが、アップストリームサーバーのDNS SRVレコードに割り当てられた重みに従ってリクエストを分散する様子を示しています。このダッシュボードを使用すると、NGINXをロードバランサーとして使用するマイクロサービスアーキテクチャでNGINXを監視できます

指定した重みに従ってリクエストが分散されていることに注目してください。重みが1の10.0.0.11:8091サーバーにはリクエストの3分の1が、重みが2の10.0.0.10:8090サーバーには3分の2が送信されます。バックアップサーバーである10.0.0.12:8092サーバーには、ほかの2台のサーバーがダウンしない限り、リクエストは送信されません。

注意事項

NGINX PlusでDNSを使用してサービスディスカバリを行う場合は、いくつかの点に注意してください。

  • DNSサーバーは、高可用性を確保するか、バックアップサーバーを用意する必要があります。DNSサーバーが利用できなくなると、NGINX Plusは更新情報を取得できなくなります。NGINX Plusを再起動するか、設定を再読み込みしない限り、対応するレコードのTTL値を無視して、既存のバックエンドを設定内に保持します。
  • 複数のネームサーバーをresolverディレクティブで指定できます。いずれかが停止している場合、NGINX Plusは他のネームサーバーへの接続を試みます。
  • 冒頭で説明したように、NGINX Plusでサービスディスカバリを行う際は、DNSの代わりにNGINX Plus APIを使用することもできます。このAPIでは、簡単なHTTPリクエストを使用して、アップストリームグループのサーバーを追加または削除できます。

例

完全な例を詳しく確認するには、DNSを使用するサービスディスカバリプラットフォームとNGINXおよびNGINX Plusの統合について解説した、以下のブログ記事をご覧ください。

今後、新しい統合オプションに関する記事を追加する際に、このリストも更新します。

まとめ

NGINX Plusで完全に利用可能なDNSによるサービスディスカバリを使用すると、マイクロサービス環境でロードバランサーの設定を簡単に更新できます。SRVレコードはRelease 9以降でサポートされており、NGINX PlusはバックエンドのIPアドレスだけでなくポート番号も取得できるため、さらに強力になります。

NGINX PlusのDNSを使用したサービスディスカバリや、その他の強化機能をお試しになりませんか?今すぐ30日間の無料トライアルを開始するか、ユースケースについてご相談ください。


共有
タグ: DevOps, F5 NGINX, Tech, 2016

関連するブログ記事

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
NGINX | 2024/01/18

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する

OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
NGINX | 2023/05/31

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正

Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
NGINX | 2023/02/09

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法

Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINX | 2022/05/24

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング

NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
NGINX | 2018/08/17

SELinuxでNGINXおよびNGINX Plusを使用する

Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。

NGINX PlusによるAWS Auto Scalingグループの負荷分散
NGINX | 2017/03/06

NGINX PlusによるAWS Auto Scalingグループの負荷分散

新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります