Infrastructure as code met Azure

Contenttype
Blog
Kennis Blog Infrastructure As Code With Azure
Auteur
Oscar van Tol

Vanaf het moment dat een ontwikkelaar code schrijft voor een nieuwe functionaliteit of om een bug op te lossen begint een reis. Hopelijk begint die reis met een commit naar een versiebeheersysteem. De bestemming van deze reis is bekend de productieomgeving in welke vorm dan ook. De reis kan kort en eenvoudig zijn of lang en ingewikkeld en de duur wordt vooral bepaald door het kwaliteitsproces en het niveau van automatisering van de CI/CD pijplijn.

Build en release

Tegenwoordig is het heel normaal dat teams hun builds automatiseren en laten starten bij een nieuwe commit. In deze eerste CI stap is het ook gebruikelijk om een vorm van unit testing uit te voeren. De volgende stap is het releaseproces. In de meeste gevallen pakt dit proces een build op en deployt het naar een omgeving of dat nu een QA omgeving een ring een canary of direct productie is.

Maar waar wordt eigenlijk naartoe gereleased? Vroeger was dat een fysieke server maar tegenwoordig is het vaker een virtuele machine container of een hippe cloud service. Omdat de deploymentdoelen vroeger statischer en stateful waren werd hun creatie vaak niet geautomatiseerd. Als je je omgeving inclusief configuratie niet kunt reproduceren met actuele documentatie of automatisering loop je technische schuld op die je niet moet onderschatten.

Documentatie perfect up-to-date houden

Op basis van ervaring is de kans heel klein dat dit ooit volledig lukt. En zelfs als het zou lukken is het nog steeds inefficiënt.

// TODO: write some documentation
// TODO: Remove this code after 2009-01-01

Infrastructure as code

Het automatisch aanmaken van resources betaalt zich snel terug. Stel dat je een nieuw stuk code bedenkt dat een storage service en webservice in Azure gebruikt. Het kost maar een paar klikken in de Azure Portal om deze aan te maken. Maar dit doe je waarschijnlijk in een veilige ontwikkelomgeving waar je alle rechten hebt. Je nieuwe services en hun configuratie moeten ook naar testomgevingen en de productieomgeving. Door het processen van deze creatie te scripten en te parameteriseren word je snel efficiënter. Een extra voordeel is dat je scripts gereviewd kunnen worden en dat problemen zoals naamgevingsconventies vroeg gesignaleerd worden. Als je je scripts als code behandelt en in versiebeheer opslaat heb je een perfect historisch overzicht van hoe een resource is aangemaakt.

Mooi laten we dit doen! Vertel me hoe!

Zoals altijd zijn er meerdere manieren om dit te bereiken. Azure stelt API’s beschikbaar om resources te beheren en er zijn veel tools die hiermee kunnen praten. Voor nu richten we ons op de opties die het dichtst bij Azure zelf staan en eenvoudig te triggeren zijn in een Azure Pipeline.

De volgende drie opties bevatten een voorbeeld uit de officiële Azure documentatie. Deze voorbeelden laten zien hoe je een Azure Web App met een Service Plan aanmaakt.

1. ARM Templates

De meest voorkomende manier om Infrastructure as Code in Azure te doen is met ARM templates. ARM staat voor Azure Resource Manager en is al jaren de standaard API set. Services die als Classic worden aangeduid gebruiken de ASM API.

ARM templates zijn JSON representaties van één of meer resources in Azure. In één template kun je een complexe set resources en afhankelijkheden binnen een resourcegroep definiëren. In de Azure Portal kun je bij elke resource een ARM template exporteren. Dat klinkt als een logische start toch? Maar dit genereert vaak een complex script dat beter leesbaar is voor een machine dan voor een mens. Het voorbeeld hieronder is misschien leesbaar maar voor mij is het lastig om zoiets zonder ervaring vanaf nul te schrijven.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "webAppName": {
      "type": "string",
      "metadata": {
        "description": "Base name of the resource such as web app name and app service plan"
      },
      "minLength": 2
    },
    "sku":{
      "type": "string",
      "defaultValue" : "S1",
      "metadata": {
        "description": "The SKU of App Service Plan, by default is Standard S1"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources"
      }
    }
  },
  "variables": {
    "webAppPortalName": "[concat(parameters('webAppName'), '-webapp')]",
    "appServicePlanName": "[concat('AppServicePlan-', parameters('webAppName'))]"
  },
  "resources": [
    {
      "apiVersion": "2018-02-01",
      "type": "Microsoft.Web/serverfarms",
      "kind": "app",
      "name": "[variables('appServicePlanName')]",
      "location": "[parameters('location')]",
      "properties": {},
      "dependsOn": [],
      "sku": {
        "name": "[parameters('sku')]"
      }
    },
    {
      "apiVersion": "2018-11-01",
      "type": "Microsoft.Web/sites",
      "kind": "app",
      "name": "[variables('webAppPortalName')]",
      "location": "[parameters('location')]",
      "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
      ]
    }
  ]
}

2. Azure CLI scripts

Commandline tools zijn enorm populair geworden en dat geldt ook voor Azure CLI. Azure CLI is eigenlijk een commandline versie van de Azure Portal met goede vindbaarheid door inline help. Omdat je commandline tools kunt scripten in PowerShell of Bash kun je geautomatiseerde parameteriseerbare scripts maken die je in broncodebeheer bewaart en in CD pipelines draait. De flow lijkt sterk op handmatig resources aanmaken in de portal.

az group create -l westeurope -n MyResourceGroup
az appservice plan create -g MyResourceGroup -n MyPlan -l westeurope
az webapp create -g MyResourceGroup -p MyPlan -n MyUniqueAppName

3. Azure Management Libraries voor .NET

Deze libraries zie je normaal in delen van applicaties die infrastructuur in Azure moeten aansturen. Bijvoorbeeld bij een multi tenant SAAS applicatie met per tenant een SQL database om bij een nieuwe klant automatisch een nieuwe database aan te maken. Of bij specifieke schaalbehoeften die vanuit de applicatie te automatiseren zijn. Als ontwikkelaars comfortabel zijn met C# kan dit ook een fijne manier zijn om resources te maken. De libraries bieden een fluent API.

IAzure azure = Azure.Authenticate(credFile).WithDefaultSubscription();

var webApp = azure.WebApps.Define(appName)
    .WithRegion(Region.USWest)
    .WithNewResourceGroup(rgName)
    .WithNewFreeAppServicePlan()
    .Create();

Een keuze maken

Het belangrijkste is om te omarmen dat de definitie van de infrastructuur die je code nodig heeft moet worden vastgelegd in een versiebeheersysteem. De officiële aanbeveling lijkt nog steeds ARM templates te zijn. Het sterke punt van ARM templates is dat je geen script schrijft maar een gewenste staat definieert waardoor gedrag reproduceerbaar is ongeacht de beginsituatie. Azure CLI commando’s zijn eenvoudig te schrijven maar je definieert minder compleet de gewenste staat waardoor je extra flow moet scripten. De meeste commando’s zijn idempotent maar sommige hebben onverwacht gedrag. Azure Management Libraries geven maximale controle in complexe setups en hebben zeker hun plek maar je bouwt wel weer een applicatie in plaats van een script.

Handige links
• ARM Templates documentation
• Azure CLI command reference
• Azure Management Libraries for .NET

Meer blogposts

  • Exploring the essentials of professional software engineering

    Jelle verkende in deze serie wat een software engineer professioneel maakt en deelt inzichten uit eigen ervaring. Hieronder staat een korte terugblik op de besproken onderwerpen.
    Contenttype
    Blog
    Kennis Blog Exploring The Essentials Of Professional Software Engineering
  • The Software Engineer Oath

    In dit laatste deel blikken we terug op de hele reeks, van codekwaliteit tot ethiek, teamwork, professionaliteit en de introductie van Dijkstra’s Eed voor verantwoord software-engineeringschap.
    Contenttype
    Blog
    Kennis Blog The Software Engineer Oath
  • The development process Part 2

    Deze blog laat zien hoe succesvolle softwareontwikkeling draait om mensen: samenwerking, teamdynamiek, psychologische veiligheid en ontwikkelaars die actief bijdragen aan productvisie, groei en verandering.
    Contenttype
    Blog
    Kennis Blog The Development Process 2

Altijd op de hoogte met onze tech-updates!

Schrijf je in en ontvang om de week een update met de nieuwste kennis en ontwikkelingen.