演習 - Bicep ファイルをリファクタリングする

完了

前の演習では、おもちゃのトラックの仮想マシンと関連リソースを含む最初の Bicep ファイルを作成しました。 しかし、その Bicep テンプレートはベスト プラクティスに従っていないので、少し読みにくくなっています。 このユニットでは、ファイルをリファクタリングします。

リファクタリング プロセスでは、次のことを行います。

  • リソースとパラメーターのシンボリック名を更新する。
  • 重複するパラメーター、リソース、およびプロパティを削除する。
  • 変数とパラメーターを使用して、Bicep ファイルを再利用できるようにする。

リソースのシンボリック名を更新する

  1. Visual Studio Code で main.bicep ファイルを開きます。

  2. ネットワーク セキュリティ グループ リソースのシンボリック名を選択します。これは、networkSecurityGroups_ToyTruckServer_nsg_name_resource のような名前です。

    シンボリック名を変更します。 F2 キーを押すか、右クリックして [シンボルの名前変更] を選択できます。

    networkSecurityGroup という名前を入力して Enter キーを押します。 Visual Studio Code によって、ファイルのすべての参照と名前が更新されます。

  3. 各リソースに対してこの手順を繰り返します。 次の表のようにリソースの名前を変更します。

    Note

    実際のデプロイでのリソースの名前は、表の名前とは若干異なります。 これらの名前に近い名前のリソースを見つけてください。

    リソースの種類 現在のシンボリック名 新しいシンボリック名
    パブリック IP アドレス publicIPAddresses_ToyTruckServer_ip_name_resource publicIPAddress
    仮想マシン virtualMachines_ToyTruckServer_name_resource virtualMachine
    仮想ネットワーク virtualNetworks_ToyTruck_vnet_name_resource virtualNetwork
    Subnet virtualNetworks_ToyTruck_vnet_name_default defaultSubnet
    ネットワーク インターフェイス networkInterfaces_toytruckserver890_name_resource networkInterface

重複するサブネット リソースを削除する

現在、仮想ネットワークのサブネットは 2 回定義されています。 virtualNetwork リソースで 1 回定義され、defaultSubnet という名前のその子リソースでもう 1 回定義されています。 サブネットを 2 回定義しても意味はありません。

  1. defaultSubnet リソースを削除します。

    現在、networkInterface リソースに問題が表示されていることに注意してください。これは、既定のサブネットのリソース ID を参照しているためです。

    Screenshot of Visual Studio Code that shows the network interface resource definition. The error is highlighted.

  2. サブネットへの existing 参照を含むように、virtualNetwork リソースを更新します。 existing 参照を追加することで、Bicep コード内のサブネットを再定義せずに、もう一度参照できます。

    resource virtualNetwork 'Microsoft.Network/virtualNetworks@2020-11-01' = {
      name: virtualNetworks_ToyTruck_vnet_name
      location: 'westus'
      properties: {
        addressSpace: {
          addressPrefixes: [
            '10.0.0.0/16'
          ]
        }
        subnets: [
          {
            name: 'default'
            properties: {
              addressPrefix: '10.0.0.0/24'
              delegations: []
              privateEndpointNetworkPolicies: 'Enabled'
              privateLinkServiceNetworkPolicies: 'Enabled'
            }
          }
        ]
        virtualNetworkPeerings: []
        enableDdosProtection: false
      }
    
      resource defaultSubnet 'subnets' existing = {
        name: 'default'
      }
    }
    
  3. サブネットのリソース ID を参照するように networkInterface リソースを更新します。

    resource networkInterface 'Microsoft.Network/networkInterfaces@2022-05-01' = {
      name: networkInterfaces_toytruckserver890_name
      location: 'westus3'
      properties: {
        ipConfigurations: [
          {
            name: 'ipconfig1'
            properties: {
              privateIPAddress: '10.0.0.4'
              privateIPAllocationMethod: 'Dynamic'
              publicIPAddress: {
                id: publicIPAddress.id
              }
              subnet: {
                id: virtualNetwork::defaultSubnet.id
              }
              primary: true
              privateIPAddressVersion: 'IPv4'
            }
          }
        ]
        dnsSettings: {
          dnsServers: []
        }
        enableAcceleratedNetworking: true
        enableIPForwarding: false
        disableTcpStateTracking: false
        networkSecurityGroup: {
          id: networkSecurityGroup.id
        }
        nicType: 'Standard'
      }
    }
    

    式がサイクルに含まれているというエラーが表示されます。 次のステップではこれを修正します。

  4. virtualNetwork リソースの subnets プロパティに移動し、id: defaultSubnet.id を削除してエラーを解決します。

パラメーターを変数に変更する

テンプレートのパラメーターは、パラメーターである必要はありません。 次に、パラメーターの名前をよりわかりやすい名前に変更し、変数に変換します。

  1. virtualNetworks_ToyTruck_vnet_name パラメーターのシンボリック名を選択します。 名前を virtualNetworkName に変更します。

  2. パラメーターを変数に変更します。 変数の定義に型が含まれていないため、型を削除することを忘れないでください。

    var virtualNetworkName = 'ToyTruck-vnet'
    
  3. パラメーターごとにプロセスを繰り返します。 次の表のようにパラメーターの名前を変更します。

    networkInterfaceName の値に 3 桁の数値が含まれていることに注目してください。 数値はデプロイごとに異なります。 必ず、参照テンプレートから変数の値をコピーしてください。

    現在のパラメーター名 新しい変数名
    virtualMachines_ToyTruckServer_name virtualMachineName
    networkInterfaces_toytruckserver890_name networkInterfaceName
    publicIPAddresses_ToyTruckServer_ip_name publicIPAddressName
    networkSecurityGroups_ToyTruckServer_nsg_name networkSecurityGroupName
  4. 変数宣言が次の例のようになっていることを確認します。

    var virtualNetworkName = 'ToyTruck-vnet'
    var virtualMachineName = 'ToyTruckServer'
    var networkInterfaceName = 'YOUR-NETWORK-INTERFACE-NAME'
    var publicIPAddressName = 'ToyTruckServer-ip'
    var networkSecurityGroupName = 'ToyTruckServer-nsg'
    

リソースの場所を更新する

現在、すべてのリソースでハードコーディングされた場所が使用されています。 ここでパラメーターを追加して、テンプレートをより再利用しやすくします。

  1. ファイルの先頭に、新しいパラメーターと説明のデコレーターを追加して、パラメーターの目的を明確にします。

    @description('The location where resources are deployed.')
    param location string = resourceGroup().location
    
  2. 各リソースを更新し、ハードコーディングされた westus3 の場所ではなく、location パラメーターを使用するようにします。

パラメーターと変数の追加

テンプレートには、パラメーターまたは変数がより適切になるハードコーディングされた値がいくつかあります。 次に、デプロイ間で変わる可能性のあるプロパティのパラメーターと、そうならない値の変数を追加します。

  1. main.bicep ファイルの先頭の location パラメーターの下に、次のパラメーターを追加します。

    @description('The name of the size of the virtual machine to deploy.')
    param virtualMachineSizeName string = 'Standard_D2s_v3'
    
    @description('The name of the storage account SKU to use for the virtual machine\'s managed disk.')
    param virtualMachineManagedDiskStorageAccountType string = 'Premium_LRS'
    
    @description('The administrator username for the virtual machine.')
    param virtualMachineAdminUsername string = 'toytruckadmin'
    
    @description('The administrator password for the virtual machine.')
    @secure()
    param virtualMachineAdminPassword string
    
    @description('The name of the SKU of the public IP address to deploy.')
    param publicIPAddressSkuName string = 'Standard'
    
    @description('The virtual network address range.')
    param virtualNetworkAddressPrefix string
    
    @description('The default subnet address range within the virtual network')
    param virtualNetworkDefaultSubnetAddressPrefix string
    

    パラメーターには、既定値が設定されているものと、いないものがあります。 後で、パラメーター ファイルを作成して、これらの値のほとんどを設定します。

  2. networkSecurityGroupName 変数の下に、次の新しい変数宣言を追加します。

    var virtualNetworkDefaultSubnetName = 'default'
    var virtualMachineImageReference = {
      publisher: 'canonical'
      offer: '0001-com-ubuntu-server-focal'
      sku: '20_04-lts-gen2'
      version: 'latest'
    }
    
  3. 次の変数宣言を追加します。 この値を、自分の参照テンプレートの OS ディスク名に置き換えます。

    var virtualMachineOSDiskName = 'YOUR-OS-DISK-NAME'
    

    virtualMachineOSDiskName の値が一意です。 値はデプロイごとに異なります。 必ず、参照テンプレートから変数の値をコピーしてください。

    警告

    必ず、virtualMachineOSDiskNamenetworkInterfaceName 変数に正しい値をコピーしてください。 そうしないと、既存のリソースを宣言していることが Azure によって検出されず、新しいリソースの作成が試みられる可能性があります。

    現在、変数宣言は次の例のようになっているはずです。

    var virtualNetworkName = 'ToyTruck-vnet'
    var virtualMachineName = 'ToyTruckServer'
    var networkInterfaceName = 'YOUR-NETWORK-INTERFACE-NAME'
    var publicIPAddressName = 'ToyTruckServer-ip'
    var networkSecurityGroupName = 'ToyTruckServer-nsg'
    var virtualNetworkDefaultSubnetName = 'default'
    var virtualMachineImageReference = {
      publisher: 'canonical'
      offer: '0001-com-ubuntu-server-focal'
      sku: '20_04-lts-gen2'
      version: 'latest'
    }
    var virtualMachineOSDiskName = 'YOUR-OS-DISK-NAME'
    
  4. パラメーターを参照するように publicIPAddress リソースを更新します。

    プロパティ パラメーター
    sku.name publicIPAddressSkuName
  5. virtualMachine リソースを更新し、パラメーターと変数を参照するようにします。

    プロパティ パラメーターまたは変数
    hardwareProfile.vmSize virtualMachineSizeName
    storageProfile.imageReference virtualMachineImageReference
    変数名を使って、中かっこを含むオブジェクトの値を置き換えます。
    storageProfile.osDisk.name virtualMachineOSDiskName
    storageProfile.osDisk.managedDisk.storageAccountType virtualMachineManagedDiskStorageAccountType
    osProfile.adminUsername virtualMachineAdminUsername
    osProfile.adminPassword
    osProfile.adminUsername の下にこのプロパティを追加します
    virtualMachineAdminPassword
  6. virtualNetwork リソースを更新し、パラメーターと変数を参照するようにします。

    プロパティ パラメーターまたは変数
    addressSpace.addressPrefixes virtualNetworkAddressPrefix
    subnets.name virtualNetworkDefaultSubnetName
    subnets.addressPrefix virtualNetworkDefaultSubnetAddressPrefix
  7. virtualNetwork リソースの入れ子になったリソース defaultSubnet を更新します。

    プロパティ 変数
    name virtualNetworkDefaultSubnetName

不要なプロパティを削除する

エクスポート プロセスでは、多くのリソースに重複するプロパティが追加されます。 次の手順のようにして、不要なプロパティを削除します。

  1. networkSecurityGroup リソースでは、securityRules プロパティが空なので properties を削除します。

  2. publicIPAddress リソースでは、次のプロパティを削除します。

    • Azure によって自動的に設定されるため、ipAddress プロパティ
    • 空であるため、ipTags プロパティ
  3. virtualMachine リソースでは、次のプロパティを削除します。

    • 仮想マシンのデプロイ時に Azure によって自動的に決定されるため、storageProfile.osDisk.managedDisk.id プロパティ

      重要

      このプロパティを削除しないと、テンプレートは正しくデプロイされません。

    • 空であるため、storageProfile.dataDisks プロパティ

    • 空であるため、osProfile.secrets プロパティ

    • Azure によって自動的に設定されるため、osProfile.requireGuestProvisionSignal プロパティ

  4. virtualNetwork リソースでは、次のプロパティを削除します。

    • 空であるため、delegationsvirtualNetworkPeerings プロパティ。
    • type: 'Microsoft.Network/virtualNetworks/subnets' の行
  5. networkInterface リソースでは、次のプロパティを削除します。

    • kind プロパティ

    • ipConfigurations から idetagtypeprivateIPAddress。これは Azure によって自動的に設定され、割り当て方法が Dynamic であるため

    • ipConfigurations.properties から:

      • provisioningState
    • publicIPAddress から namepropertiestypesku

    • dnsServers プロパティが空であるため、dnsSettings

ヒント

独自のテンプレートで作業する場合は、ここで行ったように、削除する必要があるプロパティがあるかどうかを判断する必要があります。

Visual Studio Code では、リソースの最小プロパティを設定するのに Bicep 拡張機能が役立ちます。 リソース定義の等号の後にスペースを追加すると、Visual Studio Code では、必須プロパティを選ぶよう求められます。

Screenshot of Visual Studio Code that shows the required-properties option.

required-properties を選択すると、Visual Studio Code によってリソース定義に必須のプロパティが設定されます。 required-properties を参照して、変換後のテンプレートのプロパティがすべて存在する必要があるかどうかを判断できます。

このタスクには Azure クイック スタート テンプレート リポジトリも役立ちます。 実行しようとしていることとほぼ同じことを行うクイックスタート テンプレートを見つけて、リソースに設定されたプロパティを確認します。

パラメーター ファイルを作成する

テンプレート内のパラメーターは、現在、既定値として定義されています。 テンプレートが環境全体で適切に機能するように、パラメーター ファイルを作成し、各環境で変更する必要があるパラメーターの既定値を削除することをお勧めします。

  1. main.parameters.production.json という名前の新しいファイルを作成します。

  2. 次の JSON を、main.parameters.production.json ファイルに貼り付けます。

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "virtualMachineSizeName": {
          "value": "Standard_D2s_v3"
        },
        "virtualMachineManagedDiskStorageAccountType": {
            "value": "Premium_LRS"
        },
        "virtualMachineAdminUsername": {
            "value": "toytruckadmin"
        },
        "virtualNetworkAddressPrefix": {
            "value": "YOUR-VIRTUAL-NETWORK-ADDRESS-PREFIX"
        },
        "virtualNetworkDefaultSubnetAddressPrefix": {
            "value": "YOUR-SUBNET-ADDRESS-PREFIX"
        }
      }
    }
    
  3. 参照テンプレートの仮想ネットワーク リソースで指定されている IP アドレスの範囲に一致するように、virtualNetworkAddressPrefix および virtualNetworkDefaultSubnetAddressPrefix パラメーターの値を更新します。

    たとえば、参照テンプレートでは次のように値が指定されます。 実際の IP アドレスは、この例で使用されている IP アドレスと異なる場合があります。

    resource virtualNetworks_ToyTruck_vnet_name_resource 'Microsoft.Network/virtualNetworks@2022-05-01' = {
      name: virtualNetworks_ToyTruck_vnet_name
      location: 'westus3'
      properties: {
        addressSpace: {
          addressPrefixes: [
            '10.0.0.0/16'
          ]
        }
        subnets: [
          {
            name: 'default'
            id: virtualNetworks_ToyTruck_vnet_name_default.id
            properties: {
              addressPrefix: '10.0.0.0/24'
              delegations: []
              privateEndpointNetworkPolicies: 'Disabled'
              privateLinkServiceNetworkPolicies: 'Enabled'
            }
            type: 'Microsoft.Network/virtualNetworks/subnets'
          }
        ]
        virtualNetworkPeerings: []
        enableDdosProtection: false
      }
    }
    
  4. main.bicep ファイルを更新し、パラメーター ファイルで指定したパラメーターの既定値を削除するようにします。

    • virtualMachineSizeName
    • virtualMachineManagedDiskStorageAccountType
    • virtualMachineAdminUsername

location パラメーターと publicIPAddressSkuName パラメーターの既定値は変更しないでください。これらの値はすべての環境で同じである可能性があります。

テンプレートを確認する

  1. リファクタリング フェーズの最後に、main.bicep ファイルは次の例のようになるはずです。

    @description('The location where resources are deployed.')
    param location string = resourceGroup().location
    
    @description('The name of the size of the virtual machine to deploy.')
    param virtualMachineSizeName string
    
    @description('The name of the storage account SKU to use for the virtual machine\'s managed disk.')
    param virtualMachineManagedDiskStorageAccountType string
    
    @description('The administrator username for the virtual machine.')
    param virtualMachineAdminUsername string
    
    @description('The administrator password for the virtual machine.')
    @secure()
    param virtualMachineAdminPassword string
    
    @description('The name of the SKU of the public IP address to deploy.')
    param publicIPAddressSkuName string = 'Standard'
    
    @description('The virtual network address range.')
    param virtualNetworkAddressPrefix string
    
    @description('The default subnet address range within the virtual network')
    param virtualNetworkDefaultSubnetAddressPrefix string
    
    var virtualNetworkName = 'ToyTruck-vnet'
    var virtualMachineName = 'ToyTruckServer'
    var networkInterfaceName = 'YOUR-NETWORK-INTERFACE-NAME'
    var publicIPAddressName = 'ToyTruckServer-ip'
    var networkSecurityGroupName = 'ToyTruckServer-nsg'
    var virtualNetworkDefaultSubnetName = 'default'
    var virtualMachineImageReference = {
      publisher: 'canonical'
      offer: '0001-com-ubuntu-server-focal'
      sku: '20_04-lts-gen2'
      version: 'latest'
    }
    var virtualMachineOSDiskName = 'YOUR-OS-DISK-NAME'
    
    resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2022-05-01' = {
      name: networkSecurityGroupName
      location: location
    }
    
    resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2022-05-01' = {
      name: publicIPAddressName
      location: location
      sku: {
        name: publicIPAddressSkuName
        tier: 'Regional'
      }
      properties: {
        publicIPAddressVersion: 'IPv4'
        publicIPAllocationMethod: 'Static'
        idleTimeoutInMinutes: 4
      }
    }
    
    resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-08-01' = {
      name: virtualMachineName
      location: location
      properties: {
        hardwareProfile: {
          vmSize: virtualMachineSizeName
        }
        storageProfile: {
          imageReference: virtualMachineImageReference
          osDisk: {
            osType: 'Linux'
            name: virtualMachineOSDiskName
            createOption: 'FromImage'
            caching: 'ReadWrite'
            managedDisk: {
              storageAccountType: virtualMachineManagedDiskStorageAccountType
            }
            deleteOption: 'Delete'
            diskSizeGB: 30
          }
        }
        osProfile: {
          computerName: virtualMachineName
          adminUsername: virtualMachineAdminUsername
          adminPassword: virtualMachineAdminPassword
          linuxConfiguration: {
            disablePasswordAuthentication: false
            provisionVMAgent: true
            patchSettings: {
              patchMode: 'ImageDefault'
              assessmentMode: 'ImageDefault'
            }
            enableVMAgentPlatformUpdates: false
          }
          allowExtensionOperations: true
        }
        networkProfile: {
          networkInterfaces: [
            {
              id: networkInterface.id
              properties: {
                deleteOption: 'Detach'
              }
            }
          ]
        }
        diagnosticsProfile: {
          bootDiagnostics: {
            enabled: true
          }
        }
      }
    }
    
    resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-05-01' = {
      name: virtualNetworkName
      location: location
      properties: {
        addressSpace: {
          addressPrefixes: [
            virtualNetworkAddressPrefix
          ]
        }
        subnets: [
          {
            name: virtualNetworkDefaultSubnetName
            properties: {
              addressPrefix: virtualNetworkDefaultSubnetAddressPrefix
              privateEndpointNetworkPolicies: 'Disabled'
              privateLinkServiceNetworkPolicies: 'Enabled'
            }
          }
        ]
        enableDdosProtection: false
      }
    
      resource defaultSubnet 'subnets' existing = {
        name: virtualNetworkDefaultSubnetName
      }
    }
    
    resource networkInterface 'Microsoft.Network/networkInterfaces@2022-05-01' = {
      name: networkInterfaceName
      location: location
      properties: {
        ipConfigurations: [
          {
            name: 'ipconfig1'
            properties: {
              privateIPAllocationMethod: 'Dynamic'
              publicIPAddress: {
                id: publicIPAddress.id
              }
              subnet: {
                id: virtualNetwork::defaultSubnet.id
              }
              primary: true
              privateIPAddressVersion: 'IPv4'
            }
          }
        ]
        enableAcceleratedNetworking: true
        enableIPForwarding: false
        disableTcpStateTracking: false
        networkSecurityGroup: {
          id: networkSecurityGroup.id
        }
        nicType: 'Standard'
      }
    }
    

    main.parameters.production.json ファイルは次のファイルのようになるはずです。ただし、別の IP アドレス範囲が一覧表示される可能性があります。

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "virtualMachineSizeName": {
          "value": "Standard_D2s_v3"
        },
        "virtualMachineManagedDiskStorageAccountType": {
            "value": "Premium_LRS"
        },
        "virtualMachineAdminUsername": {
            "value": "toytruckadmin"
        },
        "virtualNetworkAddressPrefix": {
            "value": "10.0.0.0/16"
        },
        "virtualNetworkDefaultSubnetAddressPrefix": {
            "value": "10.0.0.0/24"
        }
      }
    }
    
  2. [表示]>[問題] を選択して、問題ペインを表示します。

    何も問題は示されません。

ヒント

独自のテンプレートで作業を行う場合は、パラメーター化するプロパティとその他のカスタマイズについて、さまざまな選択を行うことができます。 このモジュールを通して、作業を開始するのに役立つ一般的なガイダンスが提供されますが、独自の Bicep ファイルをリファクタリングする方法を決定するときに、独自の環境と、テンプレートを再利用する方法について検討する必要があります。