Effettuare il provisioning di una macchina virtuale Linux usando Bicep

Completato

L'elemento principale di un modello Bicep è la risorsa, che definisce una risorsa di Azure. Ogni risorsa contiene un set di proprietà generico e specifico delle risorse. Ad esempio, il modello usato nell'esempio seguente descrive una rete virtuale di Azure. Mentre le proprietà name e location sono generiche, addressPrefix è specifico della risorsa. La Microsoft.Network/virtualNetworks@2021-05-01 stringa accanto alla risorsa designa la versione dell'API e la virtualNetwork voce rappresenta il nome simbolico, che consente di fare riferimento alla risorsa all'interno del modello.

Oltre all'elemento risorsa, il modello di esempio seguente include anche un elemento parametro che consente di assegnare un nome alla rete virtuale durante la distribuzione. Se non si assegna un nome in quel momento, si applica il valore predefinito di lnx-bcp-vnet. L'elemento description è un esempio di decorator, come indicato dal carattere iniziale @ . Il suo scopo è descrivere il ruolo del parametro e il relativo output viene visualizzato accanto alla casella di testo del parametro quando si usa il portale di Azure per esaminare o distribuire il modello di Azure Resource Manager corrispondente. Usare l'esempio di codice seguente per effettuare il provisioning di una macchina virtuale Linux tramite 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
      ]
    }
  }
}

Distribuire una macchina virtuale Linux tramite modelli Bicep

L'uso di Bicep prevede la creazione e la distribuzione di modelli. Per semplificare e migliorare l'esperienza di creazione, usare Visual Studio Code con l'estensione Bicep. La stessa estensione supporta inoltre le distribuzioni basate su Bicep. Se si preferisce attivare una distribuzione da una riga di comando o come parte di un'attività con script, è possibile installare e usare l'interfaccia della riga di comando Bicep come utilità autonoma o usarla direttamente dall'interno di una sessione dell'interfaccia della riga di comando di Azure. L'interfaccia della riga di comando di Azure installa automaticamente l'interfaccia della riga di comando di Bicep durante la prima chiamata di qualsiasi az bicep comando. Tuttavia, per eseguire un'installazione manuale di Bicep, eseguire az bicep install.

In effetti, il provisioning di una macchina virtuale di Azure che esegue Linux tramite Bicep prevede in genere questa sequenza di passaggi principali:

  • Identificare un'immagine di macchina virtuale adatta.
  • Identificare le dimensioni della macchina virtuale appropriate.
  • Creare un modello Bicep.
  • Avviare la distribuzione del modello Bicep.

Quando si distribuiscono modelli Bicep, un'attività denominata traspilazione li converte automaticamente in modelli di Azure Resource Manager equivalenti. È anche possibile eseguire una conversione tra i formati Bicep e Azure Resource Manager eseguendo rispettivamente i comandi bicep build e bicep decompile.

Per identificare l'immagine e le dimensioni della macchina virtuale adatta, seguire i passaggi descritti nelle unità precedenti di questo modulo. Questa unità è incentrata sulle attività specifiche di Bicep.

Creare un modello Bicep

Per creare un modello Bicep, iniziare avviando una sessione di Visual Studio Code con l'estensione Bicep installata. Creare quindi un file denominato main.bicep. Aggiungere il contenuto seguente al file e salvare quindi la modifica:

Nota

I nomi scelti per i file Bicep sono arbitrari, anche se è consigliabile scegliere un nome che riflette il contenuto o lo scopo del file e usare ".bicep" per l'estensione di tale file.

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

Nota

Questo modello si basa sul contenuto del repository GitHub Modelli di avvio rapido di Azure.

Avviare la distribuzione del modello Bicep

Dopo aver salvato il file main.bicep, è possibile procedere con una distribuzione basata su modelli. Avviare innanzitutto una sessione dell'interfaccia della riga di comando di Azure nel computer locale ed eseguire az login per l'autenticazione. Sarà necessario fornire le credenziali di un utente con privilegi sufficienti per effettuare il provisioning delle risorse nella sottoscrizione di Azure. Modificare poi la directory corrente in quella in cui risiede il file main.bicep. In alternativa, è possibile avviare una sessione Bash di Azure Cloud Shell e caricare il file nella home directory all'interno dell'ambiente di Cloud Shell di Azure.

Eseguire quindi il comando seguente da una sessione dell'interfaccia della riga di comando di Azure autenticata per creare un gruppo di risorse che conterrà tutte le risorse che fanno parte della distribuzione successiva:

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

Prima di procedere ulteriormente, assicurarsi di usare la versione più recente dell'interfaccia della riga di comando di Bicep eseguendo il comando seguente:

az bicep upgrade

Avviare infine la distribuzione eseguendo il comando seguente:

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

Nota

Questo comando include l'opzione --parameters, che in questo caso imposta il nome dell'amministratore locale per la macchina virtuale di Azure distribuita. L'interfaccia della riga di comando di Azure richiede di specificare la password corrispondente perché il valore predefinito del adminPasswordOrKey parametro non è impostato.

La macchina virtuale di Azure dovrebbe iniziare a funzionare a breve, in genere entro pochi minuti. Per connettersi, identificare il nome di dominio completo (FQDN) associato alla relativa interfaccia di rete esaminando l'output generato dalla distribuzione. In alternativa, è possibile usare il valore shCommand. Quando richiesto, specificare la nuova password impostata per l'autenticazione quando si stabilisce una connessione SSH.

Nel caso in cui non siano stati registrati i valori di output della distribuzione Bicep, è possibile visualizzarli di nuovo eseguendo il comando seguente:

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

L'output in formato JSON dovrebbe essere simile al contenuto seguente:

{
  "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"
  }
}