Wie teste ich eine Terraform-Konfiguration?


37

Wenn Sie eine Terraform- Konfiguration mit einem moderaten Grad an Komplexität hätten, wie würden Sie Tests für die Konfiguration schreiben, die als Teil einer Continuous Integration / Continuous Delivery-Pipeline ausgeführt werden könnten?

Beispielsweise verfügen Sie möglicherweise über eine Multi-Cloud-Konfiguration, die den folgenden gewünschten Status angibt:

  • Azure Container Services zum Hosten von Docker in Azure
  • Azure Blob-Speicher
  • SQL Azure
  • EC2 Container Service zum Hosten von Docker in AWS
  • Amazon S3-Speicherdienst
  • Amazon RDS SQL Server-Datenbank

Möglicherweise terraform applykönnte das Obige von Grund auf neu erstellt werden oder der Übergang von einem teilweise entfalteten Zustand in den oben gewünschten Zustand.

Mir ist bekannt, dass Terraform seine Arbeit in die Phase des Ausführungsplans und die Anwendungsphase aufteilt, in der tatsächlich Änderungen an der Zielarchitektur vorgenommen werden. Kann dies verwendet werden, um Tests gegen den Ausführungsplan zu schreiben, wenn ja, gibt es Frameworks, um diese zu schreiben?



Interessant in der Tat, möglicherweise würdig zu beantworten.
Richard Slater

Ich benutze Terraform nicht selbst, also lasse ich jemanden mit echter Erfahrung eine Antwort schreiben :)
Tensibai

Antworten:


20

Derzeit gibt es keine vollständige Lösung für diese in Terraform integrierte Aufgabe. Es gibt jedoch einige Bausteine, die hilfreich sein könnten, um Tests in einer separaten Programmiersprache zu schreiben.

Terraform erstellt Statusdateien im JSON-Format, die im Prinzip von externen Programmen verwendet werden können, um bestimmte Daten zu extrahieren, die Terraform erstellt hat. Obwohl dieses Format noch nicht als offiziell stabil angesehen wird, ändert es sich in der Praxis nur selten genug, um von den Benutzern erfolgreich integriert zu werden, und akzeptiert, dass sie möglicherweise Anpassungen vornehmen müssen, wenn sie Terraform aktualisieren.

Welche Strategie hier angemessen ist, hängt stark davon ab, was genau Sie testen möchten. Beispielsweise:

  • In einer Umgebung, in der virtuelle Server hochgefahren werden, können mit Tools wie Serverspec Tests aus der Perspektive dieser Server ausgeführt werden. Dies kann entweder separat von Terraform mithilfe eines Out-of-Band-Prozesses ausgeführt werden oder im Rahmen von Terraform mithilfe des remote-execProvisioners angewendet werden . Dies ermöglicht die Überprüfung von Fragen wie "Kann der Server die Datenbank erreichen?", Ist jedoch nicht für Fragen wie "Ist die Sicherheitsgruppe der Instanz restriktiv genug?" Geeignet, da eine zuverlässige Überprüfung erfordert, dass von außerhalb der Instanz auf Daten zugegriffen wird.

  • Es ist möglich, Tests mit einem vorhandenen Testframework (wie RSpec für Ruby, unittestfür Python usw.) zu schreiben , die relevante Ressourcen-IDs oder -Adressen aus der Terraform- Statusdatei abrufen und dann das SDK der entsprechenden Plattform verwenden, um Daten zu den Ressourcen abzurufen und diese zu bestätigen Sie werden wie erwartet eingerichtet. Dies ist eine allgemeinere Form der vorherigen Idee, bei der die Tests aus der Perspektive eines Hosts außerhalb der zu testenden Infrastruktur ausgeführt werden. Auf diese Weise kann ein breiterer Datensatz erfasst werden, über den Aussagen getroffen werden können.

  • Bei bescheideneren Anforderungen kann man sich darauf verlassen, dass der Terraform-Zustand eine genaue Darstellung der Realität ist (eine in vielen Fällen gültige Annahme), und dies einfach direkt bestätigen. Dies ist am besten für einfache "fusselartige" Fälle geeignet, z. B. um zu überprüfen, ob das richtige Ressourcen-Tagging-Schema für die Kostenzuordnung eingehalten wird.

Darüber wird in einer relevanten Ausgabe von Terraform Github ausführlicher diskutiert .

In den neuesten Versionen von Terraform wird dringend empfohlen, ein Remote-Backend für alle Nicht-Spielzeug-Anwendungen zu verwenden. Dies bedeutet jedoch, dass die Statusdaten nicht direkt auf der lokalen Festplatte verfügbar sind. Ein Snapshot davon kann jedoch mit dem terraform state pullBefehl aus dem Remote-Backend abgerufen werden , der die JSON-formatierten Statusdaten auf stdout druckt, damit sie von einem aufrufenden Programm erfasst und analysiert werden können.


12

Als Update zu dieser Frage gibt es jetzt Kitchen-Terraform , mit dem Sie Terraform-Konfigurationsdateien testen können, ohne die Produktionsumgebung zu beschädigen. Das Repository enthält auch einige Beispiele für verschiedene Terraform-Anbieter.


12

Vor kurzem haben wir Terratest , unser Schweizer Taschenmesser , zum Testen von Infrastrukturcode geöffnet .

Heute testen Sie wahrscheinlich Ihren gesamten Infrastrukturcode manuell, indem Sie ihn bereitstellen, validieren und wieder rückgängig machen. Terratest hilft Ihnen, diesen Prozess zu automatisieren:

  1. Schreibe Tests in Go.
  2. Verwenden Sie Helfer in Terratest, um Ihre echten IaC-Tools (z. B. Terraform, Packer usw.) auszuführen und eine echte Infrastruktur (z. B. Server) in einer echten Umgebung (z. B. AWS) bereitzustellen.
  3. Verwenden Sie Helfer in Terratest, um zu überprüfen, ob die Infrastruktur in dieser Umgebung ordnungsgemäß funktioniert, indem Sie HTTP-Anforderungen, API-Aufrufe, SSH-Verbindungen usw. ausführen.
  4. Verwenden Sie Helfer in Terratest, um die Bereitstellung am Ende des Tests aufzuheben.

Hier ist ein Beispieltest für einen Terraform-Code:

terraformOptions := &terraform.Options {
  // The path to where your Terraform code is located
  TerraformDir: "../examples/terraform-basic-example",
}

// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)

// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// Run `terraform output` to get the value of an output variable
instanceUrl := terraform.Output(t, terraformOptions, "instance_url")

// Verify that we get back a 200 OK with the expected text
// It can take a minute or so for the Instance to boot up, so retry a few times
expected := "Hello, World"
maxRetries := 15
timeBetweenRetries := 5 * time.Second
http_helper.HttpGetWithRetry(t, instanceUrl, 200, expected, maxRetries, timeBetweenRetries)

Dies sind Integrationstests, die je nach Testdauer 5 bis 50 Minuten dauern können. Es ist nicht schnell (obwohl Sie mit Docker und Testphasen einige Dinge beschleunigen können), und Sie müssen daran arbeiten, die Tests zuverlässig zu machen, aber es ist die Zeit wert.

Im Terratest-Repo finden Sie Dokumente und viele Beispiele für verschiedene Arten von Infrastrukturcode sowie die entsprechenden Tests für diese.


1
Ich habe auch einen Blog-Beitrag geschrieben, in dem ich eines meiner Beispielprojekte mit Terratest ausführlicher teste : brightfame.co/blog/… . Es kann für jeden von Wert sein. Prost, Rob!
Rob Morgan

Großer Fan von Terratest!
Jlucktay

7

Zusätzlich zu allen anderen genannten Optionen möchte ich erwähnen, dass InSpec 2.0 die Unterstützung für Cloud-Provider-APIs hinzugefügt hat. Grundsätzlich können Sie die IaC mit Terraform weiter schreiben und dann mit InSpec Konformitätsprüfungen für Ihre Cloud-Ressourcen durchführen. Darüber hinaus unterstützt InSpec das Schreiben von Tests für einzelne Maschinen, falls Sie diese jemals benötigen.

Hier ist ein Artikel von Christoph Hartmann (Mitentwickler von Inspec) zur Verwendung von Inspec mit Terraform: https://lollyrock.com/articles/inspec-terraform/


5

Auf der Aws-Seite gibt es https://github.com/k1LoW/awspec - es sollte möglich sein, terraform.state einzuspeisen und zu testen, ob terraform korrekt angewendet wurde.

Aber ich denke, abgesehen davon, dass Sie das von Ihnen verwendete Tool auf niedriger Ebene getestet haben, ist es wahrscheinlich eine bessere Idee, darüber nachzudenken, wie ganze Infrastrukturen getestet werden können.

Wir diskutieren hier über diese Idee:

https://github.com/DomainDrivenArchitecture/dda-cloudspec/blob/development/README.md

Für das Testen von Invarianten im Voraus kenne ich keine gebrauchsfertige Lösung ...

Wir haben einige Experimente mit einer Mischung aus terraform plan -out=plan.dumpund grepohne Elementnamen durchgeführt. Eine Diskussion über ein zugänglicheres Planformat gibt es hier: github.com/hashicorp/terraform/issues/11883

Momentan verwenden wir jedoch einen manuellen Planprüfungsprozess für wichtige Teile unserer Infrastruktur.


4
Das Ziel ist es, zu testen, ob die Änderungen in der Terraform-Konfiguration die erwarteten Anforderungen nicht beeinträchtigen. Wenn sie erst einmal bereitgestellt wurden, ist es zu spät. Bestenfalls können Sie nicht feststellen, dass eine Datenbank an der Stelle entfernt wurde, an der sie nicht entfernt werden sollte. Sie haben jedoch die Zielumgebung bereits beschädigt. .. die Frage ist über das Testen des Terraform-Codes, nicht das Testen des Endergebnisses, Unit-Tests vs Integrationstests.
Tensibai

guter Punkt ... hat einen Abschnitt zum Testen von Invarianten hinzugefügt.
jerger

0

Ich habe diese elegante Low-Tech-Methode zum Testen von Terraform gesehen, die anscheinend von Smart in einem GitHub-Thread vorgeschlagen wurde. Es ist nicht für jede Situation geeignet, eignet sich jedoch hervorragend zum Überprüfen der Modullogik.

Erstellen Sie ein Stammmodul, das das zu testende Modul enthält und die zu testenden Ausgaben überprüft. Hier ist ein einfaches Beispiel mit zwei Dateien:

  • main.tf das wird die tests ausführen
  • simple_module/outputs.tf das ist ein Modul im Test

./main.tf

terraform {
  required_version = ">= 0.12"
}

module "simple_module" {
  source = "./simple_module"
}

locals {
  expected = 1
  got      = module.simple_module.module-returns-1
}

# Test Output
output "expect-1" {
  value = upper(local.expected == local.got)
}

output "expect-other" {
  value = "other" == local.got ? upper(true) : "FALSE. Got ${local.got}"
}

./einfaches_Modul/outputs.tf

output "module-returns-1" {
  value = 1
}

Führen Sie die Tests aus

terraform init
terraform apply -auto-approve
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.