Kontakt: +49 511 59095 – 942

Das Gleiche für alle: Lambda Funktion und Ressourcen mit der gleichen Sprache im CDK

Thumbnail

Das AWS CDK, Cloud Development Kit wurde auf der reInvent 2018 vorgestellt und soll die codebasierte Entwicklung von AWS Ressourcen vereinfachen. Infrastructure as Code zu Ende gedacht.

Nun gibt es ja schon einige andere Frameworks, wie z.B. in tRick hier beschrieben. Die Konkurrenz ist also groß! Kann man das neue CDK denn auch für Serverless/Lambda Funktionen verwenden?

Von mir ein großes “Ja”, aber lest selber…

Die Aufgabenstellung

Für eine Lambda Funktion benötigt man neben den Ressourcen auch eine Rolle und einen S3 Bucket, von dem man den Code deployed. Man kann den Funktionscode auch inline übergeben, aber das hat eine 4K Grenze, ist also nur für kleine Code-Schnipsel eine Alternative.

App Architecture

Neben diesen AWS Ressourcen muss man noch aus allen Lambda Quelldateien ein zip bauen, welches dann über den Bucket zu Lambda hochgeladen wird.

CDK Lösung

Das CDK generiert aus TypeScript (oder C#, Java, Python) Code CloudFormation Templates. Details dazu in der CDK Dokumentation.

Lambda Architecture

Dabei sind die Constructs der Apllikation wiederverwendbaren Module. CDK generiert dann ein CloudFormation Template. Auch die Auslieferung der Templates kann das CDK per CLI (Command Line Interface) steuern.

Am besten versteht man das mit einer pracktischen Übung. Dafür haben wir auf github Lambda Simple ein Beispiel zusammengestellt.

Lebenszyklus

Das Beispiel kann man in vier einfachen Schritten durchspielen. Dabei sollte node in der Version 8.10 bereits installiert sein.

  1. Installation und Bootstrap: make install.

    Das aws-cdk wird installiert und das CDK erstellt einen Deploy Bucket

  2. Herunterladen von node Bibliotheken: make init

    Die node_modules werden prall gefüllt.

  3. Installation: make deploy

    Mit einem Cloudformation und dem gezippten Inhalt des Unterverzeichnisses lambda werden die Ressourcen und die Lambda Funktion gebaut. Jetzt kann man die Funktion bereits verwenden

  4. Löschen: make remove

    Mit cdk destroy werden alle Ressourcen wieder abgebaut.

CDK Code

Struktur

Auf den ersten Blick verwirren diese vielen Dateien vielleicht. Es steckt aber eine ganz eifache Struktur dahinter:

CDK Struktur

Im cdk.json wird die Applikation definiert. In diesem einfachen Fall ist nur ein Verweis auf die Basis Applikation cdk-lambda-simple.ts enthalten. Der Code ist in *.ts typscript geschrieben. Startet man npm run watch in einem extra Fenster, so werden die ts Dateien kontinuierlich nach *.js, den eigentlichen JavaScript Dateien und den *.d.ts den Typinformationen für Typescript übersetzt.

Für das Verständnis kann man also die *.js und *.d.ts ignorieren.

Die Applikation cdk-lambda-simple.ts importiert hier nur den eigentlichen Stack cdk-lambda-simple-stack.ts.

Ressourcedefinition

 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
export class CdkLambdaSimpleStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string) {
    super(scope, id);

    // The code that defines your stack goes here
    new lambda.Function(this, 'HelloHandler', {
      code: lambda.Code.asset(path.join(__dirname,  '../lambda')),
      handler: 'hello.handler',
      runtime: lambda.Runtime.NodeJS810,
      memorySize: 1024
    });
  }
}

Die eigentliche Definition beschränkt sich nun auf wenige Zeilen. Und wie beim Serverless Framework wird die Rolle automatisch miterzeugt.

Der Entwicklungszyklus im Einzelnen

Was wird erzeugt

Nach den Basisinstallationen wird zuerst ein Diff mit dem cdk erzeugt: cdk diff

Stack CdkLambdaSimpleStack
The CdkLambdaSimpleStack stack uses assets, which are currently not accounted for in the diff output! See https://github.com/awslabs/aws-cdk/issues/395
IAM Statement Changes
┌───┬─────────────────────────────────┬────────┬────────────────┬──────────────────────────────────┬───────────┐
│   │ Resource                        │ Effect │ Action         │ Principal                        │ Condition │
├───┼─────────────────────────────────┼────────┼────────────────┼──────────────────────────────────┼───────────┤
│ + │ ${HelloHandler/ServiceRole.Arn} │ Allow  │ sts:AssumeRole │ Service:lambda.${AWS::URLSuffix} │           │
└───┴─────────────────────────────────┴────────┴────────────────┴──────────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                    │ Managed Policy ARN                                                             │
├───┼─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${HelloHandler/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See http://bit.ly/cdk-2EhF7Np)

Parameters
[+] Parameter HelloHandler/Code/S3Bucket HelloHandlerCodeS3Bucket4359A483: {"Type":"String","Description":"S3 bucket for asset \"CdkLambdaSimpleStack/HelloHandler/Code\""}
[+] Parameter HelloHandler/Code/S3VersionKey HelloHandlerCodeS3VersionKey07D12610: {"Type":"String","Description":"S3 key for asset version \"CdkLambdaSimpleStack/HelloHandler/Code\""}
[+] Parameter HelloHandler/Code/ArtifactHash HelloHandlerCodeArtifactHash5DF4E4B6: {"Type":"String","Description":"Artifact hash for asset \"CdkLambdaSimpleStack/HelloHandler/Code\""}

Resources
[+] AWS::IAM::Role HelloHandler/ServiceRole HelloHandlerServiceRole11EF7C63
[+] AWS::Lambda::Function HelloHandler HelloHandler2E4FBA4D

Deploy

Mit cdk deploy wird das Cloudformation erzeugt und der Lambda Code erzeugt.

Update

Wird jetzt entweder der Lambda Funktionscode oder der Stack geändert, prüft man mit cdk diff die Änderungen und Deployed mit cdk deploy.

Änderungen im Lamda Code werden als Asset Änderungen angezeigt:

cdk diff
Stack CdkLambdaSimpleStack
The CdkLambdaSimpleStack stack uses assets, which are currently not accounted for in the diff output! See https://github.com/awslabs/aws-cdk/issues/395
Resources
[~] AWS::Lambda::Function HelloHandler HelloHandler2E4FBA4D
 └─ [~] Metadata
     └─ [~] .aws:asset:path:
         ├─ [-] .cdk.staging/2b8228f7e33311acbcda8a46395ec767
         └─ [+] .cdk.staging/8fcab5493d6556b26fc8a85910c67f6a

Achtung

Das CDK ist zwar noch im Beta Status, aber auch im jetzigem Zustand sehr nützlich und auch stabil. Man darf auch keinen Fall Versionen mixen, daher ist es wichtig im package.json gleiche Versionen des CDKs und der Packages zu haben, hier 0.32:

"dependencies": {
    "@aws-cdk/aws-lambda": "^0.32.0",
    "@aws-cdk/cdk": "^0.32.0",
    "install": "^0.12.2",
    "npm": "^6.9.0",
    "path": "^0.12.7",
    "source-map-support": "^0.5.9"
  }

Zusammenfassung

Terraform und das Serverless Framework sind für Multi-Cloud Projekte geeignet. Fokusiert sich das Projekt auf AWS, so macht auf mich auch schon die Version 0.32 einen sehr guten Eindruck.

Viele CloudFormation Ressourcen sind sinnvoll im CDK zusammengefasst. Anders als beim serverless Framework hat man direkten Zugriff auf die Ressourcen Objekte im Code. So lassen sich Referenzen sehr einfach gestalten.

Code auf Github

Lambda Simple

Photo by Søren Astrup Jørgensen on Unsplash

Übersetzungen