Blog
Automatisieren Sie Lambda-Abhängigkeiten mit Terraform

In letzter Zeit habe ich an einigen Projekten gearbeitet, die Lambda-Funktionen beinhalteten. Das bedeutete, dass ich diese Funktionen und die gesamte Infrastruktur um sie herum über Terraform definieren und aufbauen musste. In der Vergangenheit habe ich mich immer schwer getan, einfache Wege zu finden, um die Abhängigkeiten in die Bereitstellung zu integrieren und so manuelle Eingriffe oder unnötig komplizierte Schritte zu minimieren. Deshalb habe ich dieses Mal beschlossen, etwas Zeit in die Suche nach einer besseren Lösung zu investieren! In diesem kurzen Artikel möchte ich Ihnen die Lösung vorstellen, die ich gefunden habe, sowie ihre Vor- und (frustrierenden) Nachteile.
Dir Struktur
Damit diese Lösung funktioniert, sollte das Projektverzeichnis so strukturiert sein, dass terraform die Abhängigkeiten finden kann, die Sie in Ihrem Lambda installieren möchten. Ich verwende Terraform Cloud für meine Einsätze und habe mein Verzeichnis dementsprechend strukturiert. Terraform Cloud arbeitet, indem es das Terraform-Verzeichnis vom Projekt isoliert und von dort aus arbeitet. Das bedeutet, dass sich alle relevanten Dateien in diesem Verzeichnis befinden müssen. Wenn Sie eine lokale Deployment-Methode verwenden, haben Sie mehr Freiheit, was den Speicherort Ihrer Dateien angeht. Denken Sie jedoch daran, die Pfadnamen gegebenenfalls an den richtigen Ort anzupassen.
HINWEIS: Dieses Beispiel verwendet eine Python-Funktionsstruktur, kann aber mit ein wenig Know-How an andere Sprachen angepasst werden.
Die Dir-Struktur ist wie folgt:
project/
|-README.md
|-terraform/
| |-function/
| | |-main.py
| |-layer/
| | |-requirements.txt
| |-main.tf
| |-variables.tf
Unsere requirements.txt Datei sollte die Form einer Standard-Python-Anforderungs-Textdatei haben, z.B:
boto3==1.33.8
requests>=2.0.0
Mit dieser Struktur können wir unsere Terraform-Datei zusammenstellen.
Terraform Ressourcen
Ich habe alle Konfigurationsdetails der Ressourcen, die nicht in den Geltungsbereich fallen, weggelassen, damit wir uns auf die Schichtkonfiguration konzentrieren können:
terraform {
# ... config
}
provider "aws" {
# ... config
}
resource "null_resource" "install_layer_dependencies" {
provisioner "local-exec" {
command = "pip install -r layer/requirements.txt -t layer/python/lib/python3.9/site-packages"
}
triggers = {
trigger = timestamp()
}
}
data "archive_file" "layer_zip" {
type = "zip"
source_dir = "layer"
output_path = "layer.zip"
depends_on = [
null_resource.install_layer_dependencies
]
}
resource "aws_lambda_layer_version" "lambda_layer" {
filename = "layer.zip"
source_code_hash = data.archive_file.layer_zip.output_base64sha256
layer_name = "my_layer_name"
compatible_runtimes = ["python3.9"]
depends_on = [
data.archive_file.layer_zip
]
}
data "archive_file" "function_zip" {
type = "zip"
source_dir = "function"
output_path = "function.zip"
}
resource "aws_lambda_function" "lambda" {
# ... other config
filename = "function.zip"
source_code_hash = data.archive_file.functip_zip.output_base64sha256
runtime = "python3.9"
role = aws_iam_role.role.arn
layers = [
aws_lambda_layer_version.lambda_layer.arn
]
depends_on = [
data.archive_file.function_zip,
aws_lambda_layer_version.lambda_layer
]
}
resource "aws_iam_role" "role" {
# ... config
}
resource "aws_iam_role_policy" "role_policy" {
# ... config
}
Der wichtigste Teil, auf den Sie sich hier konzentrieren sollten, ist null_resource. Hier werden die Abhängigkeiten installiert. In unserem Beispiel lesen wir aus der Datei requirements.txt und installieren diese Abhängigkeiten in das Verzeichnis layer/. Anschließend zippen wir diese Datei mit der Datenquelle archive_file.layer_zip, damit sie von aws_lambda_function verwendet werden kann. Um diesen Prozess an Ihre Laufzeit- und Verzeichnisstruktur anzupassen, ändern Sie den Befehl in depends_on in den Ressourcen zu beachten, da sie dabei hilft, sicherzustellen, dass alles an seinem Platz ist, bevor die nächste Stufe eingesetzt wird.
Der nächste Punkt ist der Abschnitt triggers in der null_resource. Aufgrund der Funktionsweise der Statusdatei muss ein Auslöser hinzugefügt werden, um diese Ressource wiederholt bereitzustellen. Idealerweise wäre dieser Auslöser eine Änderung in der requirements.txt Datei, jedoch ohne die Möglichkeit, denselben Auslöser zu den Ressourcen archive_file.layer_zip und aws_lambda_layer_version hinzuzufügen, indem Sie die Änderung in requirements.txt Datei als Auslöser zu unsachgemäß verpackten Ebenen führt. Zum jetzigen Zeitpunkt ist das Beste, was wir verwenden können,
Ebene vs. Paket
In diesem Beispiel haben wir einen Layer für unsere Abhängigkeiten verwendet, aber wir können dies leicht in ein Standardpaket umwandeln. Indem wir null_resource so anpassen, dass die Abhängigkeiten in das Verzeichnis function/ installiert werden, können wir die Ressourcen Layer-Zip und Layer-Version entfernen und direkt die gezippte Funktionsdatei verwenden. Wie bereits erwähnt, führt dies jedoch dazu, dass die Abhängigkeiten bei jeder Anwendung neu erstellt werden. Wenn Sie also die Funktion und die Abhängigkeiten zusammen paketieren, bedeutet dies, dass auch der Funktionscode bei jeder Anwendung neu bereitgestellt wird. Weitere Informationen zu diesem Prozess finden Sie hier.
Zusammenfassung
Obwohl diese Methode zu langsameren Bereitstellungszeiten führt, da die Schicht jedes Mal neu erstellt werden muss, bin ich der Meinung, dass sich dieser Kompromiss lohnt. Abhängigkeiten können einfach zu requirements.txt hinzugefügt werden und werden automatisch und korrekt in Ihrer Funktion eingesetzt. Alles in allem bin ich der Meinung, dass Sie die Geschwindigkeit gegen eine Methode zur Installation von Abhängigkeiten eintauschen, die Sie einfach vergessen können. Darüber hinaus werden mit der Weiterentwicklung von Terraform hoffentlich Trigger zu anderen Ressourcen hinzugefügt, um diese Geschwindigkeitshürde zu beseitigen. Dieser Beitrag bezieht sich nur auf AWS, aber mit diesem Konzept können Sie die Methode an jede beliebige Plattform anpassen, die Sie verwenden!
Verfasst von
Andrew Stump
Unsere Ideen
Weitere Blogs
Contact



