共用方式為


如何使用 Azure CLI 大規模建立資源

身為 Azure 雲端資源管理員,在設定新環境時,您經常必須建立多個 Azure 資源。 當 Azure 資源自動從文稿建立時,您可能也會有最適合的 Azure 資源核准程式。

在本文中,您將瞭解下列項目:

  • 從從分隔 CSV 檔案收到的參數建立多個 Azure 資源。
  • 使用 IF.。THEN 語句來建立相依的 Azure 資源。
  • 將腳本進度記錄到本機 TXT 檔案。

此範例腳本已在 Azure Cloud Shell 中使用 Bash 和 PowerShell 環境,以及 PowerShell 7 進行測試。 在 Azure-samples/azure-cli-samples 中尋找 CSV 和完整腳本。

準備您的環境

請遵循下列步驟來準備您的環境,以執行範例腳本:

  • Azure Cloud Shell 中開啟 Bash 或 PowerShell 環境。 如需詳細資訊,請參閱 Azure Cloud Shell 中的 Bash 快速入門

  • 將下列 CSV 檔案下載並儲存至本機目錄。 以實際的資源組名取代 myExistingResourceGroupName 第三行。

    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]
    

    備註

    若要成為合適的 Unix 文字檔並供 Bash 讀取,CSV 檔案的最後一行數據後需要有一個換行字元。 這會導致檔案結尾處有一個空白行。 您的空白行中不需要顯示[empty line],此文字僅供以顯示空白行確實存在。 PowerShell 環境沒有這個換行符需求。

  • 將修改過的 CSV 檔案上傳至 Azure Cloud Shell 部落格記憶體帳戶。 若要這樣做,最簡單的方式是使用 Azure Cloud Shell 主功能表上的 [ 管理檔案 ] 下拉式清單。 如需 Cloud Shell 儲存的詳細資訊,請參閱 在 Azure Cloud Shell 中保留檔案

腳本概觀

本文會將單一大型腳本分成四個區段,以便說明每個步驟。

  • 變數設定
  • 資料驗證
  • 循環驗證
  • Azure 資源建立

另外還有兩個腳本提供:一個用於Bash,另一個用於PowerShell。 這兩個腳本都會使用相同的 Azure CLI 命令。 是環境或終端設定檔不同。 例如,Bash 會使用 do...doneif...then...fi。 在 PowerShell 環境中,您會使用 foreachif (something is true)...{do this} 的等價項。 在 Azure Cloud Shell 中,您可以使用 [ 切換至 PowerShell ] 或 Azure Cloud Shell 主功能表中 的 [切換至 Bash] 按鈕,在環境之間切換。

如果您想要的話,請直接移至本文在 Azure-samples/azure-cli-samples 中使用的 CSV 和腳本檔案。

設定變數

首先,建立腳本的必要變數。 下列三個變數需要您環境的實際值:

  • subscriptionID:這是您的 Azure 訂用帳戶標識碼。
  • csvFileLocation:這是 CSV 輸入檔的位置和檔名。
  • logFileLocation:這是 腳本用來建立記錄檔的位置和檔名。 您不需要建立或上傳此檔案。

具有 msdocs- 前置詞的變數可以取代為您選擇的前置詞。 所有空白 ("") 變數都會使用 CSV 輸入檔中的值。 這些空白變數充當腳本所需的佔位符。

# 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

驗證 CSV 檔案值

開始測試文本之前,請確定 CSV 檔案的格式正確,且變數已指派正確的值。 此腳本會使用 IF..THEN 語句,以便一次查看一個案例/CSV 行。

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

使用本文中提供的 CSV,驗證輸出如下所示:( 00000001 每個測試的隨機標識碼不同。

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

驗證腳本邏輯

如果您對自己編寫腳本的能力有信心,您可以略過此步驟。 不過,由於此腳本是設計來大規模建立 Azure 資源,因此使用 echowrite-host 語句來循環執行腳本,可以節省時間並避免創建非預期的可計費 Azure 資源。

有多種方式可以使用 Bash shell 遍歷 CSV 檔案。 這個範例使用 IFSwhile 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

使用本文中提供的 CSV,驗證輸出如下所示:( 00000001, 2, 3 每個測試的隨機標識碼不同,但每個 resourceNo 下的每個資源都應該共用相同的隨機識別符。

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>

建立 Azure 資源

您已建立變數區塊、驗證 CSV 值,並完成使用echowrite-host的測試運行。 執行腳本的第四個和最後部分,以建立 CSV 輸入檔中所定義的 Azure 資源。

# 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

在主控台輸出中,您是否遺漏 CSV 檔案中的最後一個資料列? 此問題可能是最後一行之後遺漏行接續字元所造成。 若要修正此問題,請在 CSV 檔案結尾新增空白行。

主控台輸出 之前的 讀取記錄檔:

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

您的記錄檔內容看起來應該像下列輸出:

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
  }

故障排除

在Bash中,「建立 Azure 資源」步驟會在步驟 1 之後停止

在Ubuntu 22.04.3 LTS和Debian12版(bookworm)中, 驗證腳本邏輯 會如預期般運作,並傳回這三個資源的結果。 不過, 建立 Azure 資源 會在建立第一個資源之後停止。 此問題的可能原因是在步驟 1 中建立 VNet 需要幾秒鐘的時間。 Ubuntu 和 Debian 都會繼續進行第二個資源,而不需要等待 VNet 完成。 您可以進一步了解這些內容,請參閱 wait 不能為 while 循環中的進程完成在 bash 腳本中等候任何進程完成

Bash 腳本會忽略 IF 語句

Bash 會區分大小寫。 這個字 true 不等於 TRUE。 此外greater than-gt,而不是>,而equals==,不是=。 請確定您的 CSV 資料行值中沒有印刷錯誤或前置/尾端空格。

變數值不會隨著每個迴圈而變更

此問題通常是由 CSV 檔案中的額外空間所造成。 CSV 檔案中的一行看起來像這樣: column1,column2,column3column1,,column3,但根據習慣,很容易建立測試檔案,其中包含每個逗號後面的空格,例如 column1, column2, column3。 當您的 CSV 中有前置或尾端空格時,資料行值實際上是 <space>columnValue。 腳本邏輯 if [ "$columnName" = "columnValue" ] 會傳回 「false」。 若要修正此問題,請移除 CSV 數據列中的所有前置和尾端空格。

無效的 CIDR 表示法

當您將不正確的地址前綴傳遞至 時,您會收到 az network vnet create 錯誤。 當地址前綴在語句中echo傳回時,視覺上看起來是正確的卻可能具有挑戰性。 若要針對從 CSV 讀取的實際值進行疑難解答,請嘗試此腳本:

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)

如果您的結果看起來像 xzy10.0.0.0 ,而不是預期的 abc10.0.0.0/24xyz,則 CSV 檔案中可能會有隱藏字元或額外的逗號。 新增具有相同前置詞值的測試數據行、重新排列 CSV 數據行,以及複製/貼上簡單的記事本編輯器中的 CSV 內容。 在本文中,CSV 資料行的重新排列最終修正了錯誤。

預期或必需的參數

當您未提供必要的參數,或有印刷錯誤導致 Azure CLI 錯誤剖析參考命令時,就會收到此錯誤。 當使用腳本時,若下列其中一項為真,您也會收到此錯誤:

  • 有遺漏或不正確的行接續字元。
  • 行接續字元右邊有尾端空格。
  • 您的變數名稱包含特殊字元,例如虛線 (-)。

無效的模板部署

當您嘗試在未提供該資源的位置中建立 Azure 資源時,您會收到類似下列訊息的錯誤:「容量限制的下列 SKU 失敗:Standard_DS1_v2』目前無法在位置 'westus' 中使用。

以下是完整的錯誤範例:

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

若要更正錯誤,請變更位置,或選取針對所需位置提供的不同參數值。

另請參閱