Exercício – Refatorar o arquivo Bicep

Concluído

No exercício anterior, você criou um arquivo Bicep inicial contendo a máquina virtual do caminhão de brinquedo e os recursos associados. No entanto, o modelo Bicep não segue as melhores práticas e é um pouco difícil de ser lido. Nesta unidade, você vai refatorar o arquivo.

Durante o processo de refatoração, você vai:

  • Atualizar os nomes simbólicos de recursos e parâmetros.
  • Remover parâmetros, recursos e propriedades redundantes.
  • Adicionar variáveis e parâmetros para tornar o arquivo Bicep reutilizável.

Atualizar os nomes simbólicos de recursos

  1. No Visual Studio Code, abra o arquivo main.bicep.

  2. Selecionar o nome simbólico do recurso de grupo de segurança de rede, que é networkSecurityGroups_ToyTruckServer_nsg_name_resource ou um nome semelhante.

    Altere o nome simbólico. Você pode pressionar F2 ou clicar com o botão direito do mouse e selecionar Renomear Símbolo.

    Insira o nome networkSecurityGroup e pressione ENTER. O Visual Studio Code atualiza o nome e todas as referências no arquivo.

  3. Repita esse processo para cada recurso. Renomeie os recursos como mostrado na tabela a seguir.

    Observação

    Os nomes dos recursos na implantação serão um pouco diferentes dos descritos na tabela. Encontre os recursos que têm nomes parecidos com esses nomes.

    Tipo de recurso Nome simbólico atual Novo nome simbólico
    Endereço IP público publicIPAddresses_ToyTruckServer_ip_name_resource publicIPAddress
    Máquina virtual virtualMachines_ToyTruckServer_name_resource virtualMachine
    Rede virtual virtualNetworks_ToyTruck_vnet_name_resource virtualNetwork
    Sub-rede virtualNetworks_ToyTruck_vnet_name_default defaultSubnet
    Adaptador de rede networkInterfaces_toytruckserver890_name_resource networkInterface

Remover o recurso de sub-rede redundante

A sub-rede da rede virtual está definida duas vezes no momento. Ela está definida uma vez no recurso virtualNetwork e novamente como o próprio recurso filho chamado defaultSubnet. Não faz sentido defini-la duas vezes.

  1. Exclua o recurso defaultSubnet.

    Observe que o recurso networkInterface agora exibe um problema, porque ele se refere à ID do recurso da sub-rede padrão:

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

  2. Atualize o recurso virtualNetwork para incluir uma referência existing à sub-rede. Se você adicionar a referência existing, poderá referenciar a sub-rede novamente dentro do código Bicep sem defini-la de novo:

    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. Atualize o recurso networkInterface para se referir à ID do recurso da sub-rede:

    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'
      }
    }
    

    Você observará um erro sobre se a expressão está envolvida em um ciclo. Você corrigirá isso na próxima etapa.

  4. Vá para a propriedade subnets do recurso virtualNetwork e remova id: defaultSubnet.id para resolver o erro.

Alterar os parâmetros para variáveis

Os parâmetros no modelo não precisam ser parâmetros. Você agora renomeará os parâmetros para nomes mais significativos e os converterá em variáveis.

  1. Selecione o nome simbólico do parâmetro virtualNetworks_ToyTruck_vnet_name. Renomeie-o como virtualNetworkName.

  2. Altere o parâmetro para uma variável. Lembre-se de remover o tipo, pois as definições de variável não incluem tipos:

    var virtualNetworkName = 'ToyTruck-vnet'
    
  3. Repita o processo para cada parâmetro. Renomeie os parâmetros como mostrado na tabela a seguir.

    Observe que o valor de networkInterfaceName inclui um número de três dígitos. O número é diferente para implantações diferentes. Copie o valor da variável do modelo de referência.

    Nome do parâmetro atual Novo nome da variável
    virtualMachines_ToyTruckServer_name virtualMachineName
    networkInterfaces_toytruckserver890_name networkInterfaceName
    publicIPAddresses_ToyTruckServer_ip_name publicIPAddressName
    networkSecurityGroups_ToyTruckServer_nsg_name networkSecurityGroupName
  4. Verifique se as declarações de variável são semelhantes ao seguinte exemplo:

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

Atualizar as localizações de recursos

No momento, todos os recursos usam uma localização embutida em código. Você adicionará um parâmetro para que o modelo se torne mais reutilizável.

  1. No início do arquivo, adicione um novo parâmetro e um decorador de descrição para que a finalidade dele fique clara:

    @description('The location where resources are deployed.')
    param location string = resourceGroup().location
    
  2. Atualize cada recurso para usar o parâmetro location em vez da localização westus3 embutida em código.

Adicionar parâmetros e variáveis

Seu modelo tem alguns valores embutido em código em que parâmetros ou variáveis seriam mais apropriados. Aqui, você adicionará parâmetros para propriedades que podem ser alteradas entre implantações e variáveis para valores que não serão alterados.

  1. No início do arquivo main.bicep, abaixo do parâmetro location, adicione os seguintes parâmetros:

    @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
    

    Alguns dos parâmetros têm valores padrão e outros não. Posteriormente, você criará um arquivo de parâmetro para definir a maioria desses valores.

  2. Sob a variável networkSecurityGroupName, adicione as seguintes novas declarações de variável:

    var virtualNetworkDefaultSubnetName = 'default'
    var virtualMachineImageReference = {
      publisher: 'canonical'
      offer: '0001-com-ubuntu-server-focal'
      sku: '20_04-lts-gen2'
      version: 'latest'
    }
    
  3. Adicione a declaração de variável a seguir. Substitua o valor pelo nome do disco de SO do seu modelo de referência.

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

    O valor de virtualMachineOSDiskName é exclusivo. O valor é diferente para cada implantação. Copie o valor da variável do modelo de referência.

    Aviso

    Copie corretamente os valores das variáveis virtualMachineOSDiskName e networkInterfaceName. Caso contrário, o Azure não entenderá que você está declarando recursos que já existem e poderá tentar criar outros recursos.

    Agora, as declarações de variável serão semelhantes a este exemplo:

    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. Atualize o recurso publicIPAddress para fazer referência a um parâmetro:

    Propriedade Parâmetro
    sku.name publicIPAddressSkuName
  5. Atualize o recurso virtualMachine para se referir aos parâmetros e às variáveis:

    Propriedade Variável ou parâmetro
    hardwareProfile.vmSize virtualMachineSizeName
    storageProfile.imageReference virtualMachineImageReference
    Use o nome da variável para substituir os valores do objeto, incluindo as chaves.
    storageProfile.osDisk.name virtualMachineOSDiskName
    storageProfile.osDisk.managedDisk.storageAccountType virtualMachineManagedDiskStorageAccountType
    osProfile.adminUsername virtualMachineAdminUsername
    osProfile.adminPassword
    Adicione esta propriedade abaixo de osProfile.adminUsername
    virtualMachineAdminPassword
  6. Atualize o recurso virtualNetwork para se referir aos parâmetros e às variáveis:

    Propriedade Variável ou parâmetro
    addressSpace.addressPrefixes virtualNetworkAddressPrefix
    subnets.name virtualNetworkDefaultSubnetName
    subnets.addressPrefix virtualNetworkDefaultSubnetAddressPrefix
  7. Atualize o recurso aninhado defaultSubnet do recurso virtualNetwork:

    Propriedade Variável
    name virtualNetworkDefaultSubnetName

Remover as propriedades desnecessárias

O processo de exportação adiciona propriedades redundantes a muitos recursos. Use estas etapas para remover as propriedades desnecessárias.

  1. No recurso networkSecurityGroup, remova properties porque a propriedade securityRules está vazia.

  2. No recurso publicIPAddress, remova as seguintes propriedades:

    • A propriedade ipAddress, pois ela é definida automaticamente pelo Azure
    • A propriedade ipTags, pois ela está vazia
  3. No recurso virtualMachine, remova as seguintes propriedades:

    • A propriedade storageProfile.osDisk.managedDisk.id, pois ela é determinada automaticamente pelo Azure quando a máquina virtual é implantada

      Importante

      Se você não remover essa propriedade, seu modelo não será implantado corretamente.

    • A propriedade storageProfile.dataDisks, pois ela está vazia

    • A propriedade osProfile.secrets, pois ela está vazia

    • A propriedade osProfile.requireGuestProvisionSignal, pois ela é definida automaticamente pelo Azure

  4. No recurso virtualNetwork, remova as seguintes propriedades:

    • As propriedades delegations e virtualNetworkPeerings, porque elas estão vazias.
    • A linha para type: 'Microsoft.Network/virtualNetworks/subnets'
  5. No recurso networkInterface, remova as seguintes propriedades:

    • A propriedade kind

    • De ipConfigurations: id, etag, type e privateIPAddress, pois ela é definida automaticamente pelo Azure e o método de alocação é Dinâmico

    • De ipConfigurations.properties:

      • provisioningState
    • De publicIPAddress, name, properties, type e sku

    • dnsSettings porque a propriedade dnsServers está vazia

Dica

Ao trabalhar com modelos próprios, você precisará determinar se há propriedades que devem ser removidas como você fez aqui.

No Visual Studio Code, a extensão Bicep ajuda você a definir as propriedades mínimas de um recurso. Quando você adiciona um espaço após o sinal de igual na definição de recurso, o Visual Studio Code solicita que você selecione required-properties:

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

Quando você seleciona required-properties, o Visual Studio Code preenche a definição de recurso com as propriedades obrigatórias. Você pode consultar required-properties para determinar se todas as propriedades no modelo convertido precisam estar presentes.

O repositório de modelos de início rápido do Azure é útil para essa tarefa. Encontre um modelo de início rápido que faça algo semelhante ao que você está tentando fazer e veja as propriedades que ele define no recurso.

Criar um arquivo de parâmetro

Seus parâmetros estão atualmente definidos como valores padrão no modelo. Para fazer com que o modelo funcione bem em vários ambientes, é uma boa ideia criar um arquivo de parâmetro e remover os valores padrão de parâmetros que precisam ser alterados para cada ambiente.

  1. Crie um arquivo chamado main.parameters.production.json.

  2. Cole o seguinte JSON no arquivo 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. Atualize os valores dos parâmetros virtualNetworkAddressPrefix e virtualNetworkDefaultSubnetAddressPrefix para que correspondam aos intervalos de endereços IP especificados no recurso de rede virtual do modelo de referência.

    Por exemplo, veja como os valores são especificados em um modelo de referência. Seus endereços IP podem ser diferentes dos endereços IP usados neste exemplo.

    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. Atualize o arquivo main.bicep para remover os valores padrão dos parâmetros especificados no arquivo de parâmetros.

    • virtualMachineSizeName
    • virtualMachineManagedDiskStorageAccountType
    • virtualMachineAdminUsername

Mantenha os valores padrão para os parâmetros location e publicIPAddressSkuName, pois eles provavelmente são os mesmos para todos os ambientes.

Verificar o modelo

  1. No final da fase de refatoração, o arquivo main.bicep será semelhante ao seguinte exemplo:

    @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'
      }
    }
    

    O arquivo main.parameters.production.json deve ser semelhante ao seguinte arquivo, embora possa haver intervalos de endereços IP diferentes listados:

    {
      "$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. Selecione Exibir>Problemas para exibir o painel de problemas.

    Nenhum problema foi indicado.

Dica

Ao trabalhar com modelos próprios, você pode fazer escolhas diferentes sobre as propriedades a serem parametrizadas e outras personalizações. Ao longo deste módulo, forneceremos diretrizes gerais para ajudar você a começar o processo, mas você precisará considerar o seu ambiente e como deseja reutilizar os modelos ao decidir como refatorar seus arquivos Bicep.