Compartir a través de


Creación de recursos a escala mediante la CLI de Azure

Como administrador de recursos de Azure, con frecuencia tiene que crear varios recursos de Azure al configurar nuevos entornos. También puede tener un proceso de aprobación de recursos de Azure que funcione mejor cuando los recursos de Azure se crean automáticamente a partir de un script.

En este artículo aprenderá lo siguiente:

  • Cree varios recursos de Azure a partir de parámetros recibidos de un archivo CSV delimitado.
  • Use IF.. Instrucciones THEN para crear recursos de Azure dependientes.
  • Registrar el progreso del script en un archivo TXT local.

Este script de ejemplo se ha probado en Azure Cloud Shell en entornos de Bash y PowerShell y PowerShell 7. Busque el archivo CSV y el script completo en Azure-samples/azure-cli-samples.

Preparación del entorno

Siga estos pasos para preparar el entorno para ejecutar el script de ejemplo:

  • Abra el entorno de Bash o PowerShell en Azure Cloud Shell. Para más información, consulte Inicio rápido para Bash en Azure Cloud Shell.

  • Descargue y guarde en un directorio local el siguiente archivo CSV. Reemplace myExistingResourceGroupName en la línea tres por un nombre 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]
    

    Nota:

    Para ser un archivo de texto unix adecuado y ser leído por Bash, el archivo CSV necesita un carácter de nueva línea al final de la última línea de datos. Esto da como resultado una línea en blanco al final del archivo. La línea en blanco no necesita decir [empty line] , ya que este texto solo se proporciona para mostrar que existe una línea vacía. Los entornos de PowerShell no tienen este requisito de carácter de nueva línea.

  • Cargue el archivo CSV modificado en la cuenta de almacenamiento del blog de Azure Cloud Shell. La manera más fácil de hacerlo es usar la lista desplegable Administrar archivos en el menú principal de Azure Cloud Shell. Para más información sobre el almacenamiento de Cloud Shell, consulte Conservación de archivos en Azure Cloud Shell.

Información general del script

En este artículo se divide un único script grande en cuatro secciones para que se pueda explicar cada paso.

  • Configuración de variables
  • Validación de datos
  • Validación de bucles
  • Creación de recursos de Azure

También se proporcionan dos scripts: uno para Bash y el segundo para PowerShell. Ambos scripts usan los mismos comandos de la CLI de Azure. Es el entorno o el perfil de terminal, que es diferente. Por ejemplo, Bash usa do...done y if...then...fi. En un entorno de PowerShell, se usan los equivalentes foreach y if (something is true)...{do this}. En Azure Cloud Shell, puede cambiar entre entornos mediante el botón Cambiar a PowerShell o Cambiar a Bash en el menú principal de Azure Cloud Shell.

Si lo prefiere, vaya directamente a los archivos CSV y de script que usa este artículo en Azure-samples/azure-cli-samples.

Configuración de variables

Para empezar, cree las variables necesarias para el script. Las tres variables siguientes necesitan valores reales para el entorno:

  • subscriptionID: este es el identificador de suscripción de Azure.
  • csvFileLocation: esta es la ubicación y el nombre de archivo del archivo de entrada CSV.
  • logFileLocation: esta es la ubicación y el nombre de archivo que usará el script para crear un archivo de registro. No es necesario crear ni cargar este archivo.

Las variables con un msdocs- prefijo se pueden reemplazar por el prefijo que prefiera. Todas las variables vacías ("") usan valores del archivo de entrada CSV. Estas variables vacías son marcadores de posición necesarios para el 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

Validación de valores de archivo CSV

Antes de empezar a probar el script de creación, asegúrese de que el archivo CSV tiene el formato correcto y las variables se asignarán valores correctos. Este script usa un IF.. Instrucción THEN para que pueda examinar una línea CSV o un escenario a la 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)

Con el ARCHIVO CSV proporcionado en este artículo, la salida de validación es la siguiente: (El 00000001 identificador aleatorio será diferente para cada prueba).

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

Validación de la lógica del script

Si confía en sus capacidades de scripting, puede omitir este paso. Sin embargo, dado que este script está diseñado para crear recursos de Azure a escala, recorrer en bucle el script con echo instrucciones o write-host puede ahorrar tiempo y recursos de Azure facturables inesperados.

Hay varias maneras de recorrer en iteración un archivo CSV mediante Bash. En este ejemplo se usa IFS con .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

Con el CSV proporcionado en este artículo, la salida de validación es la siguiente: (Los 00000001, 2, 3 identificadores aleatorios serán diferentes para cada prueba, pero cada recurso de cada resourceNo uno debe compartir el mismo identificador aleatorio).

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>

Creación de recursos de Azure

Ahora ha creado el bloque de variables, ha validado los valores CSV y ha completado una ejecución de prueba con echo o write-host. Ejecute la cuarta y última parte del script para crear recursos de Azure como se define en el archivo 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

En la salida de la consola, ¿falta la última fila en el archivo CSV? Esto puede deberse a un carácter de continuación de línea que falta después de la última línea. Agregue una línea en blanco al final del archivo CSV para corregir el problema.

Salida de la consola antes de leer el archivo de registro:

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

El contenido del archivo de registro debe tener un aspecto similar al siguiente:

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
  }

Solución de problemas

En Bash, el paso "Crear recursos de Azure" se detiene después del paso 1.

En Ubuntu 22.04.3 LTS y Debian versión 12 (bookworm), la lógica validar script funciona según lo previsto para devolver los resultados de los tres recursos. Sin embargo, la opción Crear recursos de Azure se detiene después del primer recurso. Un posible motivo de este problema es que la creación de la red virtual en el paso 1 tarda unos segundos. Ubuntu y Debian continúan con el segundo recurso sin esperar a que se complete la red virtual. Puede obtener más información sobre esto en espera no espera a que los procesos del bucle while finalicen o Esperando a que finalice cualquier proceso en el script de Bash.

El script de Bash omite la instrucción IF

Bash distingue mayúsculas de minúsculas. La palabra true no es igual a TRUE. También greater than es -gt, no >, y equals es ==, no =. Asegúrese de que no tiene un error tipográfico o espacios iniciales o finales en los valores de columna CSV.

Los valores de variable no cambian con cada bucle

Esto suele deberse a espacios adicionales en el archivo CSV. Una línea de un archivo CSV tendrá un aspecto similar al siguiente: column1,column2,column3 o column1,,column3, pero por hábito es fácil crear un archivo de prueba que contenga un espacio después de cada coma como column1, column2, column3. Cuando tiene un espacio inicial o final en el CSV, el valor de columna es realmente <space>columnValue. La lógica if [ "$columnName" = "columnValue" ] del script devuelve "false". Quite todos los espacios iniciales y finales de las filas CSV para corregir el problema.

Notación CIDR no válida

Recibirá un error InvalidCIDRNotation al pasar un prefijo de dirección incorrecto a az network vnet create. Esto puede ser difícil cuando visualmente, el prefijo de dirección es correcto cuando se devuelve en una echo instrucción . Para solucionar problemas del valor real que se lee desde csv, pruebe 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)

Si los resultados son similares xzy10.0.0.0 y no los esperados abc10.0.0.0/24xyz, es posible que haya un carácter oculto o una coma adicional que acecha en el archivo CSV. Agregue una columna de prueba con el mismo valor de prefijo, reorganice las columnas CSV y copie o pegue el contenido de CSV dentro o fuera de un editor simple del Bloc de notas. Al escribir este artículo, la reorganización de las columnas CSV finalmente corrigió el error.

Los argumentos son esperados o necesarios

Recibe este error cuando no ha proporcionado un parámetro obligatorio o hay un error tipográfico que hace que la CLI de Azure analice incorrectamente el comando de referencia. Al trabajar con un script, también recibirá este error cuando se cumple una de las siguientes opciones:

  • Falta un carácter de continuación de línea o incorrecto.
  • Hay espacios finales en el lado derecho de un carácter de continuación de línea.
  • El nombre de la variable contiene un carácter especial, como un guión (-).

InvalidTemplateDeployment

Al intentar crear un recurso de Azure en una ubicación que no ofrezca ese recurso, recibirá un error similar al siguiente: "Las SKU siguientes han producido un error en las restricciones de capacidad: Standard_DS1_v2" no está disponible actualmente en la ubicación "westus".

Este es el ejemplo de error 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 corregir el error, cambie la ubicación o seleccione un valor de parámetro diferente que se ofrezca para la ubicación deseada.

Consulte también