Azure CLI を使用して大規模なリソースを作成する方法
Azure リソース マネージャーは、新しい環境を構成するときに、複数の Azure リソースを作成する必要がある場合がよくあります。 スクリプトから Azure リソースが自動的に作成されるときに最適な Azure リソース承認プロセスがある場合もあります。
この記事では、次の内容について説明します。
- 区切り CSV ファイルから受信したパラメーターから複数の Azure リソースを作成します。
- IF を使用します。.依存する Azure リソースを作成するための THEN ステートメント。
- スクリプトの進行状況をローカル TXT ファイルに記録します。
このサンプル スクリプトは、Bash と PowerShell の両方の環境で Azure Cloud Shell および PowerShell 7 でテストされています。 csv と完全なスクリプトについては、 Azure-samples/azure-cli-samples を参照してください。
環境を準備する
サンプル スクリプトを実行する環境を準備するには、次の手順に従います。
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]
Note
適切な Unix テキスト ファイルとして Bash で読み取るために、CSV ファイルには最後のデータ行の末尾に改行文字が必要です。 これにより、ファイルの末尾に空白行が表示されます。 このテキストは空の行が存在することを示すためにのみ提供されるため、空白行は
[empty line]
を言う必要はありません。 PowerShell 環境には、この改行文字の要件はありません。変更した CSV ファイルを Azure Cloud Shell ブログ ストレージ アカウントにアップロードします。 これを行う最も簡単な方法は、Azure Cloud Shell のメイン メニューで Manage ファイル ドロップダウンを使用することです。 Cloud Shell ストレージの詳細については、「Azure Cloud Shell の Persist ファイル」を参照してください。
スクリプトの概要
この記事では、1 つの大きなスクリプトを 4 つのセクションに分割して、各手順について説明します。
- 変数の設定
- データ検証
- ループ検証
- Azure リソースの作成
また、Bash 用と PowerShell 用の 2 つのスクリプトも用意されています。 どちらのスクリプトも同じ Azure CLI コマンドを使用します。 異なるのは環境またはターミナル プロファイルです。 たとえば、Bash では do...done
と if...then...fi
が使用されます。 PowerShell 環境では、同等の foreach
と if (something is true)...{do this}
を使用します。 Azure Cloud Shell では、Azure Cloud Shell のメイン メニューの Switch to PowerShell または Switch to Bash ボタンを使用して環境を切り替えることができます。
必要に応じて、 Azure-samples/azure-cli-samples のこの記事で使用される CSV ファイルとスクリプト ファイルに直接移動します。
変数の設定
まず、スクリプトに必要な変数を作成します。 次の 3 つの変数には、実際の環境の値が必要です。
- 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 ステートメントを使用すると、一度に 1 つのシナリオ/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
ランダム ID はテストごとに異なります)。
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 を使用すると、検証の出力は次のようになります ( 00000001, 2, 3
ランダム ID はテストごとに異なりますが、各 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
を使用してテストの実行を完了しました。 スクリプトの 4 番目と最後の部分を実行して、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 では、手順 1 の後に "Azure リソースの作成" ステップが停止します
Ubuntu 22.04.3 LTS および Debian バージョン 12 (bookworm) では、 Validate スクリプト ロジック は、3 つのリソースすべてに対して期待どおりに結果を返します。 ただし、 Azure リソースの作成 は最初のリソースの後で停止します。 この問題の原因として考えられるのは、手順 1 で VNet を作成するのに数秒かかる場合です。 Ubuntu と Debian の両方が、VNet の完了を待たずに 2 番目のリソースに進みます。 この詳細については、wait が while ループ内のプロセスが完了するのを待たないか bash スクリプトでプロセスが完了するまで待機します。
Bash スクリプトで IF ステートメントが無視される
Bash では大文字と小文字が区別されます。 true
という単語はTRUE
と等しくありません。 また、greater than
は>
ではなく-gt
であり、equals
は=
ではなく==
です。 CSV 列の値に文字体裁エラーや先頭/末尾のスペースがないことを確認します。
変数の値は各ループで変更されない
これは多くの場合、CSV ファイル内の余分なスペースが原因で発生します。 CSV ファイル内の行は、 column1,column2,column3
または column1,,column3
のようになりますが、習慣によって、 column1, column2, column3
のようにコンマの後にスペースを含むテスト ファイルを簡単に作成できます。 CSV に先頭または末尾のスペースがある場合、列の値は実際には <space>columnValue
。 スクリプト ロジック if [ "$columnName" = "columnValue" ]
は "false" を返します。 CSV 行の先頭と末尾のすべてのスペースを削除して、問題を解決します。
無効な CIDR 表記
正しくないアドレス プレフィックスをaz network vnet create
に渡すと、InvalidCIDRNotation エラーが発生します。 これは、 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 が参照コマンドを誤って解析する原因となる文字体裁エラーがある場合に発生します。 スクリプトを使用する場合は、次のいずれか 1 つが当てはまる場合にも、このエラーが発生します。
- 行連結文字が見つからないか、正しくありません。
- 行連結文字の右側には末尾のスペースがあります。
- 変数名には、ダッシュ (
-
) などの特殊文字が含まれています。
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