Ik heb ontelbare uren door de AWS Console geklikt, handmatig EC2-instances gestart, security groups geconfigureerd en onvermijdelijk fouten gemaakt die uren kostten om te debuggen. Klinkt bekend? Je maakt een instance in de verkeerde availability zone, vergeet een resource te taggen, of bent een middag kwijt aan het reproduceren van exact dezelfde configuratie als vorige maand omdat je de stappen niet hebt gedocumenteerd.
Handmatige provisioning van infrastructuur is niet alleen saai, het is ook foutgevoelig, niet schaalbaar en onmogelijk te auditen. Daar verandert Terraform alles. Stel je voor dat je je hele AWS-infrastructuur definieert in tekstbestanden die je met versiebeheer kunt beheren, kunt reviewen en automatisch kunt deployen. Geen doelloos geklik meer door tientallen schermen. Geen gesprekken meer als “maar het werkte op mijn machine” met je team.
In deze tutorial laat ik je zien hoe je AWS-infrastructuur automatiseert met Terraform, met focus op een realistisch voorbeeld: het provisionen van een EC2-instance met een automatisch gebootstrapte SSM (Systems Manager) agent. Aan het einde begrijp je de basis van Infrastructure as Code en heb je werkende code die je direct in je eigen AWS-account kunt deployen.
Terraform is een open-source Infrastructure as Code (IaC) tool van HashiCorp waarmee je cloudresources kunt definiëren, provisionen en beheren met behulp van HashiCorp Configuration Language (HCL).
In plaats van door cloudconsoles te klikken of imperatieve bash-scripts te schrijven, declareer je in configuratiebestanden welke infrastructuur je wilt, en Terraform regelt de details om dat te realiseren. Deze verschuiving van imperatieve naar declaratieve infrastructuur is een fundamentele verandering in hoe we over cloudresources denken.
Imperatieve vs. declaratieve aanpak voor het starten van een AWS EC2-instance
Bij een imperatieve aanpak schrijf je stap-voor-stap instructies: "maak eerst deze security group, wacht tot die bestaat, start dan deze instance met die security group, koppel vervolgens dit volume, maak daarna deze tags aan." Jij bent verantwoordelijk voor de exacte volgorde en het afhandelen van fouten bij elke stap.
Met de declaratieve aanpak van Terraform definieer je simpelweg de eindtoestand: "Ik wil een EC2instance met deze specificaties, gekoppeld aan deze security group, met deze tags." Terraform analyseert afhankelijkheden, bepaalt de juiste volgorde en voert het plan uit. Als er iets faalt, weet Terraform precies waar het is gebleven.
Waarom specifiek Terraform kiezen voor AWS?
Ten eerste is het community-ecosysteem enorm en vind je modules, voorbeelden en oplossingen voor vrijwel elke denkbare AWS-service.
Ten tweede is Terraform provider-neutraal. Leer het één keer, en dezelfde skills en patronen werken op AWS, Azure, GCP en andere platformen. Voorkom vendor lock-in met een consistente workflow.
Ten derde houdt Terraform’s statebeheer elk resource bij, waardoor updates en wijzigingen voorspelbaar zijn. Terraform weet wat je hebt aangemaakt en kan het veilig aanpassen of verwijderen.
Voordat we hands-on configuraties ingaan, moet je drie kernbegrippen begrijpen die de basis van Terraform vormen:
Resources zijn de infrastructuurcomponenten die je maakt—EC2-instances, S3-buckets, security groups.
Providers zijn plugins waarmee Terraform met verschillende platformen kan communiceren; de AWS-provider vertaalt je HCL naar AWS API-calls.
HCL is de leesbare syntaxis waarmee je infrastructuur definieert; expressief én eenvoudig.
Met deze basis helder, gaan we je omgeving klaarmaken om echte infrastructuur te bouwen.
Je Terraform AWS-omgeving instellen
Voordat je Terraform-code schrijft, heb je de CLI nodig en geconfigureerde AWS-credentials. Ik neem je door beide heen.
Op macOS gebruik je Homebrew: installeer eerst de HashiCorp tap met brew tap hashicorp/tap, en installeer daarna Terraform met brew install hashicorp/tap/terraform.
Op Windows download je de binary van hashicorp.com en voeg je die toe aan je PATH, of gebruik Chocolatey: choco install terraform.
Op Linux download je het juiste pakket of gebruik je de pakketmanager van je distributie.
Controleer na installatie met terraform version.
AWS-credentials configureren
AWS-credentials configureren vereist een AWS-account, een access key en een secret van IAM. Gebruik nooit je root-account. Maak in plaats daarvan een IAM-gebruiker met programmatische toegang en passende permissies (AdministratorAccess). De standaardaanpak gebruikt het AWS-credentialsbestand op ~/.aws/credentials:
[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEYMogelijk gemaakt door
Als alternatief kun je omgevingsvariabelen zetten: AWS_ACCESS_KEY_ID en AWS_SECRET_ACCESS_KEY. Voor productieomgevingen gebruik je IAM-rollen die zijn gekoppeld aan EC2-instances of CI/CD-systemen in plaats van langlevende credentials.
Met de basis op orde bouwen we nu iets echts: een EC2-instance die bij het opstarten automatisch de SSM-agent installeert.
De projectstructuur opzetten
Terraform-projecten profiteren van een duidelijke en gestructureerde aanpak. Maak drie bestanden: main.tf voor resource-definities, variables.tf voor inputs en outputs.tfvoor waarden die je na deployment nodig hebt. Deze scheiding houdt je code overzichtelijk en onderhoudbaar.
Waarom dit belangrijk is: naarmate projecten groeien, wordt alles in één bestand onhoudbaar. Met variabelen kun je dezelfde code hergebruiken over verschillende omgevingen (dev, staging, productie) door alleen de inputs te wijzigen. Outputs geven je waarden die je nodig hebt, zoals instance-ID’s of IP-adressen, zonder dat je die handmatig in de AWS Console hoeft op te zoeken.
De EC2-resourceconfiguratie schrijven
Laten we nu de infrastructuur maken: een EC2-instance met vooraf geïnstalleerde SSM-agent. Voeg in het bestand main.tf de volgende configuratie toe:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}
data "aws_ami" "amazon_linux" {
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["amazon"]
}
resource "aws_instance" "web_server" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
user_data = <<-EOF
#!/bin/bash
cd /tmp
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl enable amazon-ssm-agent
sudo systemctl start amazon-ssm-agent
EOF
tags = {
Name = "TerraformWebServer"
}
}
resource "aws_iam_instance_profile" "ssm_profile" {
name = "ec2-ssm-profile"
role = aws_iam_role.ssm_role.name
}
resource "aws_iam_role" "ssm_role" {
name = "ec2-ssm-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "ssm_policy" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}Mogelijk gemaakt door
Terraform EC2-instanceconfiguratie
Het data-blok bevraagt AWS voor de meest recente Amazon Linux 2 AMI. De filters zorgen dat je het juiste imagetype krijgt, en owners = ["amazon"] garandeert dat je officiële Amazon AMI’s gebruikt. Deze aanpak werkt in alle regio’s zonder aanpassing—Terraform vindt automatisch de juiste regionale AMI.
Het cruciale onderdeel is user_data: een shellscript dat draait wanneer de instance voor het eerst opstart. Dit script downloadt en installeert de SSM-agent en zet ‘m zo in dat hij automatisch start. De IAM-rol levert de permissies die SSM nodig heeft om de instance te beheren.
Ditzelfde patroon werkt voor elke agent. Wil je CloudWatch voor logs en metrics? Pas dan het user_data-script aan om de CloudWatch-agent te installeren. Het principe blijft identiek: definieer wat je geïnstalleerd wilt hebben en Terraform zorgt dat het op elke instance gebeurt.
Voor het bestand output.tf kun je bijvoorbeeld de instance-ID toevoegen. Zodra je alle Terraform-commands uitvoert die ik in het volgende hoofdstuk behandel, verschijnt de waarde in de terminal.
output "instance_id"{
description ="EC2 instance ID for SSM connection"
value = aws_instance.web_server.id
}Mogelijk gemaakt door
De configuratie initialiseren en toepassen
Met je configuratie geschreven, bestaat de Terraform-workflow uit drie commands. Allereerst downloadt de volgende command de AWS-providerplugin en bereidt je map voor:
Ten tweede toont terraform plan precies wat Terraform gaat aanmaken, wijzigen of verwijderen. Deze preview laat je fouten onderscheppen voordat je echte wijzigingen doorvoert:
Bekijk de output zorgvuldig. Je ziet de EC2-instance, IAM-rol, instance profile en policy attachment die Terraform zal aanmaken.
Tot slot voert terraform apply de wijzigingen uit. Terraform vraagt om bevestiging voordat het doorgaat. Typ yes nadat je deze command hebt uitgevoerd:
Als alles werkt, zie je het volgende bericht zodra de resources zijn aangemaakt.
Bevestiging: Terraform-resources aangemaakt
Binnen enkele minuten heb je een draaiende EC2-instance met SSM geconfigureerd, bereikbaar zonder SSH-sleutels. Controleer in de AWS Console om de recent aangemaakte resources te zien.
Terraform-state beheren op AWS S3
Na het uitvoeren van de bovenstaande commands zie je een nieuw bestand in de map genaamd terraform.tfstate. Het statebestand van Terraform koppelt je configuratie aan echte AWS-resources. Laten we dit bestand doornemen om de inhoud te begrijpen.
Het statebestand begrijpen
Het statebestand bevat elk detail over je gedeployde infrastructuur: resource-ID’s, IP-adressen en afhankelijkheden. Terraform vergelijkt deze state met je configuratie en de feitelijke staat in AWS om te bepalen welke acties nodig zijn. Raak het statebestand kwijt en Terraform verliest het overzicht over alles wat het heeft aangemaakt.
State op je laptop bewaren is riskant. Als je machine crasht, is de state weg. Als meerdere teamleden aan dezelfde infrastructuur werken, veroorzaken conflicterende lokale states corruptie. De oplossing: remote state storage.
De S3-backend van Terraform slaat state op een gecentraliseerde, duurzame locatie op die toegankelijk is voor je hele team. Maak eerst een S3-bucket aan:
aws s3api create-bucket \--bucket datacamp-terraform-state \--region eu-central-1 \
--create-bucket-configuration LocationConstraint=eu-central-1
aws s3api put-bucket-versioning \--bucket datacamp-terraform-state \
--versioning-configuration Status=EnabledMogelijk gemaakt door
Versiebeheer is cruciaal: hiermee kun je herstellen van fouten door terug te rollen naar eerdere stateversies.
Voeg nu de backendconfiguratie toe aan je Terraform-code:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
backend "s3" {
bucket = "datacamp-terraform-state"
key = "terraform.tfstate"
region = "eu-central-1"
use_lockfile = true
}
}Mogelijk gemaakt door
Voer terraform init opnieuw uit om je lokale state naar S3 te migreren. Terraform vraagt bevestiging voordat het het statebestand verplaatst.
Terraform S3 remote backend
Na het uitvoeren van de command bevat de S3-bucket het nieuwe statebestand. Je kunt dit in de AWS Console controleren.
State locken met native S3-lockbestanden
Je hebt waarschijnlijk gezien dat we de volgende instelling hebben toegevoegd aan het main.tf-bestand: use_lockfile = true. Deze instelling activeert de nieuwste functie van Terraform: native S3-state locking. Voorheen had je een aparte DynamoDB-tabel nodig voor locking.
Terraform lock state
Deze vereenvoudiging verwijdert een hele AWS-service uit je infrastructuuropzet, terwijl je dezelfde bescherming behoudt tegen race conditions. Meerdere engineers kunnen veilig aan infrastructuur werken, in de wetenschap dat slechts één persoon tegelijk wijzigingen kan toepassen.
Infrastructuur schalen met Terraform op AWS
Naarmate je infrastructuur groeit, worden hardcoded waarden en gekopieerde code onderhoudsnachtmerries. Het variabelensysteem en de modules van Terraform lossen dit op.
Refactoren met inputvariabelen
Eerder hebben we het bestand variables.tf aangemaakt. Nu kun je de waarden die eerder hardcoded in main.tf stonden, verplaatsen naar dit nieuwe bestand met onze variabelen:
variable "aws_region" {
description = "AWS region for resources"
type = string
default = "eu-central-1"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}Mogelijk gemaakt door
Verwijs nu naar de variabelen in je resources in het bestand main.tf:
provider "aws" {
region = var.aws_region
}
resource "aws_instance" "web_server" {
instance_type = var.instance_type
# ... rest of configuration
tags = {
Environment = var.environment
}
}Mogelijk gemaakt door
Let op dat AWS S3-buckets uniek zijn, dus je kunt geen variabelen gebruiken in de regio in de backend-parameter van main.tf. Hier moet je je hardcoded regio behouden, zoals “eu-central-1”, in plaats van var.region_aws.
Nu onze variabelen zijn gedefinieerd, kun je ook verschillende omgevingen definiëren, zoals development of productie, waar variabelen kunnen verschillen. Dit doe je door nieuwe bestanden met de extensie .tfvars aan te maken.
Maak bijvoorbeeld een terraform-dev.tfvars voor development en een terraform-prod.tfvars voor productie:
Variabelen lossen het probleem van omgeving-specifieke waarden op, maar wat als je hele patronen van infrastructuur dupliceert? Daarvoor zijn modules essentieel.
Hergebruikbare resourcemodules maken
Modules bundelen gerelateerde resources tot herbruikbare componenten. De beste manier om modules te gebruiken is door een specifieke map te maken. Je kunt bijvoorbeeld een directorystructuur als deze maken:
Je kunt het eerder gemaakte bestand variables.tf verplaatsen (of een nieuwe maken) naar de modulemap. De belangrijkste wijziging gebeurt in het bestand main.tf. Die in de module bevat onze resources. Dus alles vanaf de AMI tot aan het einde van het bestand verplaats je daarheen:
data "aws_ami" "amazon_linux" {
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["amazon"]
}
resource "aws_instance" "web_server" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
user_data = <<-EOF
#!/bin/bash
cd /tmp
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl enable amazon-ssm-agent
sudo systemctl start amazon-ssm-agent
EOF
tags = {
Name = "TerraformWebServer"
}
}
resource "aws_iam_instance_profile" "ssm_profile" {
name = "ec2-ssm-profile"
role = aws_iam_role.ssm_role.name
}
resource "aws_iam_role" "ssm_role" {
name = "ec2-ssm-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "ssm_policy" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}Mogelijk gemaakt door
Om deze wijziging te vervangen, behoud je de rest van het bestand maar voeg je een module-parameter toe die verwijst naar de specifieke module.
Als je nu de commands init, plan en apply met deze setup uitvoert, deploy je dezelfde resources als eerder. Het verschil is dat modules je in staat stellen infrastructuur met vergelijkbare configuraties te starten die je kunt hergebruiken. Ze zijn cruciaal om Terraform op te schalen voorbij simpele projecten.
Laten we nu naar een ander belangrijk onderwerp gaan: security.
Best practices voor security met Terraform op AWS
Infrastructuurcode vereist dezelfde security-striktheid als applicatiecode. Het is dus cruciaal om je Terraform-deployments te beschermen.
Omgaan met secrets en gevoelige data
Commit nooit secrets naar Git. Nooit. Gebruik AWS Secrets Manager voor gevoelige waarden. Je kunt de volgende resource in Terraform gebruiken om dat te doen:
resource "aws_secretsmanager_secret" "example" {
name = "example"
}Mogelijk gemaakt door
Voor omgeving-specifieke secrets kun je omgevingsvariabelen gebruiken met het TF_VAR_-voorvoegsel.
Je kunt bijvoorbeeld variable "aws_access_key" {} gebruiken in het bestand variables.tf en het in de terminal exporteren met export TF_VAR_aws_access_key=<access_key_value>. Terraform laadt deze automatisch als variabelewaarden zonder ze in code bloot te geven.
Omgaan met configuration drift
Een ander belangrijk configuratieonderwerp is drift. Dit gebeurt wanneer iemand infrastructuur wijzigt via de AWS Console of CLI, buiten Terraform om. Voer regelmatig terraform plan uit om drift te detecteren. De plan-output toont resources die bestaan maar niet overeenkomen met je configuratie.
Als er drift optreedt, heb je twee keuzes: je Terraform-code bijwerken zodat deze overeenkomt met de realiteit, of terraform apply uitvoeren om de infrastructuur terug te dwingen naar de gewenste staat. De juiste keuze hangt af van of de handmatige wijziging bewust was.
Resources opruimen
Tot slot is het ook belangrijk om alle resources te verwijderen zodra je weet dat je ze niet meer nodig hebt, om onnodige kosten te vermijden. Je kunt de resources opruimen met de volgende command:
Bekijk het vernietigingsplan zorgvuldig. Terraform verwijdert elke resource die het heeft aangemaakt. Voor productie kun je overwegen terraform destroy -target te gebruiken om specifieke resources te verwijderen in plaats van alles.
Conclusie
Je hebt de kernworkflow van Terraform geleerd: definieer infrastructuur in code, bekijk wijzigingen vooraf met plan, pas ze toe met apply en houd alles bij met statebeheer. We hebben EC2-deployment met automatische agentinstallatie behandeld, state verplaatst naar S3 met native locking, opgeschaald met variabelen en modules, en infrastructuur beveiligd met secretsmanagement.
Behandel infrastructuurcode met dezelfde striktheid als applicatiecode. Gebruik versiebeheer, vereis code reviews voor wijzigingen en test eerst in niet-productieomgevingen. CI/CD-pijplijnen kunnen terraform apply automatiseren, zodat infrastructuurupdates net zo soepel verlopen als applicatiedeployments.
Je volgende stap: verken GitHub Actions of GitLab CI om Terraform automatisch uit te voeren wanneer je code pusht. Deze Infrastructure as Code-aanpak, gecombineerd met automatisering, transformeert hoe teams cloudresources beheren en vervangt handmatig consolewerk door betrouwbare, herhaalbare, versiebeheerbare infrastructuur.
Mijn advies is om hierop voort te bouwen en je in te schrijven voor de AWS Cloud Practitioner (CLF-C02) skill track, die je alles leert wat je moet weten om Amazon’s CLF-C02-certificering te halen.
Terraform AWS FAQ’s
Hoe kan ik met Terraform efficiënt meerdere AWS-omgevingen beheren?⌄
Gebruik variabelen en aparte .tfvars-bestanden voor elke omgeving. Maak terraform.dev.tfvars, terraform.staging.tfvars en terraform.prod.tfvars met omgeving-specifieke waarden zoals regio, instance types en tags. Deploy naar verschillende omgevingen met terraform apply -var-file="terraform.prod.tfvars". Zo onderhoud je één codebase terwijl je configuraties per omgeving aanpast zonder code te dupliceren.
Wat zijn best practices voor het beveiligen van gevoelige data in Terraform-configuraties in AWS?⌄
Commit nooit secrets naar Git. Gebruik AWS Secrets Manager om gevoelige waarden zoals databasewachtwoorden op te slaan en verwijs er in Terraform naar met data sources. Gebruik voor omgeving-specifieke secrets omgevingsvariabelen met het TF_VAR_-voorvoegsel—Terraform laadt deze automatisch zonder ze in code bloot te leggen. Schakel encryptie in op je S3-statebucket en beperk IAM-permissies tot alleen noodzakelijke gebruikers en CI/CD-systemen.
Heeft de S3-backend van Terraform nog steeds DynamoDB nodig voor state locking?⌄
Nee. Je kunt native S3-state locking gebruiken door use_lockfile = true in je backendconfiguratie te zetten. Terraform maakt direct in S3 een .tflock-bestand met conditionele writes, waardoor een aparte DynamoDB-tabel niet meer nodig is. Dit vereenvoudigt de setup, verlaagt de kosten en biedt dezelfde bescherming tegen gelijktijdige wijzigingen wanneer meerdere teamleden aan infrastructuur werken.
Hoe ga ik om met configuration drift wanneer iemand handmatig infrastructuur wijzigt?⌄
Voer regelmatig terraform plan uit om drift te detecteren. De plan-output toont resources die niet overeenkomen met je configuratie door handmatige wijzigingen in de AWS Console of CLI. Je hebt twee opties: je Terraform-code bijwerken om de handmatige wijzigingen te weerspiegelen als ze bewust waren, of terraform apply uitvoeren om de infrastructuur terug te zetten naar de gewenste staat die in code is gedefinieerd. Behandel infrastructuur zoals applicatiecode—alle wijzigingen moeten via Terraform verlopen.
Kan ik dezelfde Terraform-code gebruiken om resources in verschillende AWS-regio’s te deployen?⌄
Zeker! Gebruik de variabele aws_region in plaats van regio’s hardcoded op te nemen in het provider-blok. Gebruik data sources (zoals data "aws_ami") in plaats van hardcoded AMI-ID’s, omdat AMI-ID’s per regio verschillen. Definieer de regio in je .tfvars-bestanden: aws_region = "us-east-1" voor de ene omgeving en aws_region = "eu-west-1" voor een andere. Verwijs ernaar in je provider: provider "aws" { region = var.aws_region }. Zo maak je je code echt portabel over regio’s heen.
Als oprichter van Martin Data Solutions en freelance data scientist, ML- en AI-engineer heb ik een divers portfolio in regressie, classificatie, NLP, LLM, RAG, neurale netwerken, ensemblemethoden en computer vision.
Met succes meerdere end-to-end ML-projecten ontwikkeld, inclusief datacleaning, analytics, modellering en deployment op AWS en GCP, met impactvolle en schaalbare oplossingen als resultaat.
Interactieve en schaalbare webapplicaties gebouwd met Streamlit en Gradio voor uiteenlopende usecases in de industrie.
Studenten lesgegeven en gecoacht in data science en analytics, en hun professionele groei gestimuleerd met gepersonaliseerde leertrajecten.
Cursusinhoud ontworpen voor retrieval-augmented generation (RAG)-toepassingen, afgestemd op enterprise-vereisten.
Technische blogs met hoge impact geschreven over AI & ML, met onderwerpen als MLOps, vectordatabases en LLM’s, die veel betrokkenheid opleverden.
In elk project dat ik aanpak, pas ik actuele praktijken uit software-engineering en DevOps toe, zoals CI/CD, codelinting, formattering, modelmonitoring, experimenttracking en robuuste foutafhandeling. Ik zet me in om complete oplossingen te leveren en data-inzichten te vertalen naar praktische strategieën die bedrijven helpen groeien en het maximale halen uit data science, machine learning en AI.
Bereid je voor op Amazon's AWS Certified Cloud Practitioner (CLF-C02) door te leren hoe je de belangrijkste AWS-computing-, database- en opslagservices kunt gebruiken en beveiligen.
Ik heb ontelbare uren door de AWS Console geklikt, handmatig EC2-instances gestart, security groups geconfigureerd en onvermijdelijk fouten gemaakt die uren kostten om te debuggen. Klinkt bekend? Je maakt een instance in de verkeerde availability zone, vergeet een resource te taggen, of bent een middag kwijt aan het reproduceren van exact dezelfde configuratie als vorige maand omdat je de stappen niet hebt gedocumenteerd.
Handmatige provisioning van infrastructuur is niet alleen saai, het is ook foutgevoelig, niet schaalbaar en onmogelijk te auditen. Daar verandert Terraform alles. Stel je voor dat je je hele AWS-infrastructuur definieert in tekstbestanden die je met versiebeheer kunt beheren, kunt reviewen en automatisch kunt deployen. Geen doelloos geklik meer door tientallen schermen. Geen gesprekken meer als “maar het werkte op mijn machine” met je team.
In deze tutorial laat ik je zien hoe je AWS-infrastructuur automatiseert met Terraform, met focus op een realistisch voorbeeld: het provisionen van een EC2-instance met een automatisch gebootstrapte SSM (Systems Manager) agent. Aan het einde begrijp je de basis van Infrastructure as Code en heb je werkende code die je direct in je eigen AWS-account kunt deployen.
Als je nieuw bent met AWS, overweeg dan een van onze cursussen, zoals AWS Concepts, Introduction to AWS Boto in Python, of AWS Security and Cost Management.
Wat is Terraform?
Terraform is een open-source Infrastructure as Code (IaC) tool van HashiCorp waarmee je cloudresources kunt definiëren, provisionen en beheren met behulp van HashiCorp Configuration Language (HCL).
In plaats van door cloudconsoles te klikken of imperatieve bash-scripts te schrijven, declareer je in configuratiebestanden welke infrastructuur je wilt, en Terraform regelt de details om dat te realiseren. Deze verschuiving van imperatieve naar declaratieve infrastructuur is een fundamentele verandering in hoe we over cloudresources denken.
Imperatieve vs. declaratieve aanpak voor het starten van een AWS EC2-instance
Bij een imperatieve aanpak schrijf je stap-voor-stap instructies: "maak eerst deze security group, wacht tot die bestaat, start dan deze instance met die security group, koppel vervolgens dit volume, maak daarna deze tags aan." Jij bent verantwoordelijk voor de exacte volgorde en het afhandelen van fouten bij elke stap.
Met de declaratieve aanpak van Terraform definieer je simpelweg de eindtoestand: "Ik wil een EC2 instance met deze specificaties, gekoppeld aan deze security group, met deze tags." Terraform analyseert afhankelijkheden, bepaalt de juiste volgorde en voert het plan uit. Als er iets faalt, weet Terraform precies waar het is gebleven.
Waarom specifiek Terraform kiezen voor AWS?
Voordat we hands-on configuraties ingaan, moet je drie kernbegrippen begrijpen die de basis van Terraform vormen:
Met deze basis helder, gaan we je omgeving klaarmaken om echte infrastructuur te bouwen.
Je Terraform AWS-omgeving instellen
Voordat je Terraform-code schrijft, heb je de CLI nodig en geconfigureerde AWS-credentials. Ik neem je door beide heen.
Terraform installeren
Terraform installeren verschilt per besturingssysteem:
Op macOS gebruik je Homebrew: installeer eerst de HashiCorp tap met
brew tap hashicorp/tap, en installeer daarna Terraform metbrew install hashicorp/tap/terraform.Op Windows download je de binary van hashicorp.com en voeg je die toe aan je PATH, of gebruik Chocolatey:
choco install terraform.Op Linux download je het juiste pakket of gebruik je de pakketmanager van je distributie.
Controleer na installatie met
terraform version.AWS-credentials configureren
AWS-credentials configureren vereist een AWS-account, een access key en een secret van IAM. Gebruik nooit je root-account. Maak in plaats daarvan een IAM-gebruiker met programmatische toegang en passende permissies (
AdministratorAccess). De standaardaanpak gebruikt het AWS-credentialsbestand op~/.aws/credentials:Als alternatief kun je omgevingsvariabelen zetten:
AWS_ACCESS_KEY_IDenAWS_SECRET_ACCESS_KEY. Voor productieomgevingen gebruik je IAM-rollen die zijn gekoppeld aan EC2-instances of CI/CD-systemen in plaats van langlevende credentials.Als je aan een ander ecosysteem dan dat van Amazon denkt of gewoon een goed overzicht wilt van hoe de “grote drie” zich tot elkaar verhouden, raad ik deze AWS-, Azure- en GCP-servicesvergelijking voor Data Science & AI aan.
Een EC2-agent deployen met Terraform op AWS
Met de basis op orde bouwen we nu iets echts: een EC2-instance die bij het opstarten automatisch de SSM-agent installeert.
De projectstructuur opzetten
Terraform-projecten profiteren van een duidelijke en gestructureerde aanpak. Maak drie bestanden:
main.tfvoor resource-definities,variables.tfvoor inputs enoutputs.tfvoor waarden die je na deployment nodig hebt. Deze scheiding houdt je code overzichtelijk en onderhoudbaar.Waarom dit belangrijk is: naarmate projecten groeien, wordt alles in één bestand onhoudbaar. Met variabelen kun je dezelfde code hergebruiken over verschillende omgevingen (dev, staging, productie) door alleen de inputs te wijzigen. Outputs geven je waarden die je nodig hebt, zoals instance-ID’s of IP-adressen, zonder dat je die handmatig in de AWS Console hoeft op te zoeken.
De EC2-resourceconfiguratie schrijven
Laten we nu de infrastructuur maken: een EC2-instance met vooraf geïnstalleerde SSM-agent. Voeg in het bestand
main.tfde volgende configuratie toe:Terraform EC2-instanceconfiguratie
Het
data-blok bevraagt AWS voor de meest recente Amazon Linux 2 AMI. De filters zorgen dat je het juiste imagetype krijgt, enowners = ["amazon"]garandeert dat je officiële Amazon AMI’s gebruikt. Deze aanpak werkt in alle regio’s zonder aanpassing—Terraform vindt automatisch de juiste regionale AMI.Het cruciale onderdeel is
user_data: een shellscript dat draait wanneer de instance voor het eerst opstart. Dit script downloadt en installeert de SSM-agent en zet ‘m zo in dat hij automatisch start. De IAM-rol levert de permissies die SSM nodig heeft om de instance te beheren.Ditzelfde patroon werkt voor elke agent. Wil je CloudWatch voor logs en metrics? Pas dan het
user_data-script aan om de CloudWatch-agent te installeren. Het principe blijft identiek: definieer wat je geïnstalleerd wilt hebben en Terraform zorgt dat het op elke instance gebeurt.Voor het bestand
output.tfkun je bijvoorbeeld de instance-ID toevoegen. Zodra je alle Terraform-commands uitvoert die ik in het volgende hoofdstuk behandel, verschijnt de waarde in de terminal.De configuratie initialiseren en toepassen
Met je configuratie geschreven, bestaat de Terraform-workflow uit drie commands. Allereerst downloadt de volgende command de AWS-providerplugin en bereidt je map voor:
terraform init
Ten tweede toont
terraform planprecies wat Terraform gaat aanmaken, wijzigen of verwijderen. Deze preview laat je fouten onderscheppen voordat je echte wijzigingen doorvoert:terraform plan
Bekijk de output zorgvuldig. Je ziet de EC2-instance, IAM-rol, instance profile en policy attachment die Terraform zal aanmaken.
Tot slot voert
terraform applyde wijzigingen uit. Terraform vraagt om bevestiging voordat het doorgaat. Typ yes nadat je deze command hebt uitgevoerd:terraform apply
Als alles werkt, zie je het volgende bericht zodra de resources zijn aangemaakt.
Bevestiging: Terraform-resources aangemaakt
Binnen enkele minuten heb je een draaiende EC2-instance met SSM geconfigureerd, bereikbaar zonder SSH-sleutels. Controleer in de AWS Console om de recent aangemaakte resources te zien.
Terraform-state beheren op AWS S3
Na het uitvoeren van de bovenstaande commands zie je een nieuw bestand in de map genaamd
terraform.tfstate. Het statebestand van Terraform koppelt je configuratie aan echte AWS-resources. Laten we dit bestand doornemen om de inhoud te begrijpen.Het statebestand begrijpen
Het statebestand bevat elk detail over je gedeployde infrastructuur: resource-ID’s, IP-adressen en afhankelijkheden. Terraform vergelijkt deze state met je configuratie en de feitelijke staat in AWS om te bepalen welke acties nodig zijn. Raak het statebestand kwijt en Terraform verliest het overzicht over alles wat het heeft aangemaakt.
State op je laptop bewaren is riskant. Als je machine crasht, is de state weg. Als meerdere teamleden aan dezelfde infrastructuur werken, veroorzaken conflicterende lokale states corruptie. De oplossing: remote state storage.
Voor een deep dive in S3 en EFS, bekijk deze AWS Storage Tutorial.
Een remote S3-backend configureren
De S3-backend van Terraform slaat state op een gecentraliseerde, duurzame locatie op die toegankelijk is voor je hele team. Maak eerst een S3-bucket aan:
Versiebeheer is cruciaal: hiermee kun je herstellen van fouten door terug te rollen naar eerdere stateversies.
Voeg nu de backendconfiguratie toe aan je Terraform-code:
Voer
terraform initopnieuw uit om je lokale state naar S3 te migreren. Terraform vraagt bevestiging voordat het het statebestand verplaatst.Terraform S3 remote backend
Na het uitvoeren van de command bevat de S3-bucket het nieuwe statebestand. Je kunt dit in de AWS Console controleren.
State locken met native S3-lockbestanden
Je hebt waarschijnlijk gezien dat we de volgende instelling hebben toegevoegd aan het
main.tf-bestand:use_lockfile = true. Deze instelling activeert de nieuwste functie van Terraform: native S3-state locking. Voorheen had je een aparte DynamoDB-tabel nodig voor locking.Terraform lock state
Deze vereenvoudiging verwijdert een hele AWS-service uit je infrastructuuropzet, terwijl je dezelfde bescherming behoudt tegen race conditions. Meerdere engineers kunnen veilig aan infrastructuur werken, in de wetenschap dat slechts één persoon tegelijk wijzigingen kan toepassen.
Infrastructuur schalen met Terraform op AWS
Naarmate je infrastructuur groeit, worden hardcoded waarden en gekopieerde code onderhoudsnachtmerries. Het variabelensysteem en de modules van Terraform lossen dit op.
Refactoren met inputvariabelen
Eerder hebben we het bestand
variables.tfaangemaakt. Nu kun je de waarden die eerder hardcoded inmain.tfstonden, verplaatsen naar dit nieuwe bestand met onze variabelen:Verwijs nu naar de variabelen in je resources in het bestand
main.tf:Let op dat AWS S3-buckets uniek zijn, dus je kunt geen variabelen gebruiken in de regio in de
backend-parameter vanmain.tf. Hier moet je je hardcoded regio behouden, zoals“eu-central-1”, in plaats vanvar.region_aws.Nu onze variabelen zijn gedefinieerd, kun je ook verschillende omgevingen definiëren, zoals development of productie, waar variabelen kunnen verschillen. Dit doe je door nieuwe bestanden met de extensie
.tfvarsaan te maken.Maak bijvoorbeeld een
terraform-dev.tfvarsvoor development en eenterraform-prod.tfvarsvoor productie:Development:
Productie:
Vervolgens kun je naar de verschillende omgevingen deployen door het juiste bestand te specificeren:
Variabelen lossen het probleem van omgeving-specifieke waarden op, maar wat als je hele patronen van infrastructuur dupliceert? Daarvoor zijn modules essentieel.
Hergebruikbare resourcemodules maken
Modules bundelen gerelateerde resources tot herbruikbare componenten. De beste manier om modules te gebruiken is door een specifieke map te maken. Je kunt bijvoorbeeld een directorystructuur als deze maken:
Je kunt het eerder gemaakte bestand
variables.tfverplaatsen (of een nieuwe maken) naar de modulemap. De belangrijkste wijziging gebeurt in het bestandmain.tf. Die in de module bevat onze resources. Dus alles vanaf de AMI tot aan het einde van het bestand verplaats je daarheen:Om deze wijziging te vervangen, behoud je de rest van het bestand maar voeg je een module-parameter toe die verwijst naar de specifieke module.
Als je nu de commands
init,planenapplymet deze setup uitvoert, deploy je dezelfde resources als eerder. Het verschil is dat modules je in staat stellen infrastructuur met vergelijkbare configuraties te starten die je kunt hergebruiken. Ze zijn cruciaal om Terraform op te schalen voorbij simpele projecten.Laten we nu naar een ander belangrijk onderwerp gaan: security.
Best practices voor security met Terraform op AWS
Infrastructuurcode vereist dezelfde security-striktheid als applicatiecode. Het is dus cruciaal om je Terraform-deployments te beschermen.
Omgaan met secrets en gevoelige data
Commit nooit secrets naar Git. Nooit. Gebruik AWS Secrets Manager voor gevoelige waarden. Je kunt de volgende resource in Terraform gebruiken om dat te doen:
Voor omgeving-specifieke secrets kun je omgevingsvariabelen gebruiken met het
TF_VAR_-voorvoegsel.Je kunt bijvoorbeeld
variable "aws_access_key" {}gebruiken in het bestandvariables.tfen het in de terminal exporteren metexport TF_VAR_aws_access_key=<access_key_value>. Terraform laadt deze automatisch als variabelewaarden zonder ze in code bloot te geven.Omgaan met configuration drift
Een ander belangrijk configuratieonderwerp is drift. Dit gebeurt wanneer iemand infrastructuur wijzigt via de AWS Console of CLI, buiten Terraform om. Voer regelmatig
terraform planuit om drift te detecteren. De plan-output toont resources die bestaan maar niet overeenkomen met je configuratie.Als er drift optreedt, heb je twee keuzes: je Terraform-code bijwerken zodat deze overeenkomt met de realiteit, of
terraform applyuitvoeren om de infrastructuur terug te dwingen naar de gewenste staat. De juiste keuze hangt af van of de handmatige wijziging bewust was.Resources opruimen
Tot slot is het ook belangrijk om alle resources te verwijderen zodra je weet dat je ze niet meer nodig hebt, om onnodige kosten te vermijden. Je kunt de resources opruimen met de volgende command:
Bekijk het vernietigingsplan zorgvuldig. Terraform verwijdert elke resource die het heeft aangemaakt. Voor productie kun je overwegen
terraform destroy -targette gebruiken om specifieke resources te verwijderen in plaats van alles.Conclusie
Je hebt de kernworkflow van Terraform geleerd: definieer infrastructuur in code, bekijk wijzigingen vooraf met
plan, pas ze toe metapplyen houd alles bij met statebeheer. We hebben EC2-deployment met automatische agentinstallatie behandeld, state verplaatst naar S3 met native locking, opgeschaald met variabelen en modules, en infrastructuur beveiligd met secretsmanagement.Behandel infrastructuurcode met dezelfde striktheid als applicatiecode. Gebruik versiebeheer, vereis code reviews voor wijzigingen en test eerst in niet-productieomgevingen. CI/CD-pijplijnen kunnen
terraform applyautomatiseren, zodat infrastructuurupdates net zo soepel verlopen als applicatiedeployments.Je volgende stap: verken GitHub Actions of GitLab CI om Terraform automatisch uit te voeren wanneer je code pusht. Deze Infrastructure as Code-aanpak, gecombineerd met automatisering, transformeert hoe teams cloudresources beheren en vervangt handmatig consolewerk door betrouwbare, herhaalbare, versiebeheerbare infrastructuur.
Mijn advies is om hierop voort te bouwen en je in te schrijven voor de AWS Cloud Practitioner (CLF-C02) skill track, die je alles leert wat je moet weten om Amazon’s CLF-C02-certificering te halen.