Bicep, Iac & ARM

IaC

Dankzij de beschikbare cloud platformen kun je binnen een paar klikken de infrastructuur voor jouw applicatie realiseren. De bekende cloud platformen bieden portals aan waar je de componenten voor jouw infrastructuur benodigdheden op kunt zetten.

 

Echter zorgt deze manier van werken voor een aantal uitdagingen.

 

Weet je in de toekomst nog uit welke bouwblokken jouw infrastructuur bestaat? Indien de infrastructuur wat complexer is kan het omslachtig worden om alle componenten handmatig aan te maken. Zeker wanneer je een applicatie host die meerdere omgevingen heeft. Met de welbekende OTAP straat is dit een veel voorkomend scenario. In het geval van een rampscenario, hoe snel kun jij de infrastructuur van je applicatie weer optuigen? Hoe zat dat ook al weer met de benodigde configuratie?

 

De bovenstaande uitdagingen kun je vrijwel allemaal overwinnen door gebruik te maken van Infrastructure as Code (IaC). Zoals de naam het al weggeeft definieer je de infrastructuur van je applicatie als “code”. Dit zorgt voor consistentie, documentatie en efficiëntie.

 

Azure & Bicep

Bij Rebel:it werken we voornamelijk met het cloudplatform Azure. Azure biedt een resource implementatie- en beheerservice aan genaamd Azure Resource Manager (ARM). ARM kan templates interpreteren waarin jouw infrastructuur als JSON gedefinieerd staat. Deze templates worden snel rommelig en zijn lastig te lezen, laat staan bewerken.

 

Bicep is een taal die een gebruiksvriendelijkere infrastructuur definitie en configuratie mogelijk maakt. Onder water worden de opgestelde Bicep definities omgezet naar JSON wat de ARM kan interpreteren.

 

Een ander prettig aspect aan Bicep is de ondersteuning van zogenaamde modules. Zo kun je bijvoorbeeld per resource type een module maken. Deze modules kunnen vervolgens weer samenkomen in een overkoepelend bestand. Zo voorkom je dat je een groot onoverzichtelijk bestand krijgt.

 

Voorbeelden

Hieronder staat een voorbeeld hoe een eenvoudig bicep script er precies uit ziet. Het commentaar boven de code legt uit wat er gebeurt.

 

Om te beginnen is dit de definitie van een module die een app service resource bevat: app-service.bicep

 

// Dit zijn de parameters die meegegeven kunnen worden tijdens het aanroepen van de module. 
param environment string
param webAppName string = 'asp-${environment}'
param location string
param servicePlanId string

// Aangezien de app service op een linux plan draait is dit de runtime versie
var linuxFxVersion = 'DOTNETCORE|8.0'
param appInsightsInstrumentationKey string
param appInsightsConnectionString string

// Vervolgens definieer je de resource
resource appService 'Microsoft.Web/sites@2020-06-01' = {
    name: webAppName
    location: location
    
    // In het geval je gebruik maakt van managed identities kun je dit ook op geven. Je kunt ook rechten toekennen aan de managed identity. Let er hierbij wel op dat de persoon of het systeem die dit script uitvoert de bedodigde rechten heeft.
    identity: {
    type: 'SystemAssigned'
    }

    // Een app service heeft natuurlijk altijd een app service plan nodig. Deze kun je gemakkelijk meegeven nadat je het app service plan hebt aangemaakt. Dit kun je bijvoorbeeld weer in een andere module doen.
    properties: {
        serverFarmId: servicePlanId
        httpsOnly:true
        siteConfig: {
            alwaysOn:true
            linuxFxVersion: linuxFxVersion

            // Hier geven we een aantal app settings mee.
            appSettings: 
            [
                {
                    name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
                    value: appInsightsInstrumentationKey
                }
                {
                name: 'APPINSIGHTS_CONNECTION_STRING'
                value: appInsightsConnectionString
                }
            ]
        }
    }
}

// Tot slot gooien we een aantal variabelen omhoog die het overkoepelende bestand kan gebruiken voor een eventuele volgende stap. 
output principalId string = appService.identity.principalId
output appServiceName string = appService.name

 

Vervolgens kunnen we de module gebruiken in het main bestand.

 

main.bicep

// Eerst roepen we een andere module aan die de application insights resouce aanmaakt. Let op de modulenaam, deze wordt verderop gebruikt als referentie om vereiste variabelen op te halen.
module applicationInsights './modules/application-insights.bicep' = {
    name: 'applicationInsightsModule'

    params: {
        location: location
        environment: environment
    }
}

// Vervolgens roepen we de module aan die de app service aanmaakt. Het is je vast al opgevallen dat de parameters die we meegeven aan de module overeenkomen met de parameters die in het app-service.bicep bestand verwacht worden.

module appService './modules/app-service.bicep' = {
name: 'appServiceModule'

params: {
    location: location
    environment: environment
    servicePlanId: servicePlanId
    
// Hieronder geven we de benodigde application insights waardes mee zodat de app service wordt gekoppeld met de eerder aangemaakte application insights resource. Zoals je kunt zien kun je de modulenaam aanroepen als referentie. Vervolgens kun je de output variabelen uitlezen en meegeven aan de volgende module. In dit geval de bovenstaande app service module.

    appInsightsInstrumentationKey: applicationInsights.outputs.applicationInsightsInstrumentationKey
    appInsightsConnectionString: 
    applicationInsights.outputs.applicationInsightsConnectionString
    }
}

 

Integratie met huidige build & deploy pipelines

Een van de krachtigste aspecten van Bicep is dat je het gemakkelijk kunt integreren in je huidige multi-stage build & deploy pipeline. Zo kun je voor, of nadat je je build hebt gedraaid het Bicep script uitvoeren om te garanderen dat de infrastructuur gereed is voor de deployment van je nieuwe build. Bicep is namelijk idempotent wat inhoudt dat het niet uit maakt hoe vaak je het script uitvoert. Het resultaat zal altijd hetzelfde zijn. Daarnaast is Bicep declaratief. Indien een resource al bestaat met de opgegeven specificaties zal Bicep de resource niet opnieuw aanmaken. Het enige waar Bicep zich mee bezig houdt is om er voor te zorgen dat de eindstatus overeen komt met hetgeen wat in het script beschreven staat.

 

Let er hierbij wel op dat je pipeline rechten moet hebben om resources aan te maken in de beoogde Azure subscription. Dit kun je onder andere faciliteren door gebruik te maken van een service connection. Mocht je ook rechten toekennen aan resources onderling in je Bicep script dan kun je de service connection extra rechten toekennen.

 

Conclusie

Met Bicep kun je gemakkelijk je infrastructuur als code definiëren (IaC). Doordat Bicep declaratief en idempotent werkt hoef je niet bang te zijn dat je een omgeving ongewenst dubbel aanmaakt. Door Bicep te integreren in je huidige multi-stage build & release pipeline kun je een super gestroomlijnd ontwikkel & uitrol proces creëren.

 

Het kan een uitdaging zijn om Bicep te integreren in een bestaand landschap. Zeker in het geval van complexe configuraties en rollen & rechten. Bicep geeft dan ook de beste ervaring wanneer je het inzet in het geval van een green field situatie, of wanneer je landschap goed te overzien is.

 

Wil jij sneller waarde kunnen leveren aan je klanten doormiddel van een gestroomlijnd ontwikkel & uitrol proces, maar beschik je niet over de kennis of capaciteit om dit op te zetten? Bij Rebel:it beschikken we over de benodigde kennis & expertise.

Header: Kom je op de koffie?

Heb jij een ambitieus idee, droom je van een app die het verschil maakt, of zoek je een digitale oplossing die naadloos past bij jouw visie? Laten we samen de mogelijkheden verkennen! Vul ons contactformulier in en je mag rekenen op ons enthousiasme en samenwerking.