AWS lokal entwickeln mit Serverless Framework Offline Plugins

Keine Kommentare

Wer mit dem Serverless Framework auf AWS entwickelt, kann dies mit ein wenig Aufwand auch lokal auf dem eigenen Rechner tun. Hierfür gibt es eine Vielzahl verfügbarer Plugins, um Services wie z. B. Lambdas, DynamoDB oder S3 lokal zu nutzen. Wie ihr damit einsteigen könnt, zeige ich in diesem Artikel über Serverless Framework Offline Plugins.

Ich beschränke mich in diesem Beispiel darauf, einen AWS Stack basierend auf Node.js, API Gateway, Lambdas und einer DynamoDB lokal aufzusetzen und zu starten. Das Beispiel ist auf das Wesentliche reduziert und ich werde nur auf die relevanten Stellen der Offline-Plugins eingehen.

Wozu Offline-Plugins?

Es gibt sehr viele gute Gründe, cloudbasierte Services einzusetzen. Unser Blog ist voll von tollen Beispielen dafür, was sich da so tun lässt. Ein paar Beispiele wären:

Für Entwickler entstehen allerdings auch Hürden, die in klassischen Ansätzen weniger ausgeprägt waren. Wenn Entwicklungs-Umgebungen nur noch beim Cloud-Provider liegen, dauert es meist erheblich länger und ist mit deutlich mehr Aufwand verbunden, bis eine Änderung am Quellcode tatsächlich sichtbar wird.

Wenn ihr auf dem Serverless Framework unterwegs seid, könnt ihr die vielen verfügbaren Offline-Plugins nutzen, um euer Projekt lokal auf dem eigenen Rechner laufen lassen. Die Idee ist: Der gleiche Code, der lokal läuft, läuft auch in der Cloud.

Voraussetzungen

Ihr solltet zumindest Grundkenntnisse mit dem Serverless Framework mitbringen und dieses auch installiert haben. Ihr könnt leicht prüfen, ob dies der Fall ist, indem ihr

$ serverless --version

ausführt und schaut, ob es eine gültige Version zurückliefert.

Darüber hinaus solltet ihr Node.js installiert haben und auch rudimentär verstehen.

Falls ihr euch dafür interessiert, Node.js Webanwendungen mit Express zu entwickeln, ist vielleicht der Artikel Rezepte für Webanwendungen mit Node.js, Express.js und TypeScript interessant für euch!

Vorbereitung

Wenn ihr das Projekt nachvollziehen möchtet, klont es zunächst aus diesem Repository. Wir benötigen außerdem einige Plugins. Die Statements:

$ npm install aws-sdk
$ npm install express
$ npm install serverless-http
$ npm install serverless-dynamodb-local
$ npm install serverless-offline
$ sls dynamodb install

installieren alle erforderlichen Plugins. serverless-dynamodb-local und serverless-offline sind die Kandidaten, die uns die lokale Nutzung ermöglichen.

Plugins konfigurieren

Wenn ihr die Plugins installiert habt, müssen sie nun im serverless Projekt eingebunden werden. Dies geschieht im plugins-Block

plugins:
  - serverless-dynamodb-local
  - serverless-offline  # should be last in list

der serverless.yml-Datei. Hierdurch werden die Plugins unserem Projekt bekannt gemacht. Darüber hinaus benötigen wir ein wenig Konfiguration, die wir der custom-Sektion hinzufügen:

tableNames:
  persons: 'cc-persons'
    
dynamodb:
  start:
    migrate: true
  stages:
    - dev

tableNames definiert den Namen der DynamoDB-Tabelle, damit er an anderer Stelle wiederverwendet werden kann. migrate sorgt dafür, dass die benötigten DynamoDB-Tabellen direkt beim Start angelegt werden.

In Projekten, die keine lokalen Plugins verwenden, kümmert sich das AWS SDK automatisch um die AWS-Konfiguration. Für local Plugins gilt das nur eingeschränkt: Wir müssen dem SDK später den DynamoDB-Endpunkt mitteilen. Deswegen konfigurieren wir diesen über

custom:
  endpoints:
    dynamodb-url: 'http://localhost:8000'

vorab und machen die benötigten Werte via

provider:
  environment:
    CONFIG_PERSONS_TABLE: ${self:custom.tableNames.persons}
    CONFIG_DYNAMODB_ENDPOINT: ${self:custom.endpoints.dynamodb-url}

für die spätere Nutzung als Umgebungsvariablen bekannt. Zum Schluss müssen wir noch eine DynamoDB-Tabelle erzeugen. Hierzu fügen wir eine Ressource hinzu, die in der Datei resources/persons-table.yml beschrieben wird, und binden diese über

resources:
  - ${file(resources/persons-table.yml)}

in den resources-Block der serverless.yml-Datei ein.

Einbinden von DynamoDB im Node.js Lambda

Das Serverless Framework wird sich darum kümmern, die Tabelle anzulegen. Den Zugriff auf die Tabelle implementieren wir jedoch selbst in den Node.js Lambdas.
Hierzu beinhaltet das Projekt bereits zwei einfache Services, die in der serverless.yml im functions Block definiert sind:

  • GET auf /persons
  • POST auf /persons

Die Implementierung hierzu liegt unter handler/persons.js. Sie verwendet das Express Framework, die Details sind für uns aber nicht relevant.

Alle Aufrufe gegen die DynamoDB aus unseren Lambdas heraus werden durch das AWS SDK gekapselt. Allerdings weiß dieses noch nichts von unserer lokalen DynamoDB, und würde sich direkt gegen AWS verbinden. Wir müssen dem AWS SDK daher zunächst den zu nutzenden DynamoDB-Endpunkt mitteilen – zumindest wenn wir uns im Offline-Modus befinden.

Um herauszufinden, ob wir uns im Offline-Modus befinden, stellt das serverless Offline-Plugin eine Umgebungsvariable bereit, die wir abfragen können: IS_OFFLINE. Wir können die Variable nutzen, um eine Weiche zu bauen, die den Endpunkt im lokalen Modus überschreibt.

const CONFIG_PERSONS_TABLE = process.env.CONFIG_PERSONS_TABLE;
const CONFIG_DYNAMODB_ENDPOINT = process.env.CONFIG_DYNAMODB_ENDPOINT;
const IS_OFFLINE = process.env.IS_OFFLINE;
 
let dynamoDb;
if (IS_OFFLINE === 'true') {
  dynamoDb = new AWS.DynamoDB.DocumentClient({
    region: 'localhost',
    endpoint: CONFIG_DYNAMODB_ENDPOINT,
  });
} else {
  dynamoDb = new AWS.DynamoDB.DocumentClient();
}

Über diesen Mechanismus wird im lokalen Modus ein anderer Endpunkt verwendet, als im normalen Modus, nämlich den, den wir in der serverless.yml als Umgebungsvariable CONFIG_DYNAMODB_ENDPOINT definiert haben.

Funktionstest

Alles andere an Quellcode in diesem Projekt unterscheidet sich nicht von der Entwicklung ohne Offline-Plugins, daher ist er an dieser Stelle nicht interessant. Wir haben soweit aber bereits alles angepasst und möchten das ganze nun gerne ausprobieren. Mit dem Statement

$ serverless offline start

wird das ganze Projekt lokal gestartet. Ob alles funktioniert, erkennt ihr an der Log-Ausgabe, zum Beispiel

Dynamodb Local Started, Visit: http://localhost:8000/shell
Serverless: DynamoDB - created table cc-persons
Serverless: Starting Offline: dev/eu-central-1.
Serverless: Offline [HTTP] listening on http://localhost:3000

Es wurde also eine lokale DynamoDB gestartet, und die Tabelle cc-persons wurde angelegt. Probieren wir nun aus, ob unsere Services funktionieren, in dem wir die Statements:

$ curl -XPOST localhost:3000/persons
$ curl localhost:3000/persons

nacheinander ausführen. Dies sollte eine neue Person anlegen und diese dann ausgeben.

Mehr Möglichkeiten

Für das serverless Framework gibt es eine große Zahl weiterer Offline-Plugins, ich habe zum Beispiel serverless-offline-ssm und serverless-s3-local erfolgreich im Einsatz. Die Nutzung von Serverless Offline-Plugins ermöglicht es Entwicklern, einen kompletten AWS Stack lokal und isoliert zu entwickeln, ohne jederzeit die Cloud-Infrastruktur verfügbar zu haben. Hierdurch reduziert sich die Dauer der Entwicklungs-Zyklen, da Änderungen ohne Deployment direkt sichtbar werden.

Fragen, Wünsche, Anregungen? Lasst einfach einen Kommentar hier und ich sehe was ich tun kann 🙂

Tobias Schaber

Neben seinem Schwerpunkt „Verteilte Systeme“ beschäftigt sich Tobias mit der Automatisierung von Infrastruktur und komplexen Systemen wie z.B. Elasticsearch-Clustern. Mit ihm im Team ist außerdem immer ein leidenschaftlicher Verfechter agiler Softwareentwicklung zur Stelle, der gerne mal ein flammendes Plädoyer für agile Methoden hält.

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.