Ansible oder Terraform: Was brauchen Sie?
Terraform erstellt den VPS, Ansible konfiguriert ihn. Erfahren Sie, wo Provisioner scheitern, wie die Ubergabe gelingt und wann Ansible allein reicht.
Ansible vs Terraform in einem Satz
Ansible vs Terraform ist keine Entscheidung zwischen zwei Tools, die dieselbe Aufgabe erfüllen. Terraform definiert, welche Infrastruktur vorhanden ist: Server, Datenträger, Netzwerke und DNS-Einträge. Ansible definiert, welcher Zustand innerhalb einer bereits vorhandenen Maschine gelten soll: Pakete, Benutzer, Konfigurationsdateien und laufende Dienste. Terraform erstellt den VPS. Ansible macht daraus einen Webserver.
Beide Tools arbeiten deklarativ, und beide werden als Infrastructure as Code (IaC) bezeichnet. Der entscheidende Unterschied besteht darin, was sie speichern. Terraform schreibt eine Zustandsdatei, die jede Ressource in Ihrem Code einem realen Objekt zuordnet, das Terraform über eine API erstellt hat. Dadurch erkennt Terraform, dass das Löschen von fünf Zeilen bedeutet, dass ein Server zerstört werden muss. Ansible speichert zwischen den Ausführungen nichts. Es verbindet sich über SSH, untersucht die Maschine und ändert nur, was noch nicht dem Playbook entspricht.
Dieser eine Unterschied erklärt den Rest dieses Leitfadens. Er erklärt auch, warum es schiefgeht, wenn beide Aufgaben in einem Tool vermischt werden.
Was Terraform tatsächlich tut
Terraform greift über ein Provider-Plugin auf eine API zu. Auf der Registry-Seite Ihres Providers sind die Ressourcentypen dokumentiert, die Sie verwenden können. Ein Server auf einem Host und ein Server auf einem anderen Host sind daher unterschiedliche Ressourcennamen mit unterschiedlichen Argumenten.
resource "cloud_server" "web" {
name = "web1"
image = "ubuntu-24.04"
type = "small"
}
output "web_ip" {
value = cloud_server.web.ipv4_address
}Ersetzen Sie cloud_server durch den Ressourcentyp, den Ihr Provider dokumentiert. Der Block output ist für diese Anleitung entscheidend, weil darüber die Adresse Terraform verlässt.
terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplanterraform init lädt den Provider herunter und schreibt eine Sperrdatei. terraform plan gibt den Unterschied zwischen Ihrem Code und der Zustandsdatei aus. Die Ausgabe endet mit einer Zeile wie Plan: 1 to add, 0 to change, 0 to destroy. Lesen Sie diese Zeile jedes Mal. Einige Argumente können nicht direkt geändert werden. Der Plan zeigt das mit # forces replacement neben dem Attribut an, gefolgt von 1 to add, 0 to change, 1 to destroy. Beim Anwenden dieses Plans wird der Server gelöscht und ein neuer, leerer Server erstellt. So gehen Daten verloren, die vermeintlich sicher waren.
Wenn Sie den Plan in einer Datei speichern und die Datei anwenden, statt ein einfaches terraform apply auszuführen, wird genau der geprüfte Plan ausgeführt. Zwischen den beiden Befehlen kann eine andere Person die Infrastruktur geändert haben.
terraform.tfstate ist der Zustandsspeicher. Wenn er verloren geht, weiß Terraform nicht mehr, dass diese Server zu Ihrer Infrastruktur gehören. Beim nächsten Anwenden versucht Terraform daher, Duplikate zu erstellen. Verwenden Sie einen Remote-Backend, sobald mehr als eine Person die Befehle ausführt. Wenn zwei Personen gleichzeitig Änderungen anwenden, entsteht Folgendes:
Error: Error acquiring the state lockOpenTofu ist ein Fork von Terraform mit denselben Befehlen und demselben Dateiformat. Stand Juli 2026 funktioniert alles in dieser Anleitung, wenn Sie tofu statt terraform eingeben.
Was Ansible tatsächlich macht
Ansible benötigt weder einen Agent noch eine API. Es baut eine SSH-Verbindung auf, kopiert ein kleines Python-Modul auf das Zielsystem, führt es aus und löscht es anschließend. Alles, was Sie mit SSH und einem sudo-Passwort erreichen können, kann Ansible konfigurieren.
- 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.ymlDas Modul ping überprüft SSH, Python und sudo, bevor Sie mit der Fehlersuche in einem Playbook beginnen. Ein fehlerfreies Ergebnis ist web1 | SUCCESS => {"ping": "pong"}. Der Lauf mit --check --diff kommt einem Plan in Ansible am nächsten: Er meldet, was geändert würde, nimmt diese Änderungen aber nicht vor. Aufgaben, die von vorherigen Aufgaben abhängen, können im Check-Modus jedoch falsche Ergebnisse melden, weil die vorherige Änderung tatsächlich nicht ausgeführt wurde.
Jeder Lauf endet mit einer Zusammenfassung wie ok=6 changed=2 unreachable=0 failed=0. Führen Sie dasselbe Playbook zweimal aus. Beim zweiten Lauf sollte changed=0 gemeldet werden. Eine Aufgabe, die bei jedem Lauf eine Änderung meldet, ist nicht idempotent. Meist handelt es sich um eine command- oder shell-Aufgabe, die stattdessen ein echtes Modul verwenden sollte. Wenn dieses Thema für Sie neu ist, beginnen Sie mit einem ersten Ansible-Playbook auf einem einzelnen VPS und erweitern Sie es von dort aus.
Wo sich die beiden Tools überschneiden und wo sie sich in die Quere kommen
Terraform kann mit dem remote-exec-Provisioner Befehle auf einem neuen Server ausführen. Die eigene Dokumentation von HashiCorp bezeichnet Provisioner als letzten Ausweg. Dafür gibt es gute Gründe.
Ein Provisioner wird nur ausgeführt, wenn die Ressource erstellt wird. Wenn Sie das Skript bearbeiten, geschieht auf dem vorhandenen Server nichts, weil die Ressource aus Sicht von Terraform bereits dem Code entspricht. Schritte von Provisionern erscheinen nie in terraform plan. Bei der Prüfung ist daher nichts davon zu sehen. Wenn das Skript fehlschlägt, markiert Terraform die Ressource als fehlerhaft. Beim nächsten apply zerstört und erstellt Terraform einen Server neu, der wahrscheinlich funktionsfähig war.
Der Fehler tritt außerdem zum falschen Zeitpunkt auf. Der Provider meldet den Server als erstellt, sobald die API dies bestätigt. Das Betriebssystem wird zu diesem Zeitpunkt noch gebootet, und sshd lauscht noch nicht.
Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refusedBei Ansible besteht die umgekehrte Versuchung. Cloud-Module können Server erstellen. Für eine kleine Anzahl von Systemen funktioniert das. Sie verzichten dabei jedoch auf den Abhängigkeitsgraphen und die Zustandsdatei. Ansible erstellt eine Ressource problemlos. Wenn Sie die Aufgabe aus Ihrem Playbook löschen, bleibt die Ressource jedoch aktiv und verursacht weiterhin Kosten, weil nichts festgehalten hat, dass sie Ihnen gehört.
Daraus ergibt sich folgende Regel: Terraform verwaltet Objekte, die eine API erstellt und löscht. Ansible verwaltet alles innerhalb eines gebooteten Betriebssystems.
Die Übergabe, sauber umgesetzt
Die Übergabe ist eine Grenze, keine Integration. Terraform wird fertig, gibt eine Adresse aus und beendet sich. Ansible startet mit dieser Adresse.
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 gibt einen einzelnen Wert ohne Anführungszeichen und ohne JSON-Wrapper aus. Genau das wird innerhalb einer Shell-Substitution benötigt. Für mehrere Server verwenden Sie terraform output -json und erstellen daraus das Inventar, da -raw nur eine einzelne Zeichenfolge, Zahl oder einen booleschen Wert verarbeitet.
Der Schritt ping zwischen den beiden Tools sollte beibehalten werden. Er trennt den Fall „Terraform hat mir die falsche Adresse geliefert“ vom Fall „Mein Playbook enthält einen Fehler“. Wenn das Playbook als Erstes auf den neuen Server zugreift, sehen beide Probleme identisch aus.
Lesen des Terraform-Zustands als Ansible-Inventar
Wenn Sie überhaupt keine Inventardatei schreiben möchten, liest die Sammlung cloud.terraform den Zustand direkt ein.
ansible-galaxy collection install cloud.terraformLegen Sie terraform.yml neben Ihrem Playbook an:
plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infraansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.ymlBevor Sie sich darauf verlassen, sollten Sie zwei Dinge wissen. Das Plugin führt terraform show gegen project_path aus. Dieses Verzeichnis muss daher bereits initialisiert sein, andernfalls schlägt das Plugin fehl. Außerdem erzeugt das Plugin keine Hosts aus Ihren Serverressourcen. Es liest ansible_host- und ansible_group-Ressourcen ein, die Sie mithilfe des Ansible-Providers in Ihrem Terraform-Code deklarieren. In ansible-inventory --graph erscheint erst etwas, wenn Sie diese Ressourcen hinzufügen.
Eine einfach erzeugte Inventardatei lässt sich leichter debuggen und funktioniert mit jedem Provider. Das Plugin lohnt sich, sobald das Inventar mehr als eine Handvoll Rechner umfasst und manuelle Bearbeitung zunehmend Tippfehler verursacht. Das ist derselbe Punkt, an dem die Verwaltung mehrerer Linux-Server von einer zentralen Steuerungsmaschine aus zu einem echten Arbeitsablauf und nicht nur zu einer Gewohnheit wird.
Benötigen Sie Terraform tatsächlich?
Die meisten Leser dieses Textes benötigen Terraform nicht, zumindest noch nicht. Terraform lohnt sich, wenn das Erstellen und Löschen von Infrastruktur selbst eine wiederkehrende Aufgabe ist. Wenn Sie einen einzelnen VPS über ein Control Panel bestellt haben und ihn zwei Jahre lang betreiben möchten, beschreibt Terraform einen Vorgang, der einmal stattfindet. Zusätzlich entsteht eine State-Datei, die Sie nicht verlieren dürfen.
Verwenden Sie Terraform, wenn Sie Umgebungen häufig neu erstellen, wenn die Staging-Umgebung exakt der Produktionsumgebung entsprechen muss, wenn mehrere Personen die Infrastruktur ändern und Sie vor dem Löschen einen prüfbaren Plan benötigen oder wenn Ihre Verwaltung über Server hinausgeht und auch DNS-Einträge, Load Balancer und Firewall-Regeln umfasst, die über eine Provider-API verwaltet werden.
Verwenden Sie weiterhin ausschließlich Ansible, wenn die Server langfristig betrieben werden und ihre Anzahl gering ist und wenn die tägliche Frage lautet: „Ist dieser Server korrekt konfiguriert?“ und nicht: „Existiert dieser Server?“ Ein einzelnes Playbook, das einen neuen Server absichert, deckt denselben Bereich ab wie die ersten zehn Minuten auf einem neuen VPS. Zusätzlich wird es auf dem nächsten Server auf dieselbe Weise ausgeführt.
Daraus ergibt sich auch die Reihenfolge beim Lernen. Ansible macht sich auf dem ersten eigenen Server bezahlt. Terraform macht sich bei der dritten Umgebung bezahlt, die Sie neu erstellen.
Was bei der Übergabe schiefgeht
Der Server ist noch nicht bereit. Terraform wird erfolgreich ausgeführt, aber Ansible schlägt sofort fehl.
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}Die API hat eine Adresse zurückgegeben, bevor sshd auf Verbindungen wartete. Warten Sie auf den Port, statt eine feste Pause einzubauen. Ansible stellt dafür genau ansible.builtin.wait_for_connection bereit. Führen Sie es als erste Aufgabe des Plays aus.
Der Hostschlüssel hat sich geändert. Sie haben den Server gelöscht und neu erstellt. Der neue Server antwortet unter derselben Adresse mit einem neuen Schlüssel.
Host key verification failed.Entfernen Sie den veralteten Eintrag mit ssh-keygen -R 203.0.113.10. Das passiert häufig, sobald Terraform den Server neu erstellt. Das ist ein guter Grund, Neuerstellungen auf Rechnern mit Daten selten durchzuführen.
Sudo schlägt fehl. fatal: [web1]: FAILED! => {"msg": "Missing sudo password"} bedeutet, dass become: true auf diesem Host ein Passwort benötigt. Konfigurieren Sie entweder passwortloses sudo für den Deploy-Benutzer oder übergeben Sie --ask-become-pass.
Terraform will etwas zerstören, das Sie nicht geändert haben. Der Plan zeigt Änderungen, die Sie nie in den Code geschrieben haben. Das bedeutet, dass die reale Infrastruktur vom Code abweicht. Häufig hat jemand eine Einstellung im Webpanel des Providers geändert. Führen Sie terraform plan -refresh-only aus, um diese Abweichung isoliert anzuzeigen. Entscheiden Sie anschließend, ob der Code oder die aktive Ressource falsch ist. Wenden Sie niemals einen destruktiven Plan an, den Sie nicht Zeile für Zeile erklären können.
Ansible meldet bei jedem Durchlauf Änderungen. Eine shell-Aufgabe ohne creates- oder when-Bedingung wird immer ausgeführt. Das ist nicht nur ein kosmetisches Problem. Sie können changed=0 dann nicht mehr als Signal verwenden, dass sich ein Server im gewünschten Zustand befindet.
FAQ
Kann Terraform Ansible ersetzen?
Nicht für die Konfiguration innerhalb eines Servers. Terraform kann mit dem Provisioner remote-exec Skripte aufrufen. Diese werden jedoch nur bei der Erstellung einer Ressource ausgeführt, erscheinen nie in terraform plan und markieren die Ressource bei einem Fehler als fehlerhaft. Beim nächsten Apply wird dadurch ihre Löschung und Neuerstellung eingeplant. Terraform hat kein Äquivalent zu einem Modul, das prüft, ob nginx bereits installiert ist, und in diesem Fall nichts tut. Verwenden Sie Terraform zum Erstellen der Maschine und übergeben Sie sie anschließend an Ansible.
Kann Ansible Terraform ersetzen?
Für eine kleine Anzahl langfristig betriebener Server: ja. Ansible verfügt über Cloud-Module zum Erstellen von Servern. Wenn Sie zwei VPS-Instanzen bestellen und dauerhaft betreiben, reicht das aus. Sie verlieren jedoch die Zustandsdatei und den Abhängigkeitsgraphen: Entfernen Sie eine Aufgabe aus dem Playbook, läuft die Ressource weiter und verursacht weiterhin Kosten, weil Ansible nicht aufgezeichnet hat, dass es sie erstellt hat. Terraform hätte die Löschung eingeplant.
Welche Lösung sollte ich zuerst lernen?
Ansible, wenn Sie bereits Server betreiben. Der Nutzen zeigt sich beim ersten Rechner. Sie benötigen außer SSH nichts. Die Kenntnisse gelten auch für einen Server, den Sie manuell bestellt haben. Terraform zahlt sich später aus, wenn Sie Umgebungen wiederholt neu erstellen oder weitere Provider-Ressourcen verwalten, etwa DNS-Einträge und Firewall-Regeln.
Wie übergebe ich die IP-Adresse des neuen Servers von Terraform an Ansible?
Deklarieren Sie in Ihrem Terraform-Code eine output und lesen Sie sie nach dem Apply aus. terraform output -raw web_ip gibt den reinen Wert für eine Shell-Substitution aus. terraform output -json liefert alle Outputs gleichzeitig, wenn mehrere Hosts vorhanden sind. Schreiben Sie den Wert in eine Inventory-Datei. Alternativ installieren Sie die Collection cloud.terraform und verweisen ansible-inventory -i terraform.yml --graph auf das Projektverzeichnis.
Warum schlägt mein Playbook unmittelbar nach Abschluss von Terraform fehl?
Der Provider meldet den Server als erstellt, sobald seine API dies meldet. Das Betriebssystem startet zu diesem Zeitpunkt jedoch noch. Deshalb weist der Server SSH in den ersten Sekunden zurück. Der Fehler lautet UNREACHABLE! mit Connection refused. Machen Sie ansible.builtin.wait_for_connection zur ersten Aufgabe im Play, anstatt eine Wartezeit zu schätzen. Die Bootdauer hängt vom Image und vom Plan ab.