Freigeben über


So wird's ausgeführt: Erstellen von Ressourcen im großen Maßstab mithilfe der Azure CLI

Als Azure-Ressourcenmanager müssen Sie häufig mehrere Azure-Ressourcen erstellen, wenn Sie neue Umgebungen konfigurieren. Möglicherweise verfügen Sie auch über einen Azure-Ressourcengenehmigungsprozess, der am besten funktioniert, wenn Azure-Ressourcen automatisch aus einem Skript erstellt werden.

In diesem Artikel erfahren Sie Folgendes:

  • Erstellen Sie mehrere Azure-Ressourcen aus Parametern, die von einer durch Trennzeichen getrennten CSV-Datei empfangen werden.
  • Verwenden Sie IF.. THEN-Anweisungen zum Erstellen abhängiger Azure-Ressourcen.
  • Protokollskriptfortschritt bei einer lokalen TXT-Datei.

Dieses Beispielskript wurde in Azure Cloud Shell sowohl in Bash- als auch in PowerShell-Umgebungen und PowerShell 7 getestet. Suchen Sie die CSV-Datei und das vollständige Skript in Azure-Samples/azure-cli-Samples.

Vorbereiten der Umgebung

Führen Sie die folgenden Schritte aus, um Ihre Umgebung für die Ausführung des Beispielskripts vorzubereiten:

  • Öffnen Sie entweder die Bash- oder PowerShell-Umgebung in Azure Cloud Shell. Weitere Informationen finden Sie unter Schnellstart für Bash in Azure Cloud Shell.

  • Laden Sie die folgende CSV-Datei herunter, und speichern Sie es in einem lokalen Verzeichnis. Ersetzen Sie myExistingResourceGroupName in Zeile 3 durch einen tatsächlichen Ressourcengruppennamen.

    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]
    

    Hinweis

    Um eine richtige Unix-Textdatei zu sein und von Bash gelesen zu werden, benötigt die CSV-Datei am Ende der letzten Datenzeile ein Zeilenumbruchzeichen. Dies führt zu einer leeren Zeile am Ende der Datei. Ihre leere Zeile muss nicht sagen [empty line] , da dieser Text nur bereitgestellt wird, um Ihnen zu zeigen, dass eine leere Zeile vorhanden ist. PowerShell-Umgebungen verfügen nicht über diese Anforderung für Neueinbruchzeichen.

  • Laden Sie Ihre geänderte CSV-Datei in Ihr Azure Cloud Shell-Blogspeicherkonto hoch. Die einfachste Möglichkeit hierfür ist die Verwendung der Dropdownliste "Dateien verwalten" im Hauptmenü der Azure Cloud Shell. Weitere Informationen zum Cloud Shell-Speicher finden Sie unter Speichern von Dateien in Azure Cloud Shell.

Skriptübersicht

In diesem Artikel wird ein einzelnes großes Skript in vier Abschnitte unterteilt, sodass jeder Schritt erläutert werden kann.

  • Variable Einrichtung
  • Datenvalidierung
  • Schleifenüberprüfung
  • Azure-Ressourcenerstellung

Es gibt auch zwei Skripts: eine für Bash und die zweite für PowerShell. Beide Skripts verwenden dieselben Azure CLI-Befehle. Es handelt sich um die Umgebung oder das Terminalprofil, das anders ist. Bash verwendet do...done z. B. und if...then...fi. In einer PowerShell-Umgebung verwenden Sie die Entsprechung foreach und if (something is true)...{do this}. In Azure Cloud Shell können Sie zwischen Umgebungen wechseln, indem Sie die Schaltfläche "Zu PowerShell wechseln" oder im Hauptmenü der Azure Cloud Shell zu Bash wechseln.

Wenn Sie es vorziehen, wechseln Sie direkt zu den CSV- und Skriptdateien, die in diesem Artikel in Azure-Samples/azure-cli-samples verwendet werden.

Festlegen von Variablen

Beginnen Sie, indem Sie die für das Skript erforderlichen Variablen erstellen. Die folgenden drei Variablen benötigen tatsächliche Werte für Ihre Umgebung:

  • subscriptionID: Dies ist Ihre Azure-Abonnement-ID.
  • csvFileLocation: Dies ist der Speicherort und Dateiname Ihrer CSV-Eingabedatei.
  • logFileLocation: Dies ist der Speicherort und der Dateiname , den das Skript zum Erstellen einer Protokolldatei verwendet. Sie müssen diese Datei nicht erstellen oder hochladen.

Variablen mit einem msdocs- Präfix können durch das Präfix Ihrer Wahl ersetzt werden. Alle leeren ("") Variablen verwenden Werte aus der CSV-Eingabedatei. Diese leeren Variablen sind Platzhalter, die vom Skript benötigt werden.

# 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

Überprüfen von CSV-Dateiwerten

Bevor Sie mit dem Testen des Erstellungsskripts beginnen, stellen Sie sicher, dass Ihre CSV-Datei richtig formatiert ist, und Variablen werden die richtigen Werte zugewiesen. Dieses Skript verwendet ein IF.. THEN-Anweisung, damit Sie jeweils eine Szenario-/CSV-Zeile anzeigen können.

# 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)

Mithilfe der in diesem Artikel bereitgestellten CSV-Datei lautet die Überprüfungsausgabe wie folgt: (Die 00000001 zufällige ID wird für jeden Test unterschiedlich sein.)

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

Überprüfen der Skriptlogik

Wenn Sie mit Ihren Skriptfähigkeiten vertraut sind, können Sie diesen Schritt überspringen. Da dieses Skript jedoch so konzipiert ist, dass Azure-Ressourcen im großen Maßstab erstellt werden, können Sie durch das Skript mit echo oder write-host Anweisungen zeitsparend und unerwartete, abrechnende Azure-Ressourcen sparen.

Es gibt mehrere Möglichkeiten zum Durchlaufen einer CSV-Datei mithilfe von Bash. In diesem Beispiel wird IFS mit einer 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

Mithilfe der in diesem Artikel bereitgestellten CSV-Datei lautet die Überprüfungsausgabe wie folgt: (Die 00000001, 2, 3 zufälligen IDs sind für jeden Test unterschiedlich, aber jede Ressource unter jedem resourceNo sollte die gleiche zufällige ID aufweisen.)

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>

Erstellen von Azure-Ressourcen

Sie haben nun ihren Variablenblock erstellt, Ihre CSV-Werte überprüft und eine Testausführung mit echo oder write-hostabgeschlossen. Führen Sie den vierten und letzten Teil des Skripts aus, um Azure-Ressourcen gemäß definition in Ihrer CSV-Eingabedatei zu erstellen.

# 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

Fehlt in der Konsolenausgabe die letzte Zeile in der CSV-Datei? Dies kann durch ein fehlendes Zeilenfortsetzungszeichen nach der letzten Zeile verursacht werden. Fügen Sie am Ende der CSV-Datei eine leere Zeile hinzu, um das Problem zu beheben.

Konsolenausgabe vor dem Lesen der Protokolldatei:

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

Der Inhalt der Protokolldatei sollte etwa wie folgt aussehen:

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
  }

Problembehandlung

In Bash wird der Schritt "Azure-Ressourcen erstellen" nach Schritt 1 beendet.

In Ubuntu 22.04.3 LTS und Debian Version 12 (Buchwurm) funktioniert die Validate-Skriptlogik wie erwartet, die Ergebnisse für alle drei Ressourcen zurückgibt. Die Azure-Ressourcen werden jedoch nach der ersten Ressource beendet. Ein möglicher Grund für dieses Problem ist, dass das Erstellen des VNet in Schritt 1 einige Sekunden dauert. Sowohl Ubuntu als auch Debian fahren mit der zweiten Ressource fort, ohne auf den Abschluss des VNet zu warten. Weitere Informationen hierzu finden Sie unter "Warten" nicht, bis die Prozesse in der Schleife abgeschlossen sind oder auf den Abschluss eines Prozesses im Bash-Skript warten.

Bash-Skript ignoriert IF-Anweisung

Bei Bash wird die Groß-/Kleinschreibung beachtet. Das Wort true ist nicht gleich TRUE. Auch greater than ist -gt, nicht >, und equals ist ==, nicht =. Stellen Sie sicher, dass sie keinen typografischen Fehler oder führende/nachfolgende Leerzeichen in Ihren CSV-Spaltenwerten haben.

Variablenwerte ändern sich nicht mit jeder Schleife.

Dies wird häufig durch zusätzliche Leerzeichen in der CSV-Datei verursacht. Eine Zeile in einer CSV-Datei sieht ungefähr wie folgt aus: column1,column2,column3 oder column1,,column3, aber üblich ist es einfach, eine Testdatei zu erstellen, die nach jedem Komma ein Leerzeichen enthält column1, column2, column3. Wenn Sie einen führenden oder nachfolgenden Leerraum in Ihrer CSV haben, ist der Spaltenwert tatsächlich <space>columnValue. Die Skriptlogik if [ "$columnName" = "columnValue" ] gibt "false" zurück. Entfernen Sie alle führenden und nachfolgenden Leerzeichen in Ihren CSV-Zeilen, um das Problem zu beheben.

Ungültige CIDR-Schreibweise

Sie erhalten einen InvalidCIDRNotation-Fehler , wenn Sie ein falsches Adresspräfix an az network vnet create. Dies kann schwierig sein, wenn das Adresspräfix visuell korrekt aussieht, wenn es in einer echo Anweisung zurückgegeben wird. Um probleme mit dem tatsächlichen Wert zu beheben, der aus der CSV gelesen wird, versuchen Sie folgendes Skript:

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)

Wenn Ihre Ergebnisse wie xzy10.0.0.0 erwartet aussehen und nicht abc10.0.0.0/24xyz, gibt es möglicherweise ein ausgeblendetes Zeichen oder ein zusätzliches Komma, das in Ihrer CSV-Datei lauert. Fügen Sie eine Testspalte mit demselben Präfixwert hinzu, ordnen Sie Ihre CSV-Spalten neu an, und kopieren/einfügen Sie ihre CSV-Inhalte in/aus einem einfachen Editor für Editoren. In diesem Artikel wurde der Fehler durch die Neuanordnung der CSV-Spalten behoben.

Argumente werden erwartet oder erforderlich

Sie erhalten diesen Fehler, wenn Sie keinen erforderlichen Parameter angegeben haben oder ein typografischer Fehler vorliegt, der dazu führt, dass die Azure CLI den Verweisbefehl falsch analysiert. Wenn Sie mit einem Skript arbeiten, erhalten Sie diesen Fehler auch, wenn einer der folgenden Werte zutrifft:

  • Es ist ein fehlendes oder falsches Zeilenfortsetzungszeichen vorhanden.
  • Auf der rechten Seite eines Zeilenfortsetzungszeichens befinden sich nachfolgende Leerzeichen.
  • Der Variablename enthält ein Sonderzeichen, z. B. einen Gedankenstrich (-).

InvalidTemplateDeployment

Wenn Sie versuchen, eine Azure-Ressource an einem Speicherort zu erstellen, der diese Ressource nicht anbietet, erhalten Sie eine Fehlermeldung wie die folgenden: "Die folgenden SKUs sind für Kapazitätseinschränkungen fehlgeschlagen: Standard_DS1_v2" ist derzeit nicht am Standort "westus" verfügbar."

Hier sehen Sie das vollständige Fehlerbeispiel:

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

Um den Fehler zu beheben, ändern Sie entweder den Speicherort, oder wählen Sie einen anderen Parameterwert aus, der für Den gewünschten Standort angeboten wird.

Siehe auch