Azure Load Balancer を Basic から Standard に変更する方法

2021/01/13 追記
Basic から Standard に移行するためのスクリプトがリリースされました。
(制限事項もあるようなので、事前にテスト環境で検証したうえで利用しましょう。)

Azure Public Load Balancer をアップグレードする
https://docs.microsoft.com/ja-jp/azure/load-balancer/upgrade-basic-standard

Azure Internal Load Balancer のアップグレード – 送信接続は不要
https://docs.microsoft.com/ja-jp/azure/load-balancer/upgrade-basicinternal-standard

Azure のロードバランサーは Basic / Standard の External (ALB) / Internal (ILB) と 4 パターンありますが、以下のドキュメントにもある通り、SKU を変更することはできません。

SKU 間での移行

SKU は変更不可です。

 重要
このドキュメント全体を確認して、SKU ごとの違いを理解し、シナリオを慎重に検証してください。 シナリオに合わせて追加の変更が必要になる場合があります。

したがって、Basic から Standard に変更する場合は、一度 Basic SKU の LB を削除し、新規で Standard の LB を作る必要があります。

SKU ごとの機能差

ザックリまとめると、SKU ごとの機能差は以下の通りです。

SKU 移行時の注意点

1. LB と Public IP の SKU は統一する必要があります。

つまり、VM に Basic SKU の Public IP を紐づけている状況で、Standard SKU の LB に所属させることはできません。Public IP も Standard SKU のものを新規作成して付け替える必要があります。

2. 可用性セット内の全てのリソースで SKU を統一する必要があります。

可用性セットは、同一の役割のサーバーをグルーピングし、同一の物理サーバー上に配置させないことで、可用性を担保するための仕組みです。言い換えれば、可用性セット内の 1 台の VM は Basic の LB に、もう 1 台の VM は Standard の LB に紐づくといったことはできないため、可用性セット内の全ての VM を同一 SKU の LB 配下に入れる必要があります。

3. VM が Public IP を持たず、Standard ILB にのみ紐づく場合は Internet アクセスができません。

VM に ILB しか紐づいておらず、Public IP もない場合、Internet アクセスができなくなります。Standard ILB は SNAT の機能を有していないため、VM に直接 Public IP を紐づけるか、ILB とは別に ALB (外部 LB) を紐づける必要があります。

あとから構成変更しようとすると割と手間がかかるので、構築時にきちんと設計しましょう。

Application Gateway のテンプレートに SSL オフロード用の証明書を埋め込む方法

Application Gateway の ARM テンプレートに SSL 証明書 (PFX) とパスワードを設定する際の方法をメモしておきます。

まあ、GitHub の以下にサンプルがあるので、それを真似するだけなんですが。

azure-quickstart-templates/101-application-gateway-public-ip-ssl-offload/azuredeploy.json

該当箇所は、125 – 133 行目の以下の箇所。

    "sslCertificates": [
      {
        "name": "appGatewaySslCert",
        "properties": {
          "data": "[parameters('certData')]",
          "password": "[parameters('certPassword')]"
        }
      }
    ],

data と password のパラメーターに証明書のデータ (PFX を Base-64 エンコードしたもの) と、パスワードを指定すれば OK です。

上記の例では、[parameters()] で事前に定義した変数を参照する形になっています。 該当箇所は 50 – 61 行目のあたり。

"certData": {
  "type": "string",
  "metadata": {
    "description": "Base-64 encoded form of the .pfx file"
  }
},
"certPassword": {
  "type": "securestring",
  "metadata": {
    "description": "Password for .pfx certificate"
  }
},

PFX ファイルを Base-64 でエンコードするには、Windows PowerShell で以下の様な感じでやりましょう。

$CertPath = "<PFX ファイルのフルパス>"
[System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes($CertPath)) | Out-File "<Base64 エンコードしたテキストの出力先フルパス>"

ARM テンプレートの使い方は、この辺のリンクをどうぞ。

Azure VM の SNAT の話

Azure VM は NAT Gateway のようなリソースがなくても勝手に SNAT して Internet 接続ができるようになっています。
ただ、勝手にいい感じにやってくれる親切設計な反面、仕組みを理解せずに使ってる人が多すぎるので、整理しておこうかなと。

SNAT に使用される Public IP

一応ドキュメントに記載はあるんですが、わかりづらいのでシンプルにまとめると以下のような感じになります。

  • VM に Public IP がある場合: VM (NIC) に紐づいた Public IP で SNAT
  • VM に Public IP がなく、外部 LB に紐づいている場合: LB の Public IP で SNAT
  • VM に Public IP も外部 LB にも紐づいていない場合: 当該リージョンの任意の Public IP で SNAT

したがって、送信元 IP を固定したい (対向側の Firewall 等で IP 指定で許可設定をしたい) 場合には、前者 2 点のいずれかになります。

SNAT Port の割り当て

VM が Public IP を持たないシナリオの場合、個々の VM に割り当てられる SNAT Port の数に注意が必要です。

  • VM に Public IP がある場合: 64k Port
  • VM に Public IP がなく、外部 LB に紐づいている場合: 最大で 1024 Port
  • VM にも外部 LB にも紐づいていない場合: 1024 Port

1 つの Public IP では TCP / UDP それぞれ 64k Port しか使えませんので、外部 LB の Public IP を使用する (複数の VM で Public IP を共有する) 場合 は、1 台あたりに割り当てられる Port が 1024 までに限られる点に気を付けましょう。(なお、LB 配下の VM が 1 台だけであっても、1024 Port しか使えません)
なお、LB のバックエンド プールが 50 台を超える場合には、割り当て Port がさらに少なくなります。(参考)

SNAT Port を使い果たした場合

LB の SNAT Port が使い果たした場合、当然ですが SNAT できないため Public IP 宛の通信ができなくなります。
Azure VM から Public IP あてに多数のセッションを張る場合や、Docker などのコンテナを利用するような場合は、1024 Port を早々に食いつぶす可能性もあるので、きちんと見積もりや設計を行いましょう。(Azure 基盤側としては、VM 上で何台コンテナが起動しているかは把握できないので、同一 VM 上で稼働するすべてのコンテナで 1024 Port を共有することになります。)

ちなみに、負荷テストや再現試験などで SNAT Port を意図的に枯渇させたい場合、Linux で hping3 を使うのがお手軽です。
例えば、以下のような形で実行することで、SYN パケットを100 マイクロ秒ごとに任意の Public IP (xx.xx.xx.xx) の 65000 番の Port に対して、ひたすら投げつけることができます。(一歩間違うと SYN Flood 攻撃になるので、やり方と通信先は慎重に検討しましょう。)

apt install hping3 -y
hping3 -S -i u100 -p 65000 <xx.xx.xx.xx>

外部 LB 配下の VM (すなわち 1024 Port しか使えない環境) で上記を実行すると、1 秒ほどで大量の応答が返ったのち、突然出力が止まるかと思います。Ctrl + C で hping3 を終了すると、以下のように 1024 packets までは応答が得られたものの、あとはパケロスしていたことが確認できます。

len=46 ip=xx.xx.xx.xx ttl=57 DF id=0 sport=65000 flags=SA seq=1011 win=29200 rtt=30.4 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1016 win=29200 rtt=29.8 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1007 win=29200 rtt=31.0 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1013 win=29200 rtt=30.3 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1012 win=29200 rtt=30.6 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1006 win=29200 rtt=31.4 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1009 win=29200 rtt=31.1 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1008 win=29200 rtt=31.2 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1014 win=29200 rtt=30.4 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1021 win=29200 rtt=29.5 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1019 win=29200 rtt=29.9 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1022 win=29200 rtt=29.5 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1018 win=29200 rtt=30.1 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1017 win=29200 rtt=30.2 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1020 win=29200 rtt=29.9 ms
len=44 ip=xx.xx.xx.xx ttl=64 DF id=0 sport=65000 flags=SA seq=1023 win=29200 rtt=29.4 ms
^C
--- xx.xx.xx.xx hping statistic ---
21434 packets transmitted, 1024 packets received, 96% packet loss
round-trip min/avg/max = 3.5/9.2/32.9 ms

なお、SNAT で使用した Port はセッションが閉じられたり (FIN/ACK)、強制的に切断されたり (RST)、アイドル タイムアウトに達した場合 (既定で 4 分) に開放されます。

また、外部 LB が Standard SKU の場合に限り、使用済みの SNAT Port をメトリックの機能で確認することが可能です。
先の例のように Ctrl + C で止めずに、長時間 1024 Port を消費させたままの状態にすると、以下のような感じになります。

Basic SKU の外部 LB を使っている場合は、上記のようなメトリックは利用できませんが、たしか診断ログの機能でアラート イベント ログに “Ports exhausted” と記録されたかと思います。 (参考)

SNAT Port の割り当てを増やしたい場合

VM (NIC の ipconfig) あたり 1024 Port では足りないという場合、対処策は以下のいずれかになります。

  • VM に Public IP を直接紐づける
  • Standard SKU の外部 LB で allocatedOutboundPorts を設定して、SNAT Port の割り当てを変更する

後者の allocatedOutboundPorts は Basic SKU では使えず、Standard SKU でのみ提供される機能ですが、1 VM あたりに割り当てる SNAT Port を 10000 Port などと明示的に設定することが可能です。(もちろん、1 台当たりの Port × LB 配下の VM 台数が 64k に収まるように設計する必要があります。)

現状 Portal からは設定ができないため、Azure PowerShell や CLI、REST、JSON テンプレートなどで設定する必要があります。(参考)

# 既存の LB の設定を取得
$LB = Get-AzLoadBalancer -ResourceGroupName SNAT-Test -Name SNAT-Test-StandardLB

# OutboundRule で AllocatedOutboundPort 等のパラメーターを設定
Add-AzLoadBalancerOutboundRuleConfig -LoadBalancer $LB -Name OutboundRule -AllocatedOutboundPort 10000 -Protocol All -EnableTcpReset -IdleTimeoutInMinutes 4 -FrontendIpConfiguration $LB.FrontendIpConfigurations -BackendAddressPool $LB.BackendAddressPools[0]

# LoadBalancingRule による SNAT を無効化 (これを忘れるとエラーになるので注意)
$LB.LoadBalancingRules[0].DisableOutboundSNAT = $true

# 設定を保存
Set-AzLoadBalancer -LoadBalancer $LB

以上、Azure での SNAT でハマりやすいポイントと対処策についてでした。

Azure VM での ICMP (ping, traceroute) について

Azure VM で ICMP を扱う際には、 いくつか 気を付けないといけない点があります。
Azure をそこそこ使っている人でもハマることがあると思う (特に Azure VM から外部宛) ので、応答が得られない際のご参考までに。

Azure VM に対して ping, traceroute する場合 (Inbound)

NSG の受信許可設定が必要

Azure VM の NIC と Subnet に紐づいた NSG で、受信セキュリティ規則にて ICMP の許可設定を行っているかを確認しましょう。

OS 内の Firewall で受信許可設定が必要

NSG に加えて、当然ですが OS 内の Firewall でも ICMP を許可しましょう。
(特に Windows はデフォルトで不許可です)

LB 経由の ICMP は不可

Azure の Load Balancer は TCP / UDP の通信しか中継できません。
必ず VM の IP に対して直接 ping, traceroute を実行しましょう。

Azure VM から ping, traceroute する場合 (Outbound)

VM に直接 Public IP の付与が必要

Azure では、VM に Public IP を付与せずとも、外部 LB やデータセンターの任意の IP で SNAT して Internet 接続ができます。
ただ、LB は TCP / UDP の通信しか中継できないため、VM に直接 Public IP を紐付けていない構成では ICMP の応答が返りません。

traceroute には NSG で受信許可設定が必要

traceroute の通信は、宛先に指定した IP アドレス以外から応答が戻るため、NSG で ICMP がブロックされていると応答が戻りません。
(TTL が 0 になった時点で、経路上のルーターの IP アドレスから Time Exceeded の応答が返るためやむを得ません。)

ちなみに、はじめの数ホップ (Azure 内) は応答が返りませんが、途中からはちゃんと応答が返るので焦らずに待ちましょう。

その他のパターンも見つけたら追記します。

Azure DNS のネーム サーバーを揃えたい

Azure DNS で DNS ゾーンを作成すると、ns1-XX.azure-dns.com / .net / .org / .info の 4 つのネーム サーバー (権威サーバー) が割り当てられますが、XX の部分はランダムで決まります。逆引きゾーン (113.0.203.in-addr.arpa 等) を複数作成するような場合に、同一のネーム サーバーを利用したいといった場合があるかと思いますが、そのような場合には PowerShell のスクリプト等で同一名のゾーンを複数作成してガチャを引きましょう。(今のところ、ネーム サーバーは 01 – 09 の 9 個のみのようで、10 個目を作ろうとすると「The zone ‘113.0.203.in-addr.arpa’ is not available.」の様なエラーで失敗します。)

$ZoneName = "113.0.203.in-addr.arpa"
$Location = "JapanEast"

for($i = 9; $i -lt 10; $i++){
    New-AzResourceGroup -Name "TempRG$i" -Location $Location
    New-AzDnsZone -Name $ZoneName -ResourceGroupName "TempRG$i" -ZoneType Public
}

作成が完了すると、以下のように 01 – 09 のネームサーバーに割り当てられた 9 個の DNS ゾーンが確認できます。ここから利用したいものを選んで、残りは消してしまいましょう。

ちなみに、Azure DNS はリソース グループの移動に対応しているので、[移動] – [別のリソース グループに移動する] から任意のリソース グループへ移動することも可能です。

リソース グループを一つずつ消すのは面倒なので、必要なものだけ移動してから、PowerShell でサクっと消しましょう。

$Location = "JapanEast"

for($i = 0; $i -lt 9; $i++){
    Remove-AzResourceGroup -Name "tempRG$i" -Force
}

ちなみに、Azure DNS で逆引きゾーンをホストする方法はドキュメントもあるのであわせてどうぞ。

Microsoft の IP アドレス系の情報

Azure に限らず、Microsoft 所有の IP アドレスの情報が Download Center で公開されているのを見つけたので、忘れないようにメモしておきます。

それぞれ Details とかに書いてありますが、これらのデータは更新されることがあるので Weekly とかでチェックしましょう。