Terraform AzureRM 4.0: wat breekt er en hoe migreer je
In dit artikel

HashiCorp heeft de AzureRM provider 4.0 uitgebracht in augustus 2024. Als je Azure-infrastructuur beheert met Terraform, dan raakt dit jou, en niet op de manier van “even de versie bumpen en verder gaan”. Major version bumps volgen semver, wat betekent dat breaking changes expliciet zijn toegestaan. Resources worden hernoemd, attributen verdwijnen, default values verschuiven, en je perfect werkende terraform plan begint onverwachte diffs te tonen.
We hebben de afgelopen weken meerdere productie-codebases gemigreerd van AzureRM 3.x naar 4.0. In dit artikel bespreken we wat er effectief breekt, welke nieuwe features er zijn, en hoe je de migratie aanpakt zonder je state files om zeep te helpen.
Upgrade guide: AzureRM 4.0 Upgrade Guide - AzureRM Provider Changelog
Waarom major version bumps ertoe doen
Terraform providers zijn niet zoals applicatie-dependencies waar je een minor version kunt bumpen en je tests draait. Provider major versions veranderen het contract tussen je HCL-code en de Azure API. Een resource die bestond in 3.x kan hernoemd, opgesplitst in twee, of volledig verwijderd zijn in 4.0.
Als je pint met ~> 3.0, krijg je 4.0 niet automatisch: dat is by design. Maar elk team op 3.x bouwt migratiedebt op. Hoe langer je wacht, hoe groter de migratie wordt.
Belangrijkste breaking changes
De 4.0-release raakt heel wat resources. Dit zijn de wijzigingen die de meeste codebases treffen:
Attribute defaults gewijzigd
Dit is de sluipende. Attributen die in 3.x een bepaalde default hadden, krijgen nu een andere waarde. Je code verandert niet, maar het gedrag wel:
# 3.x - public_network_access_enabled was implicitly true
resource "azurerm_storage_account" "example" {
name = "stexample"
resource_group_name = azurerm_resource_group.rg.name
location = "westeurope"
account_tier = "Standard"
account_replication_type = "LRS"
}
# 4.0 - you need to be explicit about changed defaults
resource "azurerm_storage_account" "example" {
# ... same base config ...
public_network_access_enabled = true # was implicit, now required
}
Provider configuratie wijzigingen
Het features block had meerdere sub-blocks die aangepast of verwijderd zijn. Sommige flags die in features{} zaten, zijn verplaatst naar resource-level attributen:
# 3.x provider block
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = true
}
}
}
# 4.0 - some feature flags moved to resource attributes
provider "azurerm" {
features {}
# key_vault purge behavior is now on the resource itself
}
Registry docs: AzureRM Provider Configuration - 4.0 Breaking Changes List
Provider-Defined Functions: de grote nieuwe feature
De 4.0-release bestaat niet alleen uit breaking changes. Er worden provider-defined functions geintroduceerd, een Terraform 1.8 feature waarmee providers hun eigen functies kunnen aanbieden:
locals {
parsed = provider::azurerm::parse_resource_id(
"Microsoft.Network/virtualNetworks",
azurerm_virtual_network.example.id
)
}
output "vnet_name" {
value = local.parsed.resource_name
}
Dit vervangt het fragiele split("/", resource_id) patroon dat iedereen gebruikte. De provider function begrijpt de structuur van Azure resource IDs en vangt edge cases op die string splitting niet aankan.
Belangrijk: provider-defined functions vereisen Terraform 1.8 of later. Pas je version constraints aan:
terraform {
required_version = ">= 1.8"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
Terraform docs: Provider-defined Functions - Terraform 1.8 Release
De migratie-aanpak
Probeer geen big-bang migratie. Deze aanpak heeft voor ons gewerkt bij meerdere productie-codebases:
1. Pin op 3.x en audit. Voordat je aan de provider-versie komt, zoek je elk resource type dat je gebruikt en controleer je het tegen de upgrade guide. Weet wat er verandert voordat je iets wijzigt.
2. Werk incrementeel bij. Werk de getroffen resources af per module of stack. Begin met eenvoudige attribute renames en werk toe naar de complexere gevallen.
3. Gebruik moved blocks voor renames. Wanneer een resource type veranderd is maar de onderliggende Azure resource dezelfde blijft, handelen moved blocks dit declaratief af:
moved {
from = azurerm_some_old_resource.example
to = azurerm_some_new_resource.example
}
Deze zijn veiliger dan terraform state mv omdat ze code-reviewed worden en toegepast worden tijdens terraform apply. Gebruik terraform state mv alleen wanneer je resources moet verplaatsen tussen state files of een resource moet opsplitsen in twee.
4. Draai plan in een branch. Bump de provider, draai terraform init -upgrade, dan terraform plan tegen elke omgeving. Niet applyen, gewoon de output lezen:
terraform init -upgrade
terraform plan -out=migration.tfplan 2>&1 | tee plan-output.txt
# Resources marked for destruction = investigate before proceeding
# In-place updates = verify the attribute changes
# No changes = this module is clean
Elke resource die “destroy and recreate” toont, verdient aandacht voordat je iets applyed.
Veelvoorkomende valkuilen
azurerm_resource_group_template_deployment: het output_content attribuut is veranderd van een JSON string naar een map. Als je het parsed met jsondecode(), verwijder die call dan, het is al decoded.
Network security rules: NSG-gerelateerde attributen hebben gewijzigde defaults en validation rules. Inline security rules in azurerm_network_security_group vereisen een zorgvuldige plan-vergelijking.
Boolean defaults omgedraaid: meerdere booleans zijn veranderd van true naar false of omgekeerd. Dit is de gevaarlijkste klasse van wijzigingen, want je code verandert niet maar het gedrag wel, stilletjes. Lees elke regel van de plan diff.
subscription_id verplicht: de 4.0 provider is strenger over subscription configuratie. Als je vertrouwde op impliciete detectie, moet je het nu expliciet instellen in het provider block.
Teststrategie
Vertrouw niet alleen op een groene terraform plan. Voor elke module: draai eerst plan op 3.x om een baseline vast te leggen, bump naar 4.0 en plan opnieuw, en vergelijk dan de output regel per regel. Apply eerst in dev, migreer nooit productie zonder validatie in een lagere omgeving. Controleer de Azure portal na het applyen, want sommige attribute changes zijn cosmetisch in het plan maar betekenisvol in Azure.
Niet overslaan, niet haasten
Major provider upgrades zijn vervelend. De 4.0-release raakt honderden resources, en elke codebase zal minstens een paar breaking changes tegenkomen.
Maar de upgrade overslaan is geen optie. Het AzureRM-team zal geen nieuwe resource support backporten naar 3.x. Elke nieuwe Azure service, elke nieuwe API feature, komt alleen in 4.x terecht. Hoe langer je op 3.x blijft, hoe verder je achterloopt, en uiteindelijk sta je voor een migratie van 3.x naar 5.x, die twee keer zo pijnlijk wordt.
Pin op ~> 4.0, migreer je codebase, en blijf bij. Zet Dependabot of Renovate op om minor version updates te signaleren. Behandel provider upgrades zoals elk ander dependency-onderhoud: saai, noodzakelijk, en veel makkelijker als je het regelmatig doet. Je toekomstige zelf zal je dankbaar zijn wanneer 5.0 uitkomt en de migratie een taak van een dag is in plaats van een project van een week.
Resources: AzureRM 4.0 Upgrade Guide - Terraform Version Constraints - AzureRM Provider GitHub
Klaar om uw infrastructuur te automatiseren?
Van Infrastructure as Code tot CI/CD-pipelines, wij helpen teams sneller te leveren met vertrouwen en minder handmatig werk.
Meer van de blog
Bicep vs Terraform, waarom wij standaard voor Terraform kiezen (en wanneer Bicep wint)
Waarom elke Azure-onderneming een WAF-analysemethodologie nodig heeft