Provisionar uma máquina virtual Linux usando o Bicep

Concluído

O elemento principal de um modelo Bicep é o recurso, que designa um recurso do Azure. Cada recurso contém um conjunto de propriedades genéricas e específicas do recurso. Por exemplo, o modelo usado no exemplo a seguir descreve uma rede virtual do Azure. Embora as propriedades de nome e local sejam genéricas, o addressPrefix é específico para cada recurso. A cadeia de caracteres Microsoft.Network/virtualNetworks@2021-05-01 ao lado do recurso designa a respectiva versão da API e a inserção virtualNetwork representa seu nome simbólico, que fornece uma maneira de mencionar o recurso dentro do modelo.

Além do elemento resource, o modelo de exemplo a seguir também inclui um elemento de parâmetro que permite atribuir um nome à rede virtual durante a implantação. Se você não atribuir um nome nesse momento, o valor padrão de lnx-bcp-vnet se aplicará. O elemento de descrição é um exemplo de um decorador, conforme indicado pelo caractere @ à esquerda. Sua finalidade é descrever a função do parâmetro e sua saída aparece ao lado da caixa de texto do parâmetro quando você usa o portal do Azure para examinar ou implantar o modelo de Resource Manager correspondente do Azure. Use o exemplo de código a seguir para provisionar uma VM Linux usando o Bicep:

@description('Name of the virtual network')
param virtualNetworkName string = 'lnx-bcp-vnet'

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = {
  name: virtualNetworkName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        addressPrefix
      ]
    }
  }
}

Implantar uma VM Linux usando modelos Bicep

Trabalhar com o Bicep envolve a criação e a implantação de modelos. Para simplificar e aprimorar a experiência de criação, use Visual Studio Code com a extensão Bicep. A mesma extensão também dá suporte a implantações baseadas em Bicep. Se preferir disparar uma implantação de uma linha de comando ou como parte de uma tarefa com script, você poderá instalar e usar a CLI do Bicep como um utilitário autônomo ou usá-la diretamente de dentro de uma sessão da CLI do Azure. A CLI do Azure instalará a CLI do Bicep automaticamente durante a primeira invocação de qualquer comando az bicep. No entanto, para executar uma instalação manual do Bicep, execute az bicep install.

Efetivamente, o processo de provisionamento de uma VM do Azure que executa o Linux usando o Bicep normalmente envolve a seguinte sequência de etapas de alto nível:

  • Identifique uma imagem de VM adequada.
  • Identifique o tamanho de VM adequado.
  • Crie um modelo do Bicep.
  • Inicie a implantação do modelo Bicep.

Quando você implanta modelos do Bicep, uma tarefa chamada transpilação os converte automaticamente em modelos equivalentes do Azure Resource Manager. Você também pode executar uma conversão entre os formatos Bicep e Azure Resource Manager executando os comandos bicep build e bicep decompile , respectivamente.

Para identificar a imagem e o tamanho adequados da VM, siga as etapas descritas na unidade anterior deste módulo. Esta unidade se concentra em tarefas específicas do Bicep.

Criar um modelo do Bicep

Para criar um modelo Bicep, comece iniciando uma sessão Visual Studio Code com a extensão Bicep instalada. Em seguida, crie um arquivo chamado main.bicep. Adicione o seguinte conteúdo ao arquivo e salve a alteração:

Observação

Os nomes de arquivo escolhidos para seus arquivos Bicep são arbitrários, embora seja uma boa prática escolher um nome que reflita o conteúdo ou a finalidade do arquivo, e você deve usar ".bicep" para a extensão de arquivo.

@description('The name of your virtual machine')
param vmName string = 'lnx-bcp-vm'

@description('Username for the virtual machine')
param adminUsername string

@description('Type of authentication to use on the virtual machine')
@allowed([
  'sshPublicKey'
  'password'
])
param authenticationType string = 'password'

@description('SSH Key or password for the virtual machine')
@secure()
param adminPasswordOrKey string

@description('Unique DNS Name for the Public IP used to access the virtual machine')
param dnsLabelPrefix string = toLower('${vmName}-${uniqueString(resourceGroup().id)}')

@description('The allowed Linux distribution and version for the VM')
@allowed([
  'Ubuntu-2204'
])
param ubuntuOSVersion string = 'Ubuntu-2204'

@description('Location for all resources')
param location string = resourceGroup().location

@description('The size of the VM')
param vmSize string = 'Standard_F4s'

@description('Name of the virtual network')
param virtualNetworkName string = 'lnx-bcp-vnet'

@description('Name of the subnet in the virtual network')
param subnetName string = 'subnet0'

@description('Name of the network security group')
param networkSecurityGroupName string = 'lnx-bcp-nsg'

var imageReference = {
  'Ubuntu-2204': {
    publisher: 'Canonical'
    offer: '0001-com-ubuntu-server-jammy'
    sku: '22_04-lts-gen2'
    version: 'latest'
  }
}
var publicIPAddressName = '${vmName}-pip'
var networkInterfaceName = '${vmName}-nic'
var osDiskType = 'Standard_LRS'
var subnetAddressPrefix = '10.3.0.0/24'
var addressPrefix = '10.3.0.0/16'
var linuxConfiguration = {
  disablePasswordAuthentication: true
  ssh: {
    publicKeys: [
      {
        path: '/home/${adminUsername}/.ssh/authorized_keys'
        keyData: adminPasswordOrKey
      }
    ]
  }
}

resource networkInterface 'Microsoft.Network/networkInterfaces@2021-05-01' = {
  name: networkInterfaceName
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          subnet: {
            id: subnet.id
          }
          privateIPAllocationMethod: 'Dynamic'
          publicIPAddress: {
            id: publicIPAddress.id
          }
        }
      }
    ]
    networkSecurityGroup: {
      id: networkSecurityGroup.id
    }
  }
}

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' = {
  name: networkSecurityGroupName
  location: location
  properties: {
    securityRules: [
      {
        name: 'ssh'
        properties: {
          priority: 1000
          protocol: 'Tcp'
          access: 'Allow'
          direction: 'Inbound'
          sourceAddressPrefix: '*'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '22'
        }
      }
    ]
  }
}

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = {
  name: virtualNetworkName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        addressPrefix
      ]
    }
  }
}

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-05-01' = {
  parent: virtualNetwork
  name: subnetName
  properties: {
    addressPrefix: subnetAddressPrefix
    privateEndpointNetworkPolicies: 'Enabled'
    privateLinkServiceNetworkPolicies: 'Enabled'
  }
}

resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = {
  name: publicIPAddressName
  location: location
  sku: {
    name: 'Basic'
  }
  properties: {
    publicIPAllocationMethod: 'Dynamic'
    publicIPAddressVersion: 'IPv4'
    dnsSettings: {
      domainNameLabel: dnsLabelPrefix
    }
    idleTimeoutInMinutes: 4
  }
}

resource vm 'Microsoft.Compute/virtualMachines@2021-11-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: vmSize
    }
    storageProfile: {
      osDisk: {
        createOption: 'FromImage'
        managedDisk: {
          storageAccountType: osDiskType
        }
      }
      imageReference: imageReference[ubuntuOSVersion]
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: networkInterface.id
        }
      ]
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPasswordOrKey
      linuxConfiguration: ((authenticationType == 'password') ? null : linuxConfiguration)
    }
    securityProfile: json('null')
  }
}

output adminUsername string = adminUsername
output fqdn string = publicIPAddress.properties.dnsSettings.fqdn
output sshCommand string = 'ssh ${adminUsername}@${publicIPAddress.properties.dnsSettings.fqdn}'

Observação

Esse modelo é baseado no conteúdo do repositório GitHub Modelos de Início Rápido do Azure.

Iniciar a implantação do modelo Bicep

Depois de salvar o arquivo main.bicep, você pode continuar com uma implantação baseada em modelo. Primeiro, inicie uma sessão da CLI do Azure no computador local e execute az login para autenticar. Você precisará fornecer as credenciais de um usuário com privilégios suficientes para provisionar recursos em sua assinatura do Azure. Em seguida, altere o diretório atual para aquele em que o arquivo main.bicep reside. Como alternativa, você pode iniciar uma sessão do Azure Cloud Shell Bash e carregar esse arquivo no diretório base no ambiente de Cloud Shell do Azure.

Em seguida, execute o seguinte comando em uma sessão autenticada da CLI do Azure para criar um grupo de recursos, que conterá todos os recursos que fazem parte da implantação subsequente:

az group create --name rg-lnx-bcp --location eastus

Antes de prosseguir, convém garantir que você esteja usando a versão mais recente da CLI do Bicep executando o seguinte comando:

az bicep upgrade

Por fim, inicie a implantação executando o seguinte comando:

az deployment group create --resource-group rg-lnx-bcp --template-file main.bicep --parameters adminUsername=azureuser

Observação

Esse comando inclui a opção --parameters, que, nesse caso, define o nome do administrador local para a VM do Azure que você está implantando. A CLI do Azure solicitará que você forneça a senha correspondente porque o valor padrão do parâmetro adminPasswordOrKey não está definido.

A VM do Azure deve começar a ser executada em breve, normalmente em alguns minutos. Para se conectar a ela, identifique o nome de domínio totalmente qualificado (FQDN) associado ao adaptador de rede lendo a saída gerada pela implantação. Como alternativa, você pode usar o valor shCommand. Quando solicitado, forneça a senha recém-definida para autenticar ao estabelecer uma conexão SSH.

Caso não tenha registrado os valores de saída da implantação do Bicep, você poderá exibi-los novamente executando o seguinte comando:

az deployment group show \
  --resource-group rg-lnx-bcp \
  --name main \
  --query properties.outputs

A saída formatada JSON deve se parecer com o seguinte conteúdo:

{
  "adminUsername": {
    "type": "String",
    "value": "azureuser"
  },
  "fqdn": {
    "type": "String",
    "value": "lnx-bcp-vm-example.eastus.cloudapp.azure.com"
  },
  "sshCommand": {
    "type": "String",
    "value": "ssh azureuser@lnx-bcp-vm-example.eastus.cloudapp.azure.com"
  }
}