Azure ロードバランサでアウトバウンド方向のNATを設定する方法を説明します。小規模環境ではデフォルト設定で問題は発生しませんが、大規模環境ではSNATポート枯渇を考慮しなければなりません。このページではSNATポート枯渇の対応方法を複数紹介します。規模に応じて適切な構成を選択ください。
前提
公式ドキュメント
参考になる公式ドキュメントを以下に示します。
- 送信接続での送信元ネットワーク アドレス変換 (SNAT)を使用する
- Azure Load Balancer のアウトバウンド規則
- Azure での既定の送信アクセス
- チュートリアル: Azure portal を使用して NAT ゲートウェイとパブリック ロード バランサーを統合する
事前設定
以下、リソースグループを作成します。
az group create --name MyResourceGroup --location japaneast
以下、仮想ネットワークを作成します。
az network vnet create \ --resource-group MyResourceGroup \ --name MyVnet \ --address-prefix 172.16.0.0/16 az network vnet subnet create \ --resource-group MyResourceGroup \ --name MySubnet \ --vnet-name MyVnet \ --address-prefixes 172.16.1.0/24
以下のロードバランサを作成します。各パラメタの意味は「Azure ロードバランサの基本操作」を参照ください。
az network public-ip create \ --resource-group MyResourceGroup \ --name MyPublicIpAddress01 \ --sku Standard az network lb create \ --resource-group MyResourceGroup \ --name MyLoadBalancer \ --sku Standard \ --public-ip-address MyPublicIpAddress01 \ --frontend-ip-name MyFrontEndPool01 \ --backend-pool-name MyBackEndPool01
動作確認用の仮想マシンを作成します。
for i in `seq 10 12`; do az vm create \ --resource-group MyResourceGroup \ --name linux0${i} \ --image UbuntuLTS \ --size Standard_B1s \ --admin-username azureuser \ --admin-password P@ssw0rd1234 \ --vnet-name MyVnet \ --subnet MySubnet \ --public-ip-address '' \ --private-ip-address 172.16.1.${i} done
前述の仮想マシンはインターネットからsshでアクセスする事はできないので、Azure bastionサービス相当の機能を提供する仮想マシンを作成します。以下のbastion250を経由する事で任意の仮想マシンへsshログインできるようになります。
後述の操作で「NATゲートウェイ」を作成します。「NATゲートウェイ」は、Basic SKUのパブリックIPアドレスと併用できませんので、パブリックIPアドレスのSKUはStandardとしてください。
az vm create \ --resource-group MyResourceGroup \ --name bastion250 \ --image UbuntuLTS \ --size Standard_B1s \ --admin-username azureuser \ --ssh-key-values ~/.ssh/authorized_keys \ --vnet-name MyVnet \ --subnet MySubnet \ --public-ip-sku Standard \ --private-ip-address 172.16.1.250
概要
ロードバランサ配下の仮想マシンまたは仮想マシンスケールセットがインターネットへアクセスする方法は複数通りあります。「https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-outbound-connections」によると、4通りの方法が紹介されています。
- 送信規則による送信には、ロード バランサーのフロントエンド IP アドレスが使用される
- サブネットへの NAT ゲートウェイの関連付け
- 仮想マシンへのパブリック IP の割り当て
- 既定の送信アクセスを使用する
それぞれの特徴やメリット・デメリットについては、「https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-outbound-connections」を参照ください。
負荷分散規則のデフォルト挙動確認
デフォルト設定の確認
ロードバランサを使用する多くの場合は、負荷分散規則を定義するでしょう。負荷分散規則には、disable-outbound-snatというオプションがあり、デフォルト値はfalseです。つまり、デフォルト設定では、負荷分散規則と同時にインターネットへのアクセスが可能な状態になります。
「https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-outbound-connections」で語られるSNATの設定方法を動作確認する前に、まずは負荷分散規則のデフォルトの挙動を確認しましょう。
以下のような負荷分散規則を定義します。
az network lb rule create \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyHttpRule \ --protocol tcp \ --frontend-port 80 \ --backend-port 80 \ --frontend-ip-name MyFrontEndPool01 \ --backend-pool-name MyBackEndPool01 \ --idle-timeout 15 \ --disable-outbound-snat false \ --enable-tcp-reset true
負荷分散規則の対象に以下の仮想マシンを加えます
array=(linux010 linux011 linux012) for h in "${array[@]}" do az network nic ip-config address-pool add \ --address-pool MyBackendPool01 \ --ip-config-name ipconfig${h} \ --nic-name ${h}VMNic \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer done
bastion250を経由してlinux010へsshログインします。インターネットへの疎通が可能である事を確認します。
azureuser@linux010:~$ curl -I http://www.bing.com HTTP/1.1 200 OK Cache-Control: private Content-Length: 0 Content-Type: text/html; charset=utf-8 P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND" Set-Cookie: SUID=M; domain=.bing.com; expires=Sun, 24-Apr-2022 05:49:03 GMT; path=/; HttpOnly Set-Cookie: MUID=270ECDA6C6E7605A1398DC29C79B61AD; domain=.bing.com; expires=Thu, 18-May-2023 05:49:03 GMT; path=/ <omitted>
アウトバウンドNATの明示的拒否
負荷分散規則でoutbound-snatを明示的に拒否します。引数disable-outbound-snatにtrueを指定します。
az network lb rule update \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyHttpRule \ --disable-outbound-snat true
linux010からインターネットへアクセスできない事を確認します。
azureuser@linux010:~$ curl -I --connect-timeout 3 http://www.bing.com curl: (28) Connection timed out after 3000 milliseconds azureuser@linux010:~$
送信規則(アウトバウンド規則)
構成図
以下構成でインターネットへアクセスできるようにします。送信規則を使用するとバックエンドプール毎に異なるパブリックIPアドレスを割り当てる事ができます。
1つ目の送信規則作成
以下のようなコマンドで送信規則(アウトバウンド規則)を作成できます。作成の際は、引数address-poolでバックエンドプールを、引数frontend-ip-configsでパブリックIPアドレスを指定します。引数frontend-ip-configsはスペース区切りで複数のパブリックIPアドレスを指定できます。
az network lb outbound-rule create \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyOutboundRule01 \ --protocol All \ --address-pool MyBackEndPool01 \ --frontend-ip-configs MyFrontEndPool01
bastion250を経由してlinux010へsshログインします。インターネットへの疎通が可能である事を確認します。
azureuser@linux010:~$ curl -I http://www.bing.com HTTP/1.1 200 OK Cache-Control: private Content-Length: 0 Content-Type: text/html; charset=utf-8 P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND" Set-Cookie: SUID=M; domain=.bing.com; expires=Sun, 24-Apr-2022 08:34:51 GMT; path=/; HttpOnly <omitted>
「確認くん」などのWebサイトを用いて、送信元IPアドレスを調査します。
azureuser@linux010:~$ curl -s https://www.ugtop.com/spill.shtml | grep -i IPv4 -A 1 <th>あなたのIPアドレス(IPv4)</th> <td><font size=+2 color=blue>20.89.48.194</font></td> azureuser@linux010:~$
送信元IPアドレスがロードバランサに設定されたフロントエンドIP構成と一致する事を確認します。
2つ目の送信規則作成
送信規則(アウトバウンド規則)はバックエンドプール毎に異なる設定を適用する事もできます。複数の送信規則を作成する事によって、SNAPポート枯渇を防ぐ構成を採用する事もできます。
それでは2つ目の送信規則を作成します。まずは2つ目用途の「フロントエンドIP構成」と「バックエンドプール」を作成します。「フロントエンドIP構成」と紐づけるパブリックIPアドレスは単一のグローバルIPアドレスでもIPプレフィックスでも、どちらでも差し支えございません。今回は大規模向けのIPプレフィックスの例を紹介します。
az network public-ip prefix create \ --resource-group MyResourceGroup \ --name MyPublicIpPrefix02 \ --length 31 az network lb frontend-ip create \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyFrontEndPool02 \ --public-ip-prefix MyPublicIpPrefix02 az network lb address-pool create \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyBackEndPool02
バックエンドプールに属する仮想マシンを3台作成します。
for i in `seq 20 22`; do az vm create \ --resource-group MyResourceGroup \ --name linux0${i} \ --image UbuntuLTS \ --size Standard_B1s \ --admin-username azureuser \ --admin-password P@ssw0rd1234 \ --vnet-name MyVnet \ --subnet MySubnet \ --public-ip-address '' \ --private-ip-address 172.16.1.${i} done array=(linux020 linux021 linux022) for h in "${array[@]}" do az network nic ip-config address-pool add \ --address-pool MyBackendPool02 \ --ip-config-name ipconfig${h} \ --nic-name ${h}VMNic \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer done
2つ目の送信規則を作成します。
az network lb outbound-rule create \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyOutboundRule02 \ --protocol All \ --address-pool MyBackEndPool02 \ --frontend-ip-configs MyFrontEndPool02
bastion250を経由してlinux010へsshログインします。「確認くん」などのWebサイトを用いて、送信元IPアドレスを調査します。
「NATゲートウェイ」と異なり、1つの仮想マシンに着目した時に負荷分散される挙動ではない事に注意ください。
azureuser@linux020:~$ curl -s https://www.ugtop.com/spill.shtml | grep -i IPv4 -A 1 <th>あなたのIPアドレス(IPv4)</th> <td><font size=+2 color=blue>20.210.206.164</font></td> azureuser@linux020:~$ azureuser@linux020:~$ azureuser@linux020:~$ curl -s https://www.ugtop.com/spill.shtml | grep -i IPv4 -A 1 <th>あなたのIPアドレス(IPv4)</th> <td><font size=+2 color=blue>20.210.206.164</font></td> azureuser@linux020:~$
送信元IPアドレスがロードバランサに設定されたフロントエンドIP構成と一致する事を確認します。
SNAPポートのチューニング
「既定の送信アクセスを使用する」では、仮想マシンの台数が増えるにつれてSNAPポート枯渇のリスクが高まります。他方、送信規則は仮想マシン1台あたりの使用可能なSNAPポート数の上限が定められており、仮想マシンの増加に伴って、突然、SNAPポートが枯渇するような事故は発生しないような設計になっています。
SNAPポート数は以下のshowコマンドで確認でき、デフォルト値は仮想マシン1台あたり1024ポートである事が分かります。
$ az network lb outbound-rule show \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyOutboundRule02 { "allocatedOutboundPorts": 1024, "backendAddressPool": { "id": "/subscriptions/2e2f81a9-b030-410f-9784-c582580c932e/resourceGroups/MyResourceGroup/providers/Microsoft.Network/loadBalancers/MyLoadBalancer/backendAddressPools/MyBackEndPool02", "resourceGroup": "MyResourceGroup" }, <omitted>
これを設定変更するには以下のようなコマンドを使用します。
az network lb outbound-rule update \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyOutboundRule02 \ --outbound-ports 4096
パブリックIPアドレス1あたりで64,000個が使用できますので、この値を元にインスタンスを何個収容できるかを計算すると良いでしょう。暗算の事故が怖いならば、以下スクリーンショットのようにポータル(GUI)を使うと、事故が防げると思います。以下は、32個の仮想マシンを収容する場合は1つの仮想マシンあたり4000ポートが使用可能な事を表します。
設定変更が反映されたかどうかは以下のようなshowコマンドを使用します。
$ az network lb outbound-rule show \ --resource-group MyResourceGroup \ --lb-name MyLoadBalancer \ --name MyOutboundRule02 \ --query "allocatedOutboundPorts" 4096
NATゲートウェイ
構成図
以下構成でインターネットへアクセスできるようにします。
NATゲートウェイの作成
NATゲートウェイを作成し、ロードバランサとNATゲートウェイの併用例を示します。各コマンドの意味は「Azure NATゲートウェイ」を参照ください。
「送信規則」と「NATゲートウェイ」を同時に設定する場合は、「NATゲートウェイ」が優先されます。
az network public-ip prefix create \ --resource-group MyResourceGroup \ --name MyPublicIpPrefix03 \ --length 31 az network nat gateway create \ --resource-group MyResourceGroup \ --name MyNatGateway03 \ --public-ip-prefixes MyPublicIpPrefix03 az network vnet subnet update \ --resource-group MyResourceGroup \ --vnet-name MyVnet \ --name MySubnet \ --nat-gateway MyNatGateway03
疎通確認
bastion250を経由してlinux010へsshログインします。「確認くん」などのWebサイトを用いて、送信元IPアドレスを調査します。
「送信規則」と異なり、「NATゲートウェイ」は複数のパブリックIPアドレスに負荷分散されます。
azureuser@linux010:~$ curl -s https://www.ugtop.com/spill.shtml | grep -i IPv4 -A 1 <th>あなたのIPアドレス(IPv4)</th> <td><font size=+2 color=blue>20.222.84.51</font></td> azureuser@linux010:~$ azureuser@linux010:~$ azureuser@linux010:~$ curl -s https://www.ugtop.com/spill.shtml | grep -i IPv4 -A 1 <th>あなたのIPアドレス(IPv4)</th> <td><font size=+2 color=blue>20.222.84.50</font></td> azureuser@linux010:~$
送信元IPアドレスがNATゲートウェイに設定されたパブリックIPアドレスと一致する事を確認します。