Eine Zero-Fricton-Terraform-Grundierung | Komentor

Was ist Terraform und warum sollte es Sie interessieren? Wie können Sie sich darüber informieren, ohne echte Inhalte in Ihrem Amazon-Konto bereitstellen zu müssen?

Infrastruktur als Code

Damals, als wir begannen, uns vom Umgang mit echten Servern in einem Rack zu lösen, tauchten irgendwo eine Reihe von Cloud-Infrastrukturanbietern auf, die den Zugriff auf ihren virtuellen Besitz über eine Konsole und – wenn sie etwas taugten – eine API anboten.

Ich habe an vielen verschiedenen Orten gearbeitet, an denen diese Cloud-Anbieter verwendet wurden (OK, hauptsächlich Amazon Web Services), und ich habe ungefähr so ​​​​viele verschiedene Möglichkeiten zur Verwaltung der Infrastruktur gesehen.

Der schlechteste Weg ist natürlich über die Konsole. Das Klicken in eine GUI ist kein guter Weg, um Prozesse wiederholbar oder skalierbar zu machen. Zu den Optionen gehören darüber hinaus: CloudFormation, ein Dienst von AWS (funktioniert nur mit AWS); HEAT-Vorlagen von OpenStack, das CloudFormation sehr ähnlich ist (funktioniert nur mit OpenStack); Chef Provisioning, das von Chef nicht mehr unterstützt wird; und natürlich Terraform.

Mit all diesen Tools können Sie definieren, welche Infrastruktur Sie möchten – virtuelle Maschinen, Load Balancer, Blockspeicher, Datenbanken usw. – als eine Art maschinen- und menschenlesbare Sprache (CloudFormation verwendet beispielsweise JSON). Das Tool kann den Code interpretieren und die gewünschten Ressourcen erstellen; Der Code kann in die Versionskontrolle eingecheckt und wie Anwendungscode verfolgt werden.

Terraform

Terraform ist ein Infrastructure-as-Code-Tool von Hashicorp, das andere beliebte Software wie Vagrant herstellt. Es verwendet eine deklarative Sprache, Hashicorp Configuration Language (HCL), um den gewünschten Zustand Ihrer Cloud-Infrastruktur zu definieren. Aus diesem Code generiert es ein Abhängigkeitsdiagramm der Ressourcen und durchläuft dieses Diagramm, wenn es für einen oder mehrere Anbieter ausgeführt wird, und stellt sicher, dass die Ressourcen vorhanden und wie definiert konfiguriert sind.

Installation

Das terraform Die ausführbare Datei wird als einzelne Datei geliefert, sodass sie nur heruntergeladen und in den Pfad Ihres Systems eingefügt werden muss. Auf einem *nix-System /usr/local/bin/ ist ein guter Ort, da es oft schon auf Ihrem ist $PATH Umgebungsvariable. Suchen Sie unter dem Link „Download“ und wählen Sie die für Ihr System am besten geeignete Version aus. Laden Sie es herunter, entpacken Sie es und legen Sie die terraform Datei irgendwo, wo Sie es zum Beispiel ausführen können /usr/local/bin/.

Überprüfen Sie, ob es erfolgreich installiert wurde, und finden Sie heraus, welche Version Sie ausführen – meine ist:

$ terraform --version
Terraform v0.11.7

Definieren einer gewissen Infrastruktur

Nachdem Terraform installiert ist, müssen wir definieren, welche Infrastruktur erstellt werden soll. Wir verwenden HCL, um Ressourcen für verschiedene Anbieter zu definieren. Eine einfache ist die Zufallsanbieter, das Zufallsdaten generiert, die beispielsweise als Servernamen verwendet werden. Es arbeitet nicht gegen einen Cloud-Anbieter und erfordert keine API-Schlüssel usw., so dass es gut ist, den Workflow von Terraform zu veranschaulichen. Wir werden auch die verwenden lokaler Anbieter um diese zufälligen Daten in eine Datei zu schreiben.

Fügen Sie Folgendes in eine Datei mit dem Namen example.tf:

variable "name_length" { type = "string" default = "2" description = "The number of words to put into the random name"
} resource "random_pet" "server" { length = "${var.name_length}"
} resource "local_file" "random" { content = "${random_pet.server.id}" filename = "${path.module}/random.txt" } output "name" { value = "${random_pet.server.id}"
}

Terraform sucht in dem Verzeichnis, das Sie angeben (standardmäßig das aktuelle Verzeichnis) und findet alle *.tf Dateien – Unterverzeichnisse werden ignoriert. Es behandelt die gefundenen Dateien als eine einzige Definition und zeichnet ein Diagramm aller Ressourcen. Es ist üblich, die zu sehen variables und outputs in verschiedene Dateien aufgeteilt, um zu verdeutlichen, wo sie zu finden sind. Es ist auch üblich und eine gute Idee, Code in Module aufzuteilen, aber darüber machen wir uns heute keine Gedanken.

Führen Sie im selben Verzeichnis Folgendes aus: terraform init. Sie sollten eine Ausgabe sehen, die ungefähr so ​​​​aussieht:

$ terraform init Initializing provider plugins...
- Checking for available provider plugins on 
- Downloading plugin for provider "random" (1.3.1)...
- Downloading plugin for provider "local" (1.1.0)... The following providers do not have any version constraints in configuration,
so the latest version was installed. To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below. * provider.local: version = "~> 1.1"
* provider.random: version = "~> 1.3" Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work. If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Terraform hat sich alle angesehen *.tf Dateien, ermittelt welche Anbieter verwendet werden und hat die entsprechenden Plugins heruntergeladen. Diese werden im gespeichert .terraform/ Verzeichnis, das im aktuellen Pfad erstellt wurde.

Änderungen planen

Eine erstaunliche Funktion von Terraform ist die Möglichkeit, Änderungen in der Vorschau anzuzeigen, um eine Vorstellung davon zu bekommen, was tatsächlich passieren wird, wenn Sie sie anwenden. Wird diese Änderung meinen Loadbalancer an Ort und Stelle ändern oder wird er zerstört und neu erstellt, wodurch meine Anwendung für wertvolle Minuten offline genommen wird?

Mal sehen, wie das aussieht:

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + local_file.random id: <computed> content: "${random_pet.server.id}" filename: "/home/vagrant/workspace/tfdemo/random.txt" + random_pet.server id: <computed> length: "2" separator: "-" Plan: 2 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Dies ist das erste Mal, dass wir es ausführen, sodass alle von uns angegebenen Ressourcen erstellt werden – siehe die + neben ihrem Namen in der Ausgabe.

Achten Sie auch auf den „Hinweis“ – wir haben diesen Plan nicht gespeichert, also haben wir zwar eine gute Vorstellung davon, was Terraform tun wird, wenn wir es anwenden, es ist jedoch nicht garantiert, dass es dasselbe versucht. Wir können den Plan in einer Datei mit einem eindeutigen Namen speichern, indem wir einen Zeitstempel anhängen, dh terraform plan -out "plan-$(date +%s)".

Wenn wir das ausführen, erhalten wir stattdessen dies am Ende der Ausgabe:

...
This plan was saved to: plan-1527707537 To perform exactly these actions, run the following command to apply: terraform apply "plan-1527707537"

Wenn wir mit diesem Plan zufrieden sind, können wir ihn wirklich anwenden.

Anwenden von Änderungen

Wenn wir laufen terraform apply und übergeben Sie die Plandatei, die wir als Ausgabe erhalten, die wie folgt aussieht:

$ terraform apply "plan-1527707537"
random_pet.server: Creating... length: "" => "2" separator: "" => "-"
random_pet.server: Creation complete after 0s (ID: leading-piranha)
local_file.random: Creating... content: "" => "leading-piranha" filename: "" => "/home/vagrant/workspace/tfdemo/random.txt"
local_file.random: Creation complete after 0s (ID: 681f312327eab60da028b397bc85af8682fdc185) Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: name = leading-piranha

Der Random-Anbieter gab uns einen Kosenamen bestehend aus 2 Wörtern und dem output Direktive zeigte es am Ende des Programms. Das local_file resource schrieb den Namen in eine Datei namens random.txt im aktuellen Verzeichnis:

$ cat random.txt
leading-piranha[[email protected] tfdemo]$

Weitere Änderungen vornehmen

Hmmm, es gibt keinen Zeilenumbruch am Ende der Datei. Ich würde es vorziehen, wenn es mit einem formatiert wird, also füge ich eines in die HCL ein. Das content in dem local_file kann geändert werden zu, mit a \n angehängt:

... content = "${random_pet.server.id}\n" ...

Wenn wir die Änderungen planen, werden wir das sehen nur die Datei soll sich ändern. Es gibt keinen Grund für die random_pet Ressource überhaupt geändert werden, damit Terraform sie so verwendet, wie sie ist.

$ terraform plan -out "plan-$(date +%s)" Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage. random_pet.server: Refreshing state... (ID: leading-piranha)
local_file.random: Refreshing state... (ID: 681f312327eab60da028b397bc85af8682fdc185) ------------------------------------------------------------------------ An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement Terraform will perform the following actions: -/+ local_file.random (new resource required) id: "681f312327eab60da028b397bc85af8682fdc185" => <computed> (forces new resource) content: "leading-piranha" => "leading-piranha\n" (forces new resource) filename: "/home/vagrant/workspace/tfdemo/random.txt" => "/home/vagrant/workspace/tfdemo/random.txt" Plan: 1 to add, 0 to change, 1 to destroy. ------------------------------------------------------------------------ This plan was saved to: plan-1528126805 To perform exactly these actions, run the following command to apply: terraform apply "plan-1528126805"

Anwenden der Änderungen aus dem Plan, den wir gerade vorgenommen haben, können catWenn Sie die Datei erneut kopieren, sehen Sie, dass jetzt am Ende ein Zeilenumbruch steht:

$ terraform apply "plan-1528126805"
local_file.random: Destroying... (ID: 681f312327eab60da028b397bc85af8682fdc185)
local_file.random: Destruction complete after 0s
local_file.random: Creating... content: "" => "leading-piranha\n" filename: "" => "/home/vagrant/workspace/tfdemo/random.txt"
local_file.random: Creation complete after 0s (ID: 82c2862c8ae7053eb94b7aa498265335c5d22b22) Apply complete! Resources: 1 added, 0 changed, 1 destroyed. Outputs: name = leading-piranha $ cat random.txt
leading-piranha

Variablen

In dem example.tf Datei können Sie sehen, dass wir a deklariert haben variable genannt name_length und verwies darauf in der random_pet Ressource (length = "${var.name_length}"); Warum nicht einfach diese Nummer fest codieren?

Um die Wiederverwendung von Code zu erleichtern, können wir in Terraform verschiedene Werte für die von uns definierten Variablen übergeben. Wir benutzen das -var flag und den Namen der Variablen, etwa so:

$ $ terraform plan -var name_length=3
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage. random_pet.server: Refreshing state... (ID: leading-piranha)
local_file.random: Refreshing state... (ID: 82c2862c8ae7053eb94b7aa498265335c5d22b22) ------------------------------------------------------------------------ An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement Terraform will perform the following actions: -/+ local_file.random (new resource required) id: "82c2862c8ae7053eb94b7aa498265335c5d22b22" => <computed> (forces new resource) content: "leading-piranha\n" => "${random_pet.server.id}\n" (forces new resource) filename: "/home/vagrant/workspace/tfdemo/random.txt" => "/home/vagrant/workspace/tfdemo/random.txt" -/+ random_pet.server (new resource required) id: "leading-piranha" => <computed> (forces new resource) length: "2" => "3" (forces new resource) separator: "-" => "-" Plan: 2 to add, 0 to change, 2 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Der Plan sagt uns noch einmal, was passieren wird – beide Ressourcen werden zerstört und andere an ihrer Stelle geschaffen. Die Datei muss in diesem Fall neu erstellt werden, da sie vom Wert from abhängig ist random_pet. Terraform berechnet dies aus dem Abhängigkeitsdiagramm, das es generiert – es kann herausfinden, was es neu erstellen muss, basierend darauf, was geändert wurde und was davon abhängt.

Das Abhängigkeitsdiagramm für Ihre Infrastruktur ist in der zu sehen [DOT language]( durch Laufen terraform graph. Wenn du hast graphviz installiert, dann können Sie es rendern, indem Sie den Ausgang direkt an die leiten dot Programm:

$ terraform graph | dot -Tpng -o tfdemo.png

Dies ist ein wirklich einfaches Beispiel, und es steht keine kritische Infrastruktur auf dem Spiel, sodass wir diese Änderungen anwenden können, ohne sie durch einfaches Ausführen in einer Plandatei zu speichern terraform apply und geben Sie entweder „Ja“ an der Eingabeaufforderung ein oder übergeben Sie die -auto-approve Flagge:

$ terraform apply -var name_length=3 -auto-approve
random_pet.server: Refreshing state... (ID: leading-piranha)
local_file.random: Refreshing state... (ID: 82c2862c8ae7053eb94b7aa498265335c5d22b22)
local_file.random: Destroying... (ID: 82c2862c8ae7053eb94b7aa498265335c5d22b22)
local_file.random: Destruction complete after 0s
random_pet.server: Destroying... (ID: leading-piranha)
random_pet.server: Destruction complete after 0s
random_pet.server: Creating... length: "" => "3" separator: "" => "-"
random_pet.server: Creation complete after 0s (ID: scarcely-intense-mammoth)
local_file.random: Creating... content: "" => "scarcely-intense-mammoth\n" filename: "" => "/home/vagrant/workspace/tfdemo/random.txt"
local_file.random: Creation complete after 0s (ID: a3f2f24388d1e4ddd72872a833469002f2ad5b75) Apply complete! Resources: 2 added, 0 changed, 2 destroyed. Outputs: name = scarcely-intense-mammoth

Beachten Sie, dass wir dieselben Parameter an die Anwendungsphase übergeben müssen, die wir in der Planung übergeben haben. Dies ist ein sehr guter Grund, den Plan zu speichern und beim Laufen zu verwenden apply.

Bundesland

Zusammen mit .terraform/ Verzeichnis, in dem die Anbieter-Plugins gespeichert sind, werden Sie feststellen, dass es eine gibt terraform.tfstate dort auch ablegen. Eine schnelle Untersuchung zeigt, dass es sich um Text handelt, den wir lesen können!

$ file terraform.tfstate
terraform.tfstate: ASCII text

Dies ist der Status unserer Ressourcen im JSON-Format. Der Status repräsentiert die Sicht von Terraform auf die definierten Ressourcen. Wenn Sie die ausführen plan Befehl mit denselben Argumenten im selben Verzeichnis, dann teilt uns Terraform mit, dass nichts zu tun ist:

$ terraform plan -var name_length=3 Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage. random_pet.server: Refreshing state... (ID: scarcely-intense-mammoth)
local_file.random: Refreshing state... (ID: a3f2f24388d1e4ddd72872a833469002f2ad5b75) ------------------------------------------------------------------------ No changes. Infrastructure is up-to-date. This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

Wenn Sie Terraform ausführen, um Ihre Cloud-Infrastruktur zu erstellen, stellen Sie sicher, dass der Status der Quellcodeverwaltung verpflichtet ist oder – insbesondere wenn Sie mit anderen Ingenieuren zusammenarbeiten – in einem der Status beibehalten wird unterstützte Backends.

Einpacken

Dies veranschaulicht einen typischen Workflow für Terraform: Code -> Plan -> Apply -> Commit. Um es Ihnen so einfach wie möglich zu machen, haben wir Anbieter verwendet, die nur lokal tätig sind, aber wenn Sie eine hinzugefügt haben aws_instance Ressource, dann könnte der zufällige Servername, den wir generiert haben, leicht zum Festlegen der verwendet werden Name -Tag auf der EC2-Instance. Terraform wird den Standard aufgreifen AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY Umgebungsvariablen und Ihr Workflow bleibt unverändert, während Sie echte Infrastruktur bereitstellen.

Similar Posts

Leave a Reply

Your email address will not be published.