ステータス同期
ここでは、ステータス同期について紹介します。また具体的な利用サンプルとして Rate Limit、KeyValを紹介します
1. ステータス同期 (Zone Synchronization)
ステータス同期の設定を行います
ubuntu01 もしくは ubuntu01-nginx で以下の操作を行ってください
cd ~/
git clone https://github.com/BeF5/f5j-nginx-plus-lab2-conf
sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf-bak
sudo cp ~/f5j-nginx-plus-lab2-conf/lab/zone-sync01-nginx.conf /etc/nginx/nginx.conf
sudo nginx -s reload
ubuntu02 もしくは ubuntu02-nginx で以下の操作を行ってください
cd ~/
git clone https://github.com/BeF5/f5j-nginx-plus-lab2-conf
sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf-bak
sudo cp ~/f5j-nginx-plus-lab2-conf/lab/zone-sync02-nginx.conf /etc/nginx/nginx.conf
sudo nginx -s reload
NGINX Plus APIへ接続しステータス同期(Zone Synchronization)の状態を確認します。
curl -s 127.0.0.1:8888/api/8/stream/zone_sync | jq .
1{
2 "status": {
3 "nodes_online": 0,
4 "msgs_in": 0,
5 "msgs_out": 0,
6 "bytes_in": 0,
7 "bytes_out": 0
8 },
9 "zones": {}
10}
2. ratelimit
ステータス同期ができる機能の一つである Rate Limit を設定し、動作を確認します。
設定
設定を行います。
ubuntu01 もしくは ubuntu01-nginx 、 ubuntu02 もしくは ubuntu02-nginx で以下の操作を行ってください
sudo cp ~/f5j-nginx-plus-lab2-conf/lab/zone-sync-ratelimit.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload
設定の内容を確認します
cat ~/f5j-nginx-plus-lab2-conf/lab/zone-sync-ratelimit.conf
1limit_req_zone $remote_addr zone=req:1M rate=1r/m sync;
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行目、14行目でRate Limitの設定を行っています
1行目の末尾に
syncを指定することで、Rate Limitの状態を動悸することが可能となります
NGINX Plus APIへ接続しステータス同期(Zone Synchronization)の状態を確認します。 リクエストリミットを設定することで、カウンターが増加していることが確認できます
curl -s 127.0.0.1:8888/api/8/stream/zone_sync | jq .
1{
2 "status": {
3 "nodes_online": 1,
4 "msgs_in": 1,
5 "msgs_out": 0,
6 "bytes_in": 29,
7 "bytes_out": 0
8 },
9 "zones": {
10 "req": {
11 "records_total": 0,
12 "records_pending": 0
13 }
14 }
15}
ダッシュボードを開き状態を確認します。 F5ラボ環境を利用の場合、以下のどちらかの手段で接続してください
(推奨)リモートデスクトップに接続している場合ubuntu01http://10.1.1.7:8888/dashboard.html を開いてくださいubuntu02http://10.1.1.6:8888/dashboard.html を開いてくださいubuntu01-nginxhttp://10.1.1.11:8888/dashboard.html を開いてくださいubuntu02-nginxhttp://10.1.1.12:8888/dashboard.html を開いてください
リモートデスクトップを利用していない場合ご利用の端末から接続するため、
ubuntu01もしくはubuntu01-nginx、ubuntu02もしくはubuntu02-nginxの接続メニューよりPLUS DASHBOARDを選択してください
動作確認
ubuntu01 もしくは ubuntu01-nginx から、 ubuntu01(10.1.1.7) もしくは ubuntu01-nginx(10.1.1.11) / ubuntu02(10.1.1.6) もしくは ubuntu02-nginx(10.1.1.12) 双方に対して接続を行います。
以下の操作を行ってください
ubuntu01/02の場合
echo "== To ubuntu01 =="; for i in {1..2}; do echo "==$i=="; curl -I -s 10.1.1.7; done; sleep 1; echo "== To ubuntu02 =="; for i in {1..2}; do echo "==$i=="; curl -I -s 10.1.1.6; done
ubuntu01/02-nginxの場合
echo "== To ubuntu01 =="; for i in {1..2}; do echo "==$i=="; curl -I -s 10.1.1.11; done; sleep 1; echo "== To ubuntu02 =="; for i in {1..2}; do echo "==$i=="; curl -I -s 10.1.1.12; done
ubuntu01 もしくは ubuntu01-nginx 宛に接続した後、ステータス同期を待つため 1秒停止(sleep 1) した後、 ubuntu02 もしくは ubuntu02-nginx へ接続します
1$ echo "== To ubuntu01 =="
2== To ubuntu01 ==
3$ for i in {1..2}; do echo "==$i==" ; curl -I -s 10.1.1.7 ; done
4==1==
5HTTP/1.1 200 OK
6Server: nginx/1.21.6
7Date: Thu, 29 Sep 2022 00:15:49 GMT
8Content-Type: application/octet-stream
9Content-Length: 65
10Connection: keep-alive
11
12==2==
13HTTP/1.1 503 Service Temporarily Unavailable
14Server: nginx/1.21.6
15Date: Thu, 29 Sep 2022 00:15:49 GMT
16Content-Type: text/html
17Content-Length: 197
18Connection: keep-alive
19
20$ sleep 1;
21$ echo "== To ubuntu02 =="
22== To ubuntu02 ==
23$ for i in {1..2}; do echo "==$i==" ; curl -I -s 10.1.1.6 ; done
24==1==
25HTTP/1.1 503 Service Temporarily Unavailable
26Server: nginx/1.21.6
27Date: Thu, 29 Sep 2022 00:15:50 GMT
28Content-Type: text/html
29Content-Length: 197
30Connection: keep-alive
31
32==2==
33HTTP/1.1 503 Service Temporarily Unavailable
34Server: nginx/1.21.6
35Date: Thu, 29 Sep 2022 00:15:50 GMT
36Content-Type: text/html
37Content-Length: 197
38Connection: keep-alive
ubuntu01もしくはubuntu01-nginxに対して接続した結果を確認すると、5行目の1回目が200、13行目の2回目が503となり RateLimitにより通信が拒否されていますubuntu02もしくはubuntu02-nginxに対して接続した結果を確認すると、25行目の1回目、33行目が2回目の双方が503となり RateLimitにより通信が拒否されています。これはステータスが同期されたためこのような動作となります
ダッシュボードの状態を確認します
HTTP Zonesのタブの内容を開きます。左がubuntu01もしくはubuntu01-nginx、右がubuntu02もしくはubuntu02-nginxとなります。通信の結果、
5xxの結果を確認するとubuntu01もしくはubuntu01-nginxに1、ubuntu02もしくはubuntu02-nginxが2となっていることがわかりますLimit Reqのグラフを見ると、ubuntu02は通信の許可がなくRejectedされていることがわかります
3. Key Value Store
KeyValue Storeのステータス動機を確認します
設定
設定を行います。
ubuntu01 もしくは ubuntu01-nginx 、 ubuntu02 もしくは ubuntu02-nginx で以下の操作を行ってください
sudo cp ~/f5j-nginx-plus-lab2-conf/lab/zone-sync-keyval.conf /etc/nginx/conf.d/default.conf
sudo nginx -s reload
設定の内容を確認します
cat ~/f5j-nginx-plus-lab2-conf/lab/zone-sync-keyval.conf
1keyval_zone zone=iplist:32k state=/etc/nginx/conf.d/iplists.keyval timeout=20s sync;
2keyval $arg_user $permit_ip zone=iplist;
3
4upstream server_group {
5 zone backend 64k;
6
7 server backend1:81;
8}
9
10server {
11 listen 80;
12 location / {
13
14 # check variable is blank
15 if ( $arg_user = "" ) {
16 return 403 "No Username";
17 }
18
19 if ( $permit_ip = "" ) {
20 set $permit_ip $remote_addr;
21 }
22
23 if ( $remote_addr != $permit_ip ) {
24 return 403 "Mismatch client IP address";
25 }
26
27 # Here, we have arg_user & remote_addr = permit_ip
28 proxy_pass http://server_group;
29 }
30}
1-2行目でKeyValを指定しています。1行目の末尾に
syncを指定することで、複数のNGINXでステータスが同期されますまた
syncを指定する場合は、timeoutの指定が必要となります。timeoutは各エントリの残存期間を示し、指定の時間を経過するとエントリが削除されます2行目で KeyValの内容を指定します。
$arg_userが Key となり、$permit_ipが Valとなります。ステータス同期がなされたNGINXは、Keyを指定することで、KeyVal内のValを参照し、指定の変数名でアクセスすることが可能となります。Valの値は参照されるまでに適切に変数として格納する必要がありますので注意くださいその他の
ifなどは以下の挙動を実装するため指定しています
このサンプル設定では以下のような挙動となります
URLパラメータとして
userという名称のパラメータが指定されていない通信を拒否しますuserのURLパラメータの値をユーザとします。パラメータが指定されている場合、接続元のIPアドレスをユーザに紐づけてKeyValueに登録します同
ユーザからのアクセスに置いて、異なる接続元のIPアドレスである場合、通信を拒否します
動作確認
ubuntu01 もしくは ubuntu01-nginx で iplist という名称のKeyValが生成されていることが確認できます
curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1{
2 "iplist": {}
3}
ubuntu01 もしくは ubuntu01-nginx でサンプルのリクエストを送信し、KeyVal の結果を確認します
curl 10.1.1.7/; echo"" ; curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
もしくは
curl 10.1.1.11/; echo"" ; curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1No Username
2{
3 "iplist": {}
4}
リクエストで
userを指定しないため、応答がNo Usernameとなります。iplistにエントリは追加されていません
ubuntu01 もしくは ubuntu01-nginx でURLパラメータに user を含むサンプルのリクエストを送信し、KeyVal の結果を確認します
curl 10.1.1.7/?user=user1 ; echo"" ; curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
もしくは
curl 10.1.1.11/?user=user1 ; echo"" ; curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1{ "request_uri": "/?user=user1","server_addr":"10.1.1.8","server_port":"81"}
2{
3 "iplist": {
4 "user1": "10.1.1.7"
5}
正しくURLパラメータの
userにuser1が指定されているため、正しい応答が確認できますiplistにubuntu01もしくはubuntu01-nginxのIPアドレス 10.1.1.7/0.1.1.11 が追加されていることが確認できます
ubuntu02 もしくは ubuntu02-nginx でURLパラメータに user を含むサンプルのリクエストを送信し、KeyVal の結果を確認します
curl 10.1.1.7/?user=user1 ; echo"" ; curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
もしくは
curl 10.1.1.11/?user=user1 ; echo"" ; curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1Mismatch client IP address
2{
3 "iplist": {
4 "user1": "10.1.1.7"
5 }
6}
URLパラメータの
userにuser1が指定されていますが、Mismatch client IP addressが応答されていますiplistをみるとubuntu01もしくはubuntu01-nginxのIPアドレス 10.1.1.7/10.1.1.11 が追加されており、ubuntu02もしくはubuntu02-nginxのアドレスと一致しないためエラーとなったことがわかります
このように、KeyVal を利用することで、複雑な処理が可能となります。 またステータス同期により複数のホストで状態を同期し、協調した処理を行うことが可能となります
画像を確認いただくとカウンターの値が表示さています。 この数についての詳細ですが、この数はKeyvalのエントリが追加されたタイミングでのKeyの数を指しています。 一定時間経過後(今回の設定サンプルでは20秒)で各エントリが消えますが、そのタイミングで値は変化しません。 その後、新たにエントリの追加(または削除)を行った際に、全体の数の値が変更となります
4. APIを使ったKeyValの操作
KeyValの機能は、NGINX Plus APIを使って外部から操作することが可能です。
詳細は以下のページを参照してください
以下のコマンドを実行し動作を確認してください
追加
POST Method を利用し、エントリを 追加 します
curl -s 127.0.0.1:8888/api/8/http/keyvals/iplist -X POST -d '{
"user1":"10.0.0.1" ,
"user2":"10.0.0.2" ,
"user3":"10.0.0.3" ,
"user4":"10.0.0.4"
}'
KeyValの状態を確認します
curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1{
2 "iplist": {
3 "user2": "10.0.0.2",
4 "user3": "10.0.0.3",
5 "user4": "10.0.0.4"
6 }
7}
変更
PATCH Method を利用し、エントリを 変更 します
curl -s 127.0.0.1:8888/api/8/http/keyvals/iplist -X PATCH -d '{ "user1":"192.168.0.1" }'
KeyValの状態を確認します
curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1{
2 "iplist": {
3 "user2": "10.0.0.2",
4 "user3": "10.0.0.3",
5 "user1": "192.168.0.1",
6 "user4": "10.0.0.4"
7 }
8}
エントリの削除
PATCH Method で、特定エントリの値として null を指定することで、対象のエントリを削除することができます
curl -s 127.0.0.1:8888/api/8/http/keyvals/iplist -X PATCH -d '{ "user1":null }'
KeyValの状態を確認します
curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1{
2 "iplist": {
3 "user2": "10.0.0.2",
4 "user3": "10.0.0.3",
5 "user4": "10.0.0.4"
6 }
7}
すべてのエントリの削除
DELETED Method を利用し、すべてのエントリを 削除 します
curl -s 127.0.0.1:8888/api/8/http/keyvals/iplist -X DELETE
KeyValの状態を確認します
curl -s 127.0.0.1:8888/api/8/http/keyvals | jq .
1{
2 "iplist": {}
3}
5. その他ステータス同期に関する設定
本番環境では、対向のホストをFQDNで指定し、SSL/TLSの利用、mTLS・証明書認証などを実装することが考えられます。 これらの設定について以下のページを参照してください