SSD Nodes Learn 🎉 VPS vanaf $5.50/mnd
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-07

Ansible of Terraform: welke tool kiest u?

Kies voor Terraform bij het inrichten van infrastructuur en voor Ansible bij serverconfiguratie. Ontdek het cruciale verschil in state-beheer en hoe u beide tools combineert.

Ansible versus Terraform in één zin

Ansible versus Terraform is geen keuze tussen twee tools die hetzelfde werk verrichten. Terraform declareert welke infrastructuur er bestaat: servers, schijven, netwerken, DNS-records. Ansible declareert wat de status moet zijn binnen een machine die al bestaat: pakketten, gebruikers, configuratiebestanden, actieve services. Terraform maakt de VPS aan. Ansible verandert die VPS in een webserver.

Beide zijn declaratief en beide worden aangeduid als infrastructure as code (IaC). Het werkelijke verschil zit in wat ze onthouden. Terraform schrijft een state-bestand dat elke resource in uw code koppelt aan een echt object dat via een API is aangemaakt, zodat het kan vaststellen dat het verwijderen van vijf regels betekent dat één server moet worden vernietigd. Ansible onthoudt niets tussen runs door. Het maakt verbinding via SSH, inspecteert de machine en wijzigt alleen wat nog niet overeenkomt met het playbook.

Dat ene verschil verklaart de rest van deze handleiding, inclusief waarom het combineren van beide taken in één tool misgaat.

Wat Terraform daadwerkelijk doet

Terraform communiceert met een API via een provider-plugin. De registerpagina van uw provider definieert de resourcetypen die u kunt schrijven; een server bij de ene host en een server bij een andere host hebben daarom verschillende resourcenamen met verschillende argumenten.

resource "cloud_server" "web" {
  name  = "web1"
  image = "ubuntu-24.04"
  type  = "small"
}

output "web_ip" {
  value = cloud_server.web.ipv4_address
}

Vervang cloud_server door het resourcetype dat uw provider documenteert. Het output-blok is het belangrijkste onderdeel voor deze handleiding, omdat dit de manier is waarop het adres Terraform verlaat.

terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplan

terraform init downloadt de provider en schrijft een lock-bestand. terraform plan toont het verschil tussen uw code en het state-bestand, eindigend met een regel zoals Plan: 1 to add, 0 to change, 0 to destroy.. Lees die regel elke keer. Sommige argumenten kunnen niet in-place worden gewijzigd; het plan geeft dit aan met # forces replacement naast het attribuut, gevolgd door 1 to add, 0 to change, 1 to destroy. Het toepassen van dat plan verwijdert de server en bouwt een nieuwe, lege server op. Dit is de manier waarop mensen data verliezen waarvan zij dachten dat deze veilig was.

Door het plan op te slaan in een bestand en dat bestand toe te passen, in plaats van een kale terraform apply uit te voeren, zorgt u ervoor dat hetgeen u heeft beoordeeld ook daadwerkelijk wordt uitgevoerd. Tussen de twee commando's door kan iemand anders de infrastructuur hebben gewijzigd.

terraform.tfstate is het geheugen. Raakt u dit kwijt, dan weet Terraform niet langer dat die servers van u zijn, waardoor de volgende apply probeert duplicaten aan te maken. Sla dit op in een remote backend zodra meer dan één persoon de commando's uitvoert, omdat twee mensen die tegelijkertijd een apply uitvoeren dit resultaat opleveren:

Error: Error acquiring the state lock

OpenTofu is een fork van Terraform met dezelfde commando's en hetzelfde bestandsformaat. Sinds juli 2026 werkt alles in deze handleiding als u tofu typt in plaats van terraform.

Wat Ansible daadwerkelijk doet

Ansible vereist geen agent en geen API. Het opent een SSH-verbinding, kopieert een kleine Python-module naar de doelserver, voert deze uit en verwijdert deze vervolgens. Alles wat u kunt bereiken met SSH en een sudo-wachtwoord, kan Ansible configureren.

- name: Base web server
  hosts: web
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Ensure nginx is running at boot
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true
ansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.yml

De ping-module verifieert SSH, Python en sudo voordat u begint met het debuggen van een playbook. Een gezond resultaat is web1 | SUCCESS => {"ping": "pong"}. De --check --diff-run is het dichtstbijzijnde equivalent van een plan in Ansible: het rapporteert wat er zou veranderen zonder daadwerkelijke wijzigingen door te voeren. Taken die afhankelijk zijn van eerdere taken kunnen in de check-modus echter onjuiste informatie geven, omdat de eerdere wijziging in werkelijkheid niet heeft plaatsgevonden.

Elke run eindigt met een samenvatting zoals ok=6 changed=2 unreachable=0 failed=0. Voer hetzelfde playbook twee keer uit. De tweede run hoort changed=0 te rapporteren. Een taak die bij elke run 'changed' rapporteert, is niet idempotent. Dit is meestal een command- of shell-taak die eigenlijk een echte module had moeten zijn. Als dit nieuw voor u is, begin dan met een eerste Ansible playbook op een enkele VPS en breid dit vanaf daar uit.

Waar de twee tools overlappen en waar ze conflicteren

Terraform kan commando's uitvoeren op een nieuwe server met de remote-exec provisioner. De documentatie van HashiCorp zelf noemt provisioners een laatste redmiddel. Daar zijn goede redenen voor.

Een provisioner wordt alleen uitgevoerd wanneer de resource wordt aangemaakt. Wijzig het script en er gebeurt niets op de bestaande server, omdat de resource vanuit het perspectief van Terraform al overeenkomt met de code. Stappen van een provisioner verschijnen nooit in terraform plan, waardoor uw review geen enkel spoor ervan bevat. Als het script faalt, markeert Terraform de resource als tainted, en bij de volgende apply wordt een server vernietigd en opnieuw opgebouwd die waarschijnlijk in orde was.

De fout treedt bovendien op een ongunstig moment op. De provider rapporteert de server als aangemaakt zodra de API dit bevestigt, terwijl het besturingssysteem nog opstart en sshd nog niet luistert.

Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refused

Ansible kent de omgekeerde verleiding. Cloud-modules kunnen servers aanmaken, en voor een handvol machines werkt dat. Wat u echter opgeeft, is de afhankelijkheidsgraaf en het state-bestand. Ansible zal met plezier een resource aanmaken, maar verwijder de taak uit uw playbook en de resource blijft draaien en wordt in rekening gebracht, omdat nergens is vastgelegd dat deze ooit van u was.

De regel die hieruit voortvloeit: laat Terraform objecten beheren die door een API worden aangemaakt en vernietigd, en laat Ansible alles binnen een opgestart besturingssysteem beheren.

De overdracht, geslaagd

De overdracht is een grens, geen integratie. Terraform voltooit het proces, publiceert een adres en stopt. Ansible start vanaf dat adres.

terraform apply -auto-approve
terraform output -raw web_ip
printf '[web]\n%s ansible_user=root\n' "$(terraform output -raw web_ip)" > inventory.ini
ansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml

terraform output -raw print één waarde zonder aanhalingstekens en zonder JSON-wrapper; dit is wat u nodig heeft binnen een shell-substitutie. Gebruik voor meerdere servers terraform output -json en bouw daar de inventory mee op, aangezien -raw alleen een enkele string, getal of boolean verwerkt.

De ping-stap tussen de twee tools is het behouden waard. Het scheidt "Terraform gaf mij het verkeerde adres" van "mijn playbook bevat een bug". Deze twee problemen lijken identiek wanneer het playbook het eerste is dat de nieuwe server benadert.

Terraform-state lezen als Ansible-inventory

Als u liever helemaal geen inventory-bestand schrijft, leest de cloud.terraform-collectie de state direct in.

ansible-galaxy collection install cloud.terraform

Schrijf terraform.yml naast uw playbook:

plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infra
ansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.yml

Er zijn twee zaken die u moet weten voordat u hierop vertrouwt. De plugin voert terraform show uit tegen project_path, dus die directory moet al geïnitialiseerd zijn, anders faalt de plugin. De plugin verzint ook geen hosts op basis van uw serverresources: hij leest ansible_host- en ansible_group-resources, die u in uw Terraform-code declareert met de Ansible-provider. Er verschijnt niets in ansible-inventory --graph totdat u ze toevoegt.

Een eenvoudig gegenereerd inventory-bestand is makkelijker te debuggen en werkt met elke provider. De plugin loont zodra de inventory groeit tot voorbij een handvol machines en handmatige bewerkingen leiden tot typefouten; dit is hetzelfde punt waarop het beheren van meerdere Linux-servers vanaf één control machine een echte workflow wordt in plaats van een gewoonte.

Hebt u Terraform daadwerkelijk nodig?

De meeste lezers hebben dit niet nodig, in ieder geval nog niet. Terraform verdient zijn investering terug wanneer het aanmaken en verwijderen van infrastructuur een herhaalde taak is. Als u één VPS via een configuratiescherm hebt besteld en van plan bent deze twee jaar te behouden, beschrijft Terraform een gebeurtenis die slechts eenmaal plaatsvindt. Bovendien voegt het een state-bestand toe dat u niet mag verliezen.

Gebruik Terraform wanneer u regelmatig omgevingen opnieuw opbouwt, wanneer een staging-omgeving exact moet overeenkomen met de productieomgeving, wanneer meerdere personen infrastructuur wijzigen en u een controleerbaar plan wilt voordat er iets wordt verwijderd, of wanneer uw beheer verder gaat dan servers en ook DNS-records, load balancers en firewallregels omvat die in een provider-API staan.

Blijf bij alleen Ansible wanneer servers een lange levensduur hebben en in kleine aantallen aanwezig zijn, en wanneer de dagelijkse vraag is "is deze server correct geconfigureerd" in plaats van "bestaat deze server". Een enkel playbook dat een nieuwe server beveiligt, dekt hetzelfde terrein als de eerste tien minuten op een nieuwe VPS, met het voordeel dat het op de volgende server op dezelfde manier wordt uitgevoerd.

De volgorde van leren vloeit hieruit voort. Ansible levert rendement op bij de eerste server die u bezit. Terraform levert rendement op bij de derde omgeving die u opnieuw opbouwt.

Wat er misgaat bij de overdracht

De server is nog niet gereed. Terraform slaagt, maar Ansible faalt direct.

fatal: [web1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 203.0.113.10 port 22: Connection refused", "unreachable": true}

De API gaf een adres terug voordat sshd luisterde. Wacht op de poort in plaats van een vaste pauze toe te voegen. Ansible heeft ansible.builtin.wait_for_connection specifiek hiervoor; voer dit uit als de eerste taak van de play.

De host key is gewijzigd. U heeft de server vernietigd en opnieuw aangemaakt, en de nieuwe server antwoordt op hetzelfde adres met een nieuwe sleutel.

Host key verification failed.

Verwijder het verouderde item met ssh-keygen -R 203.0.113.10. Dit gebeurt voortdurend zodra Terraform het herbouwen beheert. Dit is een goede reden om herbouwacties te beperken op machines die data bevatten.

Sudo faalt. fatal: [web1]: FAILED! => {"msg": "Missing sudo password"} betekent dat become: true een wachtwoord vereist op die host. Configureer ofwel wachtwoordloze sudo voor de deploy-gebruiker, of geef --ask-become-pass mee.

Terraform wil iets vernietigen dat u niet heeft aangepast. Het plan toont wijzigingen die u niet heeft geschreven. Dit betekent dat de werkelijke infrastructuur is afgeweken van de code, meestal omdat iemand een instelling heeft gewijzigd in het webpaneel van de provider. Voer terraform plan -refresh-only uit om dat verschil inzichtelijk te maken en bepaal vervolgens of de code of de live resource onjuist is. Voer nooit een destructief plan uit dat u niet regel voor regel kunt verklaren.

Ansible rapporteert wijzigingen bij elke uitvoering. Een shell-taak zonder creates of when-beveiliging wordt onvoorwaardelijk uitgevoerd. Dit is geen cosmetisch probleem, omdat u changed=0 dan niet langer kunt gebruiken als signaal dat een server zich in de gevraagde staat bevindt.

FAQ

Kan Terraform Ansible vervangen?

Niet voor configuratie binnen een server. Terraform kan scripts aanroepen met de remote-exec provisioner, maar deze draaien alleen bij het aanmaken van een resource, verschijnen nooit in terraform plan en markeren de resource als 'tainted' bij een fout. Dit leidt tot een verwijdering en herbouw bij de volgende apply. Terraform heeft geen equivalent van een module die controleert of nginx al is geïnstalleerd en niets doet als dat zo is. Gebruik Terraform om de machine aan te maken en draag het beheer daarna over.

Kan Ansible Terraform vervangen?

Voor een klein aantal langdurige servers wel. Ansible heeft cloudmodules die servers aanmaken; als u twee VPS-instanties bestelt en deze behoudt, is dat voldoende. Wat u verliest is het state-bestand en de afhankelijkheidsgraaf: als u een taak uit het playbook verwijdert, blijft de resource draaien en worden er kosten in rekening gebracht, omdat Ansible nooit heeft vastgelegd dat het de resource heeft aangemaakt. Terraform zou een verwijdering hebben gepland.

Wat moet ik als eerste leren?

Ansible, als u momenteel servers beheert. Het levert direct resultaat op bij de eerste machine, vereist alleen SSH en de vaardigheid is toepasbaar op servers die u handmatig heeft besteld. Terraform levert later resultaat op, wanneer u omgevingen herhaaldelijk herbouwt of provider-resources beheert die verder gaan dan servers, zoals DNS-records en firewallregels.

Hoe geef ik het nieuwe server-IP door van Terraform aan Ansible?

Declareer een output in uw Terraform-code en lees deze uit na de apply. terraform output -raw web_ip toont de ruwe waarde voor een shell-substitutie en terraform output -json geeft alle outputs tegelijk weer wanneer er meerdere hosts zijn. Schrijf dit naar een inventory-bestand of installeer de cloud.terraform collectie en wijs ansible-inventory -i terraform.yml --graph naar de projectdirectory.

Waarom faalt mijn playbook direct nadat Terraform klaar is?

De provider rapporteert de server als aangemaakt zodra de API dit bevestigt, terwijl het besturingssysteem nog aan het opstarten is; SSH wordt daarom de eerste seconden geweigerd. De foutmelding is UNREACHABLE! met Connection refused. Maak ansible.builtin.wait_for_connection de eerste taak in het play in plaats van een wachttijd te gokken, omdat de opstarttijd varieert per image en plan.