NGINX.COM
Web Server Load Balancing with NGINX Plus

NGINX Plusは、オープンソース版のNGINXに様々な機能を拡張し搭載した商用版ソフトウェアです。これらの機能を利用することで、システムの可用性と堅牢性を向上させ、運用を簡素化できます。本特集では、NGINX(オープンソース版)とNGINX Plusの違いなど、そもそもNGINXがどのようなソフトウェアであるのか機能差を実際の設定例とともに紹介していきます。

そもそもNGINXとは

NGINXは、Igor Sysoev氏によって開発されたオープンソースソフトウェアです。初版は2004 年にリリースされました。当時、従来のWEBサーバが持っていたC10K問題(クライアント1万台問題)を解決することを念頭に開発されました。従来のWebサーバのアーキテクチャでは、1クライアントからの接続に対して、サーバの1プロセスあるいは1スレッドを割り当てて処理させていたため、同時接続数が増加すると、比例してプロセス数、スレッド数が増加し、コンテキストスイッチのオーバーヘッド等の原因により、性能低下が引き起こされていました。NGINXでは、イベント駆動型アーキテクチャの採用と、ノンブロッキングI/O多重化、ノンブロッキングI/O など、I/O処理の効率化を図り、クライアントからの接続数とプロセス数、スレッド数との対応を分離し、1プロセス内で複数のクライアントからの接続を処理することで、C10K問題を解決し、軽量で高いスケーラビリティを実現しています。(図1)

NGINXの処理方式概要

その後、2011年に米NGINX社が設立され、オープンソース版の開発と併せて、商用版であるNGINX Plusが提供されるようになりました。2019年5月、F5 NetworksがNGINX 社を買収しましたが、その後も以前と同様に、オープンソース版、商用版の双方共に、開発と提供が継続されています。

また、2019年12月度のNETCRAFT社の調査 によると、世界で最も利用されているWebサーバソフトウェアとされています。このように、NGINXはWEBサーバ単体として利用されることも多いのですが、WEBサーバ機能以外にも、以下のような豊富な機能を持っています。

  • ロードバランサ
  • リバースプロキシ
  • コンテンツ キャッシュ
  • APIゲートウェイ
  • Web Application Firewall

これらに加え、Kubernetes環境においては、Ingress Controllerとして動作させることが可能で、L7ロードバランサとして動作し、Kubernetesクラスタ内に外部からのトラッフィクを誘導します。なお、Ingress Controllerとして提供されているNGINXは3種類が存在します。1つ目は、Kubernetesコミュニティが開発およびメンテナンスを行うオープンソースの「kubernetes/ingress-nginx」、2つ目はF5 Networks/NGINXが開発およびメンテナンスを行うオープンソースの「nginxinc/kubernetes-ingress with NGINX」、3つ目がF5 Networks/NGINXが開発およびメンテナンスする商用版の「nginxinc/kubernetes-ingress with NGINX Plus」です。それぞれの特徴については、表1を参照ください。

表1 NGINX Ingress Controllerの比較

NGINX Plusとは

NGINX Plusは、NGINXの商用版ソフトウェアです。オープンソース版のNGINXに標準で実装されていないセッションパーシステンス機能や、APIによる動的設定変更機能、アクティブヘルスチェック機能などの拡張機能が数多く含まれています。利用者は、これらの機能を活用することにより、システムの可用性と堅牢性を向上させ、運用を簡素化できます。NGINX Plusはコンパイル済みのバイナリパッケージとして提供されますので、サポート対象のOSディストリビューションのパッケージ管理経由で、簡単に導入することが可能です。また、各種パブリッククラウドでは、NGINX Plusがインストールされたマシンイメージも提供されています。

NGINX Plusにはサポートが付属します。ベーシック、プロフェッショナル、エンタープライズと分かれ、サポート時間数や応答時間の異なる3種のプランが用意されており、NGINX Plusのサブスクリプション時に選択します。

その他NGINX製品

NGINX、NGINX Plus以外にも、NGINX製品シリーズとして、複数のソフトウェアやサービスが提供されています。これらの製品群について触れておきます。

NGINX Controller

NGINX Controllerは、複数のNGINX Plusノードを管理するための商用製品です。NGINX Controllerを導入することで、複数のNGINX Plusに対してロードバランサ機能の設定や、APIゲートウェイの設定およびAPIマネジメント機能を提供し、設定、構成の一元化が実現できます。また、リアルタイム監視、モニタリング機能やアラート生成機能などの運用監視機能も提供されます。管理対象のNGINX Plusノードにエージェントソフトウェアを追加インストールし、構成します。

図2 NGINX Controllerの構成
NGINX Controllerのユーザインターフェース

NGINX Unit

NGINX Unitは、複数のプログラミング言語に対応したアプリケーションサーバです。Apache2.0ライセンスで提供されており、無償で利用することができます。オープンソース版のNGINXやNGINX Plusと組合せて使うことで、Webアプリケーションシステムを構成することができます(図3)。特徴は以下の通りです。
  • Restful API経由で動的に設定を変更
  • 複数言語およびバージョンの同時実行
  • プロセス数のオンデマンドスケール
  • SSL/TLSのサポート
  • 豊富なリクエストルーティングと静的コンテンツのサポート
  • Node.js、Java 向けのWebSocketサーバ機能
  • アプリケーションの名前空間の分離
  • リクエストルーティング時のHTTPプロキシ

また、NGINX Unitが対応しているプログラミング言語は以下になります。

  • Python
  • PHP
  • Go
  • Perl
  • Ruby
  • JavaScript (Node.js)
  • Java

その他詳細は、https://www.nginx.co.jp/products/nginx-unit/を参照ください。

NGINX Unit概要

NGINX App Protect

NGINX App Protectは、2020年5月にリリースされた商用版であるNGINX Plus上で動くWAFモジュールです。アプリケーションのパフォーマンスとセキュリティを確保する製品の提供で実績があるF5の豊富なWAF機能を移植した製品となっています。その特徴の1つは、極めて低い誤検知率を実現する信頼性の高いシグネチャを中心とした防御機能の充実です。従来のシグネチャに加え、F5が独自収集しているリアルタイムの攻撃情報を元に生成した高精度シグネチャ(Threat Campaigns)を利用しセキュリティポリシーを構成することで、アプリケーションの脆弱性に対する迅速な対処が図れます。またAPIゲートウェイとしての機能強化の一環として、多様なプロトコルへの適応も進めています。

そして、もう一つのポイントはパフォーマンスです。グラフで分かる通り、ModSecurityとの比較ではThroughput、Requests/secの性能は桁違いに高く、Latencyは、WAFモジュ−ルを適応していない状態とほぼ変わらない程度に抑えられています。(F5調べ)。高性能なNGINX App Protectを利用することで、例えばパブリッククラウドでのリソース利用を抑制や、オンプレミスでのハードウェアリソースの抑制などなど、コスト削減の効果を得やすくなります。

そのほか詳細は、https://www.nginx.co.jp/products/nginx-app-protect/をご覧ください。

NGINX App Protectのパフォーマンス

NGINX Service Mesh

NGINX Service Mesh(NSM)は、データプレーンが重要であるという着想のもと、独自に設計されたシンプルなサービスメッシュソリューションです。高可用でスケーラブルなコンテナ環境の運用に、NGINX Plusをデータプレーンとして利用することで、他のリバースプロキシサイドカーでは提供不可能なレベルのインテリジェンスなトラフィック管理を提供します。

単一の設定でIngressとEgressの両方を管理する統合データプレーンによって、コンテナトラフィック管理に向けた安全なサービス管理ソリューションを提供します。Kubernetes環境におけるインテリジェントなトラフィック管理を可能にするプロダクショングレードの機能により、シンプルなトラフィック管理を実現します。

軽量でシームレスな設計になっており、小規模なシステムから安全にスケールが求められるエンタープライズグレードのシステムまで、マイクロサービスの計画におけるあらゆる段階に応じたスケーリングが可能です。

そのほか詳細は、https://www.nginx.co.jp/products/nginx-service-mesh/をご覧ください。

NGINX Service Mesh概要

オープンソース版のNGINXとNGINX Plusの違い

オープンソース版のNGINXとNGINX Plusの機能については、様々な違いがあります。

オープンソース版NGINXとNGINX Plusの違い

WEBINER

「これからはじめるNGINX技術解説~基本編」セミナー

今すぐ視聴する

ここでは、主要なものをピックアップして説明します。

ロードバランサ機能

NGINXは、ロードバランサとして動作させることができます。ユーザから通信を受け、背後のサーバ郡に通信を振り分けます。NGINXでは、これらの背後のサーバ郡をアップストリームサーバと呼びます。NGINXでは、負荷分散方式として、ラウンドロビン、最小コネクション、IPハッシュなどを選択できますが、NGINX Plusではこれに加えて、アップストリームサーバの最小コネクションと最小レスポンスタイムの情報を元に振り分けを行うLeast Timeという方式を利用できます。Least Timeを使用すると、振り分け処理時にアップストリームサーバの性能が考慮されるようになりますので、サーバによって性能のばらつきがある場合でも、負荷を均等に保つことができます。以下、この他のロードバランサ機能でのオープンソース版のNGINXとNGINX Plusの違いを記載します。

図6 NGINXのロードバランス機能

アクティブヘルスチェック

オープンソース版のNGINXでは、アップストリームサーバに対してのヘルスチェックは、実際のサービスに使われている通信状態で判定を行うパッシブヘルスチェックのみが利用可能です。このため、アップストリームサーバがダウンした際も一定期間、リクエストが当該アップストリームサーバに渡され、サービスに影響を及ばす可能性があります。一方、NGINX Plusでは、独立したヘルスチェック通信を設定でき、この結果を元に、アップストリームサーバへの振り分け処理を行うことが可能です。これにより、アップストリームサーバの異常を早期に検出し、負荷分散先から除外することで、サービスへの影響を極小化することが可能です。

実際の設定を図7に示します。

 1  upstream my_upstream {
 2      zone my_upstream 64k;
 3      server server1.example.com slow_start=30s;
 4      server server2.example.com slow_start=30s;
 5  }
 6
 7  server {
 8      location / {
 9          proxy_pass http://my_upstream;
10          health_check interval=5s uri=/test.php match=statusok;
11      }
12  }
13
14  match statusok {
15      status 200;
16      header Content-Type = text/html;
17      body ~ "Server[0-9]+ is alive";
18  }

図7 アクティブヘルスチェックの設定例

1行目からのアップストリームグループ「my_upstream」の定義では、zoneディレクティブで、ワーカープロセスが構成情報を保持するためのメモリ空間を定義します(2行目)。この設定は、アクティブヘルスチェックの設定を行うために必須の設定となります。また、3行目と4行目では、slow_startディレクティブを使い、指定サーバが利用可能となった場合にトラフィックが偏らないように指定時間をかけて重み付けを通常の状態まで戻していくように設定しています。こちらの設定も、NGINX Plusでのみ可能です。

8行目からのlocationディレクティブ内で、health_checkディレクティブを定義します(10行目)。この例では、アップストリームグループ「my_upstream」に対して、5秒ごとに/test.php宛のヘルスチェックパケットを送出します。match パラメータでは、後述するヘルスチェックの応答パケットが満たすべき条件を定義した設定名「statusok」を指定します。

14行目からのmatch ディレクティブでは、ヘルスチェックの応答パケットが満たすべき条件を定義します。図6の例では、 レスポンスコードが200であり、コンテンツヘッダにContent-Type = text/htmlが含まれ、ボディに正規表現で指定した文字列が含まれることが条件となります。

セッション維持(セッションパーシステンス)

負荷分散先のアップストリームサーバで提供されているアプリケーションがステートフルであった場合、同一のクライアントからのリクエストは同じアップストリームサーバに振り分ける必要があります。このような要件を実現するロードバランサの仕組みは、セッションパーシステンスと呼ばれます。NGINX Plusでは、Cookie を利用したSticky cookie , Sticky route , Sticky learn という3つのセッションパーシステンス方法が提供されています。

Sticky cookieは、NGINX Plus自身がセッション維持用のCookieを生成してアップストリームサーバからの応答に挿入します。Sticky cookieの設定例を、図8に示します。

1  upstream my_upstream {
2      server server1.example.com;
3      server server2.example.com;
4
5      sticky cookie srv_id expires=1h;
6  }

図8 Sticky cookieの設定例

図8の例では、「srv_id」がNGINX Plusが生成するCookie名で、有効期限を1時間に設定しています。この設定より、最初のリクエストから1時間、同一クライアントからのリクエストは同じアップストリームサーバへ振り分けられます。

Sticky routeでは、クライアントからの最初のリクエストを、アップストリームサーバグループの指定で設定されたroute情報に紐付けます。以降のリクエストは、CookieやURL中に指定されているパラメータ情報をもとに、アップストリームサーバに振り分けを行います。設定例を図9に示します。

 1  map $cookie_jsessionid $route_cookie {
 2      ~.+\.(?P<route>\w+)$ $route;
 3  }
 4
 5  map $request_uri $route_uri {
 6      ~jsessionid=.+\.(?P<route>\w+)$ $route;
 7  }
 8
 9  upstream backend {
10      server backend1.example.com route=a;
11      server backend2.example.com route=b;
12
13      sticky route $route_cookie $route_uri;
14  }

図 9 Sticky routeの設定例

図9の例では、Cookie「JSESSIONID」の値に、ピリオド(.)で区切って末尾に設定されている値があれば、それをパラメータとして採用します。当該Cookieの値がない場合は、URLのクエリ文字列中に「jsessionid」で指定されている値のピリオド(.)で区切って末尾に設定されている値をパラメータとして採用します。採用したパラメータをもとに、最初のリクエストと同じroute情報が指定されているアップストリームサーバに振り分けを行います。

Sticky learnではアップストリームサーバが生成した Cookieの値を学習し、セッション維持に使用します。設定例を図10に示します。

 1  upstream backend {
 2     server backend1.example.com;
 3     server backend2.example.com;
 4     sticky learn
 5         create=$upstream_cookie_examplecookie
 6         lookup=$cookie_examplecookie
 7         zone=client_sessions:1m
 8         timeout=1h;
 9  }

図10 Sticky Leanの設定例

図10の例では、アップストリームサーバからの応答に含まれるCookie「EXAMPLECOOKIE」の値を学習し(5行目)、クライアントからのリクエストに含まれる同じくCookie「EXAMPLECOOKIE」の値を参照し(6行目)、振り分け先のアップストリームサーバを決定します。この方式は、セッション情報をzoneと呼ばれるメモリ空間に保存します(7行目)。このため、後述のステート共有の設定を追加することで、複数のノード間にまたがってセッション情報を共有することが可能です。

DNSサービス・ディスカバリ 統合

アプリケーションサービスを構成するアップストリームサーバのIPアドレスが変更されたり、あるいはアップストリームサーバの数が増減しうる環境では、それらの変更をロードバランサが検出し動作を適応させる必要があります。NGINX Plusでは、アップストリームサーバの指定をupstreamディレクティブ内で、DNS名を使って行うことができますので、NGINX Plusが参照するDNSレコードを調整することで、このような要件に対応することが可能です。

まずは、AレコードをDNS名として使用する例を図11に示します。

 1  resolver 10.0.0.2 valid=10s;
 2
 3  upstream backends {
 4      zone backends 64k;
 5      server backends.example.com:8080 resolve;
 6  }
 7
 8  server {
 9      location / {
10          proxy_pass http://backends;
11      }
12  }

図11 Aレコードを使用する設定例

この例では、10秒ごとに指定のDNSサーバにserverディレクティブで指定したDNS名「backends.example.com」(5行目)の問い合わせを、1行目でresolverに指定したDNSサーバに対して行い、応答で得たIPアドレスをアップストリームサーバとして扱います。ポイントは、serverディレクティブの行末の「resolve」パラメータです。このパラメータが、NGINX Plusでの使用可能なもので、DNS名に対応するIPアドレスの変更を監視する動作となります。オープンソース版のNGINXでも、serverディレクティブでDNS名を指定することはできますが、プロセス起動時に名前解決を行った結果を、次回の設定の再読み込みまでキャッシュし続けてしまう等の制約があります。

また、NGINX Plusでは、DNSのSRV レコードを利用することもできます。DNSのSRVレコードでは、各サーバの優先度の設定や重み付けを行えます。また、サーバごとでサービスのリスニングポートを指定することができますので、先の例よりも柔軟にアップストリームサーバを構成することができます。

設定例を図12に示します。

 1  resolver 10.0.0.2 valid=10s;
 2
 3  upstream backends {
 4      zone backends 64k;
 5      server backends.example.com service=_http._tcp resolve;
 6  }
 7
 8  server {
 9      location / {
10          proxy_pass http://backends;
11      }
12  }

図12 SRVレコードを利用する設定例

この例では、5行目のserverパラメータで指定したDNS名「backends.example.com」(10行目)のSRVレコードの問い合わせを、1行目でresolverに指定したDNSサーバに対して行い、応答で得た情報(サーバの優先度の設定や重み付け、リスニングポートなど)をもとにアップストリームサーバとして構成します。

その他、DNSを用いたアップストリームサーバの構成例については、ブログ「Using DNS for Service Discovery with NGINX and NGINX Plus(https://www.nginx.com/blog/dns-service-discovery-nginx-plus/)」で詳細に解説されていますので、参照ください。

コンテンツ キャッシュ

NGINXは、コンテンツキャッシュサーバとしても動作させることができます。NGINXが動作しているローカルホストや外部のオリジンサーバのコンテンツをキャッシュし、レスポンスの高速化やオリジンサーバの負荷軽減が実現できます。

図13 NGINXのコンテンツキャッシュ機能

キャッシュ・パージ機能

オープンソース版のNGINX では、キャッシュを削除する仕組みが標準では提供されておらず、これを実現するためには、サードパーティモジュールを組み込む必要があります。NGINX Plusでは任意のタイミングでこのキャッシュエントリをパージする機能が標準で提供されています。この機能を利用し、キャッシュされているコンテンツを差し替えたい場合や、キャッシュ自体を無効にしたい場合に、即座に対応することができます。

設定例を図14に示します。図14 の例では、80番ポートでユーザからのリクエストをリスングして、同一ホストの8002番で動作するwebサーバからのコンテンツをキャッシュしています。

 1  http {
 2      ...
 3      proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on;
 4
 5      map $request_method $purge_method {
 6          PURGE 1;
 7          default 0;
 8      }
 9
10      server {
11          listen 80;
12          server_name www.example.com;
13
14          location / {
15              proxy_pass https://localhost:8002;
16              proxy_cache mycache;
17              proxy_cache_purge $purge_method;
18          }
19      }
20
21      geo $purge_allowed {
22         default 0;
23         10.0.0.1 1;
24         192.168.0.0/24 1;
25      }
26
27      map $request_method $purge_method {
28         PURGE $purge_allowed;
29         default 0;
30      }
31  }

図14 コンテンツキャッシュのパージ設定例

17行目のproxy_cache_purgeディレクティブで、キャッシュパージ要求と見なす条件を定義しています。この例では、$purge_method変数を条件とし、値が空でなく、また「0」でない場合に、キャッシュキーに対応するキャッシュエントリをパージします。5行目〜6行目では、リクエストメソッドがPURGEだった場合に、$purge_method変数の値が1になるように設定されています。

さらに、PURGEリクエストの送信元制限を行うため、geoモジュールを使用して、指定したIPアドレス(10.0.0.1もしくは192.168.0.0/24)に送信元IPアドレスが合致した場合のみ、$purge_method変数の値が1になるよう設定されています(21行目〜25行目)。

上記の設定をNGINX Plusで行った状態で、下記の例のように、指定したIPアドレスから、PURGEメソッドでアクセスすると、キャッシュエントリをパージすることできます。

$ curl -X PURGE -D – "http://www.example.com/*"

JWT 認証

NGINX Plusならではのセキュリティ制御関連の機能としては、JWT(JSON Web Token)の検証機能が挙げられます。この機能と他のリバースプロキシ機能と組み合わせることで、APIゲートウェイとしてNGINX Plusを使用してクライアントを認証できます。

JWT認証の詳細については、こちらのブログ「Authenticating API Clients with JWT and NGINX Plus(https://www.nginx.com/blog/authenticating-api-clients-jwt-nginx-plus/)」で解説されていますので、参照ください。

監視

オープンソース版のNGINXでは、監視用のメトリクスとして、合計リクエスト数や各種接続数(許可された接続数、処理された接続数、アクティブな接続数)などの情報を、オプションモジュールの「ngx_http_stub_status_module」経由で取得することが可能です。一方、NGINX Plusでは、これらに加え、以下のようなメトリクスを、後述するNGINX Plus APIから取得することができます。

  • HTTPステータスコードごとの応答数(4xx,5xx等)
  • アップストリームサーバごとの統計
  • キャッシュ機能の統計(サイズ、キャッシュヒット数、キャッシュミス数)
  • SSLの統計(ハンドシェイクの成功数、失敗数)

冗長化構成(HA)

NGINX Plusがサポートする高可用性(HA)を実現する冗長化構成について、オンプレミスの場合とパブリッククラウド環境の場合の2通りを解説します。また、冗長化構成と併用できる「設定の同期」と「ステート共有」の二つの機能についても紹介します。

オンプレミスの場合

NGINX Plus では、keepalivedをベースにしたactive-passive構成とactive-active構成をサポートします。NGINX Plus のリポジトリで提供されているnginx-ha-keepalivedパッケージを追加インストールし、nginx-ha-setupスクリプトを実行することで設定することが可能です。keepalivedが提供するVRRP機構で提供されるVIPをサービスのリスニングIPとして利用します。詳細はドキュメント「https://docs.nginx.com/nginx/admin-guide/high-availability/ha-keepalived/」を参照ください。

図15 オンプレミス環境での冗長化構成

パブリッククラウド環境の場合

多くのパブリッククラウド環境ではVRRPの使用ができないため、オンプレミスと同じ冗長化構成をとることができません。そうした環境では、他の冗長化構成を採用する必要があります。ここでは、AWS環境を例として、利用可能な冗長構成について紹介します。

AWS上では、以下の3つのパターンの冗長構成をとることが可能です。

■Elastic IP Addressesを利用したactive-passive構成

OS(Linuxディストリビューション)が提供するkeepalivedを利用します。これに、GitHub「https://github.com/nginxinc/aws-ha-elastic-ip」で提供されている2つのスクリプト(nginx-ha-check, nginx-ha-notify)を組み合わせます。AWS環境では、サービスのリスニングIPとして、Elastic IP Addressを使用します。activeノードの障害時には、keepalivedが、nginx-ha-notifyスクリプトをキックして、Elastic IP Addressをpassiveノードに付け替えることによって、フェイルオーバーを実現します。

図16 Elastic IP Addressesを利用したactive-passive構成

■AWS Network Load Balancerを利用したactive-active構成

AWSが提供するL4ロードバランサーであるAWS Network Load Balancerを前段に配置し、NGINX Plusノードをターゲットグループとして登録します。ユーザからのリクエストを、AWS Network Load Balancerが受け付け、背後のNGINX PlusにL4レベルで振り分けます。これにより、active-active構成を実現することができます。詳細はドキュメント「https://docs.nginx.com/nginx/deployment-guides/amazon-web-services/high-availability-network-load-balancer/」を参照ください。

図17 AWS Network Load Balancerを利用したactive-active構成

■グローバルロードバランサを利用した冗長化構成

グローバルロードバランサを利用することで、active-active構成あるいはactive-standby構成を実現することができます。AWS環境ですと、グローバルロードバランサとして、Route53を使うケースが多いと思います。NGINX Plusノードに、それぞれElastic IP Addressを割り当て、そのIPアドレスをRoute53側で、単一のDNS名に割り当て、DNSフェイルオーバーを構成することで、冗長化を実現できます。詳細はドキュメント「https://docs.nginx.com/nginx/deployment-guides/amazon-web-services/route-53-global-server-load-balancing/」を参照ください。

図18 Route53を利用した冗長構成

設定の同期

NGINX Plusでは、冗長構成のクラスタノード間での設定同期の仕組みが標準で提供されています。クラスタ内で一つのノードをマスタノードとして設定し、残りのノードをPeerノードとして設定します。マスタノードの設定が、Peerノードにrsyncで配布され、プロセスのリロードがssh経由で行われる仕組みです。(図19) この機能を利用することで、設定の均一化や、ノード追加時の設定の簡略化を簡単に実現できます。

図19 NGINX Plusの設定の同期

以下、OSがCentOSの場合の設定手順を記載します。

1.マスタノード上に、nginx-sync パッケージをインストールします。

$sudo yum install nginx-sync

2.マスタノード上でpeerノードへのssh用の鍵を生成します。

$ sudo ssh-keygen -t rsa -b 2048
$ sudo cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc ... aRsL root@node1

3.peerノード上で、マスタノードからのsshアクセスを許可します。

下記の192.168.1.2は、マスタノードのIPアドレスに読み替えてください。

$ sudo mkdir /root/.ssh
$ sudo echo 'from="192.168.1.2" ssh-rsa AAAAB3NzaC1yc ... aRsL root@node1 ' >> /root/.ssh/authorized_keys

以下を、「/etc/ssh/ sshd_config」ファイルに追加します。

PermitRootLogin without-password

sshdをリロードします。

$ sudo systemctl reload sshd 

4.マスタノード上で、設定ファイル、「/etc/nginx-sync.conf」 を作成します。図19に設定例を示します。

1  NODES="node2.example.com node3.example.com node4.example.com"
2  CONFPATHS="/etc/nginx/nginx.conf /etc/nginx/conf.d"
3  EXCLUDE="default.conf"

図20 nginx-sync.confの設定例

以下、設定項目の内容です。

1行目NODES:
peerノードを、スペースまたは改行区切りで指定します

2行目CONFPATHS:
同期する設定ファイルまたはディレクトリを、スペースまたは改行区切りで指定します

3行目EXCLUDE:
CONFPATHSで指定したディレクトリの内のファイルで同期から除外するファイルをスペースまたは改行区切りで指定します

この他、指定可能な設定項目は、ドキュメント「https://docs.nginx.com/nginx/admin-guide/high-availability/configuration-sharing/」を参照ください。

5.設定の同期は以下のコマンドで可能です

ヘルプコマンド

$ nginx-sync.sh -h 

指定したpeerノードとの設定の比較

$ nginx-sync.sh -c node2.example.com

全てのpeerノードとの設定の比較

$ nginx-sync.sh -C

peerノードと設定を同期し、NGINXプロセスをリロードする

$ nginx-sync.sh

ステート共有:スティッキーセッション維持、レート制限、キーバリューストア

NGINX/NGINX Plusでは、リクエスト処理に利用している各種ステート情報を、各ノードのメモリ空間で管理しています。各ノードが固有の情報のみ保持している場合、リクエストを受信したノードによって処理が変わってしまうという問題が発生します。NGINX Plusでは、クラスタ内のノード間でステート情報を保持しているメモリの中身を同期することが可能です。このため、クラスタ内のどのノードでリクエストを受信しても、共有しているステート情報を元に同じ処理を行うことができます。具体的には、スティッキーセッションパーシステンス(Sticky learn)の情報や、レート制限(limit_req)の情報、キーバリュストアの内容を、クラスタ内のノード間で共有させることができます。(スティッキーセッションパーシステンスは、リリースバージョンR15以降、レート制限とキーバリューストアは、リリースバージョンR16以降で共有可能です。)

前述の設定の同期では、クラスタ内でマスタノードを決定し、マスタノードの設定内容を他のpeerノードに配布するという構成でしたが、ステート共有ではマスターノードという概念はありません。クラスタ内のノードは同等で、フルメッシュ型で通信し、情報を共有します。

設定の詳細は、下記ドキュメント

https://docs.nginx.com/nginx/admin-guide/high-availability/zone_sync/

を参照ください。

プログラマビリティ

プログラマビリティに関連するNGINX Plusの機能については、「NGINX PlusAPI」と「キーバリューストア」の二つを解説します。

NGINX Plus API

NGINX Plus リリースバージョンR13以降では、NGINX plus APIと呼ばれるRESTful APIが提供されています。このAPIを利用することで、設定ファイルの編集やプロセスのリロードをすることなく、アップストーリムサーバの設定などを行うことが可能です。設定例を図21に示します。

 1  http {
 2      # ...
 3      # Configuration of the server group
 4      upstream appservers {
 5          # 共有メモリにサーバグループ構成を保存するように、ゾーンの設定を行う
 6          zone appservers 64k;
 7
 8          server appserv1.example.com      weight=5;
 9          server appserv2.example.com:8080 fail_timeout=5s;
10          server reserve1.example.com:8080 backup;
11          server reserve2.example.com:8080 backup;
12      }
13      server {
14          # Location that proxies requests to the upstream group
15          location / {
16              proxy_pass http://appservers;
17              health_check;
18          }
19
20          # Location for dynamic configuration requests
21          location /api {
22          # GET以外のメソッドをBasic認証で制限
23              limit_except GET {
24                  auth_basic "NGINX Plus API";
25                  auth_basic_user_file /etc/nginx/.htpasswd;
26              }
27          # APIを書き込みモードで動作させる
28              api write=on;
29          # アクセス元をローカルホストのみに制限
30              allow 127.0.0.1;
31              deny  all;
32          }
33      }
34  }

図21 NGINX Plus APIの設定例

上記の設定を行った後、以下のコマンドをローカルから実行すると、アップスストリームグループであるappserversに、新しいサーバ” 172.16.0.70”、リスニングポート80番を追加することができます。

(下記コマンドは、一行として実行してください。また、$USER$PASSWORDはベーシック認証で設定したものに読み替えてください。)

curl -u $USER:$PASSWORD -X POST -d '{"server":"172.16.0.70:80", "weight":"4", "max_conns":"0","max_fails":"0", "fail_timeout":"10s", "slow_start":"10s", "backup":"true", "down":"true"}'  -s 'http://127.0.0.1/api/6/http/upstreams/appservers/servers'

その他、NGINX plus APIのエンドポイントやメソッドの詳細は、以下のドキュメント「https://nginx.org/en/docs/http/ngx_http_api_module.html」記載されています。

また、NGINX plus API に組み込まれているSwagger UIを、URL「http://_NGINX-host_/swagger-ui/」から確認することもできます。(図22)

図22 Swagger UI

図21の例では、NGINX Plusのプロセスが設定ファイルの再読み込みを行ったタイミングで、API経由で行った変更は破棄されます。API経由での設定を永続化するには、アップストリームサーバの定義をstateファイルで管理するように設定を変更します。(図23)

 1  http {
 2      # ...
 3      # Configuration of the server group
 4      upstream appservers {
 5          # 共有メモリにサーバグループ構成を保存するように、ゾーンの設定を行う
 6          zone appservers 64k;
 7          state /var/lib/nginx/state/appservers.conf;
 8          # server appserv1.example.com      weight=5;
 9          # server appserv2.example.com:8080 fail_timeout=5s;
10          # server reserve1.example.com:8080 backup;
11          # server reserve2.example.com:8080 backup;
12      }
13  }

図23 stateファイルの設定例

図23では、8行目から11行目でアップストリームサーバの設定をコメントアウトしています。一方、7行目で、stateファイルを指定しています。これらの設定後、API経由でアップストリームサーバを追加すると、stateファイルに記録され、設定ファイルの再読み込み後も変更内容が維持されます。なお、stateファイルの直接編集はサポートされていないため、必ず、API経由で設定を行う必要があります。

キーバリューストア

NGINX Plus リリースバージョンR13以降で、任意のキーと値のペアをAPI経由で、メモリ上に保存し、NGINXのプロセスに変数として処理させることで、トラフィック処理等に利用できます。前述のとおり、リリースバージョンR16以降では、クラスタ内のノード間で、このキーバリューストアを同期することができます。キーバリューストアを利用し、送信元IPアドレスやCookieの情報などを保存し、動的IPブラックリストによるアクセス制限や、動的帯域制限を実現することが可能となります。

簡単な設定例を図24に示します。

$remote_addressというキーと、$black_listという値を持つキーバリューストアを定義しています(4行目)。80番ポートでリスニングしているサーバは、送信元IPアドレスが、$remote_addressに合致する場合、$black_listの値を評価し、値が0である場合、403エラーを返します。(10行目〜12行目)

 1  http {
 2      # キーバリューストアの定義
 3      keyval_zone zone=blacklist:1M state=/tmp/blacklist.json;
 4      keyval $remote_addr $black_list zone=blacklist;
 5
 6      server {
 7      listen 80;
 8          location / {
 9              root /usr/share/nginx/html;
10              if ($black_list = 0) {
11                  return 403;
12              }
13          }
14
15          location /api {
16              # GET以外のメソッドをBasic認証で制限
17              limit_except GET {
18              auth_basic "NGINX Plus API";
19              auth_basic_user_file /etc/nginx/.htpasswd;
20              }
21              # APIを書き込みモードで動作させる
22              api write=on;
23              #アクセス元をローカルホストのみに制限
24              allow 127.0.0.1;
25              deny  all;
26          }
27      }
28  }

図24 キーバリューストアの設定例

上記の設定後、以下のコマンドで、API経由で、キーと値を設定します。

$USER$PASSWORDはベーシック認証で設定したものに読み替えてください。)

curl -u $USER:$PASSWORD -X POST -d '{"192.168.1.10":"0"}' http://localhost/api/1/http/keyvals/blacklist 

上記コマンドの実行後に、192.168.1.10からアクセスすると、403エラーが返るようになります。

その他、キーバリューストアの詳細については、ドキュメント「https://nginx.org/en/docs/http/ngx_http_keyval_module.html」を参照ください。また、キーバリューストアの活用例については以下のブログで紹介されていますので、参照ください。

動的帯域制御での活用例

https://www.nginx.com/blog/dynamic-bandwidth-limits-nginx-plus-key-value-store/

動的IPブラックリストでの活用例

https://www.nginx.com/blog/dynamic-ip-blacklisting-with-nginx-plus-and-fail2ban/

A/Bテストでの活用例

https://www.nginx.com/blog/dynamic-a-b-testing-with-nginx-plus/

WEBINER

「これからはじめるNGINX技術解説~基本編」セミナー

今すぐ視聴する

Hero image
NGINXクックブック 設定レシピ集(日本語版)

待望の【O'Reilly】NGINX Cookbook日本語版がついに完成!NGINXクックブックは、NGINXを最大限に活用する方法を解説しています。



著者について

高田 知典

ソリューションエンジニア

About F5 NGINX

F5 NGINXについて
F5, Inc.は、人気のオープンソースプロジェクト「NGINX」を支援しています。NGINXはモダンアプリケーションを開発・構築するためのテクノロジースイートを提供しています。NGINXとF5製品との併用で、コードからユーザーまでの広範なアプリケーション領域をサポートし、マルチクラウドアプリケーションサービスとしてNetOpsとDevOps間の課題を解決します。

詳しくはnginx.co.jpをご覧ください。Twitterで@nginxをフォローして会話に参加することもできます。