연습 - Bicep 파일 리팩터링

완료됨

이전 연습에서는 장난감 트럭 가상 머신 및 관련 리소스를 포함하는 초기 Bicep 파일을 만들었습니다. 그러나 Bicep 템플릿은 모범 사례를 따르지 않으며 읽기가 약간 어렵습니다. 이 단원에서는 파일을 리팩터링합니다.

리팩터링 프로세스 중에 다음을 수행합니다.

  • 리소스 및 매개 변수의 기호 이름을 업데이트합니다.
  • 중복되는 매개 변수, 리소스, 속성을 제거합니다.
  • Bicep 파일을 다시 사용할 수 있도록 변수와 매개 변수를 추가합니다.

리소스 기호 이름 업데이트

  1. Visual Studio Code에서 main.bicep 파일을 엽니다.

  2. 이름이 networkSecurityGroups_ToyTruckServer_nsg_name_resource거나 유사한 이름인 네트워크 보안 그룹 리소스의 기호 이름을 선택합니다.

    기호 이름을 바꿉니다. F2 키를 선택하거나 마우스 오른쪽 단추를 클릭한 다음 기호 이름 바꾸기를 선택할 있습니다.

    이름 networkSecurityGroup을 입력하고 Enter 키를 누릅니다. Visual Studio Code는 파일의 이름 및 모든 참조를 업데이트합니다.

  3. 각 리소스에 대해 이 프로세스를 반복합니다. 다음 표와 같이 리소스 이름을 바꿉니다.

    참고 항목

    배포의 리소스 이름은 표에 있는 이름과 약간 다릅니다. 이름이 유사한 리소스를 찾습니다.

    리소스 종류 현재 기호 이름 새 기호 이름
    공용 IP 주소 publicIPAddresses_ToyTruckServer_ip_name_resource publicIPAddress
    가상 머신 virtualMachines_ToyTruckServer_name_resource virtualMachine
    가상 네트워크 virtualNetworks_ToyTruck_vnet_name_resource virtualNetwork
    서브넷 virtualNetworks_ToyTruck_vnet_name_default defaultSubnet
    네트워크 인터페이스 networkInterfaces_toytruckserver890_name_resource networkInterface

중복 서브넷 리소스 제거

가상 네트워크의 서브넷은 현재 두 번 정의됩니다. 리소스에서 virtualNetwork 한 번 정의되고 다시 고유한 자식 리소스로 정의됩니다 defaultSubnet. 서브넷을 두 번 정의할 수는 없습니다.

  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의 값에는 세 자리 숫자가 포함됩니다. 배포에 따라 숫자가 다릅니다. 참조 템플릿에서 변수 값을 복사해야 합니다.

    현재 매개 변수 새 변수 이름
    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. 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. securityRules 속성이 비어 있으므로 networkSecurityGroup 리소스에서 properties를 제거합니다.

  2. 리소스에서 publicIPAddress 다음 속성을 제거합니다.

    • ipAddress 속성은 Azure에서 자동으로 설정되므로
    • ipTags 속성이 비어 있기 때문에
  3. 리소스에서 virtualMachine 다음 속성을 제거합니다.

    • storageProfile.osDisk.managedDisk.id 가상 머신이 배포될 때 Azure에서 이 속성을 자동으로 결정하기 때문에 속성

      Important

      이 속성을 제거하지 않으면 템플릿이 올바르게 배포되지 않습니다.

    • storageProfile.dataDisks 속성이 비어 있기 때문에

    • osProfile.secrets 속성이 비어 있기 때문에

    • osProfile.requireGuestProvisionSignal Azure에서 이 속성을 자동으로 설정하기 때문에 속성

  4. 리소스에서 virtualNetwork 다음 속성을 제거합니다.

    • delegationsvirtualNetworkPeerings 속성은 비어 있으므로 제거합니다.
    • 다음 줄 type: 'Microsoft.Network/virtualNetworks/subnets'
  5. 리소스에서 networkInterface 다음 속성을 제거합니다.

    • kind 속성

    • id: ipConfigurations, etag, typeprivateIPAddress Azure에서 자동으로 설정되고 할당 방법이 동적이므로

    • ipConfigurations.properties에서:

      • provisioningState
    • From publicIPAddress, name, properties, typesku

    • dnsSettings 속성이 dnsServers 비어 있기 때문에

사용자 고유의 템플릿을 사용하는 경우 여기에서와 같이 제거해야 하는 속성이 있는지 여부를 결정해야 합니다.

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을 기본.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 주소 범위와 일치하도록 virtualNetworkAddressPrefixvirtualNetworkDefaultSubnetAddressPrefix 매개 변수 값을 업데이트합니다.

    예를 들어 참조 템플릿에서 값이 지정되는 방식은 다음과 같습니다. 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. 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'
      }
    }
    

    나열되어 있는 IP 주소 범위가 다를 수 있지만 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": "10.0.0.0/16"
        },
        "virtualNetworkDefaultSubnetAddressPrefix": {
            "value": "10.0.0.0/24"
        }
      }
    }
    
  2. 보기>문제를 선택하여 문제 창을 표시합니다.

    문제가 표시되지 않습니다.

사용자 고유의 템플릿을 사용하여 작업하는 경우 매개 변수화할 속성과 기타 사용자 지정을 다르게 선택할 수 있습니다. 이 모듈 전체에서 시작하는 데 도움이 되는 일반적인 지침을 제공합니다. 그러나 자신의 Bicep 파일을 리팩터링하는 방법을 결정하려면 자신의 환경과 템플릿을 다시 사용하려는 방법을 고려해야 합니다.