
Wir hatten 4 Amazon-Konten, 9 VPCs und 30 leistungsstärkste Entwicklungsumgebungen, Phasen und Regressionen - insgesamt mehr als 1000 EC2-Instanzen aller Farben und Schattierungen. Seit ich Cloud-Lösungen für Unternehmen sammle, muss ich mein Hobby bis zum Ende fortsetzen und darüber nachdenken, wie ich all dies automatisieren kann.
Hallo! Mein Name ist Kirill Kazarin, ich arbeite als Ingenieur bei DINS. Wir entwickeln Cloud-basierte Geschäftskommunikationslösungen. In unserer Arbeit nutzen wir aktiv Terraform, mit dem wir unsere Infrastruktur flexibel verwalten. Ich werde meine Erfahrungen mit dieser Lösung teilen.
Der Artikel ist lang, also tanken Sie
Popcorn- Tee und los geht's!
Und noch eine Nuance - der Artikel wurde auf der Basis von Version 0.11 geschrieben, in frischem 0.12 hat sich viel geändert, aber die wichtigsten Praktiken und Tipps sind immer noch relevant. Das Problem der Migration von 0,11 auf 0,12 verdient einen separaten Artikel!
Was ist Terraform?
Terraform ist ein beliebtes Hashicorp-Tool, das 2014 veröffentlicht wurde.
Mit diesem Dienstprogramm können Sie Ihre Cloud-Infrastruktur in der
Infrastruktur als Code- Paradigma in einer sehr benutzerfreundlichen, leicht lesbaren deklarativen Sprache verwalten. Die Anwendung bietet Ihnen eine einheitliche Art von Ressourcen und die Anwendung von Code-Praktiken für das Infrastrukturmanagement, die seit langem von der Entwicklergemeinde entwickelt wurden. Terraform unterstützt alle modernen Cloud-Plattformen und ermöglicht es Ihnen, die Infrastruktur sicher und vorhersehbar zu ändern.
Beim Start liest Terraform den Code und bringt Ihre Infrastruktur mithilfe der von den Cloud-Dienstanbietern bereitgestellten Plug-Ins in den beschriebenen Zustand, indem die erforderlichen API-Aufrufe ausgeführt werden.
Unser Projekt befindet sich vollständig in Amazon und wird auf der Grundlage von AWS-Diensten bereitgestellt. Daher schreibe ich über die Verwendung von Terraform in diesem Sinne. Separat stelle ich fest, dass es nicht nur für Amazon verwendet werden kann. Sie können damit alles verwalten, was über eine API verfügt.
Darüber hinaus verwalten wir VPC-Einstellungen, IAM-Richtlinien und Rollen. Wir verwalten Routing-Tabellen, Zertifikate und Netzwerk-ACLs. Wir verwalten die Einstellungen unserer Webanwendungs-Firewall, des S3-Buckets und der SQS-Warteschlangen - alles, was unser Service in Amazon verwenden kann. Ich habe noch keine Funktionen bei Amazon gesehen, die Terraform in Bezug auf die Infrastruktur nicht beschreiben konnte.
Es stellt sich heraus, dass die Infrastruktur ziemlich groß ist und mit Ihren Händen leicht zu unterstützen ist. Aber mit Terraform ist es bequem und einfach.
Woraus Terraform besteht
Anbieter sind Plugins für die Arbeit mit der API eines Dienstes. Ich habe sie
mehr als 100 gezählt . Darunter sind Anbieter für Amazon, Google, DigitalOcean, VMware Vsphere und Docker. Ich habe sogar einen Anbieter auf dieser offiziellen Liste gefunden, mit dem Sie
die Regeln für den Cisco ASA verwalten können !
Unter anderem können Sie steuern:
Und das sind nur offizielle Anbieter, es gibt noch mehr inoffizielle Anbieter. Während der Experimente stieß ich auf GitHub auf einen Drittanbieter, der nicht im offiziellen Listenanbieter enthalten war und der
die Arbeit mit DNS von GoDaddy sowie mit
Proxmox-Ressourcen ermöglichte .
Innerhalb eines Terraform-Projekts können Sie verschiedene Anbieter und entsprechend die Ressourcen verschiedener Dienstleister oder Technologien verwenden. Beispielsweise können Sie Ihre Infrastruktur in AWS mit externem DNS von GoDaddy verwalten. Und morgen hat Ihr Unternehmen ein Startup gekauft, das in DO oder Azure gehostet wird. Und während Sie sich entscheiden, dies auf AWS zu migrieren oder nicht, können Sie dies auch mit demselben Tool unterstützen!
Ressourcen. Dies sind Cloud-Entitäten, die Sie mit Terraform erstellen können. Ihre Liste, Syntax und Eigenschaften hängen vom verwendeten Anbieter ab - tatsächlich von der verwendeten Cloud. Oder nicht nur Wolken.
Module Mit diesen Entitäten können Sie mit Terraform Ihre Konfiguration vorlegen. Mit Vorlagen können Sie Ihren Code also verkleinern und wiederverwenden. Nun, sie helfen, bequem mit ihm zu arbeiten.
Warum wir uns für Terraform entschieden haben
Für uns haben wir 5 Hauptgründe identifiziert. Vielleicht scheinen aus Ihrer Sicht nicht alle von Bedeutung zu sein:
- Terraform ist ein
Cloud Agnostic- Dienstprogramm zur Unterstützung mehrerer Clouds (danke für den wertvollen Kommentar in den Kommentaren) . Als wir uns für dieses Tool entschieden haben, dachten wir: - Und was passiert, wenn das Management morgen oder eine Woche zu uns kommt und sagt: „ Leute, wir dachten - lasst uns nicht nur bei Amazon bereitstellen. Wir haben eine Art Projekt, Wo wir die Infrastruktur in Google Cloud oder in Azure benötigen - das wissen Sie nie . " Wir haben uns für ein Tool entschieden, das nicht fest an einen Cloud-Service gebunden ist. - Open Source . Terraform ist eine Open Source-Lösung . Das Projekt-Repository hat eine Bewertung von mehr als 16.000 Sternen. Dies ist eine gute Bestätigung für den Ruf des Projekts.
Wir sind mehr als ein- oder zweimal auf die Tatsache gestoßen, dass es in einigen Versionen Fehler oder nicht ganz verständliches Verhalten gibt. Mit einem offenen Repository können Sie sicherstellen, dass dies wirklich ein Fehler ist, und wir können das Problem lösen, indem wir einfach die Engine oder die Version des Plugins aktualisieren. Oder dass dies ein Fehler ist, aber "Leute, warte, buchstäblich zwei Tage später wird eine neue Version veröffentlicht und wir werden sie beheben." Oder: "Ja, das ist etwas Unverständliches, Seltsames, sie klären es, aber es gibt Abhilfe." Es ist sehr bequem. - Kontrolle . Terraform als Dienstprogramm liegt vollständig unter Ihrer Kontrolle. Es kann auf einem Laptop installiert werden, auf einem Server, es kann einfach in Ihre Pipeline integriert werden, was auf der Basis eines beliebigen Tools erfolgen kann. Zum Beispiel verwenden wir es in GitLab CI.
- Überprüfen des Status der Infrastruktur . Terraform kann und überprüft den Zustand Ihrer Infrastruktur.
Angenommen, Sie haben Terraform in Ihrem Team verwendet. Sie erstellen eine Beschreibung einer Ressource in Amazon, z. B. Sicherheitsgruppe, und wenden sie an. Sie wird für Sie erstellt. Alles ist in Ordnung. Und hier - bam! Ihr Kollege, der gestern aus dem Urlaub zurückgekehrt ist und noch nicht weiß, dass Sie hier alles so schön arrangiert haben, oder sogar ein Kollege aus einer anderen Abteilung kommt herein und ändert die Einstellungen für diese Sicherheitsgruppe von Hand.
Und ohne sich mit ihm zu treffen, ohne zu sprechen oder später ein bestimmtes Problem anzunehmen, werden Sie in einer normalen Situation nie davon erfahren. Wenn Sie jedoch Terraform verwenden, zeigt Ihnen das Ausführen eines Plans im Leerlauf für diese Ressource, dass sich Änderungen in der Arbeitsumgebung ergeben.
Wenn Terraform Ihren Code betrachtet, ruft es gleichzeitig die API des Cloud-Anbieters auf, empfängt den Status der Objekte von ihm und vergleicht: "Und jetzt gibt es dasselbe, was ich zuvor getan habe. Woran erinnere ich mich?" Dann vergleicht er es mit dem Code und schaut sich an, was noch geändert werden muss. Und wenn zum Beispiel in seiner Geschichte, in seinem Gedächtnis und in Ihrem Code alles gleich ist, es dort aber Änderungen gibt, wird er es Ihnen zeigen und anbieten, es zurückzusetzen. Meiner Meinung nach auch eine sehr gute Immobilie. Dies ist für uns persönlich ein weiterer Schritt, um sicherzustellen, dass wir über eine unveränderliche Infrastruktur verfügen. - Ein weiteres sehr wichtiges Merkmal sind die Module, die ich erwähnt habe und die zählen. Ich werde etwas später darüber sprechen. Wann werde ich mit den Werkzeugen vergleichen.
Und auch eine Kirsche auf dem Kuchen: Terraform hat eine
ziemlich große Liste von eingebauten Funktionen . Diese Funktionen ermöglichen es uns, trotz der deklarativen Sprache einige zu implementieren, nicht programmatisch, sondern logisch.
Zum Beispiel einige automatische Berechnungen, geteilte Linien, Umwandlung in Klein- und Großbuchstaben, Entfernen von Zeichen aus dieser Linie. Wir nutzen es sehr aktiv. Sie erleichtern das Leben erheblich, insbesondere wenn Sie ein Modul schreiben, das später in verschiedenen Umgebungen wiederverwendet wird.
Terraform vs CloudFormation
Das Netzwerk vergleicht Terraform häufig mit CloudFormation. Diese Frage haben wir auch bei der Auswahl gestellt. Und hier ist das Ergebnis unseres Vergleichs.
Erste Schritte mit Terraform
Im Allgemeinen ist der Einstieg ziemlich einfach. Hier sind die ersten Schritte kurz:
- Erstellen Sie zunächst ein Git-Repository und speichern Sie sofort alle Ihre Änderungen, Experimente und alles.
- Lesen Sie die Kurzanleitung . Es ist klein, einfach, ziemlich detailliert und beschreibt gut, wie Sie mit diesem Dienstprogramm beginnen können.
- Schreiben Sie eine Demo, einen Arbeitscode. Sie können sogar ein Beispiel kopieren, um später damit zu spielen.
Unsere Praxis mit Terraform
Quellcode
Sie haben Ihr erstes Projekt gestartet und alles in einer großen main.tf-Datei gespeichert.
Hier ist ein typisches Beispiel (ich habe ehrlich gesagt das erste genommen, das ich von GitHub bekommen habe).
Nichts falsches, aber die Größe der Codebasis wächst mit der Zeit. Die Abhängigkeiten zwischen Ressourcen nehmen ebenfalls zu. Nach einiger Zeit wird die Datei riesig, komplex, unlesbar, schlecht gewartet - und eine unachtsame Änderung an einem Ort kann zu Problemen führen.
Als erstes empfehle ich, das sogenannte Kern-Repository oder den Kernstatus Ihres Projekts, Ihre Umgebung, hervorzuheben. Sobald Sie mit dem Erstellen oder Importieren einer Infrastruktur mit Terraform beginnen, werden Sie sofort feststellen, dass einige Entitäten nach der Bereitstellung und Konfiguration selten geändert werden. Dies sind beispielsweise VPC-Einstellungen oder VPC selbst. Dies sind Netzwerke, grundlegende allgemeine Sicherheitsgruppen wie SSH-Zugriff - Sie können eine ziemlich große Liste zusammenstellen.
Es macht keinen Sinn, dies im selben Repository zu halten wie die Dienste, die Sie häufig ändern. Wählen Sie sie in einem separaten Repository aus und docken Sie sie über eine Terraform-Funktion wie den Remote-Status an.
- Sie reduzieren die Codebasis des Teils des Projekts, mit dem Sie häufig direkt arbeiten.
- Anstelle einer großen tfstate-Datei, die eine Beschreibung des Status Ihrer Infrastruktur enthält, zwei kleinerer Dateien, und zu einem bestimmten Zeitpunkt arbeiten Sie mit einer davon.
Was ist der Trick? Wenn Terraform einen Plan erstellt, dh berechnet, berechnet, was geändert werden soll, angewendet wird, wird dieser Status vollständig wiedergegeben, anhand des Codes überprüft und anhand des Status in AWS überprüft. Je größer Ihr Bundesstaat ist, desto länger dauert der Plan.
Wir kamen zu dieser Praxis, als wir 20 Minuten brauchten, um einen Plan für die gesamte Umgebung in der Produktion zu erstellen. Aufgrund der Tatsache, dass wir alles, was wir nicht häufig ändern, in einen separaten Kern gezogen haben, haben wir die Zeit für die Erstellung eines Plans um die Hälfte reduziert. Wir haben eine Idee, wie es weiter reduziert werden kann, indem wir nicht nur in Kern- und Nicht-Kernsysteme, sondern auch nach Subsystemen zerlegen, weil wir sie miteinander verbunden haben und uns normalerweise gemeinsam ändern. Wir sagen also, wir werden 10 Minuten in 3 Minuten verwandeln. Wir sind jedoch noch dabei, eine solche Lösung zu implementieren.
Weniger Code - einfacher zu lesen
Kleiner Code ist einfacher zu verstehen und bequemer zu bearbeiten. Wenn Sie ein großes Team haben und Leute mit unterschiedlichen Erfahrungsstufen haben - nehmen Sie das, was Sie selten ändern, aber global, in einer separaten Rübe heraus und bieten Sie einen engeren Zugang.
Angenommen, Sie haben Junioren in Ihrem Team und geben ihnen keinen Zugriff auf das globale Repository, in dem die VPC-Einstellungen beschrieben werden. Auf diese Weise versichern Sie sich gegen Fehler. Wenn ein Ingenieur beim Schreiben der Instanz einen Fehler macht und etwas falsch erstellt wird, ist dies nicht beängstigend. Und wenn er bei den Optionen, die auf allen Computern installiert sind, einen Fehler macht, die Einstellungen der Subnetze oder das Routing unterbricht oder etwas unternimmt, ist dies viel schmerzhafter.
Die Auswahl des Kern-Repositorys erfolgt in mehreren Schritten.
Stufe 1 . Erstellen Sie ein separates Repository. Speichern Sie den gesamten Code separat darin - und beschreiben Sie die Entitäten, die mit dieser Ausgabe in einem Repository eines Drittanbieters wiederverwendet werden sollen. Angenommen, wir erstellen eine AWS-Subnetzressource, in der wir beschreiben, wo sie sich befindet, welche Verfügbarkeitszone und welcher Adressraum.
resource "aws_subnet" "lab_pub1a" { vpc_id = "${aws_vpc.lab.id}" cidr_block = "10.10.10.0/24" Availability_zone = "us-east-1a" ... } output "sn_lab_pub1a-id" { value = "${aws_subnet.lab_pub1a.id}" }
Und dann sagen wir, dass wir die ID dieses Objekts zur Ausgabe senden. Sie können für jeden Parameter, den Sie benötigen, eine Ausgabe durchführen.
Was ist der Trick hier? Wenn Sie einen Wert beschreiben, speichert Terraform ihn separat im Statuskern. Und wenn Sie sich an ihn wenden, muss er nicht synchronisieren, erzählen - er kann Ihnen diese Angelegenheit sofort aus diesem Zustand heraus geben. Ferner beschreiben Sie in dem Repository, das kein Kern ist, eine solche Verbindung mit dem entfernten Zustand: Sie haben einen entfernten Zustand wie diesen und solchen, er liegt im S3-Bucket so und so, so und so einem Schlüssel und einer Region.
Stufe 2 . In einem Nicht-Kernprojekt erstellen wir eine Verknüpfung zum Status des Kernprojekts, damit wir auf die durch die Ausgabe exportierten Parameter verweisen können.
data "terraform_remote_state" "lab_core" { backend = "s3" config { bucket = "lab-core-terraform-state" key = "terraform.tfstate" region = "us-east-1" } }
Stufe 3 . Erste Schritte! Wenn ich eine neue Netzwerkschnittstelle für eine Instanz in einem bestimmten Subnetz bereitstellen muss, sage ich: Hier ist der Datenfernstatus, suchen Sie den Namen dieses Status darin, suchen Sie diesen Parameter darin, der tatsächlich mit diesem Namen übereinstimmt.
resource "aws_network_interface" "fwl01" { ... subnet_id = "${data.terraform_remote_state.lab_core.sn_lab_pub1a-id}" }
Und wenn ich einen Plan für Änderungen in meinem Nicht-Core-Repository erstelle, wird dieser Wert für Terraform zu einer Konstante dafür. Wenn Sie es ändern möchten, müssen Sie es im Repository dieses natürlich Kerns tun. Da sich dies jedoch selten ändert, stört es Sie nicht viel.
Module
Ich möchte Sie daran erinnern, dass ein Modul eine eigenständige Konfiguration ist, die aus einer oder mehreren verwandten Ressourcen besteht. Es wird als Gruppe verwaltet:
Ein Modul ist äußerst praktisch, da Sie selten einfach so eine Ressource erstellen. In einem Vakuum ist es normalerweise logisch mit etwas verbunden.
module "AAA" { source = "..." count = "3" count_offset = "0" host_name_prefix = "XXX-YYY-AAA" ami_id = "${data.terraform_remote_state.lab_core.ami-base-ami_XXXX-id}" subnet_ids = ["${data.terraform_remote_state.lab_core.sn_lab_pub1a-id}", "${data.terraform_remote_state.lab_core.sn_lab_pub1b-id}"] instance_type = "t2.large" sgs_ids = [ "${data.terraform_remote_state.lab_core.sg_ssh_lab-id}", "${aws_security_group.XXX_lab.id}" ] boot_device = {volume_size = "50" volume_type = "gp2"} root_device = {device_name = "/dev/sdb" volume_size = "50" volume_type = "gp2" encrypted = "true"} tags = "${var.gas_tags}" }
Beispiel: Wenn wir eine neue EC2-Instanz bereitstellen, erstellen wir eine Netzwerkschnittstelle und einen Anhang dafür, erstellen häufig eine elastische IP-Adresse dafür, erstellen einen Route-53-Datensatz und etwas anderes. Das heißt, wir erhalten mindestens 4 Entitäten.
Jedes Mal ist es unpraktisch, sie in vier Codeteilen zu beschreiben. Außerdem sind sie ziemlich typisch. Es bittet darum, eine Vorlage zu erstellen und dann einfach auf diese Vorlage zu verweisen und Parameter zu übergeben: einen Namen, in welches Raster verschoben werden soll, welche Sicherheitsgruppe daran hängen soll. Es ist sehr bequem.
Terraform verfügt über eine Zählfunktion, mit der Sie Ihren Status weiter reduzieren können. Sie können ein großes Bündel von Instanzen mit einem Code beschreiben. Angenommen, ich muss 20 Computer des gleichen Typs bereitstellen. Ich werde nicht einmal aus einer Vorlage 20 Code schreiben, ich werde 1 Code schreiben, ich werde Count und die Nummer darin angeben - wie viel ich tun muss.
Beispielsweise gibt es einige Module, die auf eine Vorlage verweisen. Ich übergebe nur bestimmte Parameter: ID-Subnetz; AMI zum Bereitstellen mit; Art der Instanz; Sicherheitsgruppeneinstellungen; alles andere und geben Sie an, wie viele dieser Dinge mir anzutun sind. Großartig, nahm sie und drehte sie um!
Morgen kommen Entwickler zu mir und sagen: "Hören Sie, wir wollen mit der Last experimentieren, bitte geben Sie uns zwei weitere davon." Was ich tun muss: Ich ändere eine Ziffer auf 5. Die Codemenge bleibt genau gleich.
Herkömmlicherweise können Module in zwei Typen unterteilt werden - Ressource und Infrastruktur. Aus Sicht des Codes gibt es keinen Unterschied, sondern die übergeordneten Konzepte, die der Bediener selbst einführt.
Ressourcenmodule bieten eine standardisierte und parametrisierte, logisch zusammenhängende Sammlung von Ressourcen. Das obige Beispiel ist ein typisches Ressourcenmodul. Wie man mit ihnen arbeitet:
- Wir geben den Pfad zum Modul - die Quelle seiner Konfiguration - über die Source-Direktive an.
- Wir geben die Version an - ja, und der Betrieb nach dem Prinzip „Neueste und Größte“ ist hier nicht die beste Option. Sie nehmen nicht jedes Mal die neueste Version der Bibliothek in Ihr Projekt auf? Aber dazu später mehr.
- Wir geben ihm Argumente.
Wir sind an die Version des Moduls gebunden und nehmen nur die letzte - die Infrastruktur muss versioniert werden (Ressourcen können nicht versioniert werden, Code jedoch). Eine Ressource kann gelöscht oder neu erstellt werden. Das ist alles! Wir müssen auch klar wissen, welche Version wir für jede Infrastruktur erstellt haben.
Infrastrukturmodule sind recht einfach. Sie bestehen aus Ressourcen und enthalten Unternehmensstandards (z. B. Tags, Listen mit Standardwerten, akzeptierte Standardeinstellungen usw.).
In Bezug auf unser Projekt und unsere Erfahrung haben wir lange und fest auf die Verwendung von Ressourcenmodulen für alles umgestellt, was mit einem sehr strengen Versions- und Überprüfungsprozess möglich ist. Und jetzt führen wir aktiv die Praxis von Infrastrukturmodulen auf der Ebene von Labor und Staging ein.
Empfehlungen zur Verwendung von Modulen
- Wenn Sie nicht schreiben können, sondern vorgefertigte verwenden, schreiben Sie nicht. Vor allem, wenn Sie neu in diesem Bereich sind. Vertrauen Sie den vorgefertigten Modulen oder sehen Sie zumindest, wie sie es Ihnen angetan haben. Wenn Sie jedoch immer noch Ihre eigenen schreiben müssen, verwenden Sie den Anruf bei Anbietern nicht intern und gehen Sie vorsichtig mit Dienstanbietern um.
- Stellen Sie sicher, dass die Terraform-Registrierung kein vorgefertigtes Ressourcenmodul enthält.
- Wenn Sie Ihr Modul schreiben, verstecken Sie die Details unter der Haube. Der Endbenutzer muss sich keine Gedanken darüber machen, was und wie Sie intern implementieren.
- Führen Sie Eingabeparameter und Ausgabewerte von Ihrem Modul aus. Und es ist besser, wenn es sich um separate Dateien handelt. So bequem.
- Wenn Sie Ihre Module schreiben, speichern Sie sie im Repository und in der Version. Besser ein separates Repository für das Modul.
- Verwenden Sie keine lokalen Module - sie werden nicht versioniert oder wiederverwendet.
- Vermeiden Sie die Verwendung von Anbieterbeschreibungen im Modul, da Verbindungsanmeldeinformationen für verschiedene Personen unterschiedlich konfiguriert und angewendet werden können. Jemand verwendet hierfür Umgebungsvariablen, und jemand impliziert, dass seine Schlüssel und Geheimnisse in Dateien mit vorgeschriebenen Pfaden gespeichert werden. Dies muss auf einer höheren Ebene angezeigt werden.
- Verwenden Sie den lokalen Provisioner vorsichtig. Es wird lokal auf dem Computer ausgeführt, auf dem Terraform ausgeführt wird. Die Ausführungsumgebung für verschiedene Benutzer kann jedoch unterschiedlich sein. Bis Sie es in CI einbetten, können Sie auf verschiedene Artefakte stoßen: zum Beispiel auf local exec und ansible. Und jemand hat eine andere Distribution, eine andere Shell, eine andere Version von Ansible oder sogar Windows.
Anzeichen eines guten Moduls (hier
etwas ausführlicher ):
- Gute Module haben Dokumentation und Beispiele. Wenn jedes als separates Repository konzipiert ist, ist dies einfacher.
- Sie haben keine fest codierten Einstellungen (z. B. AWS-Region).
- Verwenden Sie angemessene Standardeinstellungen, die als Standardeinstellungen ausgelegt sind. Beispielsweise erstellt das Modul für die EC2-Instanz standardmäßig keine virtuelle Maschine vom Typ m5d.24xlarge für Sie, sondern verwendet hierfür einen der minimalen t2- oder t3-Typen.
- Der Code ist „sauber“ - strukturiert, mit Kommentaren versehen, nicht unnötig verwirrt und im gleichen Stil gestaltet.
- Es ist sehr wünschenswert, dass es mit Tests ausgestattet wird, obwohl es schwierig ist. Leider sind wir noch nicht dazu gekommen.
Markieren
Tags sind wichtig.
Tagging ist Abrechnung. AWS verfügt über Tools, mit denen Sie sehen können, wie viel Geld Sie für Ihre Infrastruktur ausgeben. Und unser Management wollte wirklich ein Werkzeug, mit dem sie es deterministisch sehen können. Zum Beispiel, wie viel Geld solche und solche Komponenten verbrauchen oder wie und so ein Subsystem, so und so ein Team, so und so eine Umgebung

Tagging ist die Dokumentation Ihres Systems. Damit vereinfachen Sie Ihre Suche. Selbst in der AWS-Konsole, in der diese Tags übersichtlich auf Ihrem Bildschirm angezeigt werden, können Sie leichter verstehen, worauf sich diese oder jene Art von Instanz bezieht. Wenn neue Kollegen kommen, können Sie dies leichter erklären, indem Sie zeigen: "Schauen Sie, das ist es - hier." Wir haben angefangen, Tags wie folgt zu erstellen - wir haben ein Array von Tags für jeden Ressourcentyp erstellt.
Ein Beispiel:
variable "XXX_tags" { description = "The set of XXX tags." type = "map" default = { "TerminationDate" = "03.23.2018", "Environment" = "env_name_here", "Department" = "dev", "Subsystem" = "subsystem_name", "Component" = "XXX", "Type" = "application", "Team" = "team_name" } }
Es ist vorgekommen, dass in unserem Unternehmen mehr als eines unserer Teams AWS verwendet und es eine Liste der erforderlichen Tags gibt.
- Team - Welches Team verwendet wie viele Ressourcen?
- Abteilung - ähnlich einer Abteilung.
- Umgebung - Ressourcen schlagen in "Umgebungen", aber Sie können sie beispielsweise durch ein Projekt oder ähnliches ersetzen.
- Subsystem - das Subsystem, zu dem die Komponente gehört. Komponenten können zu einem Subsystem gehören. Zum Beispiel wollen wir sehen, wie viel dieses Subsystem und seine Entitäten zu verbrauchen beginnen. So ist es beispielsweise im Vormonat plötzlich deutlich gewachsen. Wir müssen zu den Entwicklern gehen und sagen: „Leute, es ist teuer. Das Budget ist schon nahe beieinander, lasst uns die Logik irgendwie optimieren. “
- Typ - Typ der Komponente: Balancer, Speicher, Anwendung oder Datenbank.
- Komponente - die Komponente selbst, ihr Name in interner Notation.
- Kündigungsdatum - Uhrzeit, zu der es gelöscht werden soll, im Datumsformat. Wenn das Entfernen nicht erwartet wird, stellen Sie "Permanent" ein. Wir haben es eingeführt, weil wir in Entwicklungsumgebungen und sogar in einigen Phasenumgebungen eine Stresstestphase haben, die während Stresssitzungen ansteigt, dh wir halten diese Maschinen nicht regelmäßig. Wir geben das Datum an, an dem die Ressource zerstört werden soll. Darüber hinaus können Sie die Automatisierung basierend auf Lambda, einigen externen Skripten, die über die AWS-Befehlszeilenschnittstelle arbeiten, beschleunigen, wodurch diese Ressourcen automatisch zerstört werden.
Nun - wie man taggt.
Wir haben beschlossen, für jede Komponente eine eigene Tag-Map zu erstellen, in der wir alle angegebenen Tags auflisten: Wann soll sie beendet werden, worauf bezieht sie sich? Sie erkannten schnell, dass es unpraktisch war. Weil die Codebasis wächst, weil wir mehr als 30 Komponenten haben und 30 solcher Codeteile unpraktisch sind. Wenn Sie etwas ändern müssen, laufen Sie und ändern.
Um gut zu markieren, verwenden wir die Entität
Locals .
locals { common_tags = {"TerminationDate" = "XX.XX.XXXX", "Environment" = "env_name", "Department" = "dev", "Team" = "team_name"} subsystem_1_tags = "${merge(local.common_tags, map("Subsystem", "subsystem_1_name"))}" subsystem_2_tags = "${merge(local.common_tags, map("Subsystem", "subsystem_2_name"))}" }
Darin können Sie eine Teilmenge auflisten und sie dann miteinander verwenden.
Zum Beispiel haben wir einige gängige Tags in eine solche Struktur entfernt und dann bestimmte von Subsystemen. Wir sagen: "Nehmen Sie diesen Block und fügen Sie beispielsweise Subsystem 1 hinzu. Fügen Sie für Subsystem 2 Subsystem 2 hinzu." Wir sagen: "Tags, bitte nehmen Sie die allgemeinen und fügen Sie Typ, Anwendung, Name, Komponente und wer es ist zu ihnen hinzu." Es stellt sich sehr kurz, klar und zentral heraus, wenn es plötzlich erforderlich ist.
module "ZZZ02" { count = 1 count_offset = 1 name = "XXX-YYY-ZZZ" ... tags = "${merge(local.core_tags, map("Type", "application", "Component", "XXX"))}" }

Versionskontrolle
Ihre Vorlagenmodule müssen, wenn Sie sie verwenden, irgendwo gespeichert werden. Der einfachste Weg, den wahrscheinlich jeder startet, ist der lokale Speicher. Nur im selben Verzeichnis, nur in einem Unterverzeichnis, in dem Sie beispielsweise eine Vorlage für einen Dienst beschreiben. Dies ist kein guter Weg. Es ist praktisch, kann schnell repariert und getestet werden, aber es ist schwierig, es später wiederzuverwenden und schwer zu kontrollieren
module "ZZZ02" { source = "./modules/srvroles/ZZZ" name = "XXX-YYY-ZZZ" }
Angenommen, Entwickler kamen zu Ihnen und sagten: "Wir brauchen also eine solche Entität in einer solchen Konfiguration in unserer Infrastruktur." Sie haben es geschrieben und in Form eines lokalen Moduls im Repository ihres Projekts erstellt. Bereitgestellt - ausgezeichnet. Sie testeten und sagten: „Es wird! In der Produktion. " Wir kommen auf die Bühne, Stresstests, Produktion. Jedes Mal, wenn Strg-C, Strg-V; Strg-C, Strg-V. Während wir zum Verkauf kamen, nahm unser Kollege ihn, kopierte den Code aus der Laborumgebung, übertrug ihn an einen anderen Ort und änderte ihn dort. Und wir bekommen einen bereits inkonsistenten Zustand. Bei horizontaler Skalierung ist es nur ein Problem, wenn Sie so viele Laborumgebungen haben wie wir.
Daher ist es eine gute Möglichkeit, für jedes Ihrer Module ein separates Git-Repository zu erstellen und dann einfach darauf zu verweisen. Wir ändern alles an einem Ort - gut, bequem, kontrolliert.
module "ZZZ" { source = "git::ssh://git@GIT_SERVER_FQDN/terraform/modules/general-vm/2-disks.git" host_name_prefix = "XXX-YYY-ZZZ"
Vorwegnahme der Frage, wie Ihr Code die Produktion erreicht. Hierzu wird ein separates Projekt erstellt, das vorbereitete und getestete Module wiederverwendet.
Großartig, wir haben eine Codequelle, die sich zentral ändert. Ich habe genommen, geschrieben, vorbereitet und mich darauf eingestellt, dass ich morgen früh in der Produktion eingesetzt werde. Einen Plan erstellt, getestet - großartig, lass uns gehen. In diesem Moment hat mein Kollege, ausschließlich von guten Absichten geleitet, etwas optimiert und zu diesem Modul hinzugefügt. Und so kam es, dass diese Änderungen die Abwärtskompatibilität beeinträchtigten.
Zum Beispiel hat er die notwendigen Parameter hinzugefügt, die er übergeben muss, sonst wird das Modul nicht zusammengesetzt. Oder er hat die Namen dieser Parameter geändert. Ich komme am Morgen herein, ich habe streng begrenzte Zeit für Änderungen, beginne mit der Erstellung eines Plans und Terraform ruft Statusmodule von Git auf, beginnt mit der Erstellung eines Plans und sagt: "Ups, ich kann nicht. Nicht genug für dich, du hast umbenannt. " Ich bin überrascht: "Aber ich habe es nicht getan, wie soll ich damit umgehen?" Und wenn dies eine Ressource ist, die vor langer Zeit erstellt wurde, müssen Sie nach solchen Änderungen alle Umgebungen durchlaufen, sich irgendwie ändern und zu einem einzigen Blick führen. Dies ist unpraktisch.
Dies kann mithilfe von Git-Tags behoben werden. Wir haben uns für die
SemVer-Notation entschieden und eine einfache Regel ausgearbeitet: Sobald die Konfiguration unseres Moduls einen bestimmten stabilen Zustand erreicht,
dh wir können ihn verwenden, setzen wir ein Tag auf dieses Commit. Wenn wir Änderungen vornehmen und diese die Abwärtskompatibilität nicht beeinträchtigen, ändern wir die Nebennummer am Tag. Wenn sie nicht funktionieren, ändern wir die Hauptzahl.
Fügen Sie in der Quelladresse ein bestimmtes Tag hinzu, und wenn Sie zumindest etwas angeben, das Sie zuvor hatten, wird es immer gesammelt. Lassen Sie die Modulversion fortfahren, aber zum richtigen Zeitpunkt werden wir kommen, und wenn wir sie wirklich brauchen, werden wir sie ändern. Und was vorher funktionierte, wird zumindest nicht kaputt gehen. Das ist bequem. So sieht es in unserem GitLab aus.

Verzweigung
Die Verwendung der Verzweigung ist eine weitere wichtige Praxis. Wir haben für uns selbst die Regel entwickelt, dass Sie Änderungen nur vom Master aus vornehmen sollten. Aber für jede Änderung, die Sie vornehmen und testen möchten, erstellen Sie bitte einen separaten Zweig, spielen Sie damit, experimentieren Sie, machen Sie Pläne und sehen Sie, wie es läuft. Führen Sie dann eine Zusammenführungsanforderung durch und lassen Sie einen Kollegen den Code und die Hilfe anzeigen.

Wo tfstate speichern
Sie sollten Ihren Status nicht lokal speichern. Sie sollten Ihren Status nicht in Git speichern.
Wir haben uns daran verbrannt, als jemand beim Ausrollen der Zweige eines Nicht-Masters seinen Status erhält, in dem der Zustand gespeichert ist - dann schaltet er ihn durch Zusammenführen ein, jemand fügt seinen eigenen hinzu, es stellt sich heraus, dass Konflikte zusammengeführt werden. Oder es stellt sich ohne sie heraus, aber ein inkonsistenter Zustand, denn "er hat es bereits, ich habe es noch nicht", und dann ist es eine unangenehme Praxis, alles zu reparieren. Aus diesem Grund haben wir beschlossen, es an einem sicheren Ort zu lagern, versioniert, aber außerhalb von Git.
S3 passt perfekt dazu: Es ist verfügbar, es hat HA, soweit ich mich
genau an
vier Neunen erinnere
, vielleicht fünf . Selbst wenn Sie Ihren Status brechen, können Sie jederzeit einen Rollback durchführen. Und er gibt auch eine sehr wichtige Sache in Kombination mit DynamoDB, das meiner Meinung nach diese Terraform seit Version 0.8 gelernt hat. In DynamoDB haben Sie ein Typenschild, in dem Terraform aufzeichnet, dass es den Status blockiert.
Angenommen, ich möchte einige Änderungen vornehmen. Ich fange an, einen Plan zu erstellen oder ihn anzuwenden. Terraform geht zu DynamoDB und sagt, dass in diesem Schild angegeben wird, dass dieser Status blockiert ist. Benutzer, Computer, Zeit. In diesem Moment entschied mein Kollege, der remote oder vielleicht an ein paar Tischen von mir arbeitet, sich aber auf die Arbeit konzentriert und nicht sieht, was ich tue, auch, dass etwas geändert werden muss. Er macht einen Plan, startet ihn aber etwas später.
Terraform geht in die Dynamik, sieht - Lock, bricht ab, sagt dem Benutzer: "Sorry, tfstate ist durch etwas blockiert." Ein Kollege sieht, dass ich jetzt arbeite, er kann auf mich zukommen und sagen: "Hören Sie, mein Wechsler ist wichtiger, geben Sie mir bitte nach." Ich sage: „Gut“, ich storniere den Plan, entferne den Block, auch wenn er bei korrekter Ausführung automatisch entfernt wird, ohne Strg-C zu unterbrechen. Ein Kollege geht und tut. So versichern wir uns gegen eine Situation, in der Sie beide etwas ändern.
Zusammenführungsanforderung
Wir verwenden die Verzweigung in Git. Wir weisen unsere Zusammenführungsanfragen Kollegen zu. Darüber hinaus verwenden wir in Gitlab fast alle Tools, die uns zur Verfügung stehen, um zusammenzuarbeiten, für Zusammenführungsanforderungen oder auch nur für einige Pools: Ihren Code zu diskutieren, ihn zu überprüfen, laufende oder problematische Einstellungen vorzunehmen, so etwas. Es ist sehr nützlich, es hilft bei der Arbeit.
In diesem Fall ist das Rollback außerdem einfacher. Sie können zum vorherigen Commit zurückkehren. Wenn Sie beispielsweise entschieden haben, die Änderungen nicht nur vom Assistenten zu übernehmen, können Sie einfach zu einem stabilen Zweig wechseln. Sie haben beispielsweise einen Feature-Zweig erstellt und beschlossen, zuerst Änderungen am Feature-Zweig vorzunehmen. Und dann nehmen die Änderungen, nachdem alles gut funktioniert hat, den Meister vor. Sie haben die Änderungen in Ihrer Filiale übernommen, festgestellt, dass etwas nicht stimmt, sind zum Master gewechselt - keine Änderungen, sagte Übernehmen - er ist zurückgekehrt.
Pipelines

Wir haben beschlossen, dass wir den CI-Prozess verwenden müssen, um unsere Änderungen anzuwenden. Zu diesem Zweck schreiben wir basierend auf Gitlab CI eine Pipeline, die die Anwendung von Änderungen automatisiert. Bisher haben wir zwei Arten von ihnen:
- Pipeline für den Hauptzweig (Master-Pipeline)
- Pipeline für alle anderen Filialen (Filialpipeline)
Was macht die Brunch-Pipeline?
Es startet die automatische Codeüberprüfung (zum Beispiel dumm nach Tippfehlern suchen). Und dann beginnt es mit der Erstellung eines Plans. Und der Kollege, der Ihre Zusammenführungsanforderung überwacht, kann den erstellten Plan sofort öffnen und nicht nur den Code anzeigen, sondern auch das, was Sie hinzufügen. Er wird auch sehen, wie es auf Ihre Infrastruktur fallen wird. Es ist klar und nützlich.
Im Assistenten wird hier ein weiterer Schritt hinzugefügt. Der Unterschied besteht darin, dass Ihr Plan nicht nur generiert, sondern auch als Artefakt gespeichert wird. Eine weitere sehr nützliche Funktion von Terraform ist, dass der Plan als Datei gespeichert und dann angewendet werden kann. Angenommen, Sie haben eine Zusammenführungsanforderung gestellt und diese beiseite gelegt. Einen Monat später erinnerten sie sich an ihn und beschlossen zurückzukehren. Ihr Code ist bereits weit fortgeschritten. Aufgrund der Tatsache, dass Sie das Artefakt des Plans behalten, können Sie es auf das anwenden, was Sie gerade wollten.
In unserem Fall wird dieses Artefakt dann in den nächsten Schritt übertragen, der von Hand ausgeführt wird. Das heißt, wir erhalten einen einzigen Anwendungspunkt für unsere Änderungen.Nachteile von Terraform
Funktionen Trotz der Tatsache, dass Terraform eine ziemlich große Anzahl integrierter Funktionen hat, sind nicht alle so gut, wie wir gerne denken würden.Es hat unangenehme Funktionen, zum Beispiel das „Element“ - in einigen Situationen, in denen es an Erfahrung mangelt, entspricht sein Verhalten möglicherweise nicht genau Ihren Erwartungen.Wenn Sie beispielsweise ein Modul verwenden, wird die Anzahl an das Modul übergeben - wie viele Instanzen bereitgestellt werden sollen, und beispielsweise wird eine Liste der nach Verfügbarkeitszonen aufgeschlüsselten Subnetze übertragen. Übertragen, angewendet, die Anzahl erhöht, noch angewendet. Und jetzt haben Sie beschlossen, die erweiterte Liste der Subnetze darauf zu übertragen. Du hast ein Gitter, du hast dich entschieden, noch ein AZ zu verwenden. Der zweite Teil der Liste ändert sich, und die Anzahl wird dieser Liste über ein Element zugeordnet.Angenommen, Sie hatten zuvor 4 AZ und 5 Instanzen, und dann haben Sie eine weitere AZ hinzugefügt - die ersten 4, die bereits in Ordnung waren, bleiben übrig. Und ungefähr am fünften wird er sagen: "Und jetzt werde ich es neu erstellen." Und du wolltest nicht! Sie wollten, dass nur neue kommen. Solche Fehler sind auf die Art der Arbeit von Terraform mit Listen zurückzuführen.Ternärer Operator. Eine Bedingung ist nur ein ternärer Operator . Uns fehlen wirklich Bedingungen. Trotzdem hätte ich gerne ein vertrauteres If und Else. Schade, dass sie nicht da sind - sie könnten mitfahren.Die Herausforderungen der Teamarbeit . Wenn Sie ein großes Team oder ein großes Projekt für eine große Anzahl von Umgebungen oder beides haben, wird es für Sie schwierig, Terraform ohne Verwendung eines CI zu verwenden.Ohne CI nehmen Sie von Ihrem Computer aus Änderungen an Ihrer lokalen Umgebung vor. Nach unserer Erfahrung führt dies dazu, dass Sie einen Zweig für sich selbst erstellt, ihn gestartet, damit experimentiert haben - und vergessen haben, eine Zusammenführung vorzunehmen, und vergessen haben, die Änderungen voranzutreiben. Das tut weh.Zum Beispiel hatten Sie und Ihr Kollege dieselbe Version auf Maschinen. Dann hat ein Kollege auf meiner Website die Version aktualisiert. Wenn Sie am nächsten Tag Änderungen vornehmen, überprüft Terraform, ob in tfstate die erforderliche Version von Terraform höher ist, und sagt: "Nein, ich kann mich nicht aktualisieren." Wenn Sie ein kleines Fenster zum Vornehmen von Änderungen haben, ist es nicht leicht zu erkennen, dass Sie zuerst das Dienstprogramm aktualisieren müssen.Wenn Sie über CI verfügen, befindet sich beispielsweise eine einzelne Entität in Ihrem Pipeline-Container. Sie versichern sich, dass solche Versionen nicht im Dienstprogramm enthalten sind.Und schließlich kann sich im Assistenten ein fehlerhafter oder nicht verwendeter Code ansammeln. Sie werden jedes Mal von Ihrem Platz aus faul sein, bis ein Plan für die gesamte Umgebung erstellt wird. Sie werden versuchen, über die Zieloption die Anwendung nur auf dem aufzubauen, was Sie geändert haben. Sie haben beispielsweise eine Instanz hinzugefügt und gesagt: "Terraform-Zielinstanz anwenden" oder Sicherheitsgruppe. Wenn in diesem Fall jedoch eine Störung auftritt (z. B. ist eine Konfiguration veraltet), wird dies beim Erstellen des vollständigen Plans angezeigt.Sie müssen viel Mühe und Zeit aufwenden, um dies auf den neuesten Stand zu bringen. Keine Notwendigkeit, dies zur Sprache zu bringen. Wenn es ein CI gibt - darin sagen wir einfach mit Nachdruck, dass Terraform den Plan vollständig erstellen wird, Sie drücken die Änderungen. Und lass ihn seinen Plan aufbauen, du gehst und machst etwas anderes. Er hat es gebaut, du hast es gesehen, du hast es in Form eines Artefakts und du bist gegangen, um es anzuwenden. Es diszipliniert.Terraform ist keine Silberkugel
Was er dir nicht erlauben wird:- Terraform , . , , . , , , . , , , .
, — Tfstate, , . . « , » — .
, -, , - — . , . , — . - Terraform , . Terraform . Warum? , . . , , AZ - -. , North Virginia, 6 . . , , : «, ». — . — , , Terraform .
- Terraform . , — 200 , 198 , 5. . , API . Leider.
- Außerdem kann er nicht berücksichtigen, dass einige Namen eindeutig sein müssen. Sie möchten beispielsweise einen S3-Bucket erstellen. Dies ist ein globaler Dienst für die Region, und selbst wenn Sie keinen Dienst mit diesem Namen in Ihrem Konto erstellt haben, ist es keine Tatsache, dass jemand anderes ihn nicht erstellt hat. Und wenn Sie es mit Terraform erstellen, wird es perfekt einen Plan erstellen, mit der Erstellung beginnen und Amazon wird sagen: "Entschuldigung, jemand hat dies bereits." Dies kann nicht im Voraus vorausgesehen werden. Nur wenn Sie versuchen, dies im Voraus mit Ihren Händen zu tun, obwohl dies der Praxis widerspricht.
Auf jeden Fall ist Terraform das Beste, was es jetzt gibt. Und wir benutzen es weiterhin, es hilft uns sehr.