Daan Toes Junior Cloud Engineer
25 juni 2021

Hoe automatiseer je public cloud deployments

met Terraform, GitLab en Azure

Als cloud engineer is het mijn taak om public cloud deployments te automatiseren en zo fouten te verminderen, tijd te besparen en de kwaliteitsprincipes van een organisatie te verbeteren. Hiervoor heb je een bepaalde toolset en software nodig. Er bestaan veel verschillende tools, maar in deze blog beschrijf ik hoe je tools als GitLab, Terraform en Azure gebruikt. Ik ga niet in op de details van de verschillende tools, want deze hebben namelijk zelf prima documentatie over het gebruik van de software.

Cloud-agnostisch met Terraform

Solvinity is een multi-cloud provider. We hebben daarom voor Terraform als cloud provisioning-tool gekozen, omdat deze cloud-agnostisch is. Hierdoor wordt de samenwerking met andere cloud engineers, die aan verschillende public cloud deployments werken, gemakkelijker.

Terraform is trouwens niet alleen een provisioning-tool voor de public cloud; je kunt er ook resources mee toewijzen aan VMware, Rundeck en een groot aantal andere providers. Daarnaast is het mogelijk om resources tegelijkertijd voor verschillende public clouds in te zetten. Met Terraform kun je Infrastructure as Code schrijven.

“Voor een productieomgeving wil je waarschijnlijk dat anderen de opzet eerst goedkeuren en controleren, voordat deze daadwerkelijk in Azure wordt uitgerold. In testomgevingen kun je deze opzet desgewenst automatisch toepassen.”
Een aangepaste CI/CD pipeline

Dus Terraform is de tool om resources uit te rollen en te beheren in de cloud. Maar hoe automatiseren we dit proces? Dat is waar de CI/CD pipeline van GitLab om de hoek komt kijken. In de pipeline wordt een GitLab-runner gebruikt. Hier worden de door ons gespecificeerde fasen en jobs uitgevoerd. Elke fase bestaat uit één of meerdere jobs. In mijn voorbeeld zijn dit de fasen:

  • Validate
  • Plan for apply
  • Apply
  • Plan for Destroy
  • Destroy

In elke fase zijn er verschillende jobs. Een job in de Validate-fase verifieert en controleert bijvoorbeeld mijn code. Als er iets mis is in mijn code, mislukt deze fase en wordt er een melding gestuurd. Daarbij zullen de andere fasen niet draaien als de Validate-fase mislukt. Zodra mijn code correct is, gaat deze door naar de volgende fase; in dit geval ‘Plan for Apply’.

We kunnen de GitLab-runner instellen, zodat duidelijk is welke fasen automatisch moeten draaien, en voor welke fasen handmatige interactie nodig is of welke fasen door bepaalde personen goedgekeurd moeten worden. In de onderstaande afbeelding zie je een voorbeeld van een pipeline waarin ik drie fasen heb doorlopen. De Apply-fase is de laatste van deze drie fasen, wat betekent dat ik resources voor Azure heb ingezet. Als ik de resources die ik heb ingezet wil verwijderen, moet ik handmatig op de laatste twee fasen klikken: Plan for Destroy en Destroy.

Dus hoe stel je de GitLab-runner in zodat duidelijk is wat er uitgevoerd moet worden? Dit doe je met een specifiek bestand binnen de repository. Het .gitlab-ci.yml-bestand is het pipeline-configuratiebestand. In dit bestand kunnen we de runner instellen zodat duidelijk is welke fasen en jobs er uitgevoerd moeten worden en in welke volgorde. Bovendien kunnen we configureren welke fase automatisch wordt geactiveerd en in welke fase handmatige interactie nodig is.

Klein voorbeeld van het .gitlab-ci.yml-bestand:

In het bovenstaande voorbeeld zie je de verschillende fasen en de configuratie van de Validate-fase. In de Validate-fase wordt één regel code onder ‘script’ gespecificeerd. Dit is een commando van Terraform en valideert mijn Terraform-code in de repository. Daarbij wordt deze fase alleen geactiveerd wanneer er in het specifieke bestand wijzigingen worden aangebracht die worden vermeld onder ‘changes’. Je wilt bijvoorbeeld niet dat de pipeline elke keer draait wanneer je een wijziging aanbrengt in het ‘readme’-bestand.

Binnen de jobs van de fase kun je zien wat de runner doet. Hieronder zie je een voorbeeld van de Validate-fase en de output van de runner.

In de Terraform-versie zien we dat Terraform correct is geïnitialiseerd en dat mijn code gevalideerd  is.

Als de Validate-fase is afgerond, zal de Plan for Apply-fase automatisch gaan draaien. In Terraform zie je een opzet van de resources die worden toegevoegd, gewijzigd of vernietigd. Als deze fase is afgerond, heb ik het zo geconfigureerd dat de opzet in de volgende fase niet automatisch wordt toegepast. Voor een productieomgeving wil je waarschijnlijk dat anderen de opzet eerst goedkeuren en controleren, voordat deze daadwerkelijk in Azure wordt uitgerold. Dit zou dus in mijn geval een handmatige handeling moeten zijn. In testomgevingen kun je deze opzet desgewenst automatisch toepassen.

Deployment in de public cloud

GitLab moet zich authenticeren in de public cloud. In mijn geval gebruik ik Azure als voorbeeld, maar AWS en GCP gebruiken iets vergelijkbaars. In Azure heeft het de voorkeur om authenticatie via een Service Principle te doen. De inloggegevens van het Service Principle kunnen in GitLab als omgevingsvariabelen worden toegevoegd. GitLab gebruikt dit Service Principle ter authenticatie voor Azure, om vervolgens de resources uit te rollen.

In de onderstaande afbeelding zie je een voorbeeld van GitLab-omgevingsvariabelen die je nodig hebt om te authenticeren met Azure. Voor deze ‘tenant’ en de subscriptie gebruikt Gitlab de inloggegevens van het Service Principle.

Let op de statefile

De ‘statefile’ is een belangrijk onderdeel van Terraform. In dit bestand worden de werkelijke resources in je configuratie ingedeeld, metagegevens bijgehouden en prestaties van grote infrastructuren verbeterd.

Dit bestand wordt door Terraform standaard lokaal op je computer opgeslagen. In een teamomgeving wil je dit echter centraal op een externe dataplaats opslaan. Om het statusbestand extern op te slaan, heb je een soort storage account (Azure) of S3 bucket (AWS) nodig waar je het bestand kunt opslaan en op afstand kunt openen. In het Terraform-bestand moet je naar die opslaglocatie verwijzen. In Terraform ziet het er ongeveer zo uit:

In dit voorbeeld kun je ook zien dat ik de Terraform-versie tussen 0.14 en 0.15 heb geconfigureerd, zodat mijn configuratie ondanks grote wijzigingen blijft gelden. Daarnaast heb ik de Azure-provider geconfigureerd omdat ik resources van Azure wil gebruiken. Ik gebruik daarom de specifieke Azure-code in mijn Terraform-bestanden. Als je resources voor een andere cloud of provider wilt inzetten, moet je deze hier specificeren.

Nu alles op zijn plaats is, kunnen we de resources in Azure uitrollen met Terraform en onze GitLab pipeline. Daarmee voldoen we aan de kwaliteitsprincipes van de organisatie, besparen we tijd en verminderen we fouten door resources gecontroleerd uit te rollen.

Meld je aan voor de Solvinity Nieuwsbrief

Ontvang elk kwartaal het laatste nieuws, blogs, artikelen en events. Meld je aan voor onze nieuwsbrief.

Lees ook

Meer