NGINX Plus の設定
0. (事前準備) NGINX Plusのインストール
1. NGINX Plusのインストール・基礎
NGINX Plus Lab 3. 基本的な動作の確認 を参照してください
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の設定を紹介します。
使用するディレクティブの詳細は以下のページを参照してください。
HTTP Request Limit の詳細: ngx_http_limit_req_module
HTTP API Status Zone の詳細: ngx_http_api_module status_zone
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
動作確認
動作を確認します。
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の内容は以下のように表示されます
Location Zone の表より
5xxが2となっていることがわかりますLimit Req のグラフより
Passedが1、Rejectedが2となっていることがわかります
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=2、nodelayオプションを指定し、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
動作確認
動作を確認します。
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の内容は以下のように表示されます
Location Zone の表より
5xxが1となっていることがわかりますLimit Req のグラフより
Passedが3、Rejectedが1となっていることがわかります
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_runonを指定します。このオプションにより、実際に通信は拒否せず、ステータスの確認が可能となります
sudo cp ~/f5j-nginx-plus-lab2-conf/lab/ratelimit3-dryrun.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload
動作確認
動作を確認します。
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の内容は以下のように表示されます
Location Zone の表より
5xxに該当はなく2xxが4となっていることがわかりますLimit Req のグラフより
Passedが3、Rejected (dry_run)が1となっていることがわかります
2. 流量制御(Connection limit)
Connection Limitの設定を紹介します。
使用するディレクティブの詳細は以下のページを参照してください。
HTTP Connection Limit の詳細: ngx_http_limit_conn_module
HTTP API Status Zone の詳細: ngx_http_api_module status_zone
設定
設定内容を確認します
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
動作確認
backend1:83 が1秒間コネクションを維持した後、応答する動作となります。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の内容は以下のように表示されます
Location Zone の表より
5xxが1となっていることがわかりますLimit Req のグラフより
Passedが1、Rejectedが1となっていることがわかります
3. ロードバランシングメソッド
ロードバランシングメソッドの設定を紹介します。
使用するディレクティブや設定の解説は以下のページを参照してください。
HTTP Upstream の詳細: ngx_http_upstream_module
HTTP Load Balancing解説: HTTP Load Balancing
1. round robin (default)
設定
設定内容を確認します
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
動作確認
動作を確認します。
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_port が 81 、 82 、 83 、という順序の応答が確認できます
NGINX Plus Dashboardの内容は以下のように表示されます
Serverの列に、ポート番号81、82、83の3つが宛先として表示されていますRequestsの列を見ると、各2となっており、均一に分散されていることが確認できます右端
Response timeの列を見ると、83のホストは応答が遅いことが確認できますが、その応答状況に関わらず均一の分散となっています
2. ip_hash
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
動作確認
動作を確認します。
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の内容は以下のように表示されます
Serverの列に、ポート番号81、82の2つが宛先として表示されていますすべてポート番号
81の宛先に転送されており、Requestsの列を見ると6となっています
3. hash (request uri)
hash は ip_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
動作確認
動作を確認します。
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の内容は以下のように表示されます
分散結果がコマンドの出力結果と一致することを確認してください
Note
/path1 と /path2 で結果に違いが見られなかった場合、自由にPATHを追加して通信結果を確認してください
4. least_time
設定
設定内容を確認します
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
動作確認
動作を確認します。
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の内容は以下のように表示されます
Serverの列に、ポート番号81、82、83の3つが宛先として表示されていますRequestsの列を見ると、上から3、2、1となっていますこれは、分散方式として
least_time headerを選択しているため、初回はすべてのホストへ接続を転送しますが、83のホストのHeader取得にかかる時間がResponse timeに示す通り 1秒程度 かかっています。このため、83が除外され、81、82へ優先して転送されます
4. アクティブヘルスチェック
アクティブヘルスチェックの設定を紹介します。
使用するディレクティブや設定の解説は以下のページを参照してください。
HTTP match の詳細: ngx_http_upstream_hc_module
HTTP Health Checks解説: HTTP Health Checks
設定
設定内容を確認します
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
動作確認
動作を確認します。
HTTP Upstreams のタブを選択してください。
4つのホストが表示されていることがわかります
Active Health Check が行われるため、
Health monitorsの列が、通信を行っていない状態でもカウントアップすることが確認できますポート番号
84のサーバでは、 Health Check が失敗し、leastの列がfailedとなりますその後、 3回連続
failedとなった後、Unhealthyが1となり、該当サーバの左端が赤色となることが確認できます
なぜこのような結果となったのか確認します。
先程反映した設定の条件で /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. セッションパーシステンス
セッションパーシステンスの設定を紹介します。
使用するディレクティブや設定の解説は以下のページを参照してください。
HTTP Upstream Sticky の詳細: ngx_http_upstream_module / sticky
HTTP Load Balancing解説: Enabling Session Persistence
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_port が 82 の 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_port が 82 の 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_port が 82 の 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の判定結果がb、URLのrouteidがa、URIのflagがaであることがわかります2行目は、2回目のリクエストの結果を示し
URLのrouteidがb、URIのflagがaであることがわかります3行目は、3回目のリクエストの結果を示し
URIのflagがbであることがわかります
それぞれ指定した値に応じて結果が出力されていたことが確認できます
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を設定したupstreamserver_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_portが81に転送されていることがわかります。
以下のように、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
upstream、serverの値を確認します1-2行目が1回目の curl 、 3-4 行目が2回目の curl となります
1行目は
server_groupの10.1.1.8:81の応答がなされた結果を示します2行目は sticky learn を設定したupstream
server_sticky_learnの127.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. サービスディスカバリ
サービスディスカバリの設定を紹介します。
使用するディレクティブや設定の解説は以下のページを参照してください。
HTTP Core Resolver の詳細: ngx_http_core_module / resolver
HTTP Load Balancing解説: Configuring HTTP Load Balancing Using DNS
設定
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サーバで解決した結果を確認
HTTP Upstreams のタブを選択してください。NGINXのresolver設定で指定したDNSサーバで名前を解決し、サーバを表示していることが確認できます。
api1 の名前を解決した結果、ホストが4つ表示されることを確認してください。
NGINX Plus Dashboardの内容は以下のように表示されます
DNSサーバで応答する内容の変更
DNSサーバの応答を変更するため、 docker_host へログインします
Windows Jump Hostへログインいただくと、SSHClientのショートカットがありますので、
そちらの docker_host をクリックし、接続してください。
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つに変化することを確認してください。
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
