今年9月にオースティンで開催されたnginx.conf 2016で、私はDocker SwarmクラスターでNGINXとNGINX Plusを使用する方法について講演しました。この記事では、Docker 1.12で導入された機能と組み合わせて、NGINXとNGINX PlusをDocker Swarmの負荷分散に使用する方法を解説します。nginx.confのデモで使用したすべてのファイル(およびその他のファイル)はGitHubで公開しており、実際にお試しいただけます。
概要
2016年7月下旬にリリースされたDockerバージョン1.12では、Docker EngineとSwarmが統合され、新たなオーケストレーション機能が追加されたことで、Kubernetesなどのコンテナプラットフォームに類似したプラットフォームが構築されています。Docker 1.12のSwarm Modeでは、一連のDockerホストを1つのswarmとしてまとめ、耐障害性、自己修復機能、分散型アーキテクチャを実現できます。また、この新しいプラットフォームでは、Swarmクラスターをより簡単にセットアップできるほか、すべてのノードをキーで保護し、ノード間のすべての通信をTLSで暗号化します。
同時に、Docker APIが拡張され、サービス(同じイメージを使用するコンテナの集合で、Docker Composeのサービスに似ていますが、より多くの機能を備えています)を認識できるようになりました。サービスの作成やスケーリング、ローリングアップデート、ヘルスチェックの作成などが可能です。DNSサービスディスカバリと負荷分散が組み込まれているほか、クラスター全体のオーバーレイネットワークも設定できます。
Docker Swarmロードバランシングのトポロジ
この説明とデモでは、マネージャー1台とワーカー2台の計3台のSwarmノードを使用します。Swarmコマンドはマネージャーノードで実行します。Swarmは、すべてのノードでスケジューリング、DNSサービスディスカバリ、スケーリング、コンテナの負荷分散(図中の小さなボックス)を処理します。

クラスター内のコンテナ間でプライベートネットワーク通信を行うため、クラスター内のすべてのノードにまたがる複数の内部オーバーレイネットワークにコンテナを接続できます。Swarmロードバランサーを介して、コンテナをクラスター外部に公開できます。

Docker Swarmロードバランサーは各ノードで稼働し、クラスター内の任意のホスト上にある任意のコンテナにリクエストを負荷分散できます。NGINXまたはNGINX Plusを使用しないSwarm環境では、Swarmロードバランサーが受信クライアントリクエスト(図3の緑色の矢印)と内部のサービス間リクエスト(赤色の矢印)の両方を処理します。

Swarmにロードバランシング機能が組み込まれた今、なぜ別のロードバランサーが必要なのでしょうか。その理由の1つは、Swarmのロードバランサーが基本的なレイヤー4(TCP)ロードバランサーだからです。多くのアプリケーションでは、たとえば次のような追加機能が必要です。
- SSL/TLS終端
- コンテンツベースのルーティング(URLやヘッダーなどに基づく)
- アクセス制御と認可
- 書き換えとリダイレクト
さらに、すでにロードバランサーの使用経験がある場合は、Swarmと組み合わせて使用することで、既存のツールや知識を活用できます。
NGINX Open SourceとNGINX Plusの使用
NGINX Open SourceとNGINX Plusは、Swarmネイティブのロードバランサーにはない、アプリケーションに不可欠な機能を提供する2つのロードバランサーです。
NGINX Open Sourceの使用
NGINX Open Sourceは、前述の機能(SSL/TLS終端など)に加え、以下の機能も提供します。
- 負荷分散アルゴリズムの選択肢
- HTTP/2やWebSocketなど、より多くのプロトコル
- 設定可能なログ記録
- リクエストレート、帯域幅、接続数などのトラフィック制限
- Lua、Perl、JavaScriptを使用した高度なユースケース向けのスクリプティング(nginScript動的モジュールを使用[編集者注 – 現在はNGINX JavaScript動的モジュールと呼ばれています])
- 許可リストや拒否リストなどのセキュリティ機能
NGINX Open Sourceを使用する最も簡単な方法は、1つ以上のコンテナを使用してサービスとしてデプロイすることです。NGINXサービスに必要なポートをクラスター上で公開すると、SwarmロードバランサーがこれらのポートへのリクエストをNGINXコンテナに分散します。

この例では、NGINXが提供するサービスはSSL/TLS終端です。その仕組みを説明するため、バックエンドサービスAをクラスターにデプロイし、3つのコンテナにスケールします(図5に示すように、1つのノードに2つのインスタンス、別のノードに1つのインスタンスを配置します)。Swarmは、クラスター内で使用する仮想IPアドレス(VIP)をサービスAに割り当てます。サービスAのアップストリームグループのNGINX設定では、各コンテナのIPアドレスを個別に列挙する代わりに、このVIPを使用します。これにより、NGINX設定を変更せずにサービスAをスケールできます。
図5に示すように、クライアントが最初のSwarmノードにサービスAへのリクエストを送信すると、そのノード上のSwarmロードバランサーがリクエストをNGINXにルーティングします。NGINXはリクエストを処理し、この例ではSSL/TLSを復号して、サービスAのVIPにルーティングします。Swarmロードバランサーは、復号されたリクエストを、いずれかのSwarmノード上にあるサービスAのコンテナの1つにルーティングします。

NGINXでリクエストをバックエンドコンテナに直接負荷分散し、内部のサービス間リクエストも処理することは可能です。ただし、そのためには、サービスAをスケーリングするたびにNGINXの設定を変更して再読み込みする、より複雑なソリューションが必要です。後ほど、NGINX Plusを使用してこれを簡単に実現する方法を説明します。
NGINX Plusの使用
NGINX Plusが提供する追加機能には、次のようなものがあります。
- アクティブなアプリケーションヘルスチェック – NGINX Plusはバックエンドノードを継続的にチェックし、正常に稼働して適切に応答していることを確認します。異常なノードは負荷分散の対象から除外します。
- セッション維持 – 別名「スティッキーセッション」。クライアントからのリクエストを継続して同じバックエンドに送信する必要があるアプリケーションで使用します。NGINX Plusはセッションドレイニングをサポートしているため、進行中のセッションがあるクライアントに影響を与えることなく、バックエンドサーバーをオフラインにできます。
- 動的再構成 – NGINXの構成を変更して再読み込みすることなく、バックエンドをスケールアップまたはスケールダウンできます。これは、Swarmなどのマイクロサービスプラットフォームでサービスディスカバリを行う場合に特に有用であり、NGINX Plusとこれらのプラットフォームとの完全な統合を可能にする最も重要な機能の1つです。動的再構成には、変更をNGINX PlusにプッシュできるAPIとDNSの2つの方法があります。NGINX PlusはDNSを継続的に確認し、ドメイン名に関連付けられたノード数の変化を検出します。このNGINX Plusのデモでは、Swarmに組み込まれたサービスディスカバリとの統合にDNSを使用しています。
- ライブアクティビティ監視 – NGINX Plusから幅広いメトリクスを取得するためのAPIと、そのAPIを基盤とするWebダッシュボードを提供します。ダッシュボードでは、メトリクスの表示に加え、バックエンドサーバーの追加、削除、変更が可能です。
前述のNGINX Open Source構成では、上記Swarmロードバランサーが外部リクエストをバックエンドコンテナに分散するとともに、コンテナ間のサービス間リクエストも処理します。NGINXの役割はSSL/TLSオフロードです。
NGINX Plusを使用する場合、外部クライアントからのリクエストは最初にSwarmロードバランサーに到達しますが、バックエンドコンテナへの実際の負荷分散はNGINX Plusが行います(図6)。クライアントリクエストを最初にSwarmロードバランサーで受けることで、NGINX Plusを容易に高可用性構成にできます。

同様に、サービス間リクエストはSwarmロードバランサーが受信しますが、実際に各サービスへ分散するのはNGINX Plusです(図7)。

デモ
NGINXを使用する場合と使用しない場合の、SwarmによるDockerの負荷分散の例として、3つのデモを作成しました。これらのデモに必要なすべてのファイルは、詳細な手順とともにGitHubで公開しています。3つのデモは次のとおりです。
Docker Swarmの負荷分散
これは、NGINXやNGINX Plusを使用せずに、シンプルなWebアプリのバックエンドへのリクエストをDocker Swarmで負荷分散する例です。
NGINX Open SourceによるDocker Swarmの負荷分散
このデモでは、NGINX Open Sourceを追加し、外部リクエストのSSL/TLSオフロードを実現します。Swarmロードバランサーは、前のデモと同じシンプルなWebアプリのバックエンドにリクエストを分散し、内部のサービス間リクエストを処理します。
NGINX PlusによるDocker Swarmの負荷分散
このデモは2つのパートで構成されています。最初のパートではNGINX Plusを使用します。NGINX Plusは、SSL/TLSオフロードに加えて、リクエストをバックエンドコンテナに直接ロードバランシングし、内部のサービス間リクエストも処理します。Swarmのサービスディスカバリと統合されており、動的DNSを使用して、バックエンドに関連付けられたドメイン名を頻繁に再解決します。NGINX Plusは、2つのバックエンドサービスであるService1とService2の負荷を分散します。また、Service1からService2にリクエストを送信することで、内部のサービス間リクエストを実演します。

第2部では、NGINX Status APIとDocker Service APIを組み合わせて、バックエンドコンテナを自動的にスケーリングする方法を説明します。Pythonプログラムは、NGINX Plus Status APIを使用してService1とService2の負荷を監視し、Docker Swarm Service APIを使用してバックエンドコンテナをスケールアップまたはスケールダウンします。

まとめ
Docker 1.12で導入された新機能により、Swarmはより強力なプラットフォームになりましたが、NGINX Open Sourceを活用することでさらに強化でき、NGINX Plusを使用すれば一層の強化が可能です。NGINX Plusは、DNSを使用した負荷分散のためにバックエンドコンテナを動的に再構成できるほか、Status APIによって可視性も確保できるため、非常に強力なコンテナソリューションを実現します。
NGINX Plusをお試しいただくには、今すぐ30日間の無料トライアルを開始するか、ユースケースについてご相談ください。
また、F5のGitHubリポジトリで公開されているデモもお試しください。
著者について

関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります