Ansible vs Terraform: wanneer gebruikt u welke tool?
Terraform beheert de infrastructuur, terwijl Ansible de configuratie binnen servers regelt. 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 doen. 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, draaiende services. Terraform maakt de VPS aan. Ansible verandert die VPS in een webserver.
Beide zijn declaratief en beide worden infrastructure as code (IaC) genoemd. Het werkelijke verschil is 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 bepalen 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 op de ene host en een server op 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 tfplanterraform 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.
Het opslaan van het plan in een bestand en het toepassen van dat bestand, in plaats van het uitvoeren van een kale terraform apply, zorgt 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. Verliest u dit, 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 lockOpenTofu 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 door Ansible worden geconfigureerd.
- 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: trueansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.ymlDe ping-module controleert 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 voor Ansible het dichtst bij een plan: het rapporteert wat er zou veranderen zonder de wijziging daadwerkelijk door te voeren. Taken die afhankelijk zijn van eerdere taken kunnen in de check-modus echter onjuiste resultaten 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 terrein 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 laat zien. Als het script faalt, markeert Terraform de resource als tainted, en de volgende apply vernietigt en herbouwt een server die waarschijnlijk in orde was.
Het falen vindt bovendien op een slecht moment plaats. De provider rapporteert de server als aangemaakt zodra de API dit bevestigt, terwijl het besturingssysteem nog aan het opstarten is en sshd nog niet luistert.
Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refusedAnsible kent de tegenovergestelde 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 eigenaar zijn van objecten die een API aanmaakt en vernietigt, en laat Ansible eigenaar zijn van alles binnen een opgestart besturingssysteem.
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.ymlterraform 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.
Het is de moeite waard om de ping-stap tussen de twee tools te behouden. Dit scheidt het probleem "Terraform gaf mij het verkeerde adres" van "mijn playbook bevat een bug". Deze twee problemen zien er identiek uit wanneer het playbook het eerste is dat de nieuwe machine benadert.
Terraform-state lezen als Ansible-inventory
Als u liever helemaal geen inventory-bestand schrijft, leest de cloud.terraform-collectie de state rechtstreeks uit.
ansible-galaxy collection install cloud.terraformSchrijf terraform.yml naast uw playbook:
plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infraansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.ymlEr zijn twee zaken om te weten voordat u hierop vertrouwt. De plugin voert terraform show uit tegen project_path, dus die map moet al zijn geïnitialiseerd, anders faalt de plugin. Daarnaast worden hosts niet automatisch gegenereerd op basis van uw serverresources: de plugin 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, althans 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 handeling die slechts eenmaal plaatsvindt en voegt het een state-bestand toe dat u niet mag verliezen.
Kies voor Terraform wanneer u vaak omgevingen opnieuw opbouwt, wanneer staging exact moet overeenkomen met productie, wanneer meerdere personen wijzigingen aanbrengen in de infrastructuur 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 leven.
Blijf bij enkel Ansible wanneer de servers een lange levensduur hebben en in klein aantal aanwezig zijn, en wanneer de dagelijkse vraag is "is deze machine correct geconfigureerd" in plaats van "bestaat deze machine". 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 vanaf de eerste server die u bezit. Terraform levert rendement op vanaf 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 in te lassen. Ansible heeft ansible.builtin.wait_for_connection specifiek hiervoor; voer dit uit als de eerste taak van de play. Zodra hetzelfde playbook zich op een groep richt in plaats van op één nieuwe machine, bepaal dan vooraf wat er moet gebeuren als één host onbereikbaar blijft, omdat Ansible die host uit de rest van de run verwijdert en de samenvattingsregel de enige plek is waar dit wordt gemeld.
De host key is gewijzigd. U heeft de server vernietigd en opnieuw aangemaakt, en de nieuwe server reageert op hetzelfde adres met een nieuwe sleutel.
Host key verification failed.Verwijder de verouderde vermelding met ssh-keygen -R 203.0.113.10. Dit gebeurt constant zodra Terraform het herbouwen afhandelt, wat een goede reden is om rebuilds zeldzaam te houden 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 sudo zonder wachtwoord voor de deploy-gebruiker, of geef --ask-become-pass mee.
Terraform wil iets vernietigen wat 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 in kaart te brengen 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 bij elke run 'changed'. 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 het signaal dat een server zich in de gewenste staat bevindt.
FAQ
Kan Terraform Ansible vervangen?
Niet voor configuratie binnen een server. Terraform kan scripts aanroepen met de remote-exec provisioner, maar deze worden alleen uitgevoerd bij het aanmaken van de resource, verschijnen nooit in terraform plan en markeren de resource als 'tainted' wanneer ze falen. Dit plant een vernietiging en herbouw in bij de volgende apply. Terraform heeft geen equivalent van een module die controleert of nginx al is geïnstalleerd en niets doet als dat het geval is. Gebruik Terraform om de machine aan te maken en draag het beheer daarna over.
Kan Ansible Terraform vervangen?
Voor een klein aantal langdurig actieve servers wel. Ansible beschikt over cloud-modules die servers aanmaken, en 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 actief en worden er kosten in rekening gebracht, omdat Ansible nooit heeft vastgelegd dat het de resource heeft aangemaakt. Terraform zou een vernietiging hebben gepland.
Welke moet ik als eerste leren?
Ansible, als u momenteel servers beheert. Het levert direct resultaat op bij de eerste machine, vereist niets anders dan SSH, en de vaardigheid is toepasbaar op een server die u handmatig heeft besteld. Terraform levert later resultaat op, wanneer u omgevingen herhaaldelijk opnieuw opbouwt 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 print de ruwe waarde voor een shell-substitutie, en terraform output -json geeft u alle outputs tegelijk 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 projectmap.
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; hierdoor wordt SSH de eerste seconden geweigerd. De foutmelding is UNREACHABLE! met Connection refused. Maak ansible.builtin.wait_for_connection de eerste taak in de play in plaats van te gokken op een wachttijd, omdat de opstarttijd varieert per image en plan.