Azure Administrator(AZ-104)：Azure Load BalancerのSKUとバックエンドプール

この記事は、Microsoft Azure Administrator(AZ-104)の受験勉強の中で、自分が間違えやすい、覚えにくいと思ったポイントの一つをまとめたものです。同じく資格取得に向けて勉強されている方の参考になれば幸いです。

## Azure Load Balancerの概要
Azureには負荷分散に使用できるリソースがいくつかあり、Load Balancer(以後、LBと記載)もその一つです。
開放型システム間相互接続(OSI)モデルの第4レイヤー(L4)で動作します。SSL終端させたり、WAFを動作させたり、ということはできません。
パブリックと内部(プライベート)の2種類があります。
- パブリック：インターネットトラフィックの負荷分散
- 内部：仮想ネットワーク内の負荷分散

## SKU
SKUにはBasicとStandardがあります(他に、ネットワーク仮想アプライアンス向けのGatewayというのもあります)。Basicは、SLAがない、以外にも制限や設定の違いがあります。詳細は[MS Learnのドキュメント](https://learn.microsoft.com/ja-jp/training/modules/configure-azure-load-balancer/5-determine-skus)を参照ください。
Basicは2025年9月30日に廃止されるようです。AZ-104でBasicに関してまだ出題されるのか、はわかりませんが...

## SKUとバックエンドプール
この記事でとりあげたいポイントです。LBに接続するバックエンドプールを構成できる仮想マシン(以後、VMと記載)もSKUによって違いがあります。

- Basic：単一の可用性セット、または仮想マシンスケールセットにあるVM
- Standard：単一仮想ネットワークにあるVM

可用性セットや仮想マシンスケールセットを組んでいないVMをBasicのLBに接続することはできないことになります。逆に言えば、複数VMへの接続でBasicのLBを使っています、という場合には、これらいずれかのセットが組まれているのだ、ということがわかります。
StandardのLBも、仮想ネットワークが異なるVMを接続することはできません。

また、VMにパブリックIPアドレスが設定されている場合、パブリックIPアドレスのSKUとLBのSKUが異なると、バックエンドプールにVMを追加できない点にも注意が必要です。
パブリックIPアドレスのSKUにはBasicとStandardがありますが、大きな違いとして、Standardには動的なIPアドレスの割り当てはありません。パブリックIPアドレスが動的、という記述があればSKUがBasicであることがわかります。

## 検証
上記が頭に入れば、以降は読み飛ばしていただいても結構ですが、実際試してみた内容を以下に記載します。

下図のようにLB経由でVMに接続するような構成を作成してみます。

![スクリーンショット_20230118_163925.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/335447a8-dc90-f8f0-3c5c-618fdda2ab92.png)


VM0からLB1経由でVM1、VM2にHTTP接続し、VM1、VM2は自分のホスト名を返すようにします。
VM1、VM2にはNode.jsの簡単なアプリを組み込んでおきます。VM作成時にcloud-initを使ってセットアップするようにします。

<details><summary>cloud-init.txtの内容</summary><div>

```
#cloud-config
#set parameter --admin-username azureuser
package_upgrade: true
packages:
  - nginx
  - nodejs
  - npm
write_files:
  - owner: www-data:www-data
    path: /etc/nginx/sites-available/default
    content: |
      server {
        listen 80;
        location / {
          proxy_pass http://localhost:3000;
        }
      }
  - owner: azureuser:azureuser
    path: /home/azureuser/app1/index.js
    content: |
      var express = require('express')
      var app = express()
      var os = require('os');
      app.get('/', function (req, res) {
        res.send('OK from host:' + os.hostname() + '\n')
      })
      app.listen(3000, function () {
        console.log('listening on port 3000')
      })
runcmd:
  - service nginx restart
  - cd "/home/azureuser/app1"
  - npm init
  - npm install express -y
  - nodejs index.js
```

</div></details>

まずAzure CLIを使ってVM0を作成します。仮想ネットワークVNET1のサブネットSUBNET0も同時に作成します。
```
az vm create \
    --resource-group $RG \
    --name VM0 \
    --image UbuntuLTS \
    --admin-username azureuser \
    --vnet-name VNET1 \
    --subnet SUBNET0 \
    --generate-ssh-keys
```
※環境変数RGには任意のリソースグループ名を設定しておきます。

次に可用性セットAVSET1を作成します。障害ドメイン、更新ドメインは2としています。
```
az vm availability-set create \
    --resource-group $RG \
    --name AVSET1 \
    --platform-fault-domain-count 2 \
    --platform-update-domain-count 2
```
VM0とは別のサブネットSUBNET1を作成します。
```
az network vnet subnet create --address-prefixes 10.0.1.0/24 \
                              --name SUBNET1 \
                              --resource-group $RG \
                              --vnet-name VNET1
```
AVSET1、SUBNET1に属するVM1、VM2を作成します。HTTP接続のためポート80を開けておきます。
```
for i in `seq 1 2`; do
  az vm create \
     --resource-group $RG \
     --name VM$i \
     --availability-set AVSET1 \
     --size Standard_DS1_v2  \
     --vnet-name VNET1 \
     --subnet SUBNET1 \
     --image UbuntuLTS \
     --admin-username azureuser \
     --generate-ssh-keys \
     --custom-data cloud-init.txt
  az vm open-port --port 80 --resource-group $RG --name VM$i
done
```
この状態で、Basic LBを作成してみましょう。
Azureポータルからロードバランサーの作成を選択し、SKUにBasicを選択して作成、フロントエンドの構成を設定後にバックエンドプールの追加を選択すると、作成したVMが一覧表示されます。
![スクリーンショット_20230118_114726.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/720a99b7-7243-5068-9f7e-ffbfc75768bb.png)
ここでAVSET1のVM1を選択すると、選択できるのは同じくAVSET1に属するVM2のみとなります。Basic LBの制約通りですね。
![スクリーンショット_20230118_114748.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/d6ce0023-fb4f-c176-d8b2-fa2f88f5ccea.png)
VM1、VM2をバックエンドプールに追加し、負荷分散規則で80番ポートへの接続をバックエンドプールの80番ポートにフォワードするように設定してみます。
なお、LB1のフロントエンドIPは10.0.1.100固定としました。VNET1に接続するデバイスのIPは下図のようになっています。
![スクリーンショット_20230118_115043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/7f82a8f5-67ea-eacb-eff7-09ae69dd247c.png)
VM0から、VM1、VM2に直接接続すると、それぞれのホスト名を示す応答が返ってきます。VM0からLB1に接続すると、VM1、またはVM2のホスト名を返す応答が返ってきます。
![スクリーンショット_20230118_120019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/8f0b89cd-b791-37c0-571f-aeb93ec23fe6.png)
LB1がVM1、VM2の負荷分散を行っていることが確認できました。

なお、LB作成時にSKUとしてStandardを選択すると、バックエンドプールのVMとしてVM0～VM2を設定することができません。VM0～VM2のパブリックIPアドレスのSKUは、Basicとなっており、LBのSKUと一致しないためです。
![スクリーンショット_20230118_120915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/15be6438-2b98-3e8e-0a26-bb8ff85f1fad.png)

`az vm create`実行時に下記メッセージが表示されていたのですが、現状はVM作成時のSKUはBasicとなっており、将来的にはStandardに変更されるようです。
```
It is recommended to use parameter "--public-ip-sku Standard" 
to create new VM with Standard public IP. 
Please note that the default public IP used for VM creation 
will be changed from Basic to Standard in the future.
```