Azure CLI: 데이터 디스크 복제 및 VM 생성 스크립트

Background

이번에는 원본 Virtual Machine을 이미지로 만들어서 총 9대의 Virtual Machine을 만들어 달라는 신청이 들어왔다. 처음에는 OsDisk와 DataDisk 모두 일반화 (Sysprep 사용) 하여 마스터 이미지를 만들어서 배포할 생각이었는데, 그렇게 하면 DataDisk의 리소스 이름이 자동설정되어 사내 정책과 맞지 않는다는 이유로 수동으로 만들게 되었다.

..너무 귀찮잖아

주말에 심심하기도 하고, 원본 DataDisk의 Snapshot을 사용하여 Managed Disk 를 만드는 스크립트를 만들어 보려고 한다.

대충 흐름도인 것..

Step.1: Data Disk 스냅샷 두 개 만들기

Azure Portal 에서 Data Disk의 스냅샷을 생성한다. 어차피 원본 두 개만 필요하기 때문에 Azure Portal 에서 빠르게 만들어 준다.

Tip. 스냅샷 페이지에서 [+Create disk]를 선택하여, Azure Portal 에서 관리 디스크를 만들 수 있다.

Source Data Disk Snapshot x2

Step2: VM 이미지 만들기

Data Disk 제거하기

Virtual Machine Disk Management

Data Disk를 포함한 상태에서 Virtual Machine 일반화를 실행하면, Data Disk가 예약되므로 Dettach 한 후에 일반화한다.

Azure Portal 에서 Dettach 버튼을 선택한 후 설정을 저장한다.

DataDisk_0 볼륨이 사라져 있다.

Windows 일반화 (Sysprep) 실행

Tip. 일반화 실행 후 VM은 사용 불가능하므로 필요하다면 백업을 한다.

Microsoft Learn Sysprep Link

%WINDIR%\system32\sysprep\sysprep.exe /generalize /shutdown /oobe
Command Prompt

Tip. PowerShell 에서는 동일한 명령어 실행이 불가능하므로 주의

PowerShell

Azure Computing Gallery 이미지 등록

Tip. Virtual Machine 과 동일한 Subscription 의 Azure Computing Gallery 에만 이미지를 등록할 수 있다.

Virtual Machine의 이미지 정의 및 등록은 간단하므로 설명은 생략한다.

등록된 Virtual Machine 이미지

Step3: Virtual Machine 복제하기

GitHub Link

# Source resource variable

# Source resource variable
$rg_name = "system-1"
$vm_name = "azrwin-1"

원본 리소스에 관련된 Resource group, Virtual machine 의 이름을 지정한다.

# Replication resource variable

# Replication resource variable
$location = "japaneast" 
$rep_rg_name = "system-2"
$rep_vm_names = @("azrwin-2", "azrwin-3")
$rep_vm_size = "Standard_DS1_v2"
$rep_disk_sku = "StandardSSD_LRS"
$rep_disk_size = 4
$rep_vnet_name = "system-2-vnet"
$rep_subnet_name = "subnet-1"
$rep_subnet_id = az network vnet subnet list --resource-group $rep_rg_name --vnet-name $rep_vnet_name --query "[?contains(name, '$rep_subnet_name')].id" -o tsv

Virtual Machine 의 복제를 만들기 위해서 필요한 변수 값이다.

Tip. 사용자 정의로 필요에 따라서 수정하면 된다.

# Get image definition ID

# Get image definition ID
$img_def_id = az sig image-definition list --resource-group $rg_name --gallery-name 'win_gal' --query "[?contains(name, '$vm_name')].id" -o tsv

원본 Virtual Machine의 이미지 정의의 ID 값을 가져온다.

# Get snapshot IDs

# Get snapshot IDs
$snapshot_ids = az snapshot list --resource-group $rg_name --query "[?contains(name, '$vm_name') && contains(name, 'DataDisk')].id" -o tsv | Out-String -Stream | ForEach-Object { $_.Trim() }

Data Disk의 스냅샷 ID값을 가져온다. 원본 Virtual Machine과 DataDisk의 이름으로 필터링하여 값을 저장한다.

# Create disks and VMs for each replication VM name

# Create disks and VMs for each replication VM name
foreach ($rep_vm_name in $rep_vm_names) {
  $data_disk_names = @()
  $i = 0

  # Create data disk for each snapshot
  $i = 0
  foreach ($snapshot_id in $snapshot_ids) {
    $data_disk_name = "${rep_vm_name}_DataDisk_$i"
    az disk create --resource-group $rep_rg_name `
      --name $data_disk_name `
      --sku $rep_disk_sku `
      --size-gb $rep_disk_size `
      --source $snapshot_id

    $data_disk_names += $data_disk_name
    $i++
  }

$snapshot_ids의 개수 만큼 Data disk를 작성하고, Virtual Machine에 Attach 한다.

$rep_vm_names의 개수 만큼 Virtual Machine을 배포한다.

 # Create network interface card

  # Create network interface card
  $rep_nic_name = "${rep_vm_name}-nic"
  az network nic create --resource-group $rep_rg_name `
    --name $rep_nic_name `
    --subnet $rep_subnet_id `
    --accelerated-networking true

  $rep_nic_id = az network nic list --query "[?name=='$rep_nic_name'].id" -o tsv

Tip. 필요없다면 삭제해도 되는 부분 (파라메터 값을 지정하지 않으면 자동으로 생성된다.)

각 Virtual Machine에 할당할 Network Interface Card 를 생성하고, 리소스 ID를 저장한다.

# Create VM

  # Create VM
  az vm create --resource-group $rep_rg_name `
    --name $rep_vm_name `
    --size $rep_vm_size `
    --image $img_def_id `
    --attach-data-disks $data_disk_names `
    --location $location `
    --admin-username "azureuser" `
    --admin-password "P@ssW0rd2024#01#21" `
    --nics $rep_nic_id `
    --security-type TrustedLaunch
}

위에서 작성한 리소스를 가져다가 복제 Virtual Machine을 생성한다.

Script 실행 결과

PS C:\Users\cchi9\OneDrive\Vscode\azure-cli\virtualMachine> .\New-ReplicationVMwithSnapshot.ps1
{
  "burstingEnabled": null,
  "burstingEnabledTime": null,
  "completionPercent": null,
  "creationData": {
    "createOption": "Copy",
  .. Skip
  {
  "fqdns": "",
  "id": "/subscriptions/0b5f5005-c30c-4a28-89c1-9457d0cd5e0f/resourceGroups/system-2/providers/Microsoft.Compute/virtualMachines/azrwin-2",
  "location": "japaneast",
  "macAddress": "00-22-48-E7-B5-34",
  "powerState": "VM running",
  "privateIpAddress": "10.0.0.4",
  "publicIpAddress": "",
  "resourceGroup": "system-2",
  "zones": ""
}