arm-templateにてnat-gatewayを構成する①

前回、AzureにてVPCとSubnetの`privateLinkServiceNetworkPolicies`をarm-templateから無効にした
今回は、nat-gatewayをarm-templateからデプロイする

https://qiita.com/nicnic69/items/ed9c3f704b4ad424cab3

前回と同様に構成は以下になる
```
infrastructure-templates/
├── README.md                        # プロジェクトの概要や使用方法を記載
├── environments/                    # 環境ごとの設定を格納するディレクトリ
│   ├── dev/                         # 開発環境用の設定ディレクトリ
│   │   ├── dev.parameters.json      # 開発環境のパラメータファイル（VMサイズ、リージョン等）
│   │   └── main.json                # 開発環境用のARMテンプレート（リソース定義）
│   ├── prod/                        # 本番環境用の設定ディレクトリ
│   │   ├── main.json                # 本番環境用のARMテンプレート（リソース定義）
│   │   └── prod.parameters.json     # 本番環境のパラメータファイル（VMサイズ、リージョン等）
│   └── staging/                     # ステージング環境用の設定ディレクトリ
│       ├── main.json                # ステージング環境用のARMテンプレート（リソース定義）
│       └── staging.parameters.json  # ステージング環境のパラメータファイル（VMサイズ、リージョン等）
├── modules/                         # 共通のリソースモジュールを格納するディレクトリ
│   ├── app-service-template.json    # アプリサービス関連のリソース定義（App Service）
│   ├── network-template.json        # ネットワークリソース関連のリソース定義（VNet、サブネット等）
│   └── storage-template.json        # ストレージリソース関連のリソース定義（Storage Account等）
├── infra-common.json                # 共通リソースを定義（VNet、ストレージなど）
├── ci-cd-pipelines/                 # CI/CD パイプライン設定ディレクトリ（Azure DevOps や GitHub Actions の設定）
│   ├── azure-pipelines.yml          # Azure DevOps Pipelines 設定ファイル
│   └── github-actions.yml           # GitHub Actions 設定ファイル
└── .gitignore                       # Git で追跡しないファイルやディレクトリの設定
```

nat-gatewayでパブリックIPアドレスを使用する必要があるため、パブリックIPアドレスを作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3146038/54e00265-cb13-ea10-c9dc-09183215696e.png)

|項目|入力/選択|説明|
|:-|:-|:-|
|サブスクリプション|-|Azureリソースの料金管理や請求情報の単位。|
|リソースグループ|-|複数のAzureリソースを論理的にグループ化して管理する単位。|
|リージョン|-|リソースをデプロイするAzureの地理的な場所。|
|名前|pip-dev-japaneast-001|パブリックIPアドレスの名前。|
|IP バージョン|IPv4|2025-01-13時点で、IPv6がサポートされていないため、IPv4を選択。|
|SKU|Standard|2025-9-30に、Azure Basic パブリック IP は廃止されるため、Standardを選択。|
|可用性ゾーン|Zone-Redundant|ゾーン冗長を選択。|
|レベル|regional|Geo-Redundant構成はしていないため、regionalを選択。|
|IP アドレスの割り当て|静的|Standardは静的のみをサポートしている|
|ルーティングの優先順位||一般的なインターネットプロバイダーでも問題なく、コストを抑えたいため選択。|
|アイドル タイムアウト (分)|4|デフォルトを使用する。|
|DNS 名ラベル|xxxxx|使用するリージョンでドメイン名ラベルは一意である必要がある。|
|ドメイン名ラベルのスコープ (プレビュー)|-|プレビュー段階のため、使用しない|



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3146038/a47e50cb-85f7-a38c-000b-040652104d5d.png)


VnetでDDoS保護を有効化していないが、継承するを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3146038/ef9069d4-d0b9-1af5-18c8-680a07b08524.png)

タグは設定しない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3146038/3c368509-b4ce-7be0-4a0a-83a9fef3d473.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3146038/9b9c5b87-ab9a-26ea-5bda-49984514e1fe.png)

ARMTemplateにパブリックIPアドレスの記述を追加する

what-ifで記述に差分がないか確認する
```bash
# az deployment group what-if   --resource-group rg-xxxx-xxxx-001   --template-file main.json   --parameters dev.parameters.json
Note: The result may contain false positive predictions (noise).
You can help us improve the accuracy of the result by opening an issue here: https://aka.ms/WhatIfIssues

Resource and property changes are indicated with these symbols:
  = Nochange
  x Noeffect

The deployment will update the following scope:

Scope: /subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001

  = Microsoft.Network/publicIPAddresses/pip-dev-japaneast-001 [2024-01-01]
    x properties.dnsSettings.fqdn: "dev-web-20250113-qoo.japaneast.cloudapp.azure.com"
    x properties.ipAddress:        "48.218.127.120"

  = Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001 [2024-01-01]
    x properties.subnets[0].type: "Microsoft.Network/virtualNetworks/subnets"

  = Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001/subnets/snet-dev-japaneast-001 [2024-01-01]

Resource changes: 3 no change.
```

```bash
az network public-ip show \
    --name pip-dev-japaneast-001 \
    --resource-group rg-xxxx-xxxx-001
{
  "ddosSettings": {
    "protectionMode": "VirtualNetworkInherited"
  },
  "dnsSettings": {
    "domainNameLabel": "dev-web-20250113-qoo",
    "fqdn": "dev-web-20250113-qoo.japaneast.cloudapp.azure.com"
  },
  "etag": "W/\"7dd837ee-574c-4f1b-ad39-cb054e470ebd\"",
  "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/publicIPAddresses/pip-dev-japaneast-001",
  "idleTimeoutInMinutes": 4,
  "ipAddress": "48.218.127.120",
  "ipTags": [],
  "location": "japaneast",
  "name": "pip-dev-japaneast-001",
  "provisioningState": "Succeeded",
  "publicIPAddressVersion": "IPv4",
  "publicIPAllocationMethod": "Static",
  "resourceGroup": "rg-xxxx-xxxx-001",
  "resourceGuid": "8e4754f2-c195-465d-a6e2-68622136fcf4",
  "sku": {
    "name": "Standard",
    "tier": "Regional"
  },
  "tags": {},
  "type": "Microsoft.Network/publicIPAddresses",
  "zones": [
    "3",
    "1",
    "2"
  ]
}
```

コマンドでパブリックIPアドレスを確認する
```bash
az network public-ip show \
    --name pip-dev-japaneast-001 \
    --resource-group rg-xxxx-xxxx-001
```
出力結果
```bash
{
  "ddosSettings": {
    "protectionMode": "VirtualNetworkInherited"
  },
  "dnsSettings": {
    "domainNameLabel": "dev-web-20250113-qoo",
    "fqdn": "dev-web-20250113-qoo.japaneast.cloudapp.azure.com"
  },
  "etag": "W/\"7dd837ee-574c-4f1b-ad39-cb054e470ebd\"",
  "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/publicIPAddresses/pip-dev-japaneast-001",
  "idleTimeoutInMinutes": 4,
  "ipAddress": "48.218.127.120",
  "ipTags": [],
  "location": "japaneast",
  "name": "pip-dev-japaneast-001",
  "provisioningState": "Succeeded",
  "publicIPAddressVersion": "IPv4",
  "publicIPAllocationMethod": "Static",
  "resourceGroup": "rg-xxxx-xxxx-001",
  "resourceGuid": "8e4754f2-c195-465d-a6e2-68622136fcf4",
  "sku": {
    "name": "Standard",
    "tier": "Regional"
  },
  "tags": {},
  "type": "Microsoft.Network/publicIPAddresses",
  "zones": [
    "3",
    "1",
    "2"
  ]
}
```

削除する
```bash
# az network public-ip delete \
    --name pip-dev-japaneast-001 \
    --resource-group rg-xxxx-xxxx-001
```

削除されたか確認する
```bash
az network public-ip show \
    --name pip-dev-japaneast-001 \
    --resource-group rg-xxxx-xxxx-001
```
what-ifで差分確認をする
```bash
# az deployment group what-if   --resource-group rg-xxxx-xxxx-001   --template-file main.json   --parameters dev.parameters.json
Note: The result may contain false positive predictions (noise).
You can help us improve the accuracy of the result by opening an issue here: https://aka.ms/WhatIfIssues

Resource and property changes are indicated with these symbols:
  + Create
  = Nochange
  x Noeffect

The deployment will update the following scope:

Scope: /subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001

  + Microsoft.Network/publicIPAddresses/pip-dev-japaneast-001 [2024-01-01]

      apiVersion:                             "2024-01-01"
      id:                                     "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/publicIPAddresses/pip-dev-japaneast-001"
      location:                               "japaneast"
      name:                                   "pip-dev-japaneast-001"
      properties.ddosSettings.protectionMode: "VirtualNetworkInherited"
      properties.dnsSettings.domainNameLabel: "dev-web-20250113-qoo"
      properties.idleTimeoutInMinutes:        4
      properties.publicIPAddressVersion:      "IPv4"
      properties.publicIPAllocationMethod:    "Static"
      sku.name:                               "Standard"
      sku.tier:                               "Regional"
      type:                                   "Microsoft.Network/publicIPAddresses"
      zones: [
        0: "3"
        1: "1"
        2: "2"
      ]

  = Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001 [2024-01-01]
    x properties.subnets[0].type: "Microsoft.Network/virtualNetworks/subnets"

  = Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001/subnets/snet-dev-japaneast-001 [2024-01-01]

Resource changes: 1 to create, 2 no change.
```

デプロイする
```bash
# az deployment group create \
  --resource-group rg-xxxx-xxxx-001 \
  --template-file main.json \
  --parameters dev.parameters.json \
  --mode Incremental
{
  "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Resources/deployments/main",
  "location": null,
  "name": "main",
  "properties": {
    "correlationId": "e124d31a-a65b-4b11-9160-b695afd66d4b",
    "debugSetting": null,
    "dependencies": [
      {
        "dependsOn": [
          {
            "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001",      
            "resourceGroup": "rg-xxxx-xxxx-001",
            "resourceName": "vnet-dev-japaneast-001",
            "resourceType": "Microsoft.Network/virtualNetworks"
          }
        ],
        "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001/subnets/snet-dev-japaneast-001",
        "resourceGroup": "rg-xxxx-xxxx-001",
        "resourceName": "vnet-dev-japaneast-001/snet-dev-japaneast-001",
        "resourceType": "Microsoft.Network/virtualNetworks/subnets"
      }
    ],
    "duration": "PT6.7255764S",
    "error": null,
    "mode": "Incremental",
    "onErrorDeployment": null,
    "outputResources": [
      {
        "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/publicIPAddresses/pip-dev-japaneast-001",
        "resourceGroup": "rg-xxxx-xxxx-001"
      },
      {
        "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001",
        "resourceGroup": "rg-xxxx-xxxx-001"
      },
      {
        "id": "/subscriptions/xxxx/resourceGroups/rg-xxxx-xxxx-001/providers/Microsoft.Network/virtualNetworks/vnet-dev-japaneast-001/subnets/snet-dev-japaneast-001",
        "resourceGroup": "rg-xxxx-xxxx-001"
      }
    ],
    "outputs": null,
    "parameters": {
      "location": {
        "type": "String",
        "value": "japaneast"
      },
      "pipName": {
        "type": "String",
        "value": "pip-dev-japaneast-001"
      },
      "snetAddressPrefix": {
        "type": "String",
        "value": "10.0.0.0/24"
      },
      "snetName": {
        "type": "String",
        "value": "snet-dev-japaneast-001"
      },
      "vnetName": {
        "type": "String",
        "value": "vnet-dev-japaneast-001"
      }
    },
    "parametersLink": null,
    "providers": [
      {
        "id": null,
        "namespace": "Microsoft.Network",
        "providerAuthorizationConsentState": null,
        "registrationPolicy": null,
        "registrationState": null,
        "resourceTypes": [
          {
            "aliases": null,
            "apiProfiles": null,
            "apiVersions": null,
            "capabilities": null,
            "defaultApiVersion": null,
            "locationMappings": null,
            "locations": [
              "japaneast"
            ],
            "properties": null,
            "resourceType": "virtualNetworks",
            "zoneMappings": null
          },
          {
            "aliases": null,
            "apiProfiles": null,
            "apiVersions": null,
            "capabilities": null,
            "defaultApiVersion": null,
            "locationMappings": null,
            "locations": [
              null
            ],
            "properties": null,
            "resourceType": "virtualNetworks/subnets",
            "zoneMappings": null
          },
          {
            "aliases": null,
            "apiProfiles": null,
            "apiVersions": null,
            "capabilities": null,
            "defaultApiVersion": null,
            "locationMappings": null,
            "locations": [
              "japaneast"
            ],
            "properties": null,
            "resourceType": "publicIPAddresses",
            "zoneMappings": null
          }
        ]
      }
    ],
    "provisioningState": "Succeeded",
    "templateHash": "2140139128441717049",
    "templateLink": null,
    "timestamp": "2025-01-13T21:08:04.225152+00:00",
    "validatedResources": null
  },
  "resourceGroup": "rg-xxxx-xxxx-001",
  "tags": null,
  "type": "Microsoft.Resources/deployments"
}
```

```bash
# az resource list -o table -g rg-infra-dev-001
Name                    ResourceGroup     Location    Type                                 Status
----------------------  ----------------  ----------  -----------------------------------  --------
vnet-dev-japaneast-001  rg-infra-dev-001  japaneast   Microsoft.Network/virtualNetworks
pip-dev-japaneast-001   rg-infra-dev-001  japaneast   Microsoft.Network/publicIPAddresses
```
所感
--
・AWSのパブリックIPの設定と比較して、詳細な設定項目があって驚いた
・資格勉強やWebサイト作りたくて、html/cssを始めたが、Bootstrapの使い勝手良すぎてどこまで掘るべきかわからなくなった
・Zone冗長構成にして可用性を高めたけど、料金が気になった。。個人サイトなら不要な気もする

以上

https://learn.microsoft.com/ja-jp/azure/virtual-network/ip-services/public-ip-addresses#at-a-glance

https://learn.microsoft.com/ja-jp/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations

https://learn.microsoft.com/ja-jp/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming

https://learn.microsoft.com/ja-jp/azure/reliability/availability-zones-region-support