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 환경에서는 해당 foreach
및 if (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
, -gt
not >
, 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."}]}}
오류를 수정하려면 위치를 변경하거나 원하는 위치에 대해 제공되는 다른 매개 변수 값을 선택합니다.
참고 항목
Azure CLI