Condividi tramite


Come creare risorse su larga scala usando l'interfaccia della riga di comando di Azure

In qualità di Azure Resource Manager, spesso è necessario creare più risorse di Azure durante la configurazione di nuovi ambienti. Si potrebbe anche avere un processo di approvazione delle risorse di Azure che funziona meglio quando le risorse di Azure vengono create automaticamente da uno script.

In questo articolo si apprenderà quanto segue:

  • Creare più risorse di Azure dai parametri ricevuti da un file CSV delimitato.
  • Usare IF.. Istruzioni THEN per creare risorse di Azure dipendenti.
  • Registrare lo stato dello script in un file TXT locale.

Questo script di esempio è stato testato in Azure Cloud Shell sia negli ambienti Bash che in PowerShell 7. Trovare il file CSV e lo script completo in Azure-samples/azure-cli-samples.

Predisporre l'ambiente

Seguire questa procedura per preparare l'ambiente per eseguire lo script di esempio:

  • Aprire l'ambiente Bash o PowerShell in Azure Cloud Shell. Per altre informazioni, vedere Avvio rapido su Bash in Azure Cloud Shell.

  • Scaricare e salvare in una directory locale il file CSV seguente. Sostituire myExistingResourceGroupName nella riga 3 con un nome effettivo del gruppo di risorse.

    resourceNo,location,createRG,exstingRgName,createVnet,vnetAddressPrefix,subnetAddressPrefixes,vmImage,publicIpSku,Adminuser
    1,eastus,TRUE,,TRUE,10.0.0.0/16,10.0.0.0/24,Ubuntu2204,standard,
    2,eastus2,TRUE,,FALSE,,,Debian11,standard,alex-smith
    3,southcentralus,FALSE,myExistingResourceGroupName,FALSE,,,Ubuntu2204,standard,jan-smith
    [empty line for Bash]
    

    Nota

    Per essere un file di testo Unix appropriato e essere letto da Bash, il file CSV richiede un carattere di nuova riga alla fine dell'ultima riga di dati. In questo modo viene restituita una riga vuota alla fine del file. La riga vuota non deve dire [empty line] perché questo testo viene fornito solo per mostrare che esiste una riga vuota. Gli ambienti PowerShell non hanno questo requisito di caratteri di nuova riga.

  • Caricare il file CSV modificato nell'account di archiviazione del blog di Azure Cloud Shell. Il modo più semplice per eseguire questa operazione consiste nell'usare l'elenco a discesa Gestisci file nel menu principale di Azure Cloud Shell. Per altre informazioni sull'archiviazione di Cloud Shell, vedere Rendere persistenti i file in Azure Cloud Shell.

Panoramica di script

Questo articolo suddivide un singolo script di grandi dimensioni in quattro sezioni in modo che ogni passaggio possa essere spiegato.

  • Configurazione delle variabili
  • Convalida dei dati
  • Convalida del ciclo
  • Creazione di risorse di Azure

Sono disponibili anche due script: uno per Bash e il secondo per PowerShell. Entrambi gli script usano gli stessi comandi dell'interfaccia della riga di comando di Azure. Si tratta dell'ambiente, o del profilo del terminale, diverso. Ad esempio, Bash usa do...done e if...then...fi. In un ambiente PowerShell si usano gli equivalenti foreach e if (something is true)...{do this}. In Azure Cloud Shell è possibile passare da un ambiente all'altro usando il pulsante Passa a PowerShell o Passa a Bash nel menu principale di Azure Cloud Shell.

Se si preferisce, passare direttamente ai file CSV e script usati da questo articolo in Azure-samples/azure-cli-samples.

Impostare variabili

Per iniziare, creare le variabili necessarie per lo script. Le tre variabili seguenti richiedono valori effettivi per l'ambiente:

  • subscriptionID: ID sottoscrizione di Azure.
  • csvFileLocation: percorso e nome file del file di input CSV.
  • logFileLocation: si tratta del percorso e del nome file usato dallo script per creare un file di log. Non è necessario creare o caricare il file.

Le variabili con un msdocs- prefisso possono essere sostituite con il prefisso desiderato. Tutte le variabili vuote ("") usano valori del file di input CSV. Queste variabili vuote sono segnaposto necessari per lo script.

# Variable block

# Replace these three variable values with actual values
subscriptionID=00000000-0000-0000-0000-00000000
csvFileLocation="myFilePath\myFileName.csv"
logFileLocation="myFilePath\myLogName.txt"

# Variable values that contain a prefix can be replaced with the prefix of your choice.
#   These prefixes have a random ID appended to them in the script.
# Variable values without a prefix will be overwritten by the contents of your CSV file.
location=""
createRG=""
newRgName="msdocs-rg-"
existingRgName=""

createVnet=""
vnetName="msdocs-vnet-"
subnetName="msdocs-subnet-"
vnetAddressPrefix=""
subnetAddressPrefixes=""

vmName="msdocs-vm-"
vmImage=""
publicIpSku=""
adminUser=""
adminPassword="msdocs-PW-@"

# Set your Azure subscription 
az account set --subscription $subscriptionID

Convalidare i valori dei file CSV

Prima di iniziare a testare lo script di creazione, assicurarsi che il file CSV sia formattato correttamente e che alle variabili vengano assegnati valori corretti. Questo script usa un'istanza if.. Istruzione THEN in modo da poter esaminare uno scenario o una riga CSV alla volta.

# Verify CSV columns are being read correctly

# Take a look at the CSV contents
cat $csvFileLocation

# Validate select CSV row values
while IFS=, read -r resourceNo location createRG existingRgName createVnet vnetAddressPrefix subnetAddressPrefixes vmImage publicIpSku adminUser
do
  # Generate a random ID
  let "randomIdentifier=$RANDOM*$RANDOM"

  # Return the values for the first data row
  # Change the $resourceNo to check different scenarios in your CSV
  if [ "$resourceNo" = "1" ]; then
    echo "resourceNo = $resourceNo"
    echo "location = $location"
    echo "randomIdentifier = $randomIdentifier"
    echo ""
    
    echo "RESOURCE GROUP INFORMATION:"
    echo "createRG = $createRG"
    if [ "$createRG" = "TRUE" ]; then 
      echo "newRGName = $newRgName$randomIdentifier"
    else
      echo "exsitingRgName = $existingRgName"
    fi
    echo ""

    echo "VNET INFORMATION:"
    echo "createVnet = $createVnet"
    if [ "$createVnet" = "TRUE" ]; then 
      echo "vnetName = $vnetName$randomIdentifier"
      echo "subnetName = $subnetName$randomIdentifier"
      echo "vnetAddressPrefix = $vnetAddressPrefix"
      echo "subnetAddressPrefixes = $subnetAddressPrefixes"
    fi
    echo ""

    echo "VM INFORMATION:"
    echo "vmName = $vmName$randomIdentifier"
    echo "vmImage = $vmImage"
    echo "vmSku = $publicIpSku"
    if [ `expr length "$adminUser"` == "1" ]; then
      echo "SSH keys will be generated."
    else
      echo "vmAdminUser = $adminUser"
      echo "vmAdminPassword = $adminPassword$randomIdentifier"        
    fi
  fi  
# skip the header line
done < <(tail -n +2 $csvFileLocation)

Usando il file CSV fornito in questo articolo, l'output di convalida è il seguente: (l'ID 00000001 casuale sarà diverso per ogni test).

resourceNo = 1
location = eastus

RESOURCE GROUP INFORMATION:
createRG = TRUE
newRGName = msdocs-rg-00000001

VNET INFORMATION:
createVnet = TRUE
vnetName = msdocs-vnet-00000001
subnetName = msdocs-subnet-00000001
vnetAddressPrefix = 10.0.0.0/16
subnetAddressPrefix = 10.0.0.0/24

VM INFORMATION:
vmName = msdocs-vm-00000001
vmImage = Ubuntu2204
vmSku = standard
SSH keys will be created

Convalidare la logica dello script

Se si è certi delle capacità di scripting, è possibile ignorare questo passaggio. Tuttavia, poiché questo script è progettato per creare risorse di Azure su larga scala, il ciclo dello script con echo istruzioni o write-host consente di risparmiare tempo e risorse di Azure fatturabili impreviste.

Esistono diversi modi per scorrere un file CSV usando Bash. In questo esempio viene IFS usato con un oggetto while loop.

# Validate script logic

# Create the log file
echo "SCRIPT LOGIC VALIDATION.">$logFileLocation

# Loop through each row in the CSV file
while IFS=, read -r resourceNo location createRG existingRgName createVnet vnetAddressPrefix subnetAddressPrefixes vmImage publicIpSku adminUser
do
  # Generate a random ID
  let "randomIdentifier=$RANDOM*$RANDOM"
    
  # Log resource number and random ID
  echo "resourceNo = $resourceNo">>$logFileLocation
  echo "randomIdentifier = $randomIdentifier">>$logFileLocation

  # Check if a new resource group should be created
  if [ "$createRG" == "TRUE" ]; then
    echo "Will create RG $newRgName$randomIdentifier.">>$logFileLocation
    existingRgName=$newRgName$randomIdentifier
  fi

  # Check if a new virtual network should be created, then create the VM
  if [ "$createVnet" == "TRUE" ]; then
    echo "Will create VNet $vnetName$randomIdentifier in RG $existingRgName.">>$logFileLocation
    echo "Will create VM $vmName$randomIdentifier in Vnet $vnetName$randomIdentifier in RG $existingRgName.">>$logFileLocation
  else
    echo "Will create VM $vmName$randomIdentifier in RG $existingRgName.">>$logFileLocation
  fi
# Skip the header line.
done < <(tail -n +2 $csvFileLocation)

# Clear the console and display the log file
Clear
cat $logFileLocation

Usando il file CSV fornito in questo articolo, l'output di convalida è il seguente: (gli 00000001, 2, 3 ID casuali saranno diversi per ogni test, ma ogni risorsa in ogni resourceNo risorsa deve condividere lo stesso ID casuale).

resourceNo = 1
createRG = TRUE
createVnet = TRUE
Will create RG msdocs-rg-00000001
Will create VNet msdocs-vnet-00000001 in RG msdocs-rg-00000001
Will create VM msdocs-vm-00000001 within Vnet msdocs-vnet-00000001 in RG msdocs-rg-00000001

resourceNo = 2
createRG = TRUE
createVnet = FALSE
Will create RG msdocs-rg-00000002
Will create VM msdocs-vm-00000002 without Vnet in RG msdocs-rg-00000002

resourceNo = 3
createRG = FALSE
createVnet = FALSE
Will create VM msdocs-vm-00000003 without Vnet in RG <myExistingResourceGroup>

Creare risorse Azure

A questo punto è stato creato il blocco di variabili, convalidato i valori CSV e completato un'esecuzione di test con echo o write-host. Eseguire la quarta parte finale dello script per creare risorse di Azure come definito nel file di input CSV.

# Create Azure resources

# Create the log file
echo "CREATE AZURE RESOURCES.">$logFileLocation

# Loop through each CSV row
while IFS=, read -r resourceNo location createRG existingRgName createVnet vnetAddressPrefix subnetAddressPrefixes vmImage publicIpSku adminUser
do
  # Generate a random ID
  let "randomIdentifier=$RANDOM*$RANDOM"

  # Log resource number, random ID and display start time
  echo "resourceNo = $resourceNo">>$logFileLocation
  echo "randomIdentifier = $randomIdentifier">>$logFileLocation
  echo "Starting creation of resourceNo $resourceNo at $(date +"%Y-%m-%d %T")."

  # Check if a new resource group should be created
  if [ "$createRG" == "TRUE" ]; then
    echo "Creating RG $newRgName$randomIdentifier at $(date +"%Y-%m-%d %T").">>$logFileLocation
    az group create --location $location --name $newRgName$randomIdentifier >>$logFileLocation
    existingRgName=$newRgName$randomIdentifier
    echo "  RG $newRgName$randomIdentifier creation complete"
  fi

  # Check if a new virtual network should be created, then create the VM
  if [ "$createVnet" == "TRUE" ]; then
    echo "Creating VNet $vnetName$randomIdentifier in RG $existingRgName at $(date +"%Y-%m-%d %T").">>$logFileLocation
    az network vnet create \
        --name $vnetName$randomIdentifier \
        --resource-group $existingRgName \
        --address-prefix $vnetAddressPrefix \
        --subnet-name $subnetName$randomIdentifier \
        --subnet-prefixes $subnetAddressPrefixes >>$logFileLocation
    echo "  VNet $vnetName$randomIdentifier creation complete"
    
    echo "Creating VM $vmName$randomIdentifier in Vnet $vnetName$randomIdentifier in RG $existingRgName at $(date +"%Y-%m-%d %T").">>$logFileLocation
    az vm create \
        --resource-group $existingRgName \
        --name $vmName$randomIdentifier \
        --image $vmImage \
        --vnet-name $vnetName$randomIdentifier \
        --subnet $subnetName$randomIdentifier \
        --public-ip-sku $publicIpSku \
        --generate-ssh-keys >>$logFileLocation
    echo "  VM $vmName$randomIdentifier creation complete"
  else
    echo "Creating VM $vmName$randomIdentifier in RG $existingRgName at $(date +"%Y-%m-%d %T").">>$logFileLocation
    az vm create \
        --resource-group $existingRgName \
        --name $vmName$randomIdentifier \
        --image $vmImage \
        --public-ip-sku $publicIpSku \
        --admin-username $adminUser\
        --admin-password $adminPassword$randomIdentifier >>$logFileLocation
    echo "  VM $vmName$randomIdentifier creation complete"    
  fi
# skip the header line
done < <(tail -n +2 $csvFileLocation)

# Clear the console (optional) and display the log file
# clear
cat $logFileLocation

Nell'output della console manca l'ultima riga nel file CSV? Ciò può essere causato da un carattere di continuazione di riga mancante dopo l'ultima riga. Aggiungere una riga vuota alla fine del file CSV per risolvere il problema.

Output della console prima della lettura del file di log:

Starting creation of resourceNo 1 at YYYY-MM-DD HH:MM:SS.
  RG msdocs-rg-00000001 creation complete
  VNet msdocs-vnet-00000001 creation complete
  VM msdocs-vm-00000001 creation complete

Starting creation of resourceNo 2 at YYYY-MM-DD HH:MM:SS.
  RG msdocs-rg-00000002 creation complete
  VM msdocs-vm-00000002 creation complete

Starting creation of resourceNo 3 at YYYY-MM-DD HH:MM:SS.
  VM msdocs-vm-00000003 creation complete

Il contenuto del file di log dovrebbe essere simile al seguente:

Starting creation of resourceNo 1 at YYYY-MM-DD HH:MM:SS.
  Creating RG msdocs-rg-00000001 at YYYY-MM-DD HH:MM:SS.
  {
  Resource group create output
  }
  Creating VNet msdocs-vnet-00000001 in RG msdocs-rg-000000001 at YYYY-MM-DD HH:MM:SS.
  {
  VNet create output
  }  
  Creating VM msdocs-vm-00000001 in RG msdocs-rg-00000001 at YYYY-MM-DD HH:MM:SS.
  {
  VM create output
  }

Starting creation of resourceNo 2 at YYYY-MM-DD HH:MM:SS.
  Creating RG msdocs-rg-00000002 at YYYY-MM-DD HH:MM:SS.
  {
  Resource group create output
  }
  Creating VM msdocs-vm-00000002 in RG msdocs-rg-00000002 at YYYY-MM-DD HH:MM:SS.
  {
  VM create output
  }

Starting creation of resourceNo 3 at YYYY-MM-DD HH:MM:SS.
  Creating msdocs-vm-00000003 creation complete
  {
  VM create output
  }

Risoluzione dei problemi

In Bash il passaggio "Crea risorse di Azure" si interrompe dopo il passaggio 1

In Ubuntu 22.04.3 LTS e Debian versione 12 (bookworm) la logica di convalida dello script funziona come previsto restituendo i risultati per tutte e tre le risorse. Tuttavia, la creazione di risorse di Azure si arresta dopo la prima risorsa. Un possibile motivo per questo problema è che la creazione della rete virtuale nel passaggio 1 richiede alcuni secondi. Sia Ubuntu che Debian passano alla seconda risorsa senza attendere il completamento della rete virtuale. Per altre informazioni su questo aspetto in attesa, i processi nel ciclo while non vengono completati o In attesa del completamento di qualsiasi processo nello script bash.

Lo script Bash ignora l'istruzione IF

Bash fa distinzione tra maiuscole e minuscole. La parola true non è uguale a TRUE. È anche greater than , non >e equals è ==, non =.-gt Assicurarsi di non avere un errore tipografico o di spazi iniziali/finali nei valori delle colonne CSV.

I valori delle variabili non vengono modificati con ogni ciclo

Questo è spesso causato da spazi aggiuntivi nel file CSV. Una riga in un file CSV avrà un aspetto simile al seguente: column1,column2,column3 o column1,,column3, ma per abitudine è facile creare un file di test che contiene uno spazio dopo ogni virgola come column1, column2, column3. Quando si dispone di uno spazio iniziale o finale nel file CSV, il valore della colonna è effettivamente <space>columnValue. La logica if [ "$columnName" = "columnValue" ] dello script restituisce "false". Rimuovere tutti gli spazi iniziali e finali nelle righe CSV per risolvere il problema.

Notazione CIDR non valida

Viene visualizzato un errore InvalidCIDRNotation quando si passa un prefisso di indirizzo non corretto a az network vnet create. Questa situazione può risultare complessa quando visivamente il prefisso dell'indirizzo è corretto quando viene restituito in un'istruzione echo . Per risolvere i problemi relativi al valore effettivo letto dal volume condiviso cluster, provare questo script:

while IFS=, read -r resourceNo location createRG existingRgName createVnet vnetAddressPrefix subnetAddressPrefixes vmImage publicIpSku adminUser
do
    echo "resourceNo = $resourceNo"

    if [ "$createVnet" == "TRUE" ]; then
      startTest="abc"
      endTest="xyz"
      echo $startTest$vnetAddressPrefix$endTest
    fi
done < <(tail -n +2 $setupFileLocation)

Se i risultati sono simili xzy10.0.0.0 e non previsti abc10.0.0.0/24xyz, potrebbe essere presente un carattere nascosto o un'ulteriore virgola che si nasconde nel file CSV. Aggiungere una colonna di test con lo stesso valore di prefisso, riorganizzare le colonne CSV e copiare/incollare il contenuto csv in/fuori da un semplice editor del Blocco note. Nella scrittura di questo articolo, la ridisporzione delle colonne CSV ha infine risolto l'errore.

Gli argomenti sono previsti o obbligatori

Questo errore viene visualizzato quando non è stato specificato un parametro obbligatorio o si verifica un errore tipografico che causa l'analisi non corretta del comando di riferimento da parte dell'interfaccia della riga di comando di Azure. Quando si usa uno script, questo errore viene visualizzato anche quando si verifica uno degli elementi seguenti:

  • Esiste un carattere di continuazione di riga mancante o errato.
  • Sul lato destro di un carattere di continuazione di riga sono presenti spazi finali.
  • Il nome della variabile contiene un carattere speciale, ad esempio un trattino (-).

InvalidTemplateDeployment

Quando si tenta di creare una risorsa di Azure in una posizione che non offre tale risorsa, viene visualizzato un errore simile al seguente: "Gli SKU seguenti non sono riusciti per restrizioni di capacità: Standard_DS1_v2" non sono attualmente disponibili nella posizione "westus".

Ecco l'esempio di errore completo:

{"error":{"code":"InvalidTemplateDeployment","message":"The template deployment 'vm_deploy_<32 character ID>'
is not valid according to the validation procedure. The tracking id is '<36 character ID>'.
See inner errors for details.","details":[{"code":"SkuNotAvailable","message":"The requested VM size for resource
'Following SKUs have failed for Capacity Restrictions: Standard_DS1_v2' is currently not available
in location '<your specified location>'. Please try another size or deploy to a different location
or different zone. See https://aka.ms/azureskunotavailable for details."}]}}

Per correggere l'errore, modificare il percorso o selezionare un valore di parametro diverso offerto per la posizione desiderata.

Vedi anche