Table of Contents
Serverless Computing hat die Art und Weise, wie Teams Anwendungen erstellen und bereitstellen, verändert, indem es Skalierbarkeit, Pay-per-Use-Preise und reduzierten Betriebsaufwand bietet. Serverless Anwendungen in der Produktion auszuführen, beinhaltet jedoch weit mehr als das Schreiben von Funktionscode. Sie müssen Dutzende von Cloud-Ressourcen bereitstellen und verwalten – API-Gateways, Warteschlangen, Datenbanken, IAM-Rollen, Protokollierungskonfigurationen und Netzwerkkomponenten – die alle konsistent in Entwicklungs-, Staging- und Produktionsumgebungen repliziert werden müssen. Manuelle Klick-Ops in der Konsole werden schnell fehleranfällig und unskalierbar. Infrastructure as Code (IaC)-Tools wie Terraform lösen diese Herausforderung, indem sie es Ihnen ermöglichen, jedes Stück Infrastruktur in versiongesteuerten, menschenlesbaren Konfigurationsdateien zu definieren. Dieser Artikel untersucht, wie man Terraform verwendet, um die Bereitstellung von Infrastruktur für serverlose Anwendungen zu automatisieren, und bietet konkrete Beispiele, Best Practices und Strategien für das Management von Komplexität in der realen Welt.
Was ist Terraform?
Terraform ist ein Open-Source-IaC-Tool, das von HashiCorp erstellt wurde und es Ihnen ermöglicht, Infrastrukturen über mehrere Cloud-Anbieter hinweg mit einer deklarativen Konfigurationssprache, bekannt als HCL (HashiCorp Configuration Language), bereitzustellen und zu verwalten. Anstatt imperative Skripte zu schreiben, die Schritt-für-Schritt-Befehle ausführen, deklarieren Sie den gewünschten Zustand Ihrer Infrastruktur - welche Ressourcen Sie wünschen, ihre Eigenschaften und wie sie sich zueinander verhalten - und Terraform bestimmt die notwendigen Aktionen, um diesen Zustand zu erreichen.
Im Mittelpunkt von Terraform steht der Ausführungsplan. Bevor Sie Änderungen vornehmen, vergleicht Terraform Ihre Konfiguration mit dem aktuellen Zustand der Infrastruktur und erstellt einen detaillierten Plan, was erstellt, aktualisiert oder zerstört wird. Dieser Plan kann überprüft (und in CI/CD-Pipelines genehmigt) werden, bevor er angewendet wird, sodass Sie eine sichere Feedbackschleife erhalten, die unbeabsichtigte Änderungen verhindert. Terraform verfolgt auch Ressourcen in einer Zustandsdatei, die die Konfiguration realen Cloud-Objekten zuordnet. Diese Zustandsdatei ist wichtig, damit Terraform weiß, was es verwaltet und um Drift zu erkennen.
Terraform unterstützt Hunderte von Anbietern, einschließlich aller wichtigen Cloud-Plattformen (AWS, Azure, Google Cloud) sowie SaaS-Dienste wie Cloudflare, Datadog und GitHub. Für serverlose Anwendungen auf AWS verwenden Sie normalerweise den AWS-Anbieter, um Lambda-Funktionen, API Gateway REST-APIs, DynamoDB-Tabellen, SQS-Warteschlangen, Kinesis-Streams, Cognito-Benutzerpools und jede IAM-Richtlinie, die sie miteinander verbindet, zu definieren.
Warum serverlose Apps Infrastruktur als Code benötigen
Serverlose Anwendungen bestehen aus vielen kleinen, speziell für diese Zwecke entwickelten Diensten, die asynchron oder synchron kommunizieren. Eine typische ereignisgesteuerte Architektur kann ein API Gateway beinhalten, das HTTP-Anforderungen empfängt, eine Lambda-Funktion, um sie zu verarbeiten, eine DynamoDB-Tabelle, um Ergebnisse zu speichern, und eine SQS-Warteschlange, um Arbeit für eine zweite Lambda-Funktion zu puffern. Das Erstellen dieser Ressourcen von Hand ist mühsam und fehleranfällig, insbesondere wenn Ihre Architektur Dutzende von Funktionen und Hilfsdienste umfasst. Die Herausforderungen der manuellen Verwaltung umfassen:
- Inkonsistenz: Verschiedene Umgebungen (dev, staging, prod) driften zwangsläufig auseinander, wenn sie manuell erstellt werden.
- Keine Versionshistorie: Wer hat die DynamoDB-Lesekapazität geändert? Wann? Warum? Ohne Code verlieren Sie die Auditierbarkeit.
- Erholungsalbtraum: Nach einer Katastrophe müsstest du alles von Grund auf neu konfigurieren, in der Hoffnung, dass du dich an jede Einstellung erinnerst.
- Zeitverschwendung: Wenn Sie für jede Ressource durch die Konsole klicken, werden Stunden benötigt, die in die Anwendungslogik eingehen sollten.
IaC löst diese Probleme, indem es Infrastruktur in Software umwandelt. Jede Änderung ist eine Pull-Anfrage. Jede Umgebung ist eine wiederholbare Bereitstellung. Und Ihre gesamte Architektur kann in wenigen Minuten abgerissen und neu aufgebaut werden. Für serverlose Anwendungen, bei denen das Wertversprechen Geschwindigkeit und Agilität ist, ist IaC nicht optional – es ist die Grundlage für einen zuverlässigen Produktionsablauf.
Hauptvorteile der Verwendung von Terraform für Serverless
Während jedes IaC-Tool zur Verwaltung der serverlosen Infrastruktur verwendet werden kann, bietet Terraform deutliche Vorteile, die sich gut an den Bedürfnissen serverloser Teams orientieren.
Vollständige Lifecycle-Automatisierung
Terraform übernimmt nicht nur die Bereitstellung, sondern auch die Aktualisierung und Zerstörung von Ressourcen. Wenn Sie die Speichergröße einer Lambda-Funktion oder das TTL-Attribut einer DynamoDB-Tabelle ändern müssen, aktualisieren Sie einfach die Konfiguration und führen aus. Wenn Sie mit einer Ressource fertig sind, wird der gleiche Code, der sie erstellt hat, sie bereinigen. Dies ist besonders wertvoll in ephemeren Umgebungen - wie Vorschau-Bereitstellungen für jede Pull-Anfrage - wo Sie einen vollständigen serverlosen Stapel aufdrehen und später automatisch zerstören können.
Deklaratives Abhängigkeitsmanagement
Serverlose Architekturen haben komplizierte Abhängigkeiten. Eine Lambda-Funktion hängt von einer IAM-Rolle ab, die von einer Richtlinie abhängen kann, die von einer DynamoDB-Tabelle ARN abhängen kann. Terraform erstellt aus Ihren Deklarationen ein Ressourcendiagramm und bestimmt automatisch die korrekte Reihenfolge der Operationen. Es erstellt Ressourcen, bevor sie referenziert werden und wartet auf Abhängigkeiten zur Verfügung zu stehen. Das befreit Sie vom Schreiben fehleranfälliger Skripte, die Befehle manuell abfolgen.
Multi-Environment-Konsistenz
Mithilfe von Terraform-Arbeitsbereichen oder Verzeichnisstrukturen können Sie dieselbe Konfiguration in mehreren Umgebungen mit unterschiedlichen Variablenwerten wiederverwenden. Die Konfiguration einer Lambda-Funktion kann über Entwickler, Staging und Produktion hinweg identisch sein, mit Ausnahme von umgebungsspezifischen Variablen wie Tabellennamen, Protokollebenen oder VPC-Einstellungen. Dies stellt sicher, dass die Produktionsinfrastruktur genau das ist, was in der Staging getestet wurde.
Granulare Staatskontrolle
Zustandsverwaltung ist ein wichtiges Anliegen. Terraform ermöglicht es Ihnen, Zustand ferngesteuert in Backends wie S3 (mit DynamoDB-Schließung), Terraform Cloud oder HashiCorp Consul zu speichern. Remote-Zustand ermöglicht Teamzusammenarbeit: Mehrere Ingenieure können Änderungen sicher an derselben Infrastruktur ohne Konflikte anwenden. Für serverlose Teams, die kontinuierlich bereitstellen, ist eine robuste Zustandsverwaltung unerlässlich.
Erste Schritte mit Terraform für Serverless Deployment
Lassen Sie uns durch die Einrichtung einer kompletten serverlosen Anwendung mit Terraform auf AWS gehen. Unser Beispiel wird eine einfache REST-API über API Gateway freilegen, die eine Lambda-Funktion auslöst, die Daten in eine DynamoDB-Tabelle schreibt. Wir werden auch die erforderlichen IAM-Berechtigungen abdecken.
Voraussetzungen
- Terraform installiert (download)
- AWS-Konto mit konfigurierten Anmeldeinformationen (über Umgebungsvariablen oder )
- Node.js installiert (um den Lambda-Code zu kompilieren)
Projektstruktur
serverless-terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── lambda/
│ └── index.js
└── terraform.tfvars
1. Definieren Sie den Terraform-Anbieter
In konfigurieren Sie den AWS-Provider und geben die Region an:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "serverless-app/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
}
2. IAM-Rolle für Lambda erstellen
data "aws_iam_policy_document" "lambda_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "lambda_exec" {
name = "serverless-lambda-role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
}
resource "aws_iam_policy" "lambda_dynamodb_policy" {
name = "lambda-dynamodb-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:UpdateItem"]
Effect = "Allow"
Resource = aws_dynamodb_table.items.arn
},
{
Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
Effect = "Allow"
Resource = "*"
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attach" {
role = aws_iam_role.lambda_exec.name
policy_arn = aws_iam_policy.lambda_dynamodb_policy.arn
}
3. Deployment der DynamoDB-Tabelle
resource "aws_dynamodb_table" "items" {
name = "items"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
tags = {
Environment = var.environment
}
}
4. Paketieren und Bereitstellen der Lambda-Funktion
Erstellen Sie zunächst eine einfache Lambda-Funktion in :
exports.handler = async (event) => {
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
const id = event.pathParameters.id;
const params = {
TableName: process.env.TABLE_NAME,
Item: { id, timestamp: Date.now(), data: event.body }
};
await dynamodb.put(params).promise();
return {
statusCode: 200,
body: JSON.stringify({ id })
};
};
Dann verweisen Sie in Ihrer Terraform-Konfiguration auf den Funktionscode:
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/lambda"
output_path = "${path.module}/lambda_function_payload.zip"
}
resource "aws_lambda_function" "api_handler" {
filename = data.archive_file.lambda_zip.output_path
function_name = "serverless-api-handler"
role = aws_iam_role.lambda_exec.arn
handler = "index.handler"
runtime = "nodejs18.x"
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
environment {
variables = {
TABLE_NAME = aws_dynamodb_table.items.name
}
}
}
5. Exposieren Sie das Lambda über API Gateway
resource "aws_api_gateway_rest_api" "api" {
name = "serverless-api"
}
resource "aws_api_gateway_resource" "items" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_rest_api.api.root_resource_id
path_part = "items"
}
resource "aws_api_gateway_resource" "item" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_resource.items.id
path_part = "{id}"
}
resource "aws_api_gateway_method" "put_item" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id = aws_api_gateway_resource.item.id
http_method = "PUT"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "lambda" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id = aws_api_gateway_resource.item.id
http_method = aws_api_gateway_method.put_item.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.api_handler.invoke_arn
}
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.api_handler.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
}
resource "aws_api_gateway_deployment" "prod" {
depends_on = [aws_api_gateway_integration.lambda]
rest_api_id = aws_api_gateway_rest_api.api.id
stage_name = "prod"
}
6. Outputs definieren
In , exponieren Sie den API-Endpunkt:
output "api_endpoint" {
value = "${aws_api_gateway_deployment.prod.invoke_url}/items/"
}
7. Antrag
terraform init
terraform plan
terraform apply
Nach dem Anwenden können Sie eine PUT-Anfrage an den Endpunkt mit einem JSON-Body ausgeben. Die Lambda-Funktion schreibt die Daten in DynamoDB.
Strukturierung von Terraform-Projekten für Serverless
Serverlose Anwendungen in der realen Welt sind zu groß für eine einzelne Konfigurationsdatei. Die Annahme einer skalierbaren Projektstruktur ist entscheidend. Hier sind gängige Muster:
Verwenden von Modulen zum Einkapseln wiederverwendbarer Komponenten
Terraform-Module ermöglichen es, Ressourcen in logische Einheiten zu gruppieren.
- Ein Basis-Lambda-Funktionsmodul (mit IAM-Rolle, grundlegenden CloudWatch-Berechtigungen und optionaler VPC-Konfiguration)
- API Gateway + Lambda Integrationsmodul
- Ein DynamoDB-Tabellenmodul mit standardisierten Attributen und Autoskalierung
- Ein SQS-Warteschlangenmodul mit Dead-Buchstaben-Warteschlangen
Module können in Ihrem eigenen Git-Repository gespeichert oder in der Terraform Registry veröffentlicht werden. Sie vereinfachen die umgebungsspezifischen Konfigurationen: Sie instanziieren ein Modul mit verschiedenen Variablen pro Umgebung.
Separate Umgebungen mit Verzeichnissen oder Workspaces
Es gibt zwei gemeinsame Ansätze für das Management von Umgebungen:
- Verzeichnis pro Umgebung: Erstellen Sie Ordner wie , , , jeder mit seinem eigenen und möglicherweise einem .
- Terraform Workspaces: Verwenden Sie die integrierte Workspace-Funktion, um benannte Instanzen derselben Konfiguration zu erstellen. Workspaces sind leichter, können aber im Umgang mit mehreren Teams verwirrend werden.
Für die meisten serverlosen Teams ist der Verzeichnisansatz klarer, da er Umgebungsgrenzen in der Codebasis explizit macht.
Remote State mit Sperrung
Speichern Sie niemals den Status lokal für Teamprojekte. Verwenden Sie ein S3-Backend mit DynamoDB-Schließung. Der S3-Bucket enthält die Statusdatei und DynamoDB bietet Konsistenzsperren, so dass nur eine gleichzeitig ausgeführt wird. Beispiel-Backend-Konfiguration wurde früher gezeigt. Stellen Sie sicher, dass der S3-Bucket und die DynamoDB-Tabelle außerhalb von Terraform erstellt werden (bootstrap mit einem separaten Skript oder verwenden Sie die integrierte Zustandsverwaltung von Terraform Cloud).
Geheimnisse sicher verwalten
Serverlose Anwendungen erfordern oft Geheimnisse wie Datenbankpasswörter, API-Schlüssel oder JWT-Signing-Token. Niemals diese in Terraform-Konfigurationen fest codieren.
- AWS Secrets Manager oder SSM Parameter Store, referenziert über oder Datenquellen
- Vault-Anbieter, um dynamische Geheimnisse zu holen
- Umgebungsspezifische verschlüsselte Variablendateien (z. B. mit Tools wie )
Best Practices für die Automatisierung von Infrastruktur mit Terraform
Um die Zuverlässigkeit und Teamgeschwindigkeit zu maximieren, folgen Sie diesen bewährten Praktiken:
Versionskontrolle Alles
Alle Terraform-Konfigurationen, einschließlich Module, sollten in Git mit aussagekräftigen Commit-Nachrichten gespeichert werden. Tags und Verzweigungen für Änderungen verwenden. Dies bietet einen vollständigen Audit-Trail darüber, wer was und wann geändert hat.
Immer Plan und Review ausführen
In der lokalen Entwicklung immer vor ausführen. In CI/CD einen manuellen Genehmigungsschritt für Produktionsbereitstellungen erfordern. Terraform Cloud und Atlantis sind beliebte Tools, die Plan-/Anwendungsworkflows in Pull-Requests integrieren.
Implementieren von CI/CD für Infrastruktur
Behandeln Sie Infrastrukturänderungen wie Codeänderungen. Verwenden Sie eine Pipeline, die bei Pull-Anfragen ausgeführt wird, dann ausgeführt wird und nach dem Zusammenführen ausgeführt wird. Für serverlose Anwendungen können Sie Integrationstests nach dem Anwenden durchführen, um zu überprüfen, ob die API-Endpunkte korrekt reagieren.
Verwenden Sie für die Drift Detection
Selbst mit CI/CD kann jemand eine Ressource manuell über die Konsole modifizieren. Planen Sie regelmäßige FLT:32-Läufe (z. B. nachts), um Drift zu erkennen und das Team zu alarmieren. Tools wie die Drifterkennung von Terraform Cloud können dies automatisieren.
Testen Sie Ihre Terraform-Konfigurationen
Unit-Testing-Infrastrukturcode ist mit Tools wie Terratest möglich, einer Go-Bibliothek, die echte Cloud-Ressourcen aufdreht, ihr Verhalten überprüft und sie abreißt. Für Serverless können Sie Stacks in isolierten Testkonten bereitstellen, HTTP-Tests gegen die API ausführen und DynamoDB-Inhalte validieren. Während das Schreiben von Terratest-Tests eine Investition ist, fängt es subtile Konfigurationsfehler frühzeitig auf.
Verwenden Sie Policy als Code
Definieren Sie unternehmensweite Compliance-Regeln mit HashiCorp Sentinel (Cloud) oder Open Policy Agent. Erfordern Sie beispielsweise, dass alle Lambda-Funktionen Röntgen-Tray-Tracing aktiviert haben, oder verhindern Sie öffentliche DynamoDB-Tabellen. Diese Richtlinien werden zum Planzeitpunkt durchgesetzt, wodurch Sicherheit und Kostenkontrolle systematisch werden.
Gemeinsame Herausforderungen und Lösungen
State File Locking und Konflikte
Wenn mehrere Teammitglieder gleichzeitig FLT:33 ausführen, kann es zu einer Zustandskorruption kommen. Lösung: Verwenden Sie immer ein Backend, das das Sperren unterstützt (S3 + DynamoDB) und führen Sie FLT:34 niemals direkt aus parallelen Zweigen aus. Verwenden Sie CI/CD-Pipelines, um zu serialisieren.
Umgang mit einer großen Anzahl von Lambda-Funktionen
Die Verwaltung von mehr als 50 Lambda-Funktionen in einer einzigen Konfiguration wird unhandlich. Lösung: Verwenden Sie oder mit einer Karte von Funktionsdefinitionen. Noch besser, organisieren Sie Funktionen in separate Terraform-Konfigurationen, die Zustandsdatenquellen gemeinsam nutzen. Zum Beispiel exportiert eine zentrale “Kern”-Konfiguration Ausgaben (DynamoDB-Tabellennamen, SQS-Warteschlangen-URLs), die nachgelagerte Funktionskonfigurationen über importieren.
Abhängigkeitsordnung in komplexen Architekturen
Obwohl Terraform die meisten Abhängigkeiten automatisch verarbeitet, können zirkulare Abhängigkeiten (z. B. zwei Dienste, die sich gegenseitig auf ARNs beziehen) Probleme verursachen. Lösung: Durchbrechen des Zyklus durch die Einführung einer dritten Ressource (wie ein zentrales SNS-Thema) oder die Verwendung expliziter -Blöcke. Für Serverless besteht ein gemeinsames Muster darin, IAM-Rollen und -Richtlinien getrennt von Funktionen zu erstellen, um Zyklen zu vermeiden.
Lambda Code Änderungen durchführen
Terraform ist für die Infrastruktur konzipiert, nicht für die kontinuierliche Bereitstellung von Anwendungscode. Das Schieben neuer Lambda-Versionen durch jedes Mal erneute Anwendung von Terraform ist langsam und nicht ideal für schnelle Code-Iterationen. Lösung: Trennen der Infrastrukturbereitstellung (erstellt einmal pro Umgebung) von der Codebereitstellung. Verwenden Sie CI/CD-Pipelines, die den Lambda-Funktionscode über das AWS SDK oder Tools wie das Serverless Framework aktualisieren, während Terraform die umgebenden Ressourcen verwaltet. Alternativ verwenden Sie die Datenquelle von Terraform mit einem konsistenten Quellhash, so dass nur Änderungen an der Codedatei eine neue Bereitstellung auslösen.
Schlussfolgerung
Die Automatisierung der Infrastrukturbereitstellung mit Terraform bringt die gleiche Strenge in die serverlose Infrastruktur, die Softwareteams auf Anwendungscode anwenden. Durch die Definition jeder Ressource in versiongesteuerten HCL-Dateien erhalten Sie wiederholbare Bereitstellungen, sicheres Änderungsmanagement und vollständige Audit-Trails. Ein gut strukturiertes Terraform-Projekt mit Modulen, Remote-Status und CI/CD-Integration ermöglicht es Teams, Hunderte von Lambda-Funktionen, API-Endpunkten und Datenspeichern zu verwalten, ohne Zeit in die manuelle Bereitstellung zu stecken oder sich um Umgebungsdrift zu kümmern.
Da serverlose Architekturen immer komplexer werden – mit ereignisgesteuerten Workflows, Schrittfunktionen und globaler Infrastruktur, die über mehrere Regionen verteilt sind –, nimmt die Bedeutung robuster IaC nur noch zu. Beginnend mit den Mustern und Beispielen in diesem Artikel können Sie eine Grundlage aufbauen, die mit Ihrer Anwendung und Ihrer Organisation skaliert werden kann. Die Vorabinvestition in die Automatisierung Ihrer serverlosen Infrastruktur zahlt sich um ein Vielfaches aus, indem sie Fehler reduziert, schnellere Bereitstellungen und mehr Vertrauen, dass Ihre Produktionsumgebung mit dem übereinstimmt, was Sie getestet haben.