Compartilhar via


Como criar recursos em escala usando a CLI do Azure

Como um gerenciador de recursos do Azure, você frequentemente precisa criar vários recursos do Azure ao configurar novos ambientes. Você também pode ter um processo de aprovação de recursos do Azure que funciona melhor quando os recursos do Azure são criados automaticamente a partir de um script.

Neste artigo, você aprenderá o seguinte:

  • Crie vários recursos do Azure a partir de parâmetros recebidos de um arquivo CSV delimitado.
  • Use SE.. THEN para criar recursos dependentes do Azure.
  • Registre o progresso do script em um arquivo TXT local.

Este script de exemplo foi testado no Azure Cloud Shell em ambientes Bash e PowerShell e no PowerShell 7. Encontre o CSV e o script completo em Azure-samples/azure-cli-samples.

Prepare o seu ambiente

Siga estas etapas para preparar seu ambiente para executar o script de exemplo:

  • Abra o ambiente Bash ou PowerShell no Azure Cloud Shell. Para obter mais informações, confira Início Rápido para Bash no Azure Cloud Shell.

  • Baixe e salve em um diretório local o seguinte arquivo CSV. Substitua myExistingResourceGroupName na linha três por um nome de grupo de recursos real.

    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]
    

    Observação

    Para ser um arquivo de texto Unix adequado e ser lido pelo Bash, o arquivo CSV precisa de um caractere de nova linha no final da última linha de dados. Isso resulta em uma linha em branco no final do arquivo. Sua linha em branco não precisa dizer, [empty line] pois este texto é fornecido apenas para mostrar que existe uma linha vazia. Os ambientes do PowerShell não têm esse requisito de caractere de nova linha.

  • Carregue o arquivo CSV modificado em sua conta de armazenamento de blog do Azure Cloud Shell. A maneira mais fácil de fazer isso é usar a lista suspensa Gerenciar arquivos no menu principal do Azure Cloud Shell. Para obter mais informações sobre o armazenamento do Cloud Shell, consulte Manter arquivos no Azure Cloud Shell.

Visão geral do script

Este artigo divide um único script grande em quatro seções para que cada etapa possa ser explicada.

  • Configuração variável
  • Validação de dados
  • Validação de loop
  • Criação de recursos do Azure

Também há dois scripts fornecidos: um para Bash e outro para PowerShell. Ambos os scripts usam os mesmos comandos da CLI do Azure. É o ambiente, ou perfil do terminal, que é diferente. Por exemplo, o Bash usa do...done e if...then...fi. Em um ambiente do PowerShell, você usa o equivalente foreach e if (something is true)...{do this}. No Azure Cloud Shell, você pode alternar entre ambientes usando o botão Alternar para PowerShell ou Alternar para Bash no menu principal do Azure Cloud Shell.

Se preferir, vá diretamente para os arquivos CSV e de script usados por este artigo em Azure-samples/azure-cli-samples.

Definir variáveis

Comece criando as variáveis necessárias para o script. As três variáveis a seguir precisam de valores reais para o seu ambiente:

  • subscriptionID: esta é a ID da assinatura do Azure.
  • csvFileLocation: Este é o local e o nome do arquivo de entrada CSV.
  • logFileLocation: Este é o local e o nome do arquivo que o script usará para criar um arquivo de log. Você não precisa criar ou carregar este arquivo.

As variáveis com um msdocs- prefixo podem ser substituídas pelo prefixo de sua escolha. Todas as variáveis vazias ("") usam valores do arquivo de entrada CSV. Essas variáveis vazias são espaços reservados necessários para o 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

Validar valores de arquivo CSV

Antes de começar a testar o script de criação, verifique se o arquivo CSV está formatado corretamente e se as variáveis receberão os valores corretos. Este script usa um IF.. THEN para que você possa ver um cenário/linha CSV por vez.

# 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 o CSV fornecido neste artigo, a saída da validação é a seguinte: (A 00000001 ID aleatória será diferente para cada teste.)

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

Validar lógica de script

Se você está confiante em suas habilidades de script, pode pular esta etapa. No entanto, como esse script foi projetado para criar recursos do Azure em escala, fazer um loop pelo script com echo instruções or write-host pode economizar tempo e recursos inesperados faturáveis do Azure.

Existem várias maneiras de iterar por meio de um arquivo CSV usando o Bash. Este exemplo usa IFS com um 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 o CSV fornecido neste artigo, a saída de validação é a seguinte: (As 00000001, 2, 3 IDs aleatórias serão diferentes para cada teste, mas cada recurso em cada um resourceNo deve compartilhar a mesma ID aleatória.)

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>

Criar recursos do Azure

Agora você criou seu bloco de variáveis, validou seus valores CSV e concluiu uma execução de teste com echo ou write-host. Execute a quarta e última parte do script para criar recursos do Azure, conforme definido no arquivo de entrada 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

Na saída do console, está faltando a última linha no arquivo CSV? Isso pode ser causado por um caractere de continuação de linha ausente após a última linha. Adicione uma linha em branco no final do arquivo CSV para corrigir o problema.

Saída do console antes da leitura do arquivo de 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

O conteúdo do arquivo de log deve ser semelhante a este:

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
  }

Solução de problemas

No Bash, a etapa "Criar recursos do Azure" é interrompida após a etapa 1

No Ubuntu 22.04.3 LTS e no Debian versão 12 (bookworm), a lógica do script Validate funciona conforme o esperado, retornando resultados para todos os três recursos. No entanto, a opção Criar recursos do Azure é interrompida após o primeiro recurso. Um possível motivo para esse problema é que a criação da VNet na etapa #1 leva alguns segundos. Tanto o Ubuntu quanto o Debian prosseguem para o segundo recurso sem esperar pela conclusão da VNet. Você pode ler mais sobre isso em esperar não espera que os processos no loop while terminem ou Esperando que qualquer processo termine no script bash.

O script Bash ignora a instrução IF

O Bash diferencia maiúsculas de minúsculas. A palavra true não é igual a TRUE. Também greater than é , não >, e equals é ==, não =-gt. Certifique-se de que você não tenha um erro tipográfico ou espaços à esquerda/à direita nos valores da coluna CSV.

Os valores das variáveis não estão mudando a cada loop

Isso geralmente é causado por espaços extras no arquivo CSV. Uma linha em um arquivo CSV será semelhante a esta: column1,column2,column3 ou column1,,column3, mas por hábito é fácil criar um arquivo de teste que contenha um espaço após cada vírgula como column1, column2, column3. Quando você tem um espaço à esquerda ou à direita em seu CSV, o valor da coluna é na verdade <space>columnValue. A lógica if [ "$columnName" = "columnValue" ] do script retorna "false". Remova todos os espaços à esquerda e à direita em suas linhas CSV para corrigir o problema.

Notação CIDR inválida

Você recebe um erro InvalidCIDRNotation ao passar um prefixo de endereço incorreto para az network vnet createo . Isso pode ser desafiador quando, visualmente, o prefixo de endereço parece correto quando retornado em uma echo instrução. Para solucionar problemas do valor real que está sendo lido do CSV, tente este 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 os resultados forem semelhantes xzy10.0.0.0 e não forem os esperados abc10.0.0.0/24xyz, pode haver um caractere oculto ou uma vírgula extra à espreita no arquivo CSV. Adicione uma coluna de teste com o mesmo valor de prefixo, reorganize suas colunas CSV e copie/cole seu conteúdo CSV dentro/fora de um editor de Bloco de Notas simples. Ao escrever este artigo, o rearranjo das colunas CSV finalmente corrigiu o erro.

Argumentos são esperados ou necessários

Você recebe esse erro quando não forneceu um parâmetro necessário ou há um erro tipográfico que faz com que a CLI do Azure analise incorretamente o comando de referência. Ao trabalhar com um script, você também recebe esse erro quando uma ou mais das seguintes opções é verdadeira:

  • Há um caractere de continuação de linha ausente ou incorreto.
  • Há espaços à direita no lado direito de um caractere de continuação de linha.
  • O nome da variável contém um caractere especial, como um traço (-).

InvalidTemplateDeployment

Ao tentar criar um recurso do Azure em um local que não oferece esse recurso, você recebe um erro semelhante ao seguinte: "Os SKUs a seguir falharam para restrições de capacidade: Standard_DS1_v2' não está disponível no local 'westus'".

Aqui está o exemplo de erro 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."}]}}

Para corrigir o erro, altere o local ou selecione um valor de parâmetro diferente oferecido para o local desejado.

Confira também