PowerShell: Azure'da sanal makine görüntüleri oluşturmak için Packer'ı kullanma

Şunlar için geçerlidir: ✔️ Windows VM'leri

Azure'daki her sanal makine (VM), Windows dağıtımını ve işletim sistemi sürümünü tanımlayan bir görüntüden oluşturulur. Görüntüler önceden yüklenmiş uygulamaları ve yapılandırmaları içerebilir. Azure Market, en yaygın işletim sistemi ve uygulama ortamları için birçok birinci ve üçüncü taraf görüntüsü sağlar veya ihtiyaçlarınıza göre uyarlanmış kendi özel görüntülerinizi oluşturabilirsiniz. Bu makalede, Azure'da özel görüntüler tanımlamak ve derlemek için açık kaynak araç Packer'ın nasıl kullanılacağı ayrıntılı olarak açıklanmaktadır.

Bu makale en son 5/8/2020 tarihinde Packer sürüm 1.8.1 kullanılarak test edilmiştir.

Not

Azure artık kendi özel görüntülerinizi tanımlamak ve oluşturmak için Azure Görüntü Oluşturucusu adlı bir hizmete sahiptir. Azure Image Builder, Packer üzerinde oluşturulmuş olduğundan, mevcut Packer kabuk sağlama betiklerinizi bile kullanabilirsiniz. Azure Görüntü Oluşturucusu'nu kullanmaya başlamak için bkz. Azure Görüntü Oluşturucusu ile Windows VM oluşturma.

Azure kaynak grubu oluşturma

Derleme işlemi sırasında Packer, kaynak VM'yi oluştururken geçici Azure kaynakları oluşturur. Bu kaynak VM'yi görüntü olarak kullanmak üzere yakalamak için bir kaynak grubu tanımlamanız gerekir. Packer derleme işleminin çıkışı bu kaynak grubunda depolanır.

New-AzResourceGroup ile bir kaynak grubu oluşturun. Aşağıdaki örnek eastus konumunda myPackerGroup adlı bir kaynak grubu oluşturur:

$rgName = "myPackerGroup"
$location = "East US"
New-AzResourceGroup -Name $rgName -Location $location

Azure kimlik bilgilerini oluşturma

Packer, hizmet sorumlusu kullanarak Azure'da kimlik doğrulaması yapar. Azure hizmet sorumlusu, Packer gibi uygulamalar, hizmetler ve otomasyon araçlarıyla kullanabileceğiniz bir güvenlik kimliğidir. Hizmet sorumlusunun Azure'da gerçekleştirebileceği işlemlere ilişkin izinleri denetler ve tanımlarsınız.

New-AzADServicePrincipal ile bir hizmet sorumlusu oluşturun. değerinin -DisplayName benzersiz olması gerekir; değerini gerektiği gibi kendi değerinizle değiştirin.

$sp = New-AzADServicePrincipal -DisplayName "PackerPrincipal" -role Contributor -scope /subscriptions/yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyy
$plainPassword = (New-AzADSpCredential -ObjectId $sp.Id).SecretText

Ardından parolayı ve uygulama kimliğini çıkış olarak kullanın.

$plainPassword
$sp.AppId

Azure'da kimlik doğrulaması yapmak için Get-AzSubscription ile Azure kiracınızı ve abonelik kimliklerinizi de edinmeniz gerekir:

$subName = "mySubscriptionName"
$sub = Get-AzSubscription -SubscriptionName $subName

Paketleyici şablonunu tanımlama

Görüntü oluşturmak için JSON dosyası olarak bir şablon oluşturursunuz. Şablonda, gerçek derleme işlemini gerçekleştiren oluşturucuları ve hazırlayıcıları tanımlarsınız. Packer, önceki adımda oluşturulan hizmet sorumlusu kimlik bilgileri gibi Azure kaynaklarını tanımlamanıza olanak tanıyan bir Azure oluşturucusu içerir.

windows.json adlı bir dosya oluşturun ve aşağıdaki içeriği yapıştırın. Aşağıdakiler için kendi değerlerinizi girin:

Parametre Nereden edinileceği
client_id Ile hizmet sorumlusu kimliğini görüntüleme $sp.AppId
client_secret Ile otomatik olarak oluşturulan parolayı görüntüleme $plainPassword
tenant_id Komutun çıktısı $sub.TenantId
subscription_id Komutun çıktısı $sub.SubscriptionId
managed_image_resource_group_name İlk adımda oluşturduğunuz kaynak grubunun adı
managed_image_name Oluşturulan yönetilen disk görüntüsünün adı
{
  "builders": [{
    "type": "azure-arm",

    "client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
    "client_secret": "ppppppp-pppp-pppp-pppp-ppppppppppp",
    "tenant_id": "zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz",
    "subscription_id": "yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyy",

    "managed_image_resource_group_name": "myPackerGroup",
    "managed_image_name": "myPackerImage",

    "os_type": "Windows",
    "image_publisher": "MicrosoftWindowsServer",
    "image_offer": "WindowsServer",
    "image_sku": "2016-Datacenter",

    "communicator": "winrm",
    "winrm_use_ssl": true,
    "winrm_insecure": true,
    "winrm_timeout": "5m",
    "winrm_username": "packer",

    "azure_tags": {
        "dept": "Engineering",
        "task": "Image deployment"
    },

    "build_resource_group_name": "myPackerGroup",
    "vm_size": "Standard_D2_v2"
  }],
  "provisioners": [{
    "type": "powershell",
    "inline": [
      "Add-WindowsFeature Web-Server",
      "while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
      "while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
      "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit",
      "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10  } else { break } }"
    ]
  }]
}

Ayrıca windows.pkr.hcl adlı bir dosya oluşturabilir ve yukarıdaki parametreler tablosu için kullanılan kendi değerlerinizle aşağıdaki içeriği yapıştırabilirsiniz.

source "azure-arm" "autogenerated_1" {
  azure_tags = {
    dept = "Engineering"
    task = "Image deployment"
  }
  build_resource_group_name         = "myPackerGroup"
  client_id                         = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
  client_secret                     = "ppppppp-pppp-pppp-pppp-ppppppppppp"
  communicator                      = "winrm"
  image_offer                       = "WindowsServer"
  image_publisher                   = "MicrosoftWindowsServer"
  image_sku                         = "2016-Datacenter"
  managed_image_name                = "myPackerImage"
  managed_image_resource_group_name = "myPackerGroup"
  os_type                           = "Windows"
  subscription_id                   = "yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyy"
  tenant_id                         = "zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz"
  vm_size                           = "Standard_D2_v2"
  winrm_insecure                    = true
  winrm_timeout                     = "5m"
  winrm_use_ssl                     = true
  winrm_username                    = "packer"
}

build {
  sources = ["source.azure-arm.autogenerated_1"]

  provisioner "powershell" {
    inline = ["Add-WindowsFeature Web-Server", "while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 }", "while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 }", "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit", "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10  } else { break } }"]
  }

}

Bu şablon bir Windows Server 2016 VM oluşturur, IIS yükler ve ardından Sysprep ile VM'yi genelleştirir. IIS yüklemesi, ek komutları çalıştırmak için PowerShell sağlamayı nasıl kullanabileceğinizi gösterir. Son Packer görüntüsü daha sonra gerekli yazılım yüklemesini ve yapılandırmasını içerir.

Windows Konuk Aracısı Sysprep işlemine katılır. VM'nin sysprep'edebilmesi için önce aracının tam olarak yüklü olması gerekir. Bunun doğru olduğundan emin olmak için, sysprep.exe yürütmeden önce tüm aracı hizmetlerinin çalışıyor olması gerekir. Yukarıdaki JSON kod parçacığı bunu PowerShell sağlamada gerçekleştirmenin bir yolunu gösterir. Bu kod parçacığı yalnızca VM aracıyı yükleyecek şekilde yapılandırılmışsa gereklidir ve bu varsayılan değerdir.

Derleme Paketi Oluşturucu görüntüsü

Yerel makinenizde Packer yüklü değilse Packer yükleme yönergelerini izleyin.

Görüntüyü oluşturmak için bir cmd istemi açın ve Packer şablon dosyanızı aşağıdaki gibi belirtin:

packer build windows.json

Görüntüyü aşağıdaki gibi windows.pkr.hcl dosyasını belirterek de oluşturabilirsiniz:

packer build windows.pkr.hcl

Yukarıdaki komutların çıktısının bir örneği aşağıdaki gibidir:

azure-arm output will be in this color.

==> azure-arm: Running builder ...
    azure-arm: Creating Azure Resource Manager (ARM) client ...
==> azure-arm: Creating resource group ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> Location          : ‘East US’
==> azure-arm:  -> Tags              :
==> azure-arm:  ->> task : Image deployment
==> azure-arm:  ->> dept : Engineering
==> azure-arm: Validating deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Deploying deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Getting the certificate’s URL ...
==> azure-arm:  -> Key Vault Name        : ‘pkrkvpq0mthtbtt’
==> azure-arm:  -> Key Vault Secret Name : ‘packerKeyVaultSecret’
==> azure-arm:  -> Certificate URL       : ‘https://pkrkvpq0mthtbtt.vault.azure.net/secrets/packerKeyVaultSecret/8c7bd823e4fa44e1abb747636128adbb'
==> azure-arm: Setting the certificate’s URL ...
==> azure-arm: Validating deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Deploying deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Getting the VM’s IP address ...
==> azure-arm:  -> ResourceGroupName   : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> PublicIPAddressName : ‘packerPublicIP’
==> azure-arm:  -> NicName             : ‘packerNic’
==> azure-arm:  -> Network Connection  : ‘PublicEndpoint’
==> azure-arm:  -> IP Address          : ‘40.76.55.35’
==> azure-arm: Waiting for WinRM to become available...
==> azure-arm: Connected to WinRM!
==> azure-arm: Provisioning with Powershell...
==> azure-arm: Provisioning with shell script: /var/folders/h1/ymh5bdx15wgdn5hvgj1wc0zh0000gn/T/packer-powershell-provisioner902510110
    azure-arm: #< CLIXML
    azure-arm:
    azure-arm: Success Restart Needed Exit Code      Feature Result
    azure-arm: ------- -------------- ---------      --------------
    azure-arm: True    No             Success        {Common HTTP Features, Default Document, D...
    azure-arm: <Objs Version=“1.1.0.1” xmlns=“http://schemas.microsoft.com/powershell/2004/04"><Obj S=“progress” RefId=“0"><TN RefId=“0”><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64 N=“SourceId”>1</I64><PR N=“Record”><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>
==> azure-arm: Querying the machine’s properties ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> ComputeName       : ‘pkrvmpq0mthtbtt’
==> azure-arm:  -> Managed OS Disk   : ‘/subscriptions/guid/resourceGroups/packer-Resource-Group-pq0mthtbtt/providers/Microsoft.Compute/disks/osdisk’
==> azure-arm: Powering off machine ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> ComputeName       : ‘pkrvmpq0mthtbtt’
==> azure-arm: Capturing image ...
==> azure-arm:  -> Compute ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> Compute Name              : ‘pkrvmpq0mthtbtt’
==> azure-arm:  -> Compute Location          : ‘East US’
==> azure-arm:  -> Image ResourceGroupName   : ‘myResourceGroup’
==> azure-arm:  -> Image Name                : ‘myPackerImage’
==> azure-arm:  -> Image Location            : ‘eastus’
==> azure-arm: Deleting resource group ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm: Deleting the temporary OS disk ...
==> azure-arm:  -> OS Disk : skipping, managed disk was used...
Build ‘azure-arm’ finished.

==> Builds finished. The artifacts of successful builds are:
--> azure-arm: Azure.ResourceManagement.VMImage:

ManagedImageResourceGroupName: myResourceGroup
ManagedImageName: myPackerImage
ManagedImageLocation: eastus

Packer'ın VM'yi oluşturması, sağlamayı çalıştırması ve dağıtımı temizlemesi birkaç dakika sürer.

Packer görüntüsünden VM oluşturma

Artık New-AzVM ile Görüntünüzden bir VM oluşturabilirsiniz. Destekleyen ağ kaynakları henüz yoksa oluşturulur. İstendiğinde, VM'de oluşturulacak bir yönetici kullanıcı adı ve parola girin. Aşağıdaki örnek, myPackerImage'danmyVM adlı bir VM oluşturur:

New-AzVm `
    -ResourceGroupName $rgName `
    -Name "myVM" `
    -Location $location `
    -VirtualNetworkName "myVnet" `
    -SubnetName "mySubnet" `
    -SecurityGroupName "myNetworkSecurityGroup" `
    -PublicIpAddressName "myPublicIpAddress" `
    -OpenPorts 80 `
    -Image "myPackerImage"

Packer görüntünüzden farklı bir kaynak grubunda veya bölgede VM'ler oluşturmak istiyorsanız, görüntü adı yerine görüntü kimliğini belirtin. Get-AzImage ile görüntü kimliğini alabilirsiniz.

Packer görüntünüzden VM'nin oluşturulması birkaç dakika sürer.

VM ve web sunucusunu test etme

Get-AzPublicIPAddress ile VM'nizin genel IP adresini alın. Aşağıdaki örnek, daha önce oluşturulan myPublicIP için IP adresini alır:

Get-AzPublicIPAddress `
    -ResourceGroupName $rgName `
    -Name "myPublicIPAddress" | select "IpAddress"

Packer sağlama aracından IIS yüklemesini içeren VM'nizi görmek için, bir web tarayıcısına genel IP adresini girin.

Varsayılan IIS sitesi

Sonraki adımlar

Mevcut Packer sağlama betiklerini Azure Image Builder ile de kullanabilirsiniz.