Deployments mit serverless.com, AWS CDK oder AWS SAM?

Damit Infrastruktur sinnvoll verwaltet werden kann und zuverlässig reproduzierbar bleibt, empfehlen wir immer den Einsatz von Infrastructure as Code. Für Infrastruktur mit AWS gibt es hierzu einige Tools zur Auswahl: Das serverless.com Framework, das AWS Cloud Development Kit oder das AWS Serverless Application Model.

Neben diesen drei gibt es natürlich noch eine Vielzahl an Alternativen. In unserer täglichen Arbeit haben sich die genannten als zuverlässige Werkzeuge erwiesen, daher möchten wir den jeweiligen Einsatz an Hand einer kleiner Infrastruktur vorstellen.

Infrastruktur

Als Basis für die Infrastruktur dient eine AWS Lambda Funktion und eine Amazon DynamoDB Tabelle. Die Lambda Funktion soll Zugriff auf die DynamoDB Tabelle erhalten und Einträge auslesen können. Der rudimentäre Quellcode der Lambda Funktion sieht wie folgt aus und ist als ./src/handler.js im Projektordner gespeichert:

// ./src/handler.js

const AWS = require("aws-sdk");
const client = new AWS.DynamoDB({ apiVersion: "2012-08-10" });

exports.run = async event => {
  const params = {
    TableName: process.env.TABLE_NAME,
    Key: {
      key: { S: event.key }
    }
  };

  return client.getItem(params).promise();
};

Wer bereits Erfahrung mit dem Einsatz von AWS Lambda und Amazon DynamoDB hat, erkennt dass die DynamoDB Tabelle einen Primärschlüssel mit dem Namen key besitzt und der Name der DynamoDB Tabelle an die AWS Lambda Funktion mittels der Umgebungsvariable TABLE_NAME übergeben wird. Diese grundlegende Architektur ist für alle drei Beispiele identisch.

Es geht in den kommenden Absätzen nun darum wie man die notwendige Infrastruktur mit dem serverless.com Framework, dem AWS Cloud Development Kit und AWS Serverless Application Model abbildet.

Beispiele

Alle Beispiele sind natürlich auf GitHub zu finden und können ausprobiert, heruntergeladen, und weiterverwendet werden.

Nachfolgend werden die interessanten Eigenheiten jeder Implementierung kurz vorgestellt.

serverless.com Framework

Das Framework von serverless.com lässt sich über eine Datei im YAML-Format konfigurieren. Standardmäßig heißt die Datei serverless.yml und liegt direkt im Hauptverzeichnis eines Projekts. Die Konfigurationsdatei beinhaltet einen frei wählbaren Namen für das Projekt und den zu erstellenden CloudFormation Stack, ebenso wie eine Vielzahl an grundlegenden Werten für das Deployment. So nutzen wir natürlich den AWS provider, konfigurieren die AWS Lambda runtime mit node12.x und definieren eine AWS Lambda Funktion ExampleFunction.

Im Abschnitt resources kann die bekannte CloudFormation Funktionalität genutzt werden um weitere Bauteile der Infrastruktur in AWS zu konfiguriere. Die benötigte DynamoDB Tabelle wird hier als ExampleTable angelegt:

# ./serverless.yaml

service:
  name: iac-example-serverless

provider:
  name: aws
  runtime: nodejs12.x
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:GetItem
      Resource: !GetAtt ExampleTable.Arn

functions:
  ExampleFunction:
    handler: src/handler.run
    environment:
      TABLE_NAME: !Ref ExampleTable

resources:
  Resources:
    ExampleTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: key
            AttributeType: S
        KeySchema:
          - AttributeName: key
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1

Die interessanten und wichtigen Verknüpfungen der beiden AWS Ressourcen geschehen bei der Definition der Umgebungsvariablen für die AWS Lambda Funktion und bei der Konfiguration der erlaubten Zugriffsrechte, der sogenannten IAM Role:

# Referenz auf die DynamoDB Tabelle für die AWS Lambda Umgebungsvariable

environment:
  TABLE_NAME: !Ref ExampleTable
# Referenz auf die DynamoDB Tabelle für die AWS Lambda Zugriffsrechte

iamRoleStatements:
  - Effect: Allow
    Action:
      - dynamodb:GetItem
    Resource: !GetAtt ExampleTable.Arn

Diese einfache Konfiguration der Infrastruktur kann nun mit dem Kommandozeilenprogramm des serverless.com Frameworks deployt werden:

$ > serverless deploy

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service iac-example-serverless.zip file to S3 (87.06 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
Serverless: Stack update finished...

In der AWS Management Console existiert nun eine neue AWS Lambda Funktion, eine DynamoDB Tabelle und der konfigurierte Lesezugriff der AWS Lambda Funktion auf die DynamoDB Tabelle. Zum sauberen Entfernen aller Bestandteile kann der Befehl serverless remove genutzt werden. Da alle AWS Ressourcen innerhalb eines CloudFormation Stacks erstellt wurden, lassen sie sich durch das einfache Löschen des CloudFormation Stacks wieder entfernen. Das Kommandozeilenprogramm macht mit dem genannten Befehl genau dies.

AWS Serverless Application Model

Das Serverless Application Model (kurz: AWS SAM) ist eine von AWS angebotene Erweiterung für CloudFormation inklusive einem zusätzlichen Kommandozeilenprogramms für die typischen Arbeitsschritte. Mit AWS CloudFormation kann nahezu jegliche AWS Infrastruktur mit einer Konfigurationsdatei im YAML- oder JSON-Format beschrieben und erstellt werden.

Für das vorhandene Beispiel, bestehend aus einer AWS Lambda Funktion und einer DynamoDB Tabelle, sieht eine YAML-Datei mit dem AWS Serverless Application Model wie folgt aus:

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Resources:
  ExampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handler.run
      Runtime: nodejs12.x
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Ref ExampleTable
      Environment:
        Variables:
          TABLE_NAME: !Ref ExampleTable

  ExampleTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: key
        Type: String

Neben dem speziellen CloudFormation Typ AWS::Serverless::Function für das Anlegen einer AWS Lambda Funktion bietet das AWS Serverless Application Model mit AWS::Serverless::SimpleTable ebenfalls eine vereinfachte Variante zum Anlegen einer DynamoDB Tabelle mit CloudFormation an.

Identisch zum Einsatz des serverless.com Frameworks kann einfach eine Referenz auf den Namen der DynamoDB Tabelle als Umgebungsvariable an die Lambda Funktion übergeben werden:

# Referenz auf die DynamoDB Tabelle für die AWS Lambda Umgebungsvariable

Environment:
  Variables:
    TABLE_NAME: !Ref ExampleTable

Damit die Verwaltung von Zugriffsrechten möglichst einfach abgebildet werden kann, bietet das AWS Serverless Application Model sogenannte Policy Templates mit den gängigsten Einsatzzwecken. Damit die AWS Lambda Funktion auf die DynamoDB Tabelle zugreifen darf, enthält DynamoDBReadPolicy die notwendige Konfiguration.

# Referenz auf die DynamoDB Tabelle für die AWS Lambda Zugriffsrechte

Policies:
  - DynamoDBReadPolicy:
      TableName: !Ref ExampleTable

Die Konfiguration wird als template.yml im Hauptverzeichnis des Projekts abgelegt und kann danach mit dem Kommandozeilenprogramm des AWS Serverless Application Model deployt werden:

# Deployment mit AWS Serverless Application Model

$ > sam deploy --guided

Initiating deployment
=====================
Uploading to iac-example-sam/193ed86290516b0d78a51d78b286b401  23105227 / 23105227.0  (100.00%)
Uploading to iac-example-sam/ab516db1052bf0b95fb4a6653874e5d5.template  745 / 745.0  (100.00%)

Successfully created/updated stack - iac-example-sam in us-east-1

Anders als das serverless.com Framework bietet das Kommandozeilenprogramm des AWS Serverless Application Model jedoch keinen Befehl um die Infrastruktur aus dem AWS Account wieder zu entfernen. Dies muss über die AWS Management Console geschehen; da aber alle Bestandteile in einem CloudFormation Stack angelegt werden, können sie durch das Entfernen des CloudFormation Stacks gelöscht werden. Neben dem Löschen über die Management Console kann ein CloudFormation Stack natürlich auch über das AWS Kommandozeilprogramm mit dem Befehl aws cloudformation delete-stack gelöscht werden.

AWS Cloud Development Kit

Das AWS Cloud Development Kit ist die jüngste Variante von AWS um die Konfiguration von Infrastruktur einfach zu gestalten. Anders als mit dem serverless.com Framework und AWS Serverless Application Model wird mit dem AWS Cloud Development Kit die Infrastruktur nicht beschreiben, sondern programmiert. Aktuell wird das AWS CDK in den Sprachen TypeScript, JavaScript, Python, Java, und C#/.Net angeboten.

Da die anfangs beschriebene AWS Lambda Funktion in Node.js bzw. JavaScript erstellt wurde, bietet sich für dieses Beispiel auch die Verwendung des AWS CDK in JavaScript bzw. TypeScript an:

// ./infrastructure.ts

import * as Lambda from "@aws-cdk/aws-lambda";
import * as DynamoDB from "@aws-cdk/aws-dynamodb";
import * as cdk from "@aws-cdk/core";

import * as path from "path";

class ExampleStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const exampleTable = new DynamoDB.Table(this, "ExampleTable", {
      partitionKey: { name: "key", type: DynamoDB.AttributeType.STRING }
    });

    const exampleFunction = new Lambda.Function(this, "ExampleFunction", {
      runtime: Lambda.Runtime.NODEJS_12_X,
      code: Lambda.Code.fromAsset(path.resolve(__dirname, "src")),
      handler: "handler.run",
      environment: {
        TABLE_NAME: exampleTable.tableName
      }
    });

    exampleTable.grantReadData(exampleFunction);
  }
}

const app = new cdk.App();
new ExampleStack(app, "ExampleStack", { env: { region: "us-east-1" } });

app.synth();

Damit dem AWS Cloud Development Kit alle notwendigen Abhängigkeiten zur Verfügung stehen um den CloudFormation Stack zu erstellen, muss einmalig für die Verwendung des CDK ein bootstrap Befehl für die jeweilige AWS Region ausgeführt werden:

# Das AWS CDK für die Region us-east-1 konfigurieren

$ > cdk bootstrap --region us-east-1

Danach kann nun wie gewohnt ein Kommandozeilenbefehl genutzt werden um das Deployment der Infrastruktur in AWS zu starten.

# Deployment mit AWS Cloud Development Kit

$ > cdk deploy

ExampleStack: deploying...
Updated: asset.3e5f73c2beb802451ef3bd69a62d0982189da43d8f8537d07ae0cfc20071e44e (zip)

✅  ExampleStack

Stack ARN: arn:aws:cloudformation:us-east-1:420048798477:stack/ExampleStack/b69c1d60-435f-11ea-8522-0a200f00c284

✨  Done in 137.97s.

Wie auch bei dem serverless.com Framework kann mit dem AWS CDK eine erstellte Infrastruktur einfach mittels dem Kommandozeilenprogramm wieder entfernt werden. Ein cdk delete entfernt alle angelegten Bausteine aus AWS wieder rückstandslos.

Fazit

Es gibt bei der Auswahl des Werkzeugs für die Verwaltung von Infrastruktur auf AWS kein richtig oder falsch. Der Einsatz des serverless.com Frameworks klingt für viele Kunden interessant, da man die Basisfunktionalität mit Plugins erweitern kann und neben AWS auch andere Cloud-Anbieter unterstützt werden. Das Framework wird jedoch von einem Drittanbieter gepflegt, dies kann Vor- und Nachteile bringen.

Sowohl das Cloud Development Kit wie auch das Serverless Application Model stammen direkt von AWS. Eine dauerhafte Weiterentwicklung, Support und auch Kompatibilität sind somit gewährleistet. Der Einsatz von AWS-eigenen Werkzeugen kann sich lohnen um einen tieferen Einblick in die Konfiguration und Verzahnung der Komponenten bei AWS zu erlangen. Ebenfalls wird kein Aufwand betrieben um zusätzlich zur Expertise bzgl. AWS auch noch ein Werkzeug eines Drittanbieters erlernen zu müssen.

Sebastian ist Senior Cloud Consultant bei superluminar GmbH, AWS Serverless Hero und AWS Certified Solutions Architect. Er schreibt hier auf Deutsch über AWS, Serverless, Software Entwicklung, Go, TypeScript und React. Englische Artikel sind auf seiner Webseite sbstjn.com oder auf Twitter unter @sbstjn zu finden.