Start / Seminare / Terraform und OpenTofu in der Praxis
Modul
Bestand übernehmen und refaktorieren
Modul 9 von 14 aus dem Seminar Terraform und OpenTofu in der Praxis
4 Kapitel in diesem Modul-Video · Laufzeit
Für Teams
Die Videos zeigen, wie es geht. Die Schulung sorgt dafür, dass Ihr Team es danach tut.
Ein Video kann niemanden fragen, warum es ausgerechnet in Ihrem Repository nicht funktioniert. Es kann kein Team auf eine gemeinsame Konvention bringen. Und es setzt sich niemand freiwillig drei Tage hin. In der Schulung sind am Ende alle auf demselben Stand, gearbeitet wurde am eigenen Code, und die offenen Fragen sind entschieden — in ein paar Tagen statt irgendwann nebenbei.
Vorgespräch am Telefon · Programm nach Maß · ab 1 Tag (8 Unterrichtseinheiten) · Teilnahmezertifikat
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Bestand übernehmen und refaktorieren
0:00 Bisher haben wir Infrastruktur auf der grünen Wiese gebaut: Code schreiben, planen, anwenden, fertig. Die Wirklichkeit sieht in den meisten Teams anders aus. Da läuft längst etwas — von Hand gestartet, vor Jahren eingerichtet, und niemand möchte es anfassen, weil es eben läuft. Genau darum geht es in diesem Modul. Wir holen bestehende Objekte unter die Verwaltung von Terraform und OpenTofu, ohne sie neu aufzubauen. Danach räumen wir den Code um, ohne dass dabei ein Container neu startet.
0:29 Und schließlich sehen wir uns an, was passiert, wenn jemand an der Pipeline vorbei Hand anlegt. Das ist weniger glamourös als ein Neubau, aber es ist die Arbeit, die in der Praxis am häufigsten ansteht.
Bestand übernehmen und refaktorieren
0:42 Der Leitgedanke steht auf der Folie: Was schon läuft, wird nicht neu gebaut, sondern übernommen. Für die Gärtnerei Lindenhof heißt das ganz konkret, dass die Saatplan-Datenbank ihre Daten behält und keine Sekunde ausfällt, nur weil wir ordentlicher werden wollen. Der Weg dahin hat drei Etappen: importieren, umbenennen und verschieben, Drift erkennen. Am Ende fügen wir alles in einer Übung zusammen.
Bestehende Ressourcen importieren
1:06 Bevor irgendein Objekt in den State wandert, steht eine Frage, die mit Technik wenig zu tun hat: Wer ist eigentlich zuständig? Erst wenn das geklärt ist, lohnt sich der Import. Ein Import ist ein bisschen wie das Eintragen eines Möbelstücks ins Inventar. Der Schrank steht schon im Raum, er wird nicht neu gekauft und nicht verrückt — er bekommt nur eine Nummer auf der Liste.
1:29 Genau das macht der Import: Er nimmt ein vorhandenes Objekt in den State auf und lässt es selbst völlig unberührt. Der import-Block braucht dafür zwei Angaben. Die Adresse im Code, unter der das Objekt künftig geführt wird, und die ID, unter der der Provider es kennt. Beim Docker-Provider ist das für einen Container die Container-ID, so wie docker inspect sie ausgibt.
1:50 Das klingt banal, ist aber der Schlüssel: Mit der falschen ID verwaltet man das falsche Objekt. Diese fünf Schritte sind der Weg, den jedes übernommene Objekt geht. Auffällig ist, wo die Arbeit liegt. Der eigentliche Import, also der import-Block, ist schnell geschrieben. Die Zeit fließt in den ersten und in den vierten Schritt: vorher klären, was überhaupt übernommen wird und wer es pflegt, und nachher die erzeugte Konfiguration so bereinigen, dass der Plan wirklich nur noch den Import zeigt.
2:19 Erst ganz am Ende steht das Apply. Behalten Sie diese Gewichtung im Kopf. Wer die Inventur überspringt oder die Bereinigung abkürzt, landet nicht bei einer verwalteten Ressource, sondern bei einer, die beim nächsten Lauf unerwartet ersetzt wird. Warum so viel Vorarbeit? Weil ein Objekt nur einen Herrn haben darf. Verwalten zwei States denselben Container, versucht jeder, ihn auf seinen eigenen Stand zu bringen — das ist ein Streit, den keiner gewinnt, und die Doku warnt ausdrücklich vor doppelt importierten Objekten.
2:49 Die Inventur hat noch einen zweiten Nutzen: Die Liste der Container auf docker-test und docker-prod zeigt, was Saatplan wirklich umfasst, nicht was in einer alten Wiki-Seite steht. Und sie zwingt zu einer ehrlichen Antwort. Wer ein Objekt bewusst nicht importiert, muss sagen, wer es stattdessen pflegt. Sonst bleibt es ein Waisenkind, das irgendwann jemand aus Versehen löscht.
3:11 Hier sehen Sie den Import der Saatplan-Datenbank, und er ist erfreulich kurz. Der Block sagt im Grunde nur: Das Objekt mit dieser ID gehört ab sofort zur Ressource db. Bemerkenswert ist, woher die ID kommt. Sie steht nicht fest im Code, sondern wird über eine Variable hereingereicht. Das hat einen guten Grund: Die Container-ID ist auf docker-test eine andere als auf docker-prod, der Code soll aber für beide Umgebungen derselbe bleiben.
3:36 Eine Bedingung gilt allerdings: Die ID muss schon beim Plan bekannt sein. Es darf ein fester Text oder ein Ausdruck sein, der zu einem Text auswertet — aber nichts, was erst beim Anwenden entsteht. Jetzt wird es praktisch. Zuerst fragen wir den Docker-Host nach der vollen ID des Containers saatplan-db und legen sie in der Umgebungsvariablen ab, die Terraform als Wert für die Variable liest.
4:00 Dann kommt ein Plan mit einer Besonderheit: Mit der Option generate config out schreibt das Werkzeug die passende Konfiguration gleich selbst in eine neue Datei. Das spart viel Abtipperei. Zwei Einschränkungen sollten Sie kennen. Die Zieldatei darf noch nicht existieren, sonst bricht der Lauf ab. Und die Generierung gilt in Terraform wie in OpenTofu als experimentell.
4:21 Deshalb steht dazwischen der wichtigste Schritt: das Ergebnis lesen und bereinigen, bevor geplant und angewendet wird. Es gibt zwei Wege zum Import, und die Tabelle zeigt, warum die Doku den neueren empfiehlt. Der alte Befehl terraform import wirkt sofort und an allen vorbei: kein Plan, keine Vorschau, und im Pull Request taucht er nicht auf.
4:42 Für einen einzelnen Container mag das gehen, als Arbeitsweise im Team ist es heikel. Der import-Block dagegen ist ganz normaler Code. Er läuft durch denselben Plan, denselben Review und dasselbe Apply wie jede andere Änderung. Dazu kommen zwei handfeste Vorteile: Die Konfiguration lässt sich erzeugen, und mit for_each importiert ein einziger Block gleich eine ganze Reihe von Objekten.
5:05 Die erzeugte Datei ist ein Rohentwurf, kein fertiger Code. Sie enthält alles, was der Provider auslesen konnte — auch Standardwerte und berechnete Angaben, die im Code nichts verloren haben. Heikler ist der zweite Punkt: Die Umgebungsvariablen des Containers landen im Klartext darin, das Datenbankpasswort eingeschlossen. Diese Datei darf so niemals ins Repository.
5:28 Der dritte Stolperstein überrascht viele. Das Image lässt sich laut Doku nicht importieren; zeigt der Plan dort ein Ersetzen, läuft offenbar ein anderes Image als angenommen. Die Messlatte ist deshalb streng: genau ein Import, sonst überall Nullen. Erst dann wird angewendet.
Umbenennen und verschieben
5:45 Die Datenbank ist jetzt verwaltet, aber sie liegt noch nicht dort, wo sie hingehört. Im nächsten Schritt räumen wir den Code um — und der Container soll davon nichts merken. Stellen Sie sich einen Umzug innerhalb desselben Hauses vor, bei dem nur das Türschild wechselt, die Möbel aber stehen bleiben. Genau das leistet ein moved-Block.
6:05 Er hält fest, dass ein Objekt eine neue Adresse im Code hat, weil es umbenannt, in ein Modul verschoben oder unter count oder for_each gestellt wurde. Ohne diesen Hinweis sähe das Werkzeug nur, dass eine Ressource verschwunden und eine neue aufgetaucht ist, und würde löschen und neu anlegen. Mit dem Hinweis schreibt es einfach die Adresse im State um. Sein Gegenstück ist der removed-Block: Er entlässt ein Objekt aus der Verwaltung, auf Wunsch, ohne es zu zerstören.
6:32 Hier wandert der Datenbank-Container aus der Umgebungskonfiguration in das Modul saatplan-db, das wir für genau diesen Zweck haben. Der obere Teil ist der gewohnte Modulaufruf, das Passwort kommt wie gehabt über eine Variable. Entscheidend ist der kleine Block darunter. Er verbindet die alte Adresse mit der neuen, und damit wird aus einem vermeintlichen Neubau ein bloßes Umschreiben im State. Das funktioniert in Terraform und OpenTofu gleich.
6:57 Ein Rat für geteilte Module: Lassen Sie solche Blöcke stehen, auch wenn der Umzug längst erledigt ist. Andere Teams, die das Modul in einer älteren Version nutzen, brauchen den Hinweis noch, sonst bricht ihnen der nächste Plan. Manchmal soll ein Objekt nicht umziehen, sondern ganz aus unserer Verantwortung heraus. Bei Saatplan ist das das Datenvolume, das künftig ein eigenes Team pflegt.
7:20 Der removed-Block sagt dem Werkzeug: Diese Ressource gehört nicht mehr zu uns. Und der lifecycle-Teil darin regelt, was mit dem realen Objekt geschieht. Steht dort, dass nicht zerstört werden soll, bleibt das Volume samt Daten stehen und verschwindet nur aus unserem State. Fehlt diese Angabe, behandelt das Werkzeug den Block, als hätte man die Ressource einfach aus dem Code gelöscht — und löscht das Volume gleich mit.
7:45 Das ist eine Zeile, die man nie vergessen darf. Vier Fallen lauern beim Umräumen. Die erste ist eine Grenze des Werkzeugs: Aus einer verwalteten Ressource lässt sich per moved keine Data Source machen. Die zweite ist ein Warnsignal, das man ernst nehmen sollte. Zeigt der Plan nach dem Verschieben trotzdem Änderungen, dann ist das kein reiner Umzug, sondern das Modul beschreibt den Container anders als er tatsächlich läuft.
8:09 Die dritte haben wir eben besprochen: removed ohne den Schutz vor dem Zerstören kostet das Volume samt Daten. Und die vierte betrifft die Übergabe. Das abgegebene Volume braucht einen neuen Besitzer, der es seinerseits per import-Block übernimmt — sonst ist es niemandem mehr zugeordnet.
Drift erkennen und behandeln
8:26 Der Code ist aufgeräumt, der State stimmt. Aber die Welt draußen hält still nur so lange, bis jemand schneller ist als die Pipeline — und dabei nichts aufschreibt. Drift ist der Abstand zwischen Akte und Wirklichkeit. Im State steht, dass ein Container läuft und nach einem Absturz neu startet. In Wahrheit hat ihn jemand von Hand gestoppt oder die Neustart-Regel geändert. Das Werkzeug weiß davon nichts, bis es nachsieht.
8:51 Für dieses Nachsehen gibt es einen eigenen Modus, refresh-only. Ein Plan in diesem Modus vergleicht nur den State mit der Realität und gleicht ihn samt den Ausgabewerten an. Er schlägt ausdrücklich keine Änderung an der Infrastruktur vor. Man kann sich das wie eine Inventur vorstellen, bei der nur gezählt wird und noch niemand etwas zurück ins Regal stellt.
9:12 Diese drei Aufrufe decken den ganzen Umgang mit Drift ab, und sie funktionieren mit tofu genauso. Der erste ist reines Lesen: Was hat sich draußen verändert? Der zweite übernimmt eine Abweichung bewusst in den State, mit vorheriger Rückfrage. Der dritte ist für die Automatisierung gedacht. Mit dem detaillierten Exit-Code meldet der Plan über seinen Rückgabewert, ob alles gleich ist oder ob es Änderungen gibt — ideal für einen geplanten Lauf, der Alarm schlägt.
9:40 Und eine Warnung zum Schluss: Der ältere Befehl terraform refresh ist veraltet. Er übernimmt jede Abweichung ohne Rückfrage, und genau diese fehlende Bremse wollen wir nicht. Wenn Drift gefunden ist, gibt es genau zwei ehrliche Antworten, und dieser Vergleich stellt sie nebeneinander. Entweder die Änderung war richtig. Dann übernehmen wir sie in den State und ziehen den Code im selben Zug nach, sonst dreht das nächste Apply sie wieder zurück. Oder die Änderung war ein Versehen.
10:08 Dann bleibt der Code, wie er ist, und ein normales Apply stellt den gewünschten Zustand wieder her. Wichtig ist der letzte Gedanke auf der rechten Seite: Wer nur zurückdreht, ohne zu fragen, warum es zur Abweichung kam, sieht sie bald wieder. Drift ist meist ein Symptom für einen Prozess, der irgendwo eine Abkürzung hat.
10:27 Abstrakt ist Drift schnell erklärt, aber woran erkennt man sie konkret? Beim Docker-Provider gibt es drei typische Bilder. Ein von Hand gestoppter Container taucht im Plan als Änderung auf, weil die Angabe, dass er laufen muss, plötzlich nicht mehr stimmt. Eine nachträglich geänderte Neustart-Regel zeigt sich genau an diesem Feld.
10:46 Und ein gelöschter und neu gestarteter Container ist für das Werkzeug ein völlig anderes Objekt, weil er eine neue ID trägt — der alte gilt als verschwunden. In einer Cloud-Umgebung kommen weitere Quellen hinzu: Klicks in der Konsole und fremde Automatisierung. Das Prinzip bleibt dasselbe, nur die Zahl der Hintertüren wächst.
11:05 Der häufigste Fehler beim Umgang mit Drift ist ein halber Schritt: Die Abweichung wird in den State übernommen, aber der Code bleibt alt. Beim nächsten Plan will das Werkzeug dann alles zurückdrehen, und niemand versteht, warum. Der zweite Fehler ist eine Frage des Zeitpunkts. Wer Drift erst beim nächsten Release bemerkt, sucht unter Termindruck — ein geplanter Lauf findet sie in Ruhe.
11:27 Der dritte ist tückisch: Fehlende Zugangsdaten sehen im Plan aus wie gelöschte Objekte. Darum vor jedem Übernehmen den Plan wirklich lesen. Und schließlich der Notfall-Fix, der von Hand eingespielt wurde und beim nächsten Apply stillschweigend wieder verschwindet.
Übung
11:43 Jetzt kommt alles zusammen: Importieren, Verschieben und Drift an einem einzigen Objekt. Und es gibt eine klare Bedingung — die Saatplan-Datenbank startet dabei kein einziges Mal neu. In dieser Übung übernehmen Sie den laufenden Datenbank-Container von Saatplan, ohne ihn neu aufzubauen. Es geht um eine Fähigkeit, die im Berufsalltag oft mehr zählt als jeder Neubau: vorhandene Infrastruktur behutsam unter Kontrolle zu bringen, umzubauen und Abweichungen bewusst zu bewerten.
12:11 Gearbeitet wird in der Testumgebung des Infrastruktur-Repositorys gegen docker-test. Ob es gelungen ist, sagt Ihnen der Plan: Nach Import und Verschieben darf er nichts mehr hinzufügen und nichts mehr zerstören wollen. Außerdem soll ein von Hand gestoppter Container als Drift erkannt und bewusst behandelt sein. Ein einfacher Prüfstein begleitet Sie dabei: Notieren Sie die Container-ID am Anfang und vergleichen Sie sie am Ende.
12:35 Der Weg folgt genau der Reihenfolge des Moduls. Zuerst ermitteln Sie die ID und schreiben den Import. Dann lassen Sie die Konfiguration erzeugen und räumen sie auf; dazu gehört vor allem, das Passwort aus dem Klartext zu holen und durch die Variable zu ersetzen. Danach wird so lange geplant, bis wirklich nur noch der eine Import übrig ist — Geduld an dieser Stelle zahlt sich aus.
12:57 Im vierten Schritt zieht der Container ins Modul um, und der Plan sollte das als reinen Umzug zeigen. Zum Schluss provozieren Sie Drift selbst und entscheiden, wie Sie damit umgehen. Bleibt die Container-ID über alle Schritte gleich, haben Sie den Bestand wirklich übernommen.
Dieses Modul als Schulung für Ihr Team
Das Video zeigt den Stoff. In der Schulung arbeitet Ihr Team damit — an Ihrem eigenen Code, mit Übungen und mit den Fragen, die ein Video nicht beantwortet. Sie wählen die Module aus Terraform und OpenTofu in der Praxis, wir bauen daraus ein Programm.
5 Tage·ab 900 EUR netto pro Tag (bis 3 Teilnehmende) ·Termin nach Vereinbarung