Windows Virtual Desktop (WVD) bietet bereits Vorteile gegenüber einer klassischen Remote Desktop Farm. In diesem Beitrag möchte ich aufzeigen, wie die Bereitstellung weiter optimiert werden kann. Dafür verwenden wir einen Infrastructure as Code (IaC) Ansatz um eine vollautomatische und reproduzierbare Bereitstellung zu realisieren.
Einleitung – Windows Virtual Desktop mit Azure DevOps
Bereits in einem früheren Artikel sind wir auf die Möglichkeit eingegangen eine Remote Desktop Farm in Azure zu betreiben. Ein großer Vorteil von Windows Virtual Desktop (WVD) gegenüber einer klassischen RDSH-Bereitstellung besteht ohne Frage in der geringeren Komplexität der Bereitstellung. Das ist dem Umstand geschuldet, dass die Infrastruktur für das Management der Umgebung durch Microsoft verwaltet wird.
Wer Erfahrung mit der Betreuung von Remote Desktop hat, weiß wie aufwendig alleine die Softwarepflege einer solchen Plattform sein kann. Daher ist eine vollautomatische Bereitstellung erstrebenswert und mit WVD durch einen Infrastructure as Code (IaC) Ansatz einfach möglich. In diesem Artikel wir das zugrundeliegende Windows Image skriptbasiert mit Software befüllt und individuell angepasst. Dieser Code wird in einem Repository mit Versionsverwaltung aka Git oder TFVC entwickelt. Dafür verwende ich Azure DevOps.
Azure DevOps bietet allgemein Dienste zur Unterstützung bei der Codeentwicklung, sowie der Erstellung und Bereitstellung von Anwendungen. Es handelt sich hier um die Cloudvariante von Azure DevOps Server, der Weiterentwicklung von Visual Studio Team Foundation Server (TFS). In meinem Fall kommen Azure Repos zur Codeverwaltung und Azure Pipelines für das Release-Management zum Einsatz.
Vorbereitung
Das Ziel ist eine Pipeline, die zunächst das Windows 10 Multi-Session Image aus dem Azure Marketplace mit unseren individuellen Einstellungen und Anwendungen versieht, dann generalisiert und schließlich als Hostpool bereitstellt. Voraussetzung ist ein bestehendes Active Directory inklusive AD-Connect im eigenen Azure Tenant, dass von den WVD-Hosts erreicht werden kann. Außerdem sollte bereits der Registrierungsprozess für WVD abgeschlossen sein. Wie das funktioniert, können Sie dem oben genannten Artikel entnehmen.
Zunächst erstellen wir ein Projekt über die Azure DevOps Homepage:
Um DevOps den Zugriff auf unsere Azure Subscription zu ermöglichen, müssen wir einen Service Principal mit entsprechenden Berechtigungen erstellen. Einen generischen SPN mit Contributor Rechten können wir über Project Settings -> Service Connections -> New Service Connection erzeugen und verknüpfen. Dabei kann man den Scope angeben, ich habe für dieses Beispiel der Einfachheit halber “Subscription” gewählt.
Anschließend kümmern wir uns um die notwendigen Dateien, die wir in unserer Bereitstellung verwenden werden.
ARM Template
Das ist zum einen das ARM Template zum Erstellen eines Hostpools. Eine gute Basis dafür finden wir in Github: ARM Template to Create and provision new Windows Virtual Desktop hostpool. Dazu erstelle ich im Projektrepository eine neue Datei, nenne sie “azuredeploy.json” und füge den JSON-Code ein:
Anschließend führe ich einen Commit aus.
Packer Template
Außerdem füge ich ein Packer Template hinzu, dass auf diesem Beispiel aus dem Packer Repository basiert. Dabei hinterlege ich als Basis Image das Windows 10 Multi-Image und passe die Referenzen auf bestehende Ressourcengruppen und Netzwerkressourcen meiner Subscription an. Außerdem füge ich einen Provisioner hinzu, der Chocolatey installiert. Im Anschluss nutze ich Chocolatey um FsLogix zu installieren. Auch diese Datei wird committed. Das fertige Packer Template besteht aus drei Teilen:
Variables:
Builders:
Provisioners:
Pipeline
Bevor wir die eigentliche Pipeline konfigurieren, legen wir zunächst noch eine Variablengruppe. Diese enthält die notwendigen Parameter für unser Packer-Template. Dazu wähle ich den Punkt Library, erstelle eine neue Variablengruppe und verknüpfe Sie später mit meiner Build-Pipeline. Diese Variablen werden im Anschluss vom Packer Template automatisch zum Zeitpunkt des Builds ausgelesen:
Starten wir jetzt mit dem Aufbau unserer Pipeline. Unter dem Menüpunkt Pipelines erstellen wir eine neue Pipeline über den klassischen Editor. Wir wählen unser bestehendes Repository aus und starten mit einem leeren Job. Den Agent konfiguriere ich wie hier zu sehen:
Außerdem füge ich jetzt der Pipeline folgende Tasks hinzu:
Der erste Task stellt zunächst Packer bereit. Anschließend wird über den “Build immutable image”-Task (der auf die zuvor erstellte Packer Datei verweist) unser Image erstellt. Packer stellt dazu temporär eine virtuelle Maschine in Azure bereit, installiert die Anwendungen und generalisiert dann die Maschine, um das Image zu erzeugen. Den Namen des Images speichern wir für unsere spätere Release Pipeline mittels des “Save Build Variable”-Tasks. Damit außerdem das JSON-Skript für das Deployment im Artefakt bereitsteht, kopieren wir es per “Copy-File” hinein. Schließlich publishen wir das Ergebnis des Builds im letzten Task der Pipeline.
Für die eigentliche Bereitstellung nutzen wir jetzt eine Release-Pipeline. Im Menü Pipelines unter Release erstellen wir eine neue, leere Pipeline. Als Artefakt fügen wir unser Buildartefakt hinzu.
Anschließend fügen wir die beiden folgenden beiden Tasks hinzu:
Der erste Task lädt die zuvor im Build gespeicherte Variable in die Pipeline. Anschließend beginnen wir das Deployment über das ARM Template. Die entsprechenden Variablen gebe ich über das “Override template parameters”-Feld direkt mit (in der Praxis wäre es sicher sinnvoll auch hier eine Variablengruppe zu verwenden). Zu guter Letzt setze ich noch die Einstellung für Continuous Deployment in den Pipeline Einstellungen auf aktiviert – somit wird bei jedem neuen Build-Vorgang automatisch ein Deployment ausgelöst.
Damit ist unsere Pipeline jetzt einsatzfähig und kann auch problemlos um weitere Pipelines erweitert werden. So lassen sich weitere Umgebungen z.B. für Dev/Test realisieren und auch kurzfristig on-demand deployen. Denn auch ein manuelles Triggern kann über die Build Pipeline erfolgen (im folgenden Screenshot oben rechts zu sehen):
Fazit
Die Verwendung eines Infrastructure as Code Ansatzes ist auch im Desktop-Umfeld sehr interessant. Der Azure Dienst Windows Virtual Desktop bietet genau diese Möglichkeit. Durch eine codebasierte Imageerstellung lassen sich Deployments nicht nur homogenisieren. Vor allem durch die Versionshistorie sind Fehler leichter zu beheben und Rollbacks zu früheren “stabilen” Versionen möglich. In der Developmentumgebung werden Images getestet und automatisiert auf die Produktivumgebung ausgerollt. Und das Ganze cloud-typisch, on-demand mit Pay-As-You-Go.
Lust bekommen? Nehmen Sie bei weiteren Fragen, Anregungen oder Ideen zu Windows Virtual Desktop und Azure gerne Kontakt mit uns auf!