In diesem Beitrag möchten wir kurz aufzeigen wie einfach es ist, Enwicklungs- und Testumgebungen mit Azure ARM Templates und Azure CLI aufzusetzen. Dadurch wird es möglich, autarke Umgebungen zur Featureentwicklung zu erzeugen ohne mit parallelen Entwicklungsarbeiten zu kollidieren.

Dafür haben wir Auszüge unserer Procy Infrastruktur Skripte auf GitHub bereit gestellt. Das Procy Backend besteht aus verschiedenen Services sowie einer SQL Server Datenbank. Die Services werden in einer Azure Web App deployed und die Datenbank in einer SQL Azure Instanz angelegt. Beide Services sind Azure bereitgestellte PaaS Angebote, so dass unserer Focus auf der Verwendung und nicht der Konfiguration dieser Services liegt. Um den Beispielen folgen zu können, benötigt man einen Azure Account mit gültiger Subscription. Außerdem müssen die Azure CLI Tools installiert sein.


SQL Azure

Zum Erzeugen der SQL Azure Umgebung greifen wir auf ein Azure Resource Manager (ARM) template zurück. In solch einem Template können mehrere Ressourcen mit individuellen Einstellungen definiert werden. Unter SQL Azure sind alle Ressourcen definiert, die wir für unsere Umgebung benötigen. Der Output umfasst für uns wichtige Ressourcen wie SQL server und SQL database. Diese beiden Ressourcen werden zu einer Ressource Group hinzugefügt.

Außerdem ist es möglich, Parameter in separaten Files zu hinterlegen, wobei hier die SKU, Leistung, Name usw. geändert werden können. Diese Parameter können dann ebenfalls während des Deployments überschrieben werden. Das Deployment kann mit dem az group deployment create command gestartet werden.

Für unser spezielles Beispiel müssen wir mindestens folgendes Command absetzen, um das Deployment zu triggern. Vorher sollte man sich mit az login angemeldet sowie die resource group erstellt haben.

Erstellen einer Resource Group

az group create 
--name myResourceGroup 
--location myResourceGroupLocation

Erstellen der SQL Azure Umgebung

az group deployment create  
--resource-group myResourceGroup
--template-file azuredeploy.json
--parameters @basic.parameters.json
--parameters sqlserveradminpw=myPassword

Dabei muss zwingend die Resource Group sowie ein admin password für den SQL server angegeben werden. Außerdem ist im Beispiel nur ein Paramters File hinterlegt, welches angegeben werden muss, da keine default Werte hinterlegt sind.

Werden beide oben dargestellten Befehle für die Ressourcengruppe sql-example-basic-rg ausgeführt, sollten wir im Azure Portal die Ressourcengruppe samt beider Resourcen sehen können. Basic im rg Namen bezieht sich hierbei auf das Prameterfile bzw. die Stage, die damit erzeugt wurde.

Benötigen wir für ein Feature FeatureXYZ eine weitere Datenbank mit gleichen Zugangsdaten, dann können wir einfach einen anderen Datenbanknamen wählen und Skript erneut ausführen. Im konkreten Beispiel können wir für die Datenbank ProcyFeatureXYZ folgenden Command absetzen.

az group deployment create  
--resource-group blog-example-basic-rg  
--template-file azuredeploy.json  
--parameters @basic.parameters.json  
--parameters database_name=ProcyDBFeatureXYZ

Werfen wir wieder einen Blick auf unsere Resource Group, ist nun eine weitere Datenbank zu sehen, welche mit den gleichen Credentials verwendet werden kann. Einzig der Name der Datenbank muss im Connectionstring getauscht werden.

Das wir kein Passwort übergeben mussten, ist der Condition(al) Property im azuredeploy.json file geschuldet. Wird kein Passwort übergeben, wird das Deployment des Servers nicht beachtet, was in unserem Fall einer weiteren Datenbank auch nicht notwendig ist.

"condition": "[greater(length(parameters('sqlserveradminpw')) , 0)]",

Das Deployment der Datenbank kann auch über Azure CLI commands durchgeführt werden. Das ist ausreichend, falls sich die Menge an Konfigurationen in Grenzen hält.

az sql db create 
-g sql-example-basic-rg 
-s procydbserver 
-n ProcyDBFeatureXYZ 
--service-objective Basic 
--catalog-collation SQL_Latin1_General_CP1_CI_AS

Möchte man Auditing, Azure Advisor, Firewallsettings usw. für alle Datenbanken verwenden, empfiehlt sich die Verwendung des ARM templates wie weiter oben beschrieben. Dadurch wird sicher gestellt, dass alle Datenbanken auf den gleichen Settings basieren.


Azure Web App

Um die notwendigen Backendservices zu deployen, greifen wir auf den Azure Service Azure Web App zurück. Dafür muss ein App Service Plan ausgewählt werden, unter dem die einzelnen Apps erstellt werden können. Solange Apps zu einem App Service Plan gehören, werden die Ressourcen geteilt. Im Gegensatz zum SQL Deployment, bestimmen wir hier die Leistung anhand des übergeordneten App Service Plans und können es nicht je App konfigurieren. Dafür können verschiedene Entwicklungssysteme aufgesetzt werden, wobei nur für einen App Service Plan bezahlt werden muss.

Für unseren Zweck genügen wenige Einstellungen, so dass wir auf die Verwendung der ARM Templates verzichten und alles mit Hilfe der Azure CLI deployen können. Im Infrastructure Repository sind alle notwendigen Commands im File deploy-webapp.sh im Ordner WebApp zu finden.  

Auch hier sollten wir mit einer separaten Resource Group beginnen, einen App Service Plan und letztendlich die zugehörige App erstellen. Durch die Verwendung von Resource Gruppen erhalten wir eine einfache Kostenübersicht und sind in der Lage alle Ressourcen zu löschen.

az group create  --name webapp-example-rg --location "West Europe"

az appservice plan create --name webapp-example-plan --resource-group webapp-example-rg --sku F1

Auf Grundlage des erstellten Service Plans, kann nun die erste App angelegt werden. Da wir in diesem Beispiel keine weiteren Settings, wie Programmiersprache, Runtime usw. benötigen, genügt ebenfalls ein einfacher Azure CLI command.

az webapp create --name webapp-example-app --resource-group webapp-example-rg --plan webapp-example-plan

Nachdem absetzen der Commands sollte im Portal folgendes zu sehen sein. In der Resource Group sind sowohl die App als auch der App Service Plan als eigenständige Ressource zu sehen.

Bisher konnten wir sowohl die Infrastruktur für die Datenbank als auch das Backend provisionieren. Was aktuell fehlt, ist die Verbidnung zwischen den beiden Services. Dafür müssen wir den Connection string zur Datenbank setzen. Das können wir entweder manuell vornehmen oder auch über die Azure CLI abbilden.

az webapp config connection-string set -g webapp-example-rg -n webapp-example-app -t SQLAzure --settings ProcyDbConnectionString="yourConnectionString"

Unsere Anwendung sucht konkret in den Appsettings bzw. unten den Environment Variablen nach dem ProcyDbConnectionString. Der Bezeichner kann natürlich frei gewählt werden und muss mit der App übereinstimmen.

Staging Slots für Produktivbetrieb

Da es sich lediglich um Entwicklungs- und Testumgebungen handelt, werden keine Staging Slots verwendet. Für den Produktivbetrieb sollten jedoch wenigstens zwei Slots verwendet werden. Einen für dir produktiven Betrieb und einen für das letzte stabile System als Backup. Dadurch können Rollbacks einfach durchgeführt werden.


Orchestrierung durch Skripte

Um die ganzen Commands nicht alle manuell ausführen zu müssen, haben wir diese in ein einfaches Shell Skript gepackt. In diesem Skript wird ebenfalls der Connectionstring zusammen gebaut und gesetzt. Die Beispiele sind stark Procy (ursprüngliche App) lastig, was bedeutet, dass diese Bezeichner in den Skripten umbenannt werden müssten.

Weiter ist es notwendig, sowohl für das SQL Azure Skript als auch für das WebApp Skript die Parameter DatabaseServer, DatabaseName und SQLAdminPassword zu übergeben. Der Datanbankbenutzer (User) kann aktuell nicht geändert werden! Für lokale Zwecke könnte ein weiteres Shell Skript verwendet werden, welches die beiden Skripte nacheinander aufruft und so die komplette Infratsruktur erzeugt. Dabei wäre die Eingabe bestimmter Parameter nur einmalig notwendig. Wir verwenden dafür jedoch AzureDevOps.

Zusammenfassung

In diesem Beitrag konnten wir aufzeigen, wie einfach Services in Azure provisioniert werden können. Durch die Verwendung von Azure ARM templates sowie der Azure CLI können solche Prozesse stark automatisiert und vereinheitlicht werden.

Durch die Verwendung und Zuordnung von Resource Group’s erhalten wir zum Einen eine einfache Übersicht aller Kosten je Gruppe und zum Anderen können die Ressourcen leicht entfernt werden, sobald der Kunde beispielsweise den Test des Features abgeschlossen hat. Somit fallen keine unnötigen Kosten an.

Des Weiteren kann das Thema role-based access control (RBAC) in der Praxis sehr wichtig werden, wobei Resource Groups ein wichtige Rolle spielen. Für unser Beispiel benötigen wir es nicht zwingend, da der Zugriff auf die spezifischen Azure Resourcen nicht freigegeben wird, sondern der Fokus ausschließlich auf dem Testen der deployten Software liegt.

Im nächsten Beitrag werden wir aufzeigen, welche Rolle AzureDevOps, ehemals Visual Studio Team Services (VSTS), dabei spielen kann, eine komplett neue Infrastruktur für einen neuen Kunden aufsetzen zu lassen.