Terraform voor Kubernetes: complete Infrastructure as Code gids
Terraform is de standaard Infrastructure as Code (IaC) tool voor het declaratief beheren van cloud-infrastructuur. Met Terraform definieer je in HCL (HashiCorp Configuration Language) welke resources je wilt — Kubernetes clusters, netwerken, databases, DNS-records — en Terraform zorgt ervoor dat de werkelijkheid overeenkomt met jouw definitie. Voor iedereen die werkt met Kubernetes op AWS, Azure, GCP of on-premises is Terraform een essentieel onderdeel van de toolchain.
Kernconcepten
- Provider — plugin die communicatie met een cloud of dienst afhandelt (AWS, Azure, Google, Kubernetes)
- Resource — een infrastructuurobject dat Terraform beheert (een EKS-cluster, een namespace, een DNS-record)
- State — Terraform houdt bij welke resources het beheert in een state-bestand (terraform.tfstate)
- Plan — een overzicht van wat Terraform gaat aanmaken, wijzigen of verwijderen
- Apply — het daadwerkelijk uitvoeren van het plan
- Module — herbruikbare groep van resources, vergelijkbaar met een functie
- Workspace — meerdere omgevingen (dev, staging, productie) vanuit dezelfde code
Installatie
# Via tfenv (aanbevolen — beheert meerdere versies)
brew install tfenv # macOS
tfenv install latest
tfenv use latest
# Direct via package manager
brew install terraform # macOS
choco install terraform # Windows
sudo apt-get install terraform # Ubuntu
# Via de officiële binary
curl -LO https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_amd64.zip
unzip terraform_1.9.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
# Versie verifiëren
terraform version
Basisworkflow
# 1. Initialiseer — download providers en modules
terraform init
# 2. Valideer — controleer syntaxis en configuratie
terraform validate
# 3. Plan — toon wat er zou worden aangemaakt/gewijzigd/verwijderd
terraform plan
# 4. Apply — voer het plan uit (vraagt bevestiging)
terraform apply
# Apply zonder bevestigingsvraag (voor CI/CD)
terraform apply -auto-approve
# 5. Destroy — verwijder alle beheerde resources
terraform destroy
Een Kubernetes-cluster aanmaken op AWS (EKS)
# main.tf
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# Remote state in S3 (aanbevolen voor teams)
backend "s3" {
bucket = "mijn-terraform-state"
key = "eks/terraform.tfstate"
region = "eu-west-1"
}
}
provider "aws" {
region = var.regio
}
# EKS cluster via de community module
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = var.cluster_naam
cluster_version = "1.30"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
eks_managed_node_groups = {
standaard = {
min_size = 2
max_size = 10
desired_size = 3
instance_types = ["m5.xlarge"]
capacity_type = "ON_DEMAND"
}
spot = {
min_size = 0
max_size = 10
desired_size = 2
instance_types = ["m5.xlarge", "m5a.xlarge"]
capacity_type = "SPOT"
}
}
tags = local.tags
}
# VPC
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "${var.cluster_naam}-vpc"
cidr = "10.0.0.0/16"
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = false # HA: één per AZ
tags = local.tags
}
Variabelen en outputs
# variables.tf
variable "cluster_naam" {
description = "Naam van het EKS-cluster"
type = string
default = "mijn-cluster"
}
variable "regio" {
description = "AWS-regio"
type = string
default = "eu-west-1"
}
variable "omgeving" {
description = "Omgeving: dev, staging of productie"
type = string
validation {
condition = contains(["dev", "staging", "productie"], var.omgeving)
error_message = "Omgeving moet dev, staging of productie zijn."
}
}
# outputs.tf
output "cluster_endpoint" {
description = "EKS API server endpoint"
value = module.eks.cluster_endpoint
sensitive = false
}
output "cluster_naam" {
description = "Naam van het EKS-cluster"
value = module.eks.cluster_name
}
output "kubeconfig_commando" {
description = "Commando om kubeconfig bij te werken"
value = "aws eks update-kubeconfig --name ${module.eks.cluster_name} --region ${var.regio}"
}
Terraform de Kubernetes-provider gebruiken
# Kubernetes-resources beheren met Terraform
provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
token = data.aws_eks_cluster_auth.cluster.token
}
# Namespace aanmaken
resource "kubernetes_namespace" "productie" {
metadata {
name = "productie"
labels = {
environment = "productie"
managed-by = "terraform"
}
}
}
# ConfigMap aanmaken
resource "kubernetes_config_map" "app-config" {
metadata {
name = "app-config"
namespace = kubernetes_namespace.productie.metadata[0].name
}
data = {
LOG_LEVEL = "info"
DATABASE_URL = "postgres://db.voorbeeld.nl:5432/mijn_db"
}
}
# Helm release via Terraform
provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
token = data.aws_eks_cluster_auth.cluster.token
}
}
resource "helm_release" "ingress_nginx" {
name = "ingress-nginx"
repository = "https://kubernetes.github.io/ingress-nginx"
chart = "ingress-nginx"
version = "4.9.1"
namespace = "ingress-nginx"
create_namespace = true
set {
name = "controller.replicaCount"
value = "2"
}
}
State-beheer voor teams
# Remote state in AWS S3 met DynamoDB locking
terraform {
backend "s3" {
bucket = "mijn-terraform-state"
key = "productie/terraform.tfstate"
region = "eu-west-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
# State-bestand inspecteren
terraform state list
terraform state show module.eks.aws_eks_cluster.this
# Resource importeren (bestaande resource in Terraform state brengen)
terraform import kubernetes_namespace.productie productie
# State opschonen (resource uit state verwijderen zonder te verwijderen)
terraform state rm module.oud_module
Workspaces voor meerdere omgevingen
# Workspace aanmaken en wisselen
terraform workspace new dev
terraform workspace new staging
terraform workspace new productie
terraform workspace list
terraform workspace select productie
# Workspace gebruiken in configuratie
locals {
omgeving = terraform.workspace
tags = {
Environment = terraform.workspace
ManagedBy = "terraform"
}
}
# Omgeving-specifieke waarden
variable "cluster_grootte" {
default = {
dev = 2
staging = 3
productie = 5
}
}
resource "aws_eks_node_group" "workers" {
scaling_config {
desired_size = var.cluster_grootte[terraform.workspace]
min_size = 1
max_size = var.cluster_grootte[terraform.workspace] * 2
}
}
Terraform in CI/CD (GitLab voorbeeld)
# .gitlab-ci.yml
variables:
TF_ROOT: ${CI_PROJECT_DIR}/terraform
TF_VAR_omgeving: ${CI_ENVIRONMENT_NAME}
stages:
- validate
- plan
- apply
validate:
stage: validate
script:
- cd $TF_ROOT
- terraform init -backend=false
- terraform validate
- terraform fmt -check
plan:
stage: plan
script:
- cd $TF_ROOT
- terraform init
- terraform plan -out=tfplan
artifacts:
paths: [terraform/tfplan]
expire_in: 1 week
environment:
name: productie
apply:
stage: apply
script:
- cd $TF_ROOT
- terraform init
- terraform apply tfplan
dependencies: [plan]
when: manual # Handmatige goedkeuring vereist
environment:
name: productie
Belangrijkste CLI-commando’s
# Initialisatie
terraform init # Providers en modules downloaden
terraform init -upgrade # Providers upgraden naar nieuwste versie
# Validatie en opmaak
terraform validate # Syntaxcontrole
terraform fmt # Code formatteren
terraform fmt -recursive # Alle bestanden recursief
# Planning
terraform plan # Wijzigingen vooraf bekijken
terraform plan -out=tfplan # Plan opslaan voor later apply
terraform plan -target=module.eks # Alleen specifieke module plannen
terraform plan -var="omgeving=dev" # Variabele opgeven
# Uitvoering
terraform apply # Plan uitvoeren (met bevestiging)
terraform apply tfplan # Opgeslagen plan uitvoeren
terraform apply -auto-approve # Zonder bevestiging (CI/CD)
terraform destroy # Alles verwijderen
# State-beheer
terraform state list # Alle beheerde resources
terraform state show # Details van één resource
terraform state rm # Uit state verwijderen (niet verwijderen)
terraform import # Bestaande resource importeren
# Outputs
terraform output # Alle outputs weergeven
terraform output cluster_naam # Specifieke output
Terraform in relatie tot certificeringen
- CKA/CKAD — Terraform wordt gebruikt voor het opzetten van oefenomgevingen (EKS, GKE, AKS)
- EX380 — Infrastructure as Code is een kernonderdeel van enterprise OpenShift-beheer
- CGOA/CAPA — Terraform-modules als GitOps-bron voor ArgoCD en Flux
- Terraform Associate — HashiCorp biedt een eigen certificering voor Terraform (003)
Veelgestelde vragen
Wat is het verschil tussen Terraform en Ansible?
Terraform beheert infrastructuur (clusters, netwerken, databases) en is declaratief: je beschrijft de gewenste eindstaat. Ansible beheert configuratie op bestaande servers en is procedureel: je beschrijft de stappen om de gewenste toestand te bereiken. In de praktijk worden beide gecombineerd: Terraform voor de infrastructuur, Ansible voor de configuratie.
Is Terraform gratis?
De open-source versie van Terraform is gratis. In 2023 stapte HashiCorp over naar de Business Source License (BSL), wat commercieel gebruik in concurrerende producten beperkt maar voor intern gebruik vrij blijft. OpenTofu is een volledig open-source fork van Terraform onder de Mozilla Public License, vergelijkbaar met de relatie tussen OpenBao en Vault.
Hoe ga ik om met gevoelige waarden zoals wachtwoorden?
Gebruik nooit wachtwoorden direct in je Terraform-code of in version control. De aanbevolen aanpakken zijn: variabelen als “sensitive = true” markeren, waarden ophalen uit een secrets manager (AWS Secrets Manager, OpenBao/Vault), of omgevingsvariabelen gebruiken (TF_VAR_naam). De Terraform state bevat altijd plain text waarden — beveilig je state-backend met versleuteling en toegangscontrole.