Sharing is caring: Lambda Layers mit Serverless und Node.js

Keine Kommentare

AWS Lambda ist der Serverless Computation Service von AWS. Dieser ermöglicht es, Code Event-getrieben auszuführen. Für jede Funktionalität muss dafür eine Lambda-Funktion mit einem Code-Segment definiert werden, welche durch Events ausgeführt werden kann. Beim Aufbau einer Serverless-Anwendungen auf der Basis von AWS ist es meist nötig, sehr viele Lambda-Funktionen zu definieren. Dabei ist es nicht unwahrscheinlich, dass sich benötigte Code-Teile – z. B. Libraries, CRUD-Operationen oder Business-Logik – wiederholen.

AWS Lambda functions with duplicated code

Mittels Lamdba Layers lassen sich diese Code-Teile auslagern und in verschiedenen Lambda-Funktionen verwenden.
AWS Lambda functions with layers

Dies reduziert die Komplexität der jeweiligen Funktionen und führt zu eine besseren Wartbarkeit des gesamten Codes. So können z. B. Layers und Funktionen unabhängig entwickelt und getestet werden.

Layers in Aktion

Es existieren viele verschiedene Möglichkeiten, um AWS Lambda + Layers zu verwenden. Ich habe mich für das Serverless Framework mit Node.js entschieden. Lösungen mit anderen Programmiersprachen wie Python oder Frameworks wie SAM funktionieren jedoch ähnlich. Im Folgenden werden wir zwei Layers erstellen. Ein Dependencies Layer mit der Library Moment.js und ein Business Layer, welches auch als Lib in das Layer eingebunden wird. Diese beiden Layers werden dann von einer Lambda-Funktion eingebunden und verwendet. Der Code ist hier zu finden.

AWS Lambda functions with layers example

Initialisierung

Wenn du nicht mit dem Serverless Framework vertraut bist, existiert hier eine Anleitung um die cli aufzusetzen, die wir im Folgenden verwenden.
Zunächst setzten wir ein neues Serverless-Projekt mit folgendem Befehl auf:

serverless create --template aws-nodejs --path lambda-layer-functions

Dies erzeugt einen neuen Ordner mit den Dateien handler.js und serverless.yml. Die handler.js enthält unsere spätere Lambda-Funktion. Die serverless.yml beschreibt unseren Cloudformation Stack. Wir könnten in dieser serverless.yml unsere Layers registrieren. Dies würde jedoch bei jedem Deployen der Funktion zu einer neuen Version der Layer führen. Deshalb legen wir, parallel zum Functions-Projekt, für unsere Layer ein separates Serverless-Projekt mit folgenden Befehl an:

serverless create --template aws-nodejs --path lambda-layers

Aus dem nun erstellten Ordner können wir die handler.js und die Funktion aus der serverless.yml entfernen, da wir in dem Layer-Projekt keine Funktionen erstellen werden.

Erstellen des Dependency Layers

Nun erstellen wir das Dependency Layer mit der Bibliothek Moment. Dafür erstellen wir eine package.json unter lambda-layers/dependencieslayer/nodejs, indem wir im Ordner

npm init

ausführen. Dabei setzen wir den Namen auf „dependencies-layer“ und nutzen sonst den default-Wert. Mittels

npm install --save moment

im Ordner lambda-layers/dependencieslayer/nodejs fügen wir die Bibliothek „moment“ hinzu und laden die Abhängigkeiten herunter. Nun haben wir unseren Code für das Dependency Layer.

Dependency Layer registrieren

Nun registrieren wir das Dependency Layer in der lambda-layers/serverless.yml, indem wir folgenden Zeilen hinzufügen:

layers:
   dependencies:
    path: dependencieslayer
    name: ${self:provider.stage}-dependencies-layer # optional
    description: Description of what the lambda layer does # optional
    compatibleRuntimes: # optional
      - nodejs
    allowedAccounts:
      - '*' # all accounts or specify your account!

Erstellen des Business Layers

Jetzt brauchen wir unseren Business-Code, den wir teilen wollen. Wir erstellen dafür an einem beliebigen anderen Ordner eine index.js mit:

const theAnswerToLifeTheUniverseAndEverything = () => 42;
 
module.exports = {
    theAnswerToLifeTheUniverseAndEverything
};

und fügen eine package.json mittels

npm init

mit dem Namen „business-code“ hinzu. Jetzt wiederholen wir die Schritte, die wir für das Dependency Layers ausgeführt haben.

  • Erstellen einer package.json unter lambda-layers/businesslayer/nodejs mit
    npm init

    und setzen den Namen auf „business-layer“.

  • Installieren der Dependencies.
    Eigentlich sollte man den Business-Code in sein npm repository deployen und im Business Layer verwenden. Wir werden jedoch für das Tutorial den festen Pfad eintragen, um kein Repository zu benötigen. Deshalb installieren wir die Dependencies, indem wir im Ordner

    npm install file:../../../businesscode

    ausführen.

  • Wir fügen unser Layer zur Layers lambda-layers/serverless.yml hinzu.
layers:
  business:
    path: businesslayer
    name: ${self:provider.stage}-business-layer # optional
    description: Description of what the lambda layer does # optional
    compatibleRuntimes: # optional
      - nodejs
    allowedAccounts:
      - '*' # all accounts or specify your account!

Deploy Layers

Wenn wir nun „sls deploy“ im Layers-Ordner ausführen, werden unsere Layer nach AWS deployed. Die Ausgabe sollte wie folgt aussehen:

AWS Lambda serverless deploy output

Unter Layers sehen wir die Amazon-Ressourcennamen (ARN) der erstellten Layers. Dieser benötigen wir später, um sie in unsere Funktion zu verwenden. Um einen Überblick über die vorliegenden Layers zu erhalten, kannst du diese in der AWS-Konsole unter Lambda > Layers ansehen. Dabei solltest du sicherstellen, dass du die richtige Region ausgewählt hast. In der Konsole solltest du nun etwa folgendes sehen:

AWS Console Lambda layers

Layers zur Funktion hinzufügen

Nun müssen wir die Layer noch in unser Funktion serverless.yml verwenden. Dafür fügen wir die ARN der Layer zu der Funktion wie im folgenden zu sehen hinzu.

functions:
  hello:
    handler: src/app/handler.hello
    layers: # layer refs
      - ... arn...

Wenn wir nun sls deploy für die Funktion ausführen und uns die Konsole ansehen, sollten wir schon sehen, dass die Layer der Funktion hinzugefügt wurden.

AWS Console Lambda function with layers

Layers verwenden

Die Verwendung der Layers ist nun so einfach wie die Verwendung einer Library. Wir können in unserer handler.js wie folgt die Libraries importieren und dann verwenden.

const moment = require('moment');
const {theAnswerToLifeTheUniverseAndEverything} = require('business-code');

Limits

Bei der Verwendung von Layers existieren momentan ein paar harte Limits, die hier zu finden sind. So ist die maximale Anzahl von Layers pro Funktion auf fünf und die Größe von Layers + Funktion package auf 250 MB begrenzt. Deshalb sollten die Schnitte, die man für seine Layers wählt, sinnvoll gewählt werden.

Zusammenfassung

Layers sind eine praktische Möglichkeit, um Code zwischen Lambda-Funktionen zu teilen. Sie helfen dabei, die Wartbarkeit des AWS-Lambda-Codes zu erhöhen, da durch die Auslagerung des Codes dieser separat getestet und erweitert werden kann. Somit erhält man kleine austauschbare Funktionen.

Fabian Schmauder

Fabian Schmauder arbeitet seit April 2017 als Software Engineer bei der codecentric AG. Er legt immer Wert auf clean code, Testing und neue Technologien.

Kommentieren

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