Es ist möglich, imports.tf
mit einem einfachen Skript zu verwalten, anstatt terraform.tfstate
zu pflegen. Im Gegensatz zum Zustand enthält imports.tf
keine vetraulichen Informationen und kann daher sicher committed werden.
Einleitung
Wir schätzen
Terraform
als Tool zur Verwaltung von Infrastruktur als Code. Mit terraform apply
wird der tatsächliche Zustand der verwalteten Infrastruktur an den Sollzustand aus den .tf
Dateien angepasst. Terraform verwaltet seinen Zustand in einer Datei terraform.tfstate
, die
laut offizieller Dokumentation
erforderlich ist:
Terraform must store state about your managed infrastructure and configuration. This state is used by Terraform to map real world resources to your configuration, keep track of metadata, and to improve performance for large infrastructures.
Aber woher weiß Terraform, dass der Zustand aktuell ist, wenn es sich auf eine lokale oder gemeinsam genutzte Datei stützt?
Prior to any operation, Terraform does a refresh to update the state with the real infrastructure.
Zustand ist immer einer Fehler– und Komplexitätsquelle. Weiterhin kann .tfstate
vertrauliche Informationen wie Zugangsdaten enthalten. Dieser Artikel zeigt, wie wir Terraform ohne .tfstate
nutzen.
.tfstate
mit imports.tf
ersetzen
terraform.tfstate
wird von Terraform benötigt, um zu verstehen, wie die in den Terraform Quelldateien beschreibenen Ressourcen mit der Infrastruktur zusammenhängen. Dies geschieht durch die Zuordnung von IDs. Terraform erkennt anhand des Zustands, ob eine Ressource erstellt oder geändert werden soll.
Was aber, wenn bereits bestehende Ressourcen mit Terraform verwaltet werden sollen? Für diesen Fall unterstützt Terraform das Importieren von Ressourcen in den Zustand mit import
Blocks.
Beispiel
Der gewünschte Zustand ist eine in main.tf
definierte OpenStack Public Floating IP:
resource "openstack_networking_floatingip_v2" "my_ip" {
pool = "my-pool"
}
Nach dem Ausführen von terraform apply
enthält die resultierende terraform.tfstate
eine Beziehung zwischen den IDs innerhalb der Terraform-Konfiguration und denen der Infrastruktur:
{
// ...
"resources": [
{
// Identification of the resource inside the terraform files (desired state)
"mode": "managed",
"type": "openstack_networking_floatingip_v2",
"name": "my_ip",
"provider": "provider[\"registry.terraform.io/terraform-provider-openstack/openstack\"]",
"instances": [
{
"attributes": {
// Identification of the resource in the managed infrastructure
"id": "2b13d767-7446-4a91-a9ff-6fa63a25303e",
// ...
}
// ...
}
]
}
// ...
]
}
Der gleiche Zustand kann durch Importieren der vorhandenen Ressource mit imports.tf
und terraform refresh
(oder apply
) erreicht werden:
import {
to = openstack_networking_floatingip_v2.my_ip
id = "2b13d767-7446-4a91-a9ff-6fa63a25303e"
}
Ein Jsonnet Skript zur Erzeugung von imports.tf
Nach terraform apply
oder terraform refresh
ist terraform.tfstate
aktuell. imports.tf
kann dann mit einem Skript daraus abgeleitet werden.
Wir verwenden dieses Jsonnet -Skript hierzu:
# tfstate.jsonnet
# LICENSE: MIT. Copyright 2025 Daydream Unicorn GmbH & Co. KG
function(tfstate)
std.join('\n', [
] +
std.flattenArrays(
std.map(
function(e) ['import {\n to = %(module)s%(type)s.%(name)s%(index_key)s\n id = "%(id)s"\n}' % {
module: if std.objectHas(e, 'module') then e.module + '.' else '',
type: e.type,
name: e.name,
id: x.id,
index_key: if std.get(x, 'index_key') == null then '' else '["' + std.get(x, 'index_key') + '"]'
} for x in [{ id: i.attributes.id, index_key: std.get(i, 'index_key') } for i in e.instances] ],
std.filter(
function(e) e != null && std.objectHas(e, "mode") && e.mode == "managed",
tfstate.resources
)
)
) +[
]
)
Anwendung:
#/bin/bash
jsonnet tfstate.jsonnet --tla-code-file tfstate=terraform.tfstate -S > imports.tf
Workflow
#!/bin/bash
git clone <your terraform repo>
cd <your terraform repo>
# Zustand aktualisieren, Ressourcen importieren
terraform refresh
# "Warning: Empty or non-existent state" nach dem ersten refresh kann ignoriert werden.
# Dateien wie geüwnsch editieren, dann
terraform apply
# Zum Schluss imports.tf aktualisieren
jsonnet tfstate.jsonnet --tla-code-file tfstate=terraform.tfstate -S > imports.tf
rm terraform.tfstate
git add <changed files>
git add imports.tf
imports.tf
muss neu generiert werden, wenn sichterraform.tfstate
geändert hat. Es kann zusammen mit den entsprechenden Änderungen committet werden.- Wenn sich die Ressourcenidentifikation in der Konfiguration ändert, z. B. aufgrund einer Umbenennung von Ressourcen innerhalb der Terraform Dateien, müssen die IDs in
imports.tf
undterraform.tfstate
aktualisiert werden.imports.tf
muss auf dem neuesten Stand sein, bevor solche Änderungen durchgeführt werden. - Geheimnisse können mit
terraform apply -var=my_secret=(password manager command to obtain the secret) ...
übergeben werden.
Einschränkungen
- Es wurde nicht untersucht, ob resources.instances.attributes.id immer das identifizierende Feld ist. Dies kann vom terraform provider abhängen oder auch nicht.
- Das Format von
terraform.tfstate
könnte sich ändern. - Terraform verwendet seinen Zustand auch als Cache zur Leistungsoptimierung. Das Importieren vieler Ressourcen kann eine Weile dauern. Der zustandslose Ansatz kann zu langsam sein, wenn sehr viele Ressourcen mit demselben
terraform apply
verwaltet werden. - Abhängigkeiten müssen möglicherweise
in der Terraform-Konfiguration mit
depends_on
explizit modelliert werden - Einige Eigenschaften sind möglicherweise nicht aus der Infrastruktur lesbar. Dies ist zwar eine Einschränkung des jeweiligen Infrastrukturanbieters und nicht dieses Workflows, aber Terraform zeigt häufiger eine Warnung dazu an, da es davon ausgeht, dass diese Eigenschaften bekannt sind, wenn es sie aus
terraform.tfstate
lesen kann.