SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-24

Ansible oder Terraform: Welches Tool brauchen Sie?

Terraform erstellt den VPS, Ansible konfiguriert ihn. Erfahren Sie, wo Provisioner scheitern, wie die Übergabe per Befehlen funktioniert und wann Ansible allein genügt.

Ansible vs Terraform in einem Satz

Ansible vs Terraform ist keine Wahl zwischen zwei Tools, die dieselbe Aufgabe erfüllen. Terraform legt fest, welche Infrastruktur vorhanden ist: Server, Datenträger, Netzwerke und DNS-Einträge. Ansible legt fest, welcher Zustand innerhalb einer bereits vorhandenen Maschine gilt: Pakete, Benutzer, Konfigurationsdateien und laufende Dienste. Terraform erstellt den VPS. Ansible macht daraus einen Webserver.

Beide arbeiten deklarativ, und beide werden als Infrastructure as Code (IaC) bezeichnet. Der eigentliche Unterschied besteht darin, was sie sich merken. Terraform schreibt eine State-Datei, 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 die Zerstörung eines Servers bedeutet. Ansible speichert zwischen den Ausführungen keinen Zustand. Es verbindet sich über SSH, prüft 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 fehlschlägt, beide Aufgaben in einem Tool zu kombinieren.

Was Terraform tatsächlich tut

Terraform kommuniziert über ein Provider-Plugin mit einer API. Auf der Registry-Seite Ihres Providers sind die Ressourcentypen dokumentiert, die Sie verwenden können. Daher haben ein Server auf einem Host und ein Server auf einem anderen Host unterschiedliche Ressourcennamen und Argumente.

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 tfplan

terraform init lädt den Provider herunter und schreibt eine Lock-Datei. terraform plan zeigt den Unterschied zwischen Ihrem Code und der State-Datei an und 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 kennzeichnet sie neben dem Attribut mit # forces replacement, 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 einen einfachen Aufruf von 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 enthält den aktuellen Zustand. Wenn diese Information 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 ein Remote-Backend, sobald mehr als eine Person die Befehle ausführt. Wenn zwei Personen den Plan gleichzeitig anwenden, entsteht Folgendes:

Error: Error acquiring the state lock

OpenTofu ist ein Fork von Terraform mit denselben Befehlen und demselben Dateiformat. Im Juli 2026 funktioniert alles in dieser Anleitung, wenn Sie tofu statt terraform eingeben.

Was Ansible tatsächlich tut

Ansible benötigt weder einen Agenten noch eine API. Es öffnet eine SSH-Verbindung, 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: 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

Das Modul ping überprüft SSH, Python und sudo, bevor Sie mit der Fehlersuche in einem Playbook beginnen. Ein erfolgreiches Ergebnis ist web1 | SUCCESS => {"ping": "pong"}. Der Lauf mit --check --diff kommt in Ansible einem Plan am nächsten: Er meldet, was geändert würde, ohne Änderungen vorzunehmen. 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 den Status changed meldet, ist nicht idempotent. In der Regel handelt es sich um eine command- oder shell-Aufgabe, die ein echtes Modul hätte verwenden sollen. Wenn dieses Thema für Sie neu ist, beginnen Sie mit einem ersten Ansible-Playbook auf einem einzelnen VPS und bauen Sie darauf auf.

Wo sich die beiden Werkzeuge überschneiden und wo sie sich gegenseitig behindern

Terraform kann mit dem Provisioner remote-exec Befehle auf einem neuen Server ausführen. In der eigenen Dokumentation bezeichnet HashiCorp Provisioner als letzte Möglichkeit. 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 weiterhin dem Code entspricht. Die Schritte des Provisioners erscheinen nie in terraform plan. Bei einer Überprüfung sind sie daher nicht erkennbar. Wenn das Skript fehlschlägt, markiert Terraform die Ressource als fehlerhaft. Beim nächsten Apply löscht und erstellt Terraform dann einen Server neu, der wahrscheinlich ordnungsgemäß funktioniert hat.

Der Fehler tritt außerdem zu einem ungünstigen Zeitpunkt auf. Der Provider meldet den Server in dem Moment als erstellt, in dem die API dies bestätigt. Das Betriebssystem startet zu diesem Zeitpunkt jedoch noch, und sshd lauscht noch nicht.

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

Bei Ansible besteht die gegenteilige Versuchung. Cloud-Module können Server erstellen. Für eine kleine Anzahl von Maschinen funktioniert das. Sie verzichten dabei jedoch auf den Abhängigkeitsgraphen und die Zustandsdatei. Ansible erstellt eine Ressource ohne Weiteres. Wenn Sie die Aufgabe aus Ihrem Playbook löschen, bleibt die Ressource jedoch aktiv und verursacht weiterhin Kosten, weil nirgends festgehalten wurde, dass sie ursprünglich von Ihnen erstellt wurde.

Daraus ergibt sich folgende Regel: Überlassen Sie Terraform die Objekte, die eine API erstellt und löscht. Überlassen Sie Ansible alles innerhalb eines gestarteten Betriebssystems.

Die Übergabe funktioniert

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.yml

terraform output -raw gibt einen einzelnen Wert ohne Anführungszeichen und ohne JSON-Wrapper aus. Das ist für eine Shell-Substitution genau richtig. Bei mehreren Servern verwenden Sie terraform output -json und erstellen daraus das Inventory, da -raw nur eine einzelne Zeichenkette, 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 übergeben“ vom Fall „Mein Playbook enthält einen Fehler“. Wenn das Playbook als Erstes auf die neue Maschine zugreift, sehen diese beiden Probleme identisch aus.

Lesen des Terraform-Status als Ansible-Inventar

Wenn Sie überhaupt keine Inventardatei schreiben möchten, liest die Sammlung cloud.terraform den Status direkt ein.

ansible-galaxy collection install cloud.terraform

Legen Sie terraform.yml neben Ihrem Playbook ab:

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

Bevor Sie sich darauf verlassen, müssen Sie zwei Dinge wissen. Das Plugin führt terraform show für project_path aus. Dieses Verzeichnis muss daher bereits initialisiert sein, sonst schlägt das Plugin fehl. Außerdem erstellt es keine Hosts aus Ihren Serverressourcen. Es liest ansible_host- und ansible_group-Ressourcen ein. Diese deklarieren Sie in Ihrem Terraform-Code mithilfe des Ansible-Providers. In ansible-inventory --graph wird erst dann etwas angezeigt, wenn Sie diese Ressourcen hinzufügen.

Eine einfach generierte Inventardatei lässt sich leichter debuggen und funktioniert mit jedem Provider. Das Plugin lohnt sich, sobald das Inventar über eine Handvoll Rechner hinausgewachsen ist und manuelle Bearbeitungen zu Tippfehlern führen. Das ist meist auch der 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 Leserinnen und 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 behalten möchten, beschreibt Terraform einen Vorgang, der einmalig stattfindet. Zusätzlich entsteht eine State-Datei, die Sie nicht verlieren dürfen.

Verwenden Sie Terraform, wenn Sie Umgebungen häufig neu erstellen, wenn Staging exakt mit Produktion übereinstimmen muss, wenn mehrere Personen die Infrastruktur ändern und Sie vor dem Löschen einen überprüfbaren Plan benötigen oder wenn sich Ihre Verwaltung nicht auf Server beschränkt, sondern auch DNS-Einträge, Load Balancer und Firewall-Regeln umfasst, die über eine Provider-API verwaltet werden.

Verwenden Sie weiterhin nur Ansible, wenn die Server langfristig betrieben werden und ihre Anzahl gering ist. Das gilt auch, 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. Es hat zusätzlich den Vorteil, dass es auf dem nächsten Server auf dieselbe Weise ausgeführt wird.

Daraus ergibt sich auch die Reihenfolge beim Lernen. Ansible macht sich bereits auf dem ersten eigenen Server bezahlt. Terraform macht sich ab der dritten Umgebung bezahlt, die Sie neu erstellen.

Was bei der Übergabe schiefgeht

Der Server ist 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 gewartet hat. Warten Sie auf den Port, statt eine feste Pause einzubauen. Ansible bietet dafür ansible.builtin.wait_for_connection. Führen Sie es als ersten Task des Plays aus. Sobald dasselbe Playbook auf eine Gruppe statt auf einen einzelnen neuen Server zielt, legen Sie vorher fest, was geschehen soll, wenn ein Host nicht erreichbar bleibt. Ansible nimmt diesen Host aus dem restlichen Lauf. Die Recap-Zeile ist die einzige Stelle, an der dieser Umstand gemeldet wird.

Der Host-Key hat sich geändert. Sie haben den Server zerstört und neu erstellt. Der neue Server antwortet unter derselben Adresse mit einem neuen Key.

Host key verification failed.

Entfernen Sie den veralteten Eintrag mit ssh-keygen -R 203.0.113.10. Das geschieht häufig, sobald Terraform den Wiederaufbau übernimmt. Deshalb sollten Sie Wiederaufbauten auf Systemen mit Daten möglichst selten durchfü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 möchte etwas zerstören, das Sie nicht geändert haben. Der Plan zeigt Änderungen, die Sie nicht 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 laufende 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 Lauf Änderungen. Ein shell-Task ohne creates- oder when-Bedingung wird immer ausgeführt. Das ist kein rein kosmetisches Problem. Sie können changed=0 dann nicht mehr als Signal dafür 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 Ressourcenerstellung 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 geplant. Terraform hat kein gleichwertiges Modul, das prüft, ob nginx bereits installiert ist, und bei einer vorhandenen Installation 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 beispielsweise zwei VPS-Instanzen bestellen und behalten, 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 geplant.

Welches Tool sollte ich zuerst lernen?

Ansible, wenn Sie heute eigene Server betreiben. Es macht sich bereits beim ersten Rechner bezahlt, benötigt außer SSH nichts und ist auch auf einen Server anwendbar, den Sie manuell bestellt haben. Terraform macht sich später bezahlt, wenn Sie Umgebungen wiederholt neu erstellen oder Provider-Ressourcen über Server hinaus verwalten, beispielsweise DNS-Einträge und Firewall-Regeln.

Wie übergebe ich die IP-Adresse des neuen Servers von Terraform an Ansible?

Definieren Sie in Ihrem Terraform-Code ein output und lesen Sie es nach dem Apply aus. terraform output -raw web_ip gibt den reinen Wert für eine Shell-Substitution aus. terraform output -json liefert bei mehreren Hosts alle Ausgaben auf einmal. Schreiben Sie diesen Wert in eine Inventory-Datei oder installieren Sie die Collection cloud.terraform und verweisen Sie ansible-inventory -i terraform.yml --graph auf das Projektverzeichnis.

Warum schlägt mein Playbook direkt nach Abschluss von Terraform fehl?

Der Provider meldet den Server als erstellt, sobald seine API dies angibt. Das Betriebssystem startet zu diesem Zeitpunkt jedoch noch, sodass SSH in den ersten Sekunden abgewiesen wird. Der Fehler lautet UNREACHABLE! mit Connection refused. Machen Sie ansible.builtin.wait_for_connection zur ersten Aufgabe im Play, anstatt eine feste Wartezeit zu schätzen. Die Bootdauer hängt vom Image und vom Plan ab.