Azure CLI를 사용하여 대규모로 리소스를 만드는 방법

Azure 리소스 관리자는 새 환경을 구성할 때 여러 Azure 리소스를 만들어야 하는 경우가 많습니다. 스크립트에서 Azure 리소스를 자동으로 만들 때 가장 적합한 Azure 리소스 승인 프로세스가 있을 수도 있습니다.

이 문서에서는 다음을 알아봅니다.

  • 구분된 CSV 파일에서 받은 매개 변수에서 여러 Azure 리소스를 만듭니다.
  • IF.를 사용합니다. 종속 Azure 리소스를 만드는 THEN 문입니다.
  • 로컬 TXT 파일에 스크립트 진행률을 기록합니다.

이 샘플 스크립트는 Bash 및 PowerShell 환경과 PowerShell 7 모두에서 Azure Cloud Shell에서 테스트되었습니다. Azure-samples/azure-cli-samples에서 CSV 및 전체 스크립트를 찾습니다.

환경 준비

다음 단계에 따라 예제 스크립트를 실행하도록 환경을 준비합니다.

  • Azure Cloud Shell에서 Bash 또는 PowerShell 환경을 엽니다. 자세한 내용은 Azure Cloud Shell의 Bash에 대한 빠른 시작을 참조하세요.

  • 다음 CSV 파일을 다운로드하여 로컬 디렉터리에 저장합니다. 3줄에서 실제 리소스 그룹 이름으로 바꿉 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는 다음을 if...then...fi사용합니다do...done. PowerShell 환경에서는 해당 foreachif (something is true)...{do this}.를 사용합니다. Azure Cloud Shell에서 PowerShell로 전환 또는 Azure Cloud Shell 주 메뉴의 Bash로 전환 단추를 사용하여 환경 간에 전환할 수 있습니다.

원하는 경우 Azure-samples/azure-cli-samples에서 이 문서에서 사용하는 CSV 및 스크립트 파일로 직접 이동합니다.

변수 설정

스크립트에 필요한 변수를 만들어 시작합니다. 다음 세 가지 변수에는 사용자 환경에 대한 실제 값이 필요합니다.

  • subscriptionID: Azure 구독 ID입니다.
  • 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를 사용하여 유효성 검사 출력은 다음과 같습니다.(임의 ID는 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 리소스를 만들도록 설계되었기 때문에 스크립트를 사용 echo 하거나 write-host 문을 사용하여 반복하면 시간과 예기치 않은 청구 가능 Azure 리소스를 절약할 수 있습니다.

Bash를 사용하여 CSV 파일을 반복하는 방법에는 여러 가지가 있습니다. 이 예제에서는 .와 while loop함께 사용합니다IFS.

# 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를 사용하여 유효성 검사 출력은 다음과 같습니다. (임의 ID는 00000001, 2, 3 각 테스트마다 다르지만 각 resourceNo 테스트의 각 리소스는 동일한 임의 ID를 공유해야 합니다.)

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 값의 유효성을 검사하고, 테스트 실행을 echo 완료했습니다 write-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 및 Debian 버전 12(bookworm) 에서 유효성 검사 스크립트 논리 는 세 리소스 모두에 대해 예상된 반환 결과로 작동합니다. 그러나 Azure 리소스 만들기는 첫 번째 리소스 이후에 중지됩니다 . 이 문제의 가능한 이유는 1단계에서 VNet을 만드는 데 몇 초 정도 걸리기 때문입니다. Ubuntu와 Debian은 모두 VNet 완료를 기다리지 않고 두 번째 리소스로 진행합니다. 대기 중 루프의 프로세스가 완료될 때까지 기다리지 않거나 bash 스크립트에서 프로세스가 완료될 때까지 기다리지 않음에서 이에 대해 자세히 읽을 수 있습니다.

Bash 스크립트가 IF 문을 무시합니다.

Bash는 대/소문자를 구분합니다. 단어 true 는 같지 TRUE않습니다. 또한 greater than , -gtnot >, and equals is ==, not =. CSV 열 값에 입력 오류 또는 선행/후행 공백이 없는지 확인합니다.

변수 값은 각 루프에서 변경되지 않습니다.

이는 CSV 파일의 추가 공백으로 인해 발생하는 경우가 많습니다. CSV 파일의 줄은 다음과 column1,column2,column3 column1,,column3같이 표시되지만 습관에 따라 각 쉼표 뒤의 공백이 포함된 테스트 파일을 쉽게 만들 수 있습니다 column1, column2, column3. CSV에 선행 또는 후행 공간이 있는 경우 열 값은 실제로 <space>columnValue입니다. 스크립트 논리 if [ "$columnName" = "columnValue" ] 는 "false"를 반환합니다. CSV 행의 선행 및 후행 공백을 모두 제거하여 문제를 해결합니다.

잘못된 CIDR 표기법

잘못된 주소 접두사를 전달할 때 InvalidCIDRNotation 오류가 발생합니다 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)

결과가 예상abc10.0.0.0/24xyz과 다르게 표시되는 xzy10.0.0.0 경우 CSV 파일에 숨겨진 문자 또는 추가 쉼표가 숨어 있을 수 있습니다. 접두사 값이 동일한 테스트 열을 추가하고, CSV 열을 다시 정렬하고, 간단한 메모장 편집기에서 CSV 콘텐츠를 복사/붙여넣습니다. 이 문서를 작성할 때 CSV 열의 다시 정렬이 마침내 오류를 수정했습니다.

인수가 필요하거나 필요합니다.

필수 매개 변수를 제공하지 않았거나 Azure CLI가 참조 명령을 잘못 구문 분석하도록 하는 입력 체계 오류가 있는 경우 이 오류가 발생합니다. 스크립트로 작업할 때 다음 중 하나 이상이 true인 경우에도 이 오류가 발생합니다.

  • 줄 연속 문자가 없거나 잘못되었습니다.
  • 줄 연속 문자의 오른쪽에는 후행 공백이 있습니다.
  • 변수 이름에는 대시(-)와 같은 특수 문자가 포함됩니다.

InvalidTemplateDeployment

해당 리소스를 제공하지 않는 위치에 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."}]}}

오류를 수정하려면 위치를 변경하거나 원하는 위치에 대해 제공되는 다른 매개 변수 값을 선택합니다.

참고 항목