NGINX Plus の設定

0. (事前準備) NGINX Plusのインストール

1. NGINX Plusのインストール・基礎

以下のページの内容を参考にNGINX Plus及びモジュールをインストールします
また、このラボは以下の内容を理解していることを前提としています。
初めてNGINX Plusを操作する方は、以下より基本的な挙動について確認をしてください。

2. 環境の初期セットアップ

以降のラボで利用するファイルを取得します

cd ~/
git clone https://github.com/BeF5/f5j-nginx-plus-lab2-conf

共通設定としてNGINX Plus API、Dashboardの設定をコピーします

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/api.conf /etc/nginx/conf.d/
sudo nginx -s reload

F5ラボ環境を利用の場合、以下のどちらかの手段で接続してください

  • (推奨)リモートデスクトップに接続している場合http://10.1.1.7:8888/dashboard.html を開いてください

  • リモートデスクトップを利用していない場合 、ご利用の端末から接続するため、 ubuntu01 の接続メニューより PLUS  DASHBOARD を選択してください

1. 流量制御(Rate limit)

Rate Limitの設定を紹介します。

../../_images/nginx-ratelimit-slide1.jpg ../../_images/nginx-ratelimit-slide2.jpg ../../_images/nginx-ratelimit-slide3.jpg ../../_images/nginx-ratelimit-slide4.jpg ../../_images/nginx-ratelimit-slide5.jpg ../../_images/nginx-ratelimit-slide6.jpg

使用するディレクティブの詳細は以下のページを参照してください。

1. ratelimit

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/ratelimit1.conf
実行結果サンプル
 1limit_req_zone $remote_addr zone=req:1M rate=1r/s;
 2
 3upstream server_group {
 4    zone backend 64k;
 5
 6    server backend1:81;
 7}
 8
 9server {
10   listen 80;
11   #status_zone server;
12   location / {
13       status_zone root;
14       limit_req zone=req;
15       proxy_pass http://server_group;
16   }
17}
  • 1行目で、Rate Limit を設定します。 Request Limit の Key を $remote_addr 、 zone名を req、rate を 1r/s(1秒間1リクエスト) と指定しています。これらにより、同一の送信元IPアドレスに対し、指定したリクエストのみを許可するルールとなります

  • 14行目で、zone名を指定する事によりポリシーを選択・適用します。複数の limit_req_zone を定義した場合、Zone名を切り替える事により適用ルールを選択することが可能です

  • 13行目で、status_zone を記述し、 root という名称の location status zone を指定しています。NGINX Plusではこの機能により、Rate Limitの状況を確認することが可能です

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/ratelimit1.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Zones のタブを選択してください。

以下のコマンドを実行し、動作を確認します。

for i in {1..3}; do echo "==$i==" ; curl -I -s localhost ; done
実行結果サンプル
 1==1==
 2HTTP/1.1 200 OK
 3Server: nginx/1.21.6
 4Date: Thu, 22 Sep 2022 07:07:33 GMT
 5Content-Type: application/octet-stream
 6Content-Length: 505
 7Connection: keep-alive
 8
 9==2==
10HTTP/1.1 503 Service Temporarily Unavailable
11Server: nginx/1.21.6
12Date: Thu, 22 Sep 2022 07:07:33 GMT
13Content-Type: text/html
14Content-Length: 197
15Connection: keep-alive
16
17==3==
18HTTP/1.1 503 Service Temporarily Unavailable
19Server: nginx/1.21.6
20Date: Thu, 22 Sep 2022 07:07:33 GMT
21Content-Type: text/html
22Content-Length: 197
23Connection: keep-alive
  • 1回目の実行で、 200 OK が応答されていることが確認できます

  • 2回目、3回目は、Rate Limit により 503 Service Temorarily Unavailable が応答されていることがわかります。

Error Log の内容を確認します

tail -2 /var/log/nginx/error.log | grep limiting
実行結果サンプル
12022/09/22 16:07:33 [error] 23556#23556: *1493 limiting requests, excess: 0.990 by zone "req", client: 127.0.0.1, server: , request: "HEAD / HTTP/1.1", host: "localhost"
22022/09/22 16:07:33 [error] 23555#23555: *1494 limiting requests, excess: 0.981 by zone "req", client: 127.0.0.1, server: , request: "HEAD / HTTP/1.1", host: "localhost"

zone req で Rate Limit が2件記録されていることが確認できます

Access Log の内容を確認します

grep HEAD /var/log/nginx/access.log | tail -3
実行結果サンプル
1127.0.0.1 - - [22/Sep/2022:16:07:33 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
2127.0.0.1 - - [22/Sep/2022:16:07:33 +0900] "HEAD / HTTP/1.1" 503 0 "-" "curl/7.68.0" "-"
3127.0.0.1 - - [22/Sep/2022:16:07:33 +0900] "HEAD / HTTP/1.1" 503 0 "-" "curl/7.68.0" "-"

1行目は、 200 が応答されており、 4行目は 503 が応答されていることが確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-ratelimit1.jpg
  • Location Zone の表より 5xx2 となっていることがわかります

  • Limit Req のグラフより Passed1Rejected2 となっていることがわかります

2. burst, nodelay(delay)

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/ratelimit2-burst-nodelay.conf
実行結果サンプル
 1limit_req_zone $remote_addr zone=req:1M rate=1r/s;
 2
 3upstream server_group {
 4    zone backend 64k;
 5
 6    server backend1:81;
 7}
 8
 9server {
10   listen 80;
11   #status_zone server;
12   location / {
13       status_zone root;
14       limit_req zone=req burst=2 nodelay;
15       proxy_pass http://server_group;
16   }
17}
  • 1. ratelimit の内容との差分を紹介します

  • 14行目で、 burst=2nodelay オプションを指定し、zone req の limit_req を適用します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/ratelimit2-burst-nodelay.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Zones のタブを選択してください。

以下のコマンドを実行し、動作を確認します。

for i in {1..4}; do echo "==$i==" ; curl -I -s localhost ; done
実行結果サンプル
 1==1==
 2HTTP/1.1 200 OK
 3Server: nginx/1.21.6
 4Date: Thu, 22 Sep 2022 07:10:20 GMT
 5Content-Type: application/octet-stream
 6Content-Length: 505
 7Connection: keep-alive
 8
 9==2==
10HTTP/1.1 200 OK
11Server: nginx/1.21.6
12Date: Thu, 22 Sep 2022 07:10:20 GMT
13Content-Type: application/octet-stream
14Content-Length: 505
15Connection: keep-alive
16
17==3==
18HTTP/1.1 200 OK
19Server: nginx/1.21.6
20Date: Thu, 22 Sep 2022 07:10:20 GMT
21Content-Type: application/octet-stream
22Content-Length: 505
23Connection: keep-alive
24
25==4==
26HTTP/1.1 503 Service Temporarily Unavailable
27Server: nginx/1.21.6
28Date: Thu, 22 Sep 2022 07:10:20 GMT
29Content-Type: text/html
30Content-Length: 197
31Connection: keep-alive
  • 1-3回目の実行で、 200 OK が応答されていることが確認できます。これは burst=2 で指定した数だけ、指定のLimitを超過するアクセスが許可されています

  • 4回目の実行で、Rate Limit により 503 Service Temorarily Unavailable が応答されていることがわかります。

Error Log の内容を確認します

tail -2 /var/log/nginx/error.log | grep limiting
実行結果サンプル
12022/09/22 16:10:20 [error] 23778#23778: *1507 limiting requests, excess: 2.972 by zone "req", client: 127.0.0.1, server: , request: "HEAD / HTTP/1.1", host: "localhost"

zone req で Rate Limit が記録されていることが確認できます

Access Log の内容を確認します

grep HEAD /var/log/nginx/access.log | tail -4
実行結果サンプル
1127.0.0.1 - - [22/Sep/2022:16:10:20 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
2127.0.0.1 - - [22/Sep/2022:16:10:20 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
3127.0.0.1 - - [22/Sep/2022:16:10:20 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
4127.0.0.1 - - [22/Sep/2022:16:10:20 +0900] "HEAD / HTTP/1.1" 503 0 "-" "curl/7.68.0" "-"

1-3行目は、 200 が応答されており、 4行目は 503 が応答されていることが確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-ratelimit2.jpg
  • Location Zone の表より 5xx1 となっていることがわかります

  • Limit Req のグラフより Passed3Rejected1 となっていることがわかります

3. dry run

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/ratelimit3-dryrun.conf
実行結果サンプル
 1limit_req_zone $remote_addr zone=req:1M rate=1r/s;
 2
 3upstream server_group {
 4    zone backend 64k;
 5
 6    server backend1:81;
 7}
 8
 9server {
10   listen 80;
11   #status_zone server;
12   location / {
13       status_zone root;
14       limit_req zone=req burst=2 nodelay;
15       limit_req_dry_run on;
16       proxy_pass http://server_group;
17   }
18}
  • 1. ratelimit の内容との差分を紹介します

  • 15行目で、 limit_req_dry_run on を指定します。このオプションにより、実際に通信は拒否せず、ステータスの確認が可能となります

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/ratelimit3-dryrun.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Zones のタブを選択してください。

以下のコマンドを実行し、動作を確認します。

for i in {1..4}; do echo "==$i==" ; curl -I -s localhost ; done
実行結果サンプル
 1==1==
 2HTTP/1.1 200 OK
 3Server: nginx/1.21.6
 4Date: Thu, 22 Sep 2022 07:20:18 GMT
 5Content-Type: application/octet-stream
 6Content-Length: 505
 7Connection: keep-alive
 8
 9==2==
10HTTP/1.1 200 OK
11Server: nginx/1.21.6
12Date: Thu, 22 Sep 2022 07:20:18 GMT
13Content-Type: application/octet-stream
14Content-Length: 505
15Connection: keep-alive
16
17==3==
18HTTP/1.1 200 OK
19Server: nginx/1.21.6
20Date: Thu, 22 Sep 2022 07:20:18 GMT
21Content-Type: application/octet-stream
22Content-Length: 505
23Connection: keep-alive
24
25==4==
26HTTP/1.1 200 OK
27Server: nginx/1.21.6
28Date: Thu, 22 Sep 2022 07:20:18 GMT
29Content-Type: application/octet-stream
30Content-Length: 505
31Connection: keep-alive

すべての実行結果が 200 OK となり、通信が拒否されていないことがわかります

Error Log の内容を確認します

tail -2 /var/log/nginx/error.log | grep limiting
実行結果サンプル
12022/09/22 16:20:18 [error] 23890#23890: *1532 limiting requests, dry run, excess: 2.953 by zone "req", client: 127.0.0.1, server: , request: "HEAD / HTTP/1.1", host: "localhost"

通信は拒否されていませんでしたが、zone req で Rate Limit の Dry Run が記録されていることが確認できます

Access Log の内容を確認します

grep HEAD /var/log/nginx/access.log  | tail -4
実行結果サンプル
1127.0.0.1 - - [22/Sep/2022:16:20:18 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
2127.0.0.1 - - [22/Sep/2022:16:20:18 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
3127.0.0.1 - - [22/Sep/2022:16:20:18 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"
4127.0.0.1 - - [22/Sep/2022:16:20:18 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"

すべての結果で 200 が応答されており、通信の拒否がないことが確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-ratelimit3.jpg
  • Location Zone の表より 5xx に該当はなく 2xx4 となっていることがわかります

  • Limit Req のグラフより Passed3Rejected (dry_run)1 となっていることがわかります

2. 流量制御(Connection limit)

Connection Limitの設定を紹介します。

../../_images/nginx-connlimit-slide1.jpg

使用するディレクティブの詳細は以下のページを参照してください。

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/connlimit1.conf
実行結果サンプル
 1limit_conn_zone $binary_remote_addr zone=addr:10m;
 2
 3upstream server_group {
 4    zone backend 64k;
 5
 6    server backend1:83;
 7}
 8
 9server {
10   listen 80;
11   #status_zone server;
12   location / {
13       status_zone root;
14       limit_conn addr 1;
15       proxy_pass http://server_group;
16   }
17}
  • 1行目で、Connection limit を設定します。 Connection Limit の Key を $remote_addr 、 zone名を addr と指定しています。これらにより、同一の送信元IPアドレスに対しコネクションリミットを適用します

  • 14行目で、zone名 addr を指定する事によりポリシーを選択・適用します。また、許可するコネクションの数として 1 を指定します

  • 13行目で、status_zone を記述し、 root という名称の location status zone を指定しています。NGINX Plusではこの機能により、Connection Limitの状況を確認することが可能です

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/connlimit1.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

以下コマンドを2回入力し、動作を確認してください。
ラボの環境では上記設定5行目の backend1:83 が1秒間コネクションを維持した後、応答する動作となります。
curlコマンドを即座にバックグラウンドで続けて 2回 実行することで、 1回目 処理中に、 2回目 のリクエストが到達する状態とします。
curl -I -s localhost &
実行結果サンプル
 1$ curl -I -s localhost &  << 1回目のリクエストを実行
 2[1] 24683
 3$ << 1回目のリクエストの結果を待たず、プロンプトが表示される
 4$ curl -I -s localhost &  << 2回目のリクエストを実行
 5[2] 24685
 6HTTP/1.1 503 Service Temporarily Unavailable
 7Server: nginx/1.21.6
 8Date: Thu, 22 Sep 2022 08:10:40 GMT
 9Content-Type: text/html
10Content-Length: 197
11Connection: keep-alive
12
13
14[2]+  Done                    curl -I -s "localhost/wait?msec=5000"
15HTTP/1.1 200 OK
16Server: nginx/1.21.6
17Date: Thu, 22 Sep 2022 08:10:44 GMT
18Content-Type: application/octet-stream
19Content-Length: 13
20Connection: keep-alive
  • 1行目で1回目のリクエストを実行しています。その後続けて、4行目で2回目のリクエストを実行しています

  • 1回目のリクエストは正しく処理中となりますが、続けて実行された2回目のリクエストは Connection Limit により即座に 503 Service Temporarily Unavaiable が応答されます

  • その後、一定時間経過後、 15行目に示す通り 1回目の実行結果が表示されます

Error Log の内容を確認します

tail -2 /var/log/nginx/error.log | grep limiting
実行結果サンプル
12022/09/23 17:41:26 [error] 2646#2646: *1186 limiting connections by zone "addr", client: 127.0.0.1, server: , request: "HEAD / HTTP/1.1", host: "localhost"

zone addr で Cnnection limit により通信が拒否されていることがわかります

Access Log の内容を確認します

grep HEAD /var/log/nginx/access.log | tail -2
実行結果サンプル
1127.0.0.1 - - [23/Sep/2022:17:41:26 +0900] "HEAD / HTTP/1.1" 503 0 "-" "curl/7.68.0" "-"
2127.0.0.1 - - [23/Sep/2022:17:41:27 +0900] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.68.0" "-"

実施した結果と同様に、先に 503 の結果が記録されており、その後に 200 の結果が表示されていることが確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-connlimit1.jpg
  • Location Zone の表より 5xx1 となっていることがわかります

  • Limit Req のグラフより Passed1Rejected1 となっていることがわかります

3. ロードバランシングメソッド

ロードバランシングメソッドの設定を紹介します。

使用するディレクティブや設定の解説は以下のページを参照してください。

1. round robin (default)

../../_images/nginx-rr-slide.jpg

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/lb1.conf
実行結果サンプル
 1upstream server_group {
 2    zone backend 64k;
 3
 4    server backend1:81;
 5    server backend1:82;
 6    server backend1:83;
 7}
 8
 9server {
10   listen 80;
11   location / {
12       proxy_pass http://server_group;
13   }
14}
  • 1-7行目が、ロードバランシングに該当する設定となります

  • この記述ではロードバランシングメソッドを記述していません。この場合には、 Round Robin の動作となります

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/lb1.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Upstreams のタブを選択してください。

以下のコマンドを実行し、動作を確認します。

for i in {1..6}; do echo "==$i==" ; curl -s localhost/; echo""; sleep 1 ; done
実行結果サンプル
 1==1==
 2{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 3==2==
 4{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"82"}
 5==3==
 6{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"83"}
 7==4==
 8{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 9==5==
10{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"82"}
11==6==
12{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"83"}

結果を確認すると、 server_port818283 、という順序の応答が確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-lb1-rr.jpg
  • Server の列に、ポート番号 818283 の3つが宛先として表示されています

  • Requests の列を見ると、各 2 となっており、均一に分散されていることが確認できます

  • 右端 Response time の列を見ると、 83 のホストは応答が遅いことが確認できますが、その応答状況に関わらず均一の分散となっています

2. ip_hash

../../_images/nginx-hash-slide.jpg

ip_hash は 送信元IPアドレスを元に転送先を設定します

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/lb2-ip_hash.conf
実行結果サンプル
 1upstream server_group {
 2    zone backend 64k;
 3    ip_hash;
 4
 5    server backend1:81;
 6    server backend1:82;
 7}
 8
 9server {
10   listen 80;
11   location / {
12       proxy_pass http://server_group;
13   }
14}
  • 1-7行目が、ロードバランシングに該当する設定となります

  • 3行目に ip_hash と記述しており、送信元IPアドレスに応じて転送先を決定する動作となります

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/lb2-ip_hash.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Upstreams のタブを選択してください。

以下のコマンドを実行し、動作を確認します。

for i in {1..6}; do echo "==$i==" ; curl -s localhost/; echo""; sleep 1 ; done
実行結果サンプル
 1==1==
 2{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 3==2==
 4{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 5==3==
 6{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 7==4==
 8{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 9==5==
10{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
11==6==
12{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}

リクエストを6回実行していますが、全て 81 が宛先となっていることが確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-lb2-ip_hash.jpg
  • Server の列に、ポート番号 8182 の2つが宛先として表示されています

  • すべてポート番号 81 の宛先に転送されており、 Requests の列を見ると 6 となっています

3. hash (request uri)

../../_images/nginx-hash-slide.jpg

haship_hash と異なり、利用するパラメータを設定で指定することが可能です

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/lb3-hash.conf
実行結果サンプル
 1upstream server_group {
 2    zone backend 64k;
 3    hash $request_uri;
 4
 5    server backend1:81;
 6    server backend1:82;
 7}
 8
 9server {
10   listen 80;
11   location / {
12       proxy_pass http://server_group;
13   }
14}
  • 1-7行目が、ロードバランシングに該当する設定となります

  • 3行目に hash $request_uri と記述しており、先程 ip_hash の送信元IPアドレスではなく、 request URI に応じて宛先が決定されます

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/lb3-hash.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Upstreams のタブを選択してください。
以下のコマンドを実行し、動作を確認します。
まず /path1 宛に通信を行います
for i in {1..3}; do echo "==$i==" ; curl -s localhost/path1; echo""; sleep 1 ; done
実行結果サンプル
1==1==
2{ "request_uri": "/path1","server_addr":"10.1.1.8","server_port":"81"}
3==2==
4{ "request_uri": "/path1","server_addr":"10.1.1.8","server_port":"81"}
5==3==
6{ "request_uri": "/path1","server_addr":"10.1.1.8","server_port":"81"}

3回実行したリクエストが、全て 81 が宛先となっていることが確認できます

次に /path2 宛に通信を行います

for i in {1..3}; do echo "==$i==" ; curl -s localhost/path2; echo""; sleep 1 ; done
実行結果サンプル
1==1==
2{ "request_uri": "/path2","server_addr":"10.1.1.8","server_port":"82"}
3==2==
4{ "request_uri": "/path2","server_addr":"10.1.1.8","server_port":"82"}
5==3==
6{ "request_uri": "/path2","server_addr":"10.1.1.8","server_port":"82"}

3回実行したリクエストが、全て 82 が宛先となっていることが確認できます

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-lb3-hash.jpg

分散結果がコマンドの出力結果と一致することを確認してください

Note

/path1/path2 で結果に違いが見られなかった場合、自由にPATHを追加して通信結果を確認してください

4. least_time

../../_images/nginx-lt-slide.jpg

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/lb4-least_time.conf
実行結果サンプル
 1upstream server_group {
 2    zone backend 64k;
 3    least_time header;
 4
 5    server backend1:81;
 6    server backend1:82;
 7    server backend1:83;
 8}
 9
10server {
11   listen 80;
12   location / {
13       proxy_pass http://server_group;
14   }
15}
  • 1-8行目が、ロードバランシングに該当する設定となります

  • 3行目に least_time header と記述しており、アクセスした際に header の取得にかかった時間の短いホストにアクセスする設定となります

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/lb4-least_time.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Upstreams のタブを選択してください。

以下のコマンドを実行し、動作を確認します。

for i in {1..6}; do echo "==$i==" ; curl -s localhost/; echo""; sleep 1 ; done
実行結果サンプル
 1==1==
 2{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 3==2==
 4{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"82"}
 5==3==
 6{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"83"}
 7==4==
 8{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
 9==5==
10{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"82"}
11==6==
12{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}

宛先が 81 > 82 > 83 となります。その後、 81 > 82 > 81 となり、 83 へ転送されていないことがわかります

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-lb4-least_time.jpg
  • Server の列に、ポート番号 818283 の3つが宛先として表示されています

  • Requests の列を見ると、上から 321 となっています

  • これは、分散方式として least_time header を選択しているため、初回はすべてのホストへ接続を転送しますが、 83 のホストのHeader取得にかかる時間が Response time に示す通り 1秒程度 かかっています。このため、 83 が除外され、 8182 へ優先して転送されます

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

アクティブヘルスチェックの設定を紹介します。

../../_images/nginx-ah-slide.jpg

使用するディレクティブや設定の解説は以下のページを参照してください。

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/active-healthcheck.conf
実行結果サンプル
 1upstream server_group {
 2    zone backend 64k;
 3
 4    server backend1:81;
 5    server backend1:82;
 6    server backend1:83;
 7    server backend1:84;
 8}
 9
10match hc_rule {
11    status 200;
12    body ~ "echo";
13}
14
15server {
16   listen 80;
17   location / {
18       proxy_pass http://server_group;
19       health_check interval=5 fails=3 passes=2 uri=/echo match=hc_rule;
20   }
21}
  • 10-13行目で、Health Checkの条件を指定します。 status で期待するHTTP Responseコード、 body でBodyの内容に期待する文字列を指定します

  • 19行目で、Health Check の実行間隔、 Unhealthy と判定されるまでの回数、復帰と判定される回数、 uri 、そして上部で指定したRuleを紐づけます

設定を反映します。

Note

この動作確認では設定反映後すぐにNGINX Plusのダッシュボードにて状態を確認します。 可能であれば設定反映前にダッシュボードを開き、その後設定を反映してください。

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/active-healthcheck.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

動作を確認します。

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Upstreams のタブを選択してください。
../../_images/nginx-active-hc1.jpg
  • 4つのホストが表示されていることがわかります

  • Active Health Check が行われるため、 Health monitors の列が、通信を行っていない状態でもカウントアップすることが確認できます

  • ポート番号 84 のサーバでは、 Health Check が失敗し、 least の列が failed となります

  • その後、 3回連続 failed となった後、 Unhealthy1 となり、該当サーバの左端が赤色となることが確認できます

なぜこのような結果となったのか確認します。

先程反映した設定の条件で /echo に対して通信を行い、HTTP Responseコードが 200 、 Bodyに echo という文字列が期待されていました。

backend1:81/echo の結果を確認します

実行結果サンプル
 1$ curl -v backend1:81/echo
 2*   Trying 10.1.1.8:81...
 3* TCP_NODELAY set
 4* Connected to backend1 (10.1.1.8) port 81 (#0)
 5> GET /echo HTTP/1.1
 6> Host: backend1:81
 7> User-Agent: curl/7.68.0
 8> Accept: */*
 9>
10* Mark bundle as not supporting multiuse
11< HTTP/1.1 200 OK
12< Server: nginx/1.21.3
13< Date: Fri, 23 Sep 2022 10:52:15 GMT
14< Content-Type: application/octet-stream
15< Content-Length: 69
16< Connection: keep-alive
17<
18* Connection #0 to host backend1 left intact
19{ "request_uri": "/echo","server_addr":"10.1.1.8","server_port":"81"}ubuntu@ip-10-1-1-7:~/f5j-nginx-plus-lab2-conf/lab$
  • curlコマンドを実行した結果、 11行目の通り 200 OK が応答されています

  • 応答のBodyを確認すると、アクセスしたPATHの文字列が挿入されているため、19行目の通り request_uri/echo という文字列が含まれています

backend1:84/echo の結果を確認します

実行結果サンプル
 1$ curl -v backend1:84/echo
 2*   Trying 10.1.1.8:84...
 3* TCP_NODELAY set
 4* Connected to backend1 (10.1.1.8) port 84 (#0)
 5> GET /echo HTTP/1.1
 6> Host: backend1:84
 7> User-Agent: curl/7.68.0
 8> Accept: */*
 9>
10* Mark bundle as not supporting multiuse
11< HTTP/1.1 500 Internal Server Error
12< Server: nginx/1.21.3
13< Date: Fri, 23 Sep 2022 10:52:50 GMT
14< Content-Type: application/octet-stream
15< Content-Length: 12
16< Connection: keep-alive
17<
18* Connection #0 to host backend1 left intact
19Server Error
  • curlコマンドを実行した結果、 11行目の通り 500 Internal Server Error が応答されています

  • 応答のBodyを確認すると、19行目の通り Server Error であるため echo という文字列が含まれていません

Health Checkはこれらの文字列ステータスをもとに、サーバの状態を判定していることが確認できました

5. セッションパーシステンス

セッションパーシステンスの設定を紹介します。

../../_images/nginx-sticky-slide.jpg

使用するディレクティブや設定の解説は以下のページを参照してください。

2. route

Sticky Route はUpstreamのサーバに対し予め route を設定し、リクエストの情報の一部から取得した route 情報を元に転送先を決定する手法となります

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/session-persistence2-route.conf
実行結果サンプル
 1log_format session_info '$remote_addr - $remote_user [$time_local] "$request" '
 2               '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
 3               'Cookie $route_cookie URIrouteid $route_uri URIflag $arg_flag';
 4
 5map $cookie_routeid $route_cookie {
 6    ~.+\.(?P<route>\w+)$ $route;
 7}
 8
 9map $request_uri $route_uri {
10    ~routeid=.+\.(?P<route>\w+)$ $route;
11}
12
13upstream server_group {
14    zone backend 64k;
15    sticky route $route_cookie $route_uri $arg_flag;
16
17    server backend1:81 route=a;
18    server backend1:82 route=b;
19}
20
21server {
22   access_log /var/log/nginx/access.log session_info;
23   listen 80;
24   location / {
25       proxy_pass http://server_group;
26   }
27}
  • 15行目および17-18行目が sticky route に関する設定となります。17-18行目の末尾に route= で示した内容が入力された場合にそれぞれのサーバに転送されます。そのrouteとして判定する条件が15行目の内容であり、左側から優先度が高くなり、設定例では、 $route_cookie$route_uri$arg_flag を指定しています

  • 5-7行目が、cookieの値を正規表現で評価し、$route_cookie に対して正規表現から取得した $route の値を格納するための map directive で、 Request URIの内容に対し同様の処理を行う箇所が9-11行目となります

  • 1-3行目、22行目はこれらの値の結果を確認するために指定したAccess Logに関する設定です

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/session-persistence2-route.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

複数のパラメータを指定し動作を確認します

優先度

種類

1

Cookie

routeid=val.b

2

URLパラメータ

routeid=val.a

3

URLパラメータ

flag=a

  • 設定の解説で確認した通り、表のような優先度で評価されます

  • Cookieの routeid の値、 .(ドット) の右側の値が route の判定で利用されます

  • URLパラメータの routeid の値、 .(ドット) の右側の値が route の判定で利用されます

  • URLパラメータの flag の値が route の判定で利用されます

リクエストを送信します

curl "localhost/?flag=a&routeid=val.a" -H "Cookie: routeid=val.b"
実行結果サンプル
1{ "request_uri": "/?flag=a&routeid=val.a","server_addr":"10.1.1.8","server_port":"82"}

route の値が b であるため、 server_port82 の server からの応答であることが確認できます。Cookie の値に従って応答返されていることが確認できます

URLパラメータのみを指定したリクエストを送信します

curl "localhost/?flag=a&routeid=val.b"
実行結果サンプル
1{ "request_uri": "/?flag=a&routeid=val.b","server_addr":"10.1.1.8","server_port":"82"}

route の値が b であるため、 server_port82 の server からの応答であることが確認できます。URLパラメータの routeid の値が適切に処理され応答が返されていることが確認できます

flag のURLパラメータを指定したリクエストを送信します

curl "localhost/?flag=b"
実行結果サンプル
1{ "request_uri": "/?flag=b","server_addr":"10.1.1.8","server_port":"82"}

route の値が b であるため、 server_port82 の server からの応答であることが確認できます。URLパラメータの flag の値が適切に処理され応答が返されていることが確認できます

どのように通信を行っているのか確認するため、ログの内容を確認します

tail -3 /var/log/nginx/access.log
実行結果サンプル
1127.0.0.1 - - [07/Oct/2022:13:52:53 +0900] "GET /?flag=a&routeid=val.a HTTP/1.1" 200 86 "-" "curl/7.68.0" Cookie b URIrouteid a URIflag a
2127.0.0.1 - - [07/Oct/2022:13:53:35 +0900] "GET /?flag=a&routeid=val.b HTTP/1.1" 200 86 "-" "curl/7.68.0" Cookie  URIrouteid b URIflag a
3127.0.0.1 - - [07/Oct/2022:13:53:57 +0900] "GET /?flag=b HTTP/1.1" 200 72 "-" "curl/7.68.0" Cookie  URIrouteid  URIflag b
  • 1行目は、1回目のリクエストの結果を示し Cookie の判定結果が bURLのrouteidaURIのflaga であることがわかります

  • 2行目は、2回目のリクエストの結果を示し URLのrouteidbURIのflaga であることがわかります

  • 3行目は、3回目のリクエストの結果を示し URIのflagb であることがわかります

それぞれ指定した値に応じて結果が出力されていたことが確認できます

3. learn

Sticky LearnはNGINXがProxyする際にクライアントへ応答されるレスポンスに含まれるCookieの名称を指定、その値を取得し、以降その値に応じて通信維持を行う手法です

設定

設定内容を確認します

cat ~/f5j-nginx-plus-lab2-conf/lab/session-persistence3-learn.conf
実行結果サンプル
 1log_format session_info '$remote_addr - $remote_user [$time_local] "$request" '
 2               '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
 3               'upstream $proxy_host $proxy_port server $upstream_addr';
 4
 5upstream server_sticky_learn {
 6    zone backend 64k;
 7    sticky learn
 8           create=$upstream_cookie_srv-id
 9           lookup=$cookie_srv-id
10           zone=sticky_learn:1m;
11
12    server localhost:8081;
13    server localhost:8082;
14}
15
16upstream server_group {
17    zone backend 64k;
18    sticky cookie srv-id expires=1h domain=.example.com path=/;
19
20    server backend1:81;
21    server backend1:82;
22}
23
24server {
25   access_log /var/log/nginx/access.log session_info;
26   listen 80;
27   location / {
28       proxy_pass http://server_sticky_learn;
29   }
30}
31
32server {
33   access_log /var/log/nginx/access.log session_info;
34   listen 8081;
35   listen 8082;
36   location / {
37       proxy_pass http://server_group;
38   }
39}
  • 8-10行目が、sticky learn の設定となります

    • create : sticky session を生成するための条件となる、upstream(分散先)から応答されたCookieの値を指定します。この例では srv-id というCookieの値が取得されます

    • lookup : 2回目以降のリクエストで通信維持の判定を行うための Cookieの名称 を指定します。この例では srv-id というCookieが提示される想定となります

    • zone : sticky learn の セッション情報を保持するZoneを指定します。1m(1 Mbyte)の場合、64bit のプラットフォームであれば約4000のエントリを保持できます

  • 28行目で、 sticky learn を設定したupstream server_sticky_learn に従って転送します。この宛先はNGINX自身がListenする 8081, 8082 となります

  • 8081 , 8082 を指定するserver directiveはupstream server_group に従って転送します。このUpstreamでは sticky cookie を設定しているためレスポンスに srv-id という名称の set-cookie を返します

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/session-persistence3-learn.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

以下のコマンドを実行し、動作を確認します。

curl -v localhost
実行結果サンプル
 1*   Trying 127.0.0.1:80...
 2* TCP_NODELAY set
 3* Connected to localhost (127.0.0.1) port 80 (#0)
 4> GET / HTTP/1.1
 5> Host: localhost
 6> User-Agent: curl/7.68.0
 7> Accept: */*
 8>
 9* Mark bundle as not supporting multiuse
10< HTTP/1.1 200 OK
11< Server: nginx/1.21.6
12< Date: Fri, 07 Oct 2022 03:45:26 GMT
13< Content-Type: application/octet-stream
14< Content-Length: 65
15< Connection: keep-alive
16< Set-Cookie: srv-id=d90714beec1b83b75b3817079340fb00; expires=Fri, 07-Oct-22 04:45:26 GMT; max-age=3600; domain=.example.com; path=/
17<
18* Connection #0 to host localhost left intact
19{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}
  • 16行目に、NGINXより Cookie が応答されていることを確認してください。 srv-id の値がSticky Sessionに利用されるCookieの値となります。この値は server_group のUpstreamの設定に応じて動作した結果となります

  • 19行目の内容より、この実行結果では、 server_port81 に転送されていることがわかります。

以下のように、curlコマンドで、 srv-id の内容を HTTP Header に指定しリクエストを送付してください

# curl -v localhost -H "Cookie: srv-id=<初回アクセス時に取得したsrv-idの値>"
curl -v localhost -H "Cookie: srv-id=d90714beec1b83b75b3817079340fb00"
実行結果サンプル
 1*   Trying 127.0.0.1:80...
 2* TCP_NODELAY set
 3* Connected to localhost (127.0.0.1) port 80 (#0)
 4> GET / HTTP/1.1
 5> Host: localhost
 6> User-Agent: curl/7.68.0
 7> Accept: */*
 8> Cookie: srv-id=d90714beec1b83b75b3817079340fb00
 9>
10* Mark bundle as not supporting multiuse
11< HTTP/1.1 200 OK
12< Server: nginx/1.21.6
13< Date: Fri, 07 Oct 2022 03:45:47 GMT
14< Content-Type: application/octet-stream
15< Content-Length: 65
16< Connection: keep-alive
17< Set-Cookie: srv-id=d90714beec1b83b75b3817079340fb00; expires=Fri, 07-Oct-22 04:45:47 GMT; max-age=3600; domain=.example.com; path=/
18<
19* Connection #0 to host localhost left intact
20{ "request_uri": "/","server_addr":"10.1.1.8","server_port":"81"}

先程と同様のホストにアクセスしていることが確認できます。その後複数回実行いただいた場合にも同様の結果となることが確認いただけます。

どのように通信を行っているのか確認するため、ログの内容を確認します

tail -4 /var/log/nginx/access.log
実行結果サンプル
1127.0.0.1 - - [07/Oct/2022:12:45:26 +0900] "GET / HTTP/1.0" 200 65 "-" "curl/7.68.0" upstream server_group 80 server 10.1.1.8:81
2127.0.0.1 - - [07/Oct/2022:12:45:26 +0900] "GET / HTTP/1.1" 200 65 "-" "curl/7.68.0" upstream server_sticky_learn 80 server 127.0.0.1:8081
3127.0.0.1 - - [07/Oct/2022:12:45:47 +0900] "GET / HTTP/1.0" 200 65 "-" "curl/7.68.0" upstream server_group 80 server 10.1.1.8:81
4127.0.0.1 - - [07/Oct/2022:12:45:47 +0900] "GET / HTTP/1.1" 200 65 "-" "curl/7.68.0" upstream server_sticky_learn 80 server 127.0.0.1:8081
  • upstreamserver の値を確認します

  • 1-2行目が1回目の curl 、 3-4 行目が2回目の curl となります

  • 1行目は server_group10.1.1.8:81 の応答がなされた結果を示します

  • 2行目は sticky learn を設定したupstream server_sticky_learn127.0.0.1:8081 の応答がなされた結果を示します

  • 3行目の curl は1行目の同様と結果、4行目の curl は2行目と同様の結果になっています

  • 3行目は server_group に設定した sticky cookie によりセッションが維持されており、 srv-id を応答しています

  • 4行目は server_sticky_learn に設定した sticky learn が srv-id の内容を取得し、以降の通信では srv-id の内容に応じて通信を転送していることがわかります

以降、同じCookieを指定し実行した場合、同様の結果となることが確認いただけます

6. サービスディスカバリ

サービスディスカバリの設定を紹介します。

../../_images/nginx-sd-slide.jpg

使用するディレクティブや設定の解説は以下のページを参照してください。

設定

DNSによる名前解決を行い、サービスディスカバリを行います。

設定内容を確認します。

cat ~/f5j-nginx-plus-lab2-conf/lab/service-discovery.conf
実行結果サンプル
 1resolver 10.1.1.5 valid=10s ipv6=off;
 2resolver_timeout 10s;
 3
 4upstream server_group {
 5    zone backend 64k;
 6
 7    server api1:80 resolve;
 8}
 9
10server {
11    listen 80;
12    location / {
13        proxy_pass http://server_group;
14    }
15}
  • 1-2行目で、NGINX が名前解決を行う際に利用するDNSサーバの情報を指定します

  • 7行目、Upstream内のサーバに対し、名前解決を実施するため、末尾に resolve を指定します。こちらを指定することにより api1 という名称を指定のDNSサーバで解決し、その結果をUpstreamのサーバとして登録します

設定を反映します

sudo cp ~/f5j-nginx-plus-lab2-conf/lab/service-discovery.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload

動作確認

  • DNSサーバで解決した結果を確認

ステータスを確認するためNGINX Plusのダッシュボードを開いてください。
画面上部 HTTP Upstreams のタブを選択してください。

NGINXのresolver設定で指定したDNSサーバで名前を解決し、サーバを表示していることが確認できます。 api1 の名前を解決した結果、ホストが4つ表示されることを確認してください。

NGINX Plus Dashboardの内容は以下のように表示されます

../../_images/nginx-dnsdiscovery-4hosts.jpg
  • DNSサーバで応答する内容の変更

DNSサーバの応答を変更するため、 docker_host へログインします

Windows Jump Hostへログインいただくと、SSHClientのショートカットがありますので、 そちらの docker_host をクリックし、接続してください。

  • ../../_images/putty_icon.jpg
  • ../../_images/putty_menu.jpg

docker_host で以下コマンドを実行しファイルを取得します。

cd ~/
git clone https://github.com/BeF5/f5j-nginx-plus-lab2-conf

以下コマンドを実行し、DNSサーバの設定ファイルを読み込みます。

cd ~/f5j-nginx-plus-lab2-conf/docker-compose/dnsmasq/
docker-compose -f dnsmasq-docker-compose2.yaml up -d
実行結果サンプル
1Recreating dnsmasq_dns_1 ... done

NGINXのDNSを利用したサービスディスカバリの結果、 api1 で指定したホストが2つに変化することを確認してください。

../../_images/nginx-dnsdiscovery-2hosts.jpg

docker_host で以下コマンドを実行すると、 api1 として元の4つのホストが表示されます

cd ~/f5j-nginx-plus-lab2-conf/docker-compose/dnsmasq/
docker-compose -f dnsmasq-docker-compose1.yaml up -d
実行結果サンプル
1Recreating dnsmasq_dns_1 ... done