Azure Standard Test Deployments (Teil 4)

Im vierten Teil der Serie erweitern wir unseren Beispiel-PowerShell-Script, der unsere bisherigen Bausteine zusammenfügt.

Dies ist der vierte von fünf Artikeln zu diesem Thema. Die anderen sind:

  • Teil 1 legt die Namenskonvention fest.
  • Teil 2 behandelt VNet und NSG
  • Teil 3 handelt von der VM und zugehörigen Ressourcen
  • Teil 4 (dieser hier) fasst das alles in einem PowerShell Skript zusammen
  • Teil 5 macht noch ein paar Bemerkungen dazu.

Vorbemerkungen

In den Teilen davor haben wir mehrere Templates erzeugt. Diese sollten alle in einem Verzeichnis gespeichert sein, wie schon erwähnt werde ich wohl irgendwann noch einen Teil schreiben, wie das mit GitHub geht (und dann auch verlinkte Templates nutzen). Wir haben:

  • deploy.ps1: PowerShell Script, Thema dieses Teils
  • vnet-nsg.json: Template für VNet und NSG
  • pip-nic.json: Template für die Public IP und die NIC
  • vm-ubuntu.json: Template für die Ubuntu VM
  • vm-windows.json: Template für die Windows-VM

Wir benötigen zuerst mal einen Mechanismus, die wenigen, immer noch notwendigen Parameter zu übergeben.

Param(
    [parameter(mandatory=$true)][string]$resourcegroup,
    [parameter(mandatory=$true)][string]$vmname,
    [parameter(mandatory=$true)][ValidateSet("linux","windows")][string]$os
)

Der Aufruf unseres Scripts sieht damit dann später mal so aus:

deploy.ps1 -resourcegroup blogdemo -vmname dc1 -os windows

Als erstes müssen wir die Ressourcengruppe erzeugen (einschließlich Tags) und VNet und PublicIP anlegen. Wir gehen einfach davon aus, dass es diese drei Dinge entweder zusammen oder gar nicht gibt, d.h. wenn die Ressourcengruppe existiert, dann gibt es auch schon das VNet und die PIP.

$to_be_deleted="{0:ddMMyyyy}" -f (get-date).AddDays(7)
$default_tags= @{"delete"=$to_be_deleted}

if ((Get-AzResourceGroup -Name $resourcegroup -ErrorAction "SilentlyContinue").count -gt 0){
    write-host "Resourcegroup already exists"
} else {
    New-AzResourceGroup -Name $resourcegroup -Location northeurope -Tags $default_tags
    New-AzResourceGroupDeployment -Name "VNET-NSG" -ResourceGroupName $resourcegroup -TemplateFile ".\vnet-nsg.json" 
}

Ein kleiner Einschub: Ich verwende hier die neuen Azure PowerShell Cmdlets. Im wesentlichen wird dabei der „-AzureRM“ Teil ersetzt durch „-Az“. Also einfach leicht anpassen oder – noch besser – das neue Modul installieren, die alte Konvention wird nur noch als „Kompatibilitätsmodus“ unterstützt.

Was machen wir hier? Für den Fall, dass es die Ressourcengruppe noch nicht gibt, erzeugen wir eine (den Namen haben wir ja auf Kommandozeile übergeben). Direkt danach starten wir auch schon das erste Deployment (VNET-NSG) unter Verweis auf unser Template. Sollte es die Gruppe schon geben, dann machen wir hier erst mal nichts.

Im nächsten Schritt testen wir, ob die VM, die wir anlegen wollen, vielleicht schon existiert (kann ja sein, dass wir den Überblick verloren haben). Wenn nicht, dann starten wir das nächste Deployment:

if ((Get-AzVM -ResourceGroupName $resourcegroup -Name $vmname -ErrorAction "SilentlyContinue").count -gt 0){
    write-host "VM already exists"
} else {
    New-AzResourceGroupDeployment -Name "PIP-NIC" -ResourceGroupName $resourcegroup -TemplateFile ".\pip-nic.json" `
    -vmname $vmname
    
    $pip=(Get-AzPublicIPAddress -ResourceGroupName $resourcegroup -Name ($vmname+"pip1")).IpAddress

Wenn das Deployment „PIP-NIC“ beendet ist, dann existieren in der Ressourcengruppe blogdemo folgende Ressourcen:

  • Ein VNet: blogdemovnet1
  • Ein Subnet: blogdemovnet1sub1
  • Eine NSG: blogdemonsg1
  • Eine PublicIP: blogdemopip1
  • Eine NIC: blogdemonic1

…und wir haben die öffentliche IP-Adresse schon mal in einer Variablen (siehe später).

Für den letzten Teil unterscheiden wir zwischen Linux und Windows und starten verschiedene Deployments. Noch eine kleine Besonderheit: Ich speichere meine Deployment-Passwörter immer in KeyVault ab. Man kann das auch direkt im Template verlinken und der neuen VM bzw. dem Deployment selbst entsprechende Rechte am KeyVault geben, für mich reicht es so, das verhindert schon mal, dass ich aus Versehen ein Passwort irgendwo im Artikel oder Template stehen habe.

Der Linux-Teil:

    if ($os -eq "linux"){

        $adminKey=(Get-AzKeyVaultSecret -VaultName defaults -Name PubKey).SecretValue
        $adminUser=(Get-AzKeyVaultSecret -VaultName defaults -Name LinuxUser).SecretValueText
        New-AzResourceGroupDeployment -Name "VM-Linux" -ResourceGroupName $resourcegroup `
           -TemplateFile ".\vm-ubuntu.json" -vmname $vmname -adminUser $adminUser -adminKey $adminKey

    
        "copy&paste to login after NSG was updated:   ssh {0}@{1}" -f $adminUser,$pip

Zeile 27 und 28 holt den Admin-User und den PublicKey aus KeyVault (drauf achten, dass einmal „SecretValue“ und einmal „SecretValueText“ verwendet wird!), und nachdem das Deployment durchgelaufen ist, geben wir noch gleich die Kommandozeile zum Einloggen aus.

Für Windows sieht das recht ähnlich aus:

    } elseif ($os -eq "windows") {

        $adminPassword=(Get-AzKeyVaultSecret -VaultName defaults -Name WindowsPassword).SecretValue
        $adminUser=(Get-AzKeyVaultSecret -VaultName defaults -Name WindowsUser).SecretValueText
        New-AzResourceGroupDeployment -Name "VM-windows" -ResourceGroupName $resourcegroup `
          -TemplateFile ".\vm-windows.json" ` -vmname $vmname -adminUser $adminUser -adminPassword $adminPassword

        "copy&paste to login when NSG was updated:   mstsc /admin /v {0}" -f $pip

    }
}

Auch hier kommen die Credentials aus KeyVault, wir starten ein Deployment (mit dem Windows-Template), und geben die Login-Zeile aus.

Fertig. Mit einer Kommandozeile haben wir die ganze Umgebung angelegt. Und jetzt kommt’s: Eine zweite VM in die selbe Gruppe? Kein Problem:

deploy.ps1 -resourcegroup blogdemo -vmname dc2 -os windows

und noch eine?

deploy.ps1 -resourcegroup blogdemo -vmname ms1 -os windows

Noch ein Linux da rein?

deploy.ps1 -resourcegroup blogdemo -vmname apache1 -os linux

Und alle Ressourcen sind klar zuordenbar. Beispiel: apache1nic1 ist die Netzwerkkarte des Servers apache1. Diese NIC ist im Subnet blogdemovnet1sub1 verlinkt, genau wie dc1nic1, dc2nic1 und ms1nic1. Und dc2 erreicht man über die öffentliche Adresse in dc2pip1, oder in PowerShell:

Get-AzPublicIpAddress -ResourceGroupName blogdemo -Name dc2pip1

Bleibt noch die Zusammenfassung im fünften Teil

4 Kommentare zu „Azure Standard Test Deployments (Teil 4)

Hinterlasse einen Kommentar