Einige Vorteile des PaaS-Dienstes Azure App Services – bestehend aus WebApps, API Apps, Mobil App und Function Apps – haben wir bereits beleuchtet. Vor allem aber lohnt sich der Cloud-Dienst wegen der vielfältigen CI/CD-Integration.
Grundsätzlich bieten die Azure App Services gleich mehrere Möglichkeiten der CI/CD-Integration. Prinzipiell gilt es dabei, zwischen …
- der „Nur-Anbindung“ eines der unterstützten Quellcode-Verzeichnisse (als Build-Service kommt dann der App-Service eigene Build-Dienst zum Einsatz)
- der Anbindung von GitHub Actions als Build Service im Zusammenhang mit GitHub als Source-Code-Repository und
- der vollständigen Orchestrierung eines CI/CD-Workflows mit Azure Pipelines
… zu unterscheiden.
Bei einer bereits bereitgestellten Webapp können Sie z. B. im Bereitstellungs-Center unter „Einstellungen / Quelle“ jederzeit eines der unterstützen Sourcecode-Repositories auswählen. Wählen Sie hier z. B. GitHub aus, erkennen Sie am Eintrag „Erstellung mit GitHub Actions“, dass GitHub Actions als Build-Anbieter vorgesehen ist, Sie aber mit einem Klick auf „Anbieter ändern“ auch zum Azure-App-Service-Build-Dienst oder Azure Pipelines wechseln können.
Was hier im Detail geht, hängt aber auch vom gewählten Laufzeitstapel/Sprachen-Framework und der gewählten OS-Basis (Linux / Windows) ab. Fassen wir das Gesagte noch einmal zusammen, unterstützt der App Service-Dienst …
- als Quellcode-Verzeichnis: GitHub, Bitbucket, Git (lokal) und Azure Repos
- als Build-Dienst: App Service-Builddienst, GitHub Actions, Azure Pipeline
Im Falle von GitHub/GitHub-Actions können Sie die CI/CD-Konfiguration je nach gewählter Runtime auch bereits im Bereitstellungsassistenten der Web App im Tab „Bereitstellung“ konfigurieren. Unabhängig von den Azure App Services lassen sich die Dienste „Azure Repos“ und „Azure Pipelines“ zusammen mit „Azure Boards“ bekanntlich auch unter dem Dach von „Azure Devops“ zur Zusammenarbeit orchestrieren. So lassen sich Deployments auch in Azure Devops auf eine Azure Webapp ausbringen, was aber letztlich keine Funktion der Azure App Services selbst ist.
Mit diesem und folgenden Beiträgen wollen wir Ihnen verschiedene Beispiele zur CI/CD-Integration für verschiedene Runtimes, Betriebssysteme und Plattformen nahebringen. Dieser Beitrag demonstriert die Bereitstellung einer containerisierten App-Service-App mit Datenbank-Backend in eine Azure-SQL-Datenbank im Rahmen eines GitHub-Actions-Workflows.
ASP.Net App in einem Container als Azure App Service
Möchten Sie diesen Workshop nachvollziehen, brauchen Sie neben einem Azure Account mit aktiver Subskription auch ein GitHub-Konto. Außerdem benötigen Sie die skizzierte Beispiel-Anwendung. Bekanntlich stellt Microsoft zu diesem Zweck auf GitHub eine ganze Reihe von Beispielanwendungen zur Verfügung. Die hier Beschriebe finden Sie in den Azure Samples auf GitHub. Dieses Repo enthält zwei verschiedene GitHub-Workflows:
1. azuredeploy.yaml dient dem Erstellen der für das Beispiel erforderlichen Azure-Ressourcen mithilfe einer ARM-Vorlage.
- App Service-Plan (Linux)
- Web-App für Container (mit einem Staging-Slot)
- Azure Container Registry
- Azure SQL Server und die Azure SQL-Datenbank für das Beispiel
- Speicherkonto
2. build-deploy.yaml erstellt die Beispiel-App mithilfe eines Containers, schiebt den Container in die Azure Container Registry, stellt den Container im Web-App-Staging-Slot bereit, aktualisiert die Datenbank und tauscht schließlich die Slots aus.
Die betreffenden Konzepte (Container, Bereitstellungs-Slots, Slot-Tausch und Azure Container Registry) sollten bekannt sein, bzw. wurde von uns bereits in verschiedenen anderen Beiträgen erläutert.
Damit das Skript zur Ressourcenbereitstellung allerdings zuverlässig funktioniert, müssen Sie für Dieses einen Dienstprinzipal zur Authentifizierung erstellen. Für Details dazu verweisen wir auf unseren Beitrag zur Azure Identity Platform. Erledigen können Sie dies z. B. mit dem Azure-CLI-Kommando „az ad sp create-for-rbac“.
az ad sp create-for-rbac –name „{Name des service-principal}“ –sdk-auth –role contributor –scopes /subscriptions/{Abonnement-ID}/resourceGroups/{Ressourcegruppen-Name}
Die Ressourcengruppe ist vorab zu erstellen. Anschließend müssen Sie in Ihrem GitHub-Repository unter „Settings“ im Abschnitt „Security“ bei „Secrets“ ein neues Actions Secret mit einem Namen Ihrer Wahl (z. B. „AZURE_CREDENTIALS“) anlegen. In das Value-Feld kopieren Sie einfach die gesamte Ausgabe des oben aufgeführten az-Befehls.
Erstellen Sie dann ein weiteres Secret mit der Bezeichnung „SQL_SERVER_ADMIN_PASSWORD“. Hier können Sie ein beliebiges Kennwort verwenden, dass den Azure-Standards für Kennwortsicherheit genügt. Wie oben skizziert, basiert der Workflow zum Erstellen der benötigten Azure-Ressourcen auf einer ARM-Vorlage (azuredeploy.yaml) im Verzeichnis .github/workflows in Ihrem Repository.
Das ARM-Template checkt den Quellcode mithilfe der Aktion „Checkout“ aus, meldet sich mit den konfigurierten Credentials bei Azure an, sammelt die benötigten Umgebungs- und Ressourceninformationen und erstellt die benötigten Azure-Ressourcen mit Hilfe der GitHub-Action „Deploy Azure Resource Manager (ARM) Template“. Zum Ausführen des ARM-Templates öffnen Sie die Datei azuredeploy.yaml in Ihrem Repository, ersetzen den Wert für AZURE_RESOURCE_GROUP mit dem korrekten Namen Ihrer Ressourcengruppe und klicken dann im Tab „Actions“ unter „All workflows“ bei „Create Azure Resources“ auf die Schaltfläche „Run workflow“.
Achtung: Unter Umständen müssen Sie „Actions“ in Ihrem GitHub-Account erst aktivieren. Achten Sie auch drauf, dass die Resource-Provider „Microsoft.Sql“ und „Microsoft.ContainerRegistry“ für Ihre Subscription registriert sind und holen Sie dies ggf. nach. Das Deployment wird dann eine Weile in Anspruch nehmen.
Nach Abschluss des Deployments sollten Sie in Ihrer Ressourcengruppe die in der Abbildung zu sehenden Azure-Ressourcen vorfinden, also eine Containerregistrierung, eine Web App nebst App-Service-Plan, eine verwaltete SQL-Datenbank nebst Server und ein Speicherkonto.
Schließlich brauchen Sie noch Secrets für die vom ARM-Deployment erzeugte Azure Container Registry (ACR). Navigieren Sie nun im Azure-Portal zur Container Registry und dort zu Zugriffsschlüssel, um sich dort die Werte für „Benutzername“ und „Password“ kopieren zu können.
Erstellen Sie dann in GitHub zwei weitere Actions-Secrets „ACR_USERNAME“ und „ACR_PASSWORD“ mit den entsprechenden Werten. Schließlich brauchen Sie noch ein weiteres GitHub-Secret mit der Bezeichnung „SQL_CONNECTION_STRING“. Dazu kopieren Sie sich zunächst im Azure-Portal bei Ihrer SQL-Datenbank im Menü „Verbindungszeichenfolgen“ im Abschnitt „Einstellungen“ den ADO.NET-String. Damit können Sie nun das fünfte benötigte GitHub-Actions-Secret anlegen. Achtung: Hierbei ersetzen Sie {your_password} durch das Ihr Secret für „SQL_SERVER_ADMIN_PASSWORD“, das Sie weiter oben gesetzt haben. Final sollten Sie in GitHub also fünf Secrets hinterlegt haben.
Jetzt fehlt nur das Erzeugen, Pushen und Bereitstellen der eigentlichen containerisierten Anwendung. Der zugehörige GitHub-Workflow „dotnetcore-containerized-sqldb-ghactions/.github/workflows/build-deploy.yaml“ erzeugt einen Container mit den aktuellen App-Änderungen, pusht den Container in die Azure Container Registry und aktualisiert den Deployment-Slot „Staging“ der WebApp.
Infolgedessen verweist der Staging-Slot auf den aktuellsten, per Push bereitgestellten Container. Der zugehörige Erstellungsauftrag checkt zunächst mit Hilfe der GitHub-Action „Checkout“ den Quellcode aus. Anschließend verwendet der Auftrag die GitHub-Action „Docker Login“ sowie ein benutzerdefiniertes Skript zur Authentifizierung bei der Azure Container Registry, zur Erstellung eines Container-Images und zur Veröffentlichung des Images in der ACR.