Serverless Development und Deployment – Wie geht das eigentlich mit CDK?

24.07.2023Tom Trapp
Tech Serverless Amazon Web Services Function as a Service Pay As You Go

👉 Serverless ist dir noch kein Begriff? Dann findest du hier alles Wissenswerte zum Thema Serverless.

Heute wollen wir uns den Entwicklungsprozess im Bereich Serverless, das Local-Development sowie den Deploymentprozess genauer anschauen. Ziel ist es, hands-on eine Serverless-Anwendung auf AWS zu entwickeln und zu deployen.

Die Idee

Wir möchten gerne unterschiedliche IaC-Provisionierungstools (Infrastructure-as-Code) anschauen und ausprobieren, um exemplarisch kleine Serverless-Anwendungen zu bauen, entwickeln und zu deployen.

Wie starten?

In Raffi’s TechUp zu Serverless Patterns haben wir bereits unterschiedliche Blueprints kennengelernt, welche uns den Einstieg in die Serverless-Welt erleichtern. Bevor wir uns in die Serverless-Welt stürzen, müssen wir aber noch einige Entscheidungen treffen.

Welches Infrastructure-as-Code (IaC) Tool wollen wir verwenden? Grundsätzlich bietet uns das Serverless Land folgende IaC-Tools für die Provisionierung von Serverless-Komponenten an:

  • AWS Cloud Development Kit (CDK): Das AWS Cloud Development Kit ist ein Open-Source-Softwareentwicklungsframework von AWS, das Entwicklern dabei hilft, IaC in verschiedenen Programmiersprachen zu schreiben und bereitzustellen.
  • AWS Serverless Application Model (SAM): Das AWS Serverless Application Model (SAM) ist ein Framework zum Entwickeln von Serverless-Anwendungen auf AWS, das auf AWS CloudFormation basiert und eine vereinfachte Syntax verwendet, um Serverless-Ressourcen zu definieren und bereitzustellen.
  • Serverless Framework: Das Serverless Framework ist ein Open-Source-Entwicklungsframework zum Erstellen von Serverless-Anwendungen auf verschiedenen Cloud-Plattformen wie AWS, Azure und Google Cloud Platform. Es bietet eine vereinfachte Möglichkeit, Serverless-Funktionen, APIs und andere Ressourcen zu definieren und zu deployen.
  • Terraform: Terraform ist ein Open-Source-Tool von HashiCorp, das es Entwicklern ermöglicht, IaC zu schreiben und zu verwalten. Es unterstützt verschiedene Cloud-Plattformen wie AWS, Azure und Google Cloud Platform sowie On-Premises-Umgebungen und bietet eine deklarative Sprache zur Infrastrukturdefinierung.
  • Pulumi: Pulumi ist ein Open-Source-Tool, das Entwicklern hilft, IaC in verschiedenen Programmiersprachen zu schreiben und bereitzustellen. Im Gegensatz zu anderen IaC-Tools verwendet Pulumi eine imperative Sprache, die Entwicklern mehr Flexibilität bei der Erstellung und Verwaltung von Infrastruktur gibt.

AWS Cloud Development Kit (CDK)

AWS CDK ist ein Open-Source-Framework, das es Entwicklern ermöglicht, Infrastruktur-As-Code zu schreiben und bereitzustellen. Im Folgenden sind einige der wichtigsten Merkmale von AWS CDK aufgeführt:

  • Unterstützt eine Vielzahl von Programmiersprachen wie TypeScript, Python, Java, C# und Go.
  • Erlaubt, Infrastruktur in einer höheren Abstraktionsebene zu definieren, indem es Konstrukte wie AWS Lambda, Amazon S3, Amazon DynamoDB, Amazon API Gateway und viele andere bereitstellt.
  • Ermöglicht die Erstellung von AWS-Cloudformation-Templates, die automatisch generiert und aktualisiert werden, wenn die Infrastruktur geändert wird.
  • Bietet die Möglichkeit, Stacks zu erstellen und zu verwalten, die eine Zusammenfassung von AWS-Ressourcen darstellen, die zu einem bestimmten Zweck zusammengefasst werden.
  • Bietet eine Bibliothek von wiederverwendbaren und anpassbaren Konstrukten, die Entwickler verwenden können, um ihre eigenen Stacks zu erstellen.
  • Ermöglicht es Entwicklern, eine lokale Entwicklungsumgebung zu verwenden, um ihre IaC zu testen, bevor sie sie in die Cloud bereitstellen.
  • Unterstützt die Integration mit CI/CD-Tools, um die Bereitstellung von IaC automatisch zu automatisieren.

Mit diesen Funktionen bietet AWS CDK eine flexible und effektive Möglichkeit für Entwickler, ihre AWS-Infrastruktur zu definieren und bereitzustellen, wodurch die Entwicklung, Test- und Bereitstellungszeit verkürzt und die Verwaltung der Infrastruktur vereinfacht wird.

Hands-On

Ziel: Eine Rest-API soll via API Gateway & Lambda Function etwas in eine DynamoDB schreiben. Serverless Land Pattern: API Gateway REST API to Lambda to DynamoDB IaC Tool: AWS Cloud Development Kit (CDK) Sprache: Golang AWS Services: API Gateway, Lambda, DynamoDB

apigw-lambda-dynamodb-cdk-go

Setup

Zu Beginn installieren wir uns CDK via NPM.

1
2
npm install -g aws-cdk
cdk --version

Anschliessend müssen wir bestimmte CDK Ressourcen deployen, um unseren AWS Account ready für CDK zu machen, diesen Vorgang nennt man Bootstrapping.

1
cdk bootstrap

Laut der AWS-Dokumentation werden nun folgende Ressourcen erstellt:

  • Amazon S3 Bucket
  • AWS KMS Key
  • IAM Rollen
  • Amazon ECR repository
  • SSM Parameter for Versionierung

Ohne das Boostrapping würden wir nicht weiter kommen und folgenden Fehler erhalten:

apigw-lambda-dynamodb-cdk-go-bootstrap.png

Development

An dieser Stelle begegnet uns das erste, grosse Fragezeichen! Nutzt man 1:1 die Quickstart Commands von Serverless Land landet man in einem DotNet-Projekt. Das wollen wir nicht, also von vorne!

Zuerst wollen wir uns das Repository von Serverless Land clonen und uns die Go-Variante anschauen.

1
2
3
git clone https://github.com/aws-samples/serverless-patterns/ 
cd serverless-patterns/apigw-lambda-dynamodb-cdk-go
code .

Sofort sind zwei Ordner ersichtlich, cdk und function welche beide eine main.go beinhalten. Welches ist dann unser Programm? Wieso gibt es zwei main.go Files?

CDK nutzt Programmiersprachen wie GoLang, um die ressourcen via IaC in der Cloud anzulegen. Diese befinden sich immer im CDK Ordner. Instruktionen, wie das CDK Teilprojekt genau deployed wird sowie weitere Konfigurationen finden wir in der Datei cdk/cdk.json.

Local Development

Selbstverständlich könnten wir das function/main.go File einfach starten, leider nimmt dies als Input-Parameter einen Context sowie einen APIGatewayProxyRequest entgegen. Bedauerlicherweise bietet CDK hier keine praktische Lösung an, um diesen Input-Parameter zu generieren. Hier würde sich ein Test-Driven-Development-Ansatz anbieten, um die Funktion zu entwickeln und lokal zu testen.

Deployment

Zuerst müssen wir unsere Go-Funktion bauen, dies geschieht via go build.

1
2
cd function
GOOS=linux go build -o my-func main.go && zip function.zip my-func

Hier ist zu beachten, dass wir Go sagen müssen, dass wir für Linux bauen wollen, da unsere Lambda-Funktion auf Linux läuft. Anschliessend sehen wir das function-zip welches den Code für unsere Lambda-Funktion beinhaltet. Nun können wir das CDK Projekt deployen.

1
2
cd ../cdk
cdk deploy

Im Output bekommen wir direkt die relevante URL unseres API-Gateways mitgeteilt, diese kopieren wir sofort und setzen sie als Umgebungsvariable.

1
export APIGW_REST_ENDPOINT=https://<api-id>.execute-api.<region>.amazonaws.com/prod/

Führen wir cdk deploy nochmals aus, erkennt CDK automatisch, dass keine Changes vorhanden sind, praktisch!

Weitere nützliche Befehle mit CDK sind:

  • cdk diff: Vergleicht den aktuellen Zustand der Infrastruktur mit dem zuvor bereitgestellten Zustand und gibt die Unterschiede aus.
  • cdk synth: Generiert das CloudFormation-Template, das von AWS CDK verwendet wird, um die Infrastruktur bereitzustellen.
  • cdk ls: Listet alle Stacks auf, die in der Anwendung vorhanden sind.
  • cdk init: Erstellt ein neues AWS-CDK-Projekt mit der gewählten Programmiersprache und Vorlage.
  • cdk doctor: Überprüft, ob das AWS CDK-Setup auf dem System ordnungsgemäss funktioniert und gibt Vorschläge zur Fehlerbehebung.

Testing

Via AWS-Console können wir sehen, dass ein API-Gateway, eine Lambda Function und eine DynamoDB Tabelle erstellt wurden.

Zuerst wollen wir beispielhaft zwei Benutzer erstellen:

1
2
3
curl -i -X POST -d '{"email":"tom.trapp@b-nova.com", "username":"ttrapp"}' $APIGW_REST_ENDPOINT

curl -i -X POST -d '{"email":"hello@b-nova.com", "username":"hello"}' $APIGW_REST_ENDPOINT

Erneute Ernüchterung, bei beiden Calls kommt ein 502 internal server error zurück. Was ist passiert? Wie bei CloudWatch sehen wir schnell folgenden Fehler in unserem ServerlessCDK Stack:

1
2
3
4
5
6
7
2023-05-01T15:27:57.236+02:00	START RequestId: e29bb8c1-a4ac-4b75-9776-43608219c867 Version: $LATEST

2023-05-01T15:27:57.236+02:00	fork/exec /var/task/my-func: exec format error: PathError null

2023-05-01T15:27:57.294+02:00	END RequestId: e29bb8c1-a4ac-4b75-9776-43608219c867

2023-05-01T15:27:57.294+02:00	REPORT RequestId: e29bb8c1-a4ac-4b75-9776-43608219c867 Duration: 58.21 ms Billed Duration: 59 ms Memory Size: 128 MB Max Memory Used: 20 MB

Leider hat uns unser Serverless Land Pattern hier erneut in einen Röstigraben manövriert. Wir müssen neben unserem GOOS auch unser GOARCH setzen. Dies ist nötig, da wir auf einer aarch64 Apple M1 Architektur arbeiten. Wir müssen aber die Zielarchitektur auf amd64 setzen, da unsere Lambda-Funktion auf einer Intel-Architektur läuft. Nun nochmals bauen und deployen.

1
2
3
4
$ cd ../function
$ GOOS=linux GOARCH=amd64 go build -o my-func main.go && zip function.zip my-func
$ cd ../cdk
$ cdk deploy

Anschliessend funktionieren auch unsere curl Commands, juhu! 🎉

Nun sehen wir, dass unseren Einträge korrekt in der DynamoDB angelegt worden sind:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ aws dynamodb scan --table-name users-table

---
{
    "Items": [
        {
            "email": {
                "S": "hello@b-nova.com"
            },
            "user_name": {
                "S": "hello"
            }
        },
        {
            "email": {
                "S": "tom.trapp@b-nova.com"
            },
            "user_name": {
                "S": "ttrapp"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2,
    "ConsumedCapacity": null
}
(END)

Und hiermit haben wir unsere erste kleine Serverless Anwendung deployed! Selbstverständlich handelt es sich hier um ein simples Beispiel, wir konnten CDK etwas kennenlernen und haben eine kleine Go-Funktion deployed.

Cleanup

Um alle Ressourcen wieder zu löschen, können wir folgenden Befehl ausführen:

1
$ cdk destroy

TLDR

Nach SAM ist CDK mit über 210 Patterns das am zweithäufigsten verwendete IaC-Tool auf Serverless Land.

Vorteile

  • Es muss keine neue Sprache gelernt werden, Infrastrukturkomponenten werden einfach via z.B. Golang angelegt
  • Klare Projektstruktur
  • Hohe Customizability, da man in Go theoretisch alles entwickeln kann
  • Unterstützt verschiedene Programmiersprachen
  • Bietet eine objektorientierte API zum Definieren von Infrastruktur
  • Integriert sich nahtlos in andere AWS-Services

Nachteil

  • Kein deklarativer Ansatz, sondern imperative Programmierung
  • Veraltete Dependencies, GoLang Version, nochmals eine go.mod in eigener Verantwortung
  • Serverless Land Pattern outdated und so nicht mehr 1:1 nutzbar
  • Lokal nicht testbar

Nachdem wir nun das erste IaC Tool in unserer Serverless-Reihe kennengelernt haben, schauen wir im nächsten Blogpost der Serie das AWS Serverless Application Model (SAM) an. Stay Tuned! 🚀

Tom Trapp

Tom Trapp – Problemlöser, Innovator, Sportler. Am liebsten feilt Tom den ganzen Tag an der moderner Software und legt viel Wert auf objektiv sauberen, leanen Code.