Der Code im Nichts?

Die Serverless Cloud – eine Einführung: AWS Lambda und das Serverless Framework

Bart Blommaerts

© Shutterstock / VS148

„Serverless – der Code im Nichts?“ – so lautet das Titelthema des neuen Java-Magazins. Auf JAXenter wollen wir den Magazin-Schwerpunkt durch weitere Beiträge begleiten. Den Anfang macht JAX-Speaker Bart Blommaerts (Ordina) mit seiner dreiteiligen Einführungsreihe zum Thema Serverless Cloud.

Was bedeutet Serverless eigentlich?

Nachdem die Cloud-Landschaft einige Jahre lang vom Thema „Microservices“ dominiert wurde, ist heute die sogenannte „Serverless“-Bewegung einer der heißesten Trends der Industrie. Nun waren Software-Entwickler immer schon schlecht darin, Dingen einen Namen zu geben, und „Serverless“ bildet dabei leider keine Ausnahme. Im Gegensatz zu dem, was der Begriff suggeriert, bedeutet Serverless keineswegs die völlige Abwesenheit von Servern. Serverless meint vielmehr, dass Entwickler für das Managen und Provisionieren der Server nicht mehr selbst verantwortlich sein müssen und stattdessen auf Anbieter kommerzieller Cloud-Lösungen zurückgreifen. „Serverless“ spielt also darauf an, dass man sich weniger über Server Gedanken machen muss. Möglicherweise wird es in der Zukunft möglich sein, diese Art von Service auch On Premise zu installieren, z.B. mit der Open-Source-Implementierung IBM OpenWhisk.

So gesehen ergibt die Definition „FaaS: Function as a Service“ wesentlich mehr Sinn. Funktionen sind kurzlebige Teile einer Runtime-Funktionalität, die keinen ständig laufenden Server benötigen. Im Prinzip könnte eine Funktion auch eine längere Ausführungszeit haben, aber die meisten FaaS-Provider begrenzen gegenwärtig die erlaubte Rechenzeit. Wenn eine Anwendung eine Funktion aufruft (z.B. einen zu berechnenden Algorithmus), wird diese Funktion neu instantiiert und nach Abschluss der Berechnung wieder zerstört. Dies führt zu einer kürzeren „Laufzeit“ und somit zu signifikanten finanziellen Einsparungen. (Die Preise des Serverless-Angebots AWS Lamdba kann man beispielsweise hier einsehen).

FaaS-Funktionen passen auch gut zu einem Event-basierten Verhalten: Wenn ein Event gesendet wird, kann eine Funktion spontan gestartet und nur für die benötigte Zeit aufrecht erhalten werden. Eine Serverless-Anwendung kann deshalb auch als eine Komposition von Event-Ketten verstanden werden. Dies macht den Serverless-Stil zu einer interessanten Option für eine API Ökonomie.

Da FaaS-Funktionen Laufzeit-Komponenten sind, sind sie „stateless“ und zur Speicherung von Zuständen auf eine Datenbank oder ein Dateiensystem angewiesen. Zustandslosigkeit und Kurzlebigkeit führt zu extrem guten horizontalen Skalierungsmöglichkeiten, was auch von allen wichtigen FaaS-Anbietern unterstützt wird.

NoOps

NoOps (No Operations) ist ein Konzept, demzufolge eine IT-Umgebung so stark automatisiert und von der zugrundeliegenden Infrastruktur abstrahiert wird, dass es keinen Grund mehr für ein spezielles Team gibt, das die Software intern administriert. NoOps ist zwar kein neues Konzept, wie ein Artikel von 2011 zeigt. Doch als die Serverless-Idee populär wurde, verbreiteten einige Leute wieder die Meinung, es gäbe nun keinen Bedarf nach speziellen Operations-Teams mehr.

Da Serverless aber, wie erwähnt, keineswegs impliziert, dass wir gar keine Server mehr brauchen, entfallen offensichtlich auch die Administrationsaufgaben nicht völlig. Was Serverless vielleicht mit sich bringen könnte, ist eine Auslagerung der Administration an ein Team mit spezialisierten Fähigkeiten. Doch wir benötigen auch dann noch Dinge wie Monitoring, Security, Remote Debugging, etc. Ich bin auf jeden Fall gespannt auf die Folgen, die Serverless Programming für gegenwärtige DevOps-Teams mit sich bringen wird. Einen interessanten Artikel über NoOps kann man hier finden.

AWS Lamdba

AWS Lambda war die erste große Plattform, die FaaS-Funktionalitäten anbot. AWS Lambda läuft auf der AWS-Infrastruktur und unterstützt derzeit drei Sprachen: Node.js, Java und Python. AWS Lambda kann sowohl für synchrone als auch für asynchrone Services verwendet werden.

Das Tooling für AWS Lambda ist momentan noch relativ unreif, aber das ändert sich schnell. So bietet die AWS-Lambda-Konsole bereits die Möglichkeit, Lambdas mittels Blueprints zu erstellen. Das ist leichter, als ein Lambda von Hand mit einer ZIP-Datei aufzusetzen. Blueprints sind Beispiel-Konfigurationen von Event-Quellen und Lambda-Funktionen. Zum Zeitpunkt des Schreibens dieses Artikels sind 45 Blueprints verfügbar. Zur Einführung wollen wir uns einmal den „Hello-World“-Blueprint etwas genauer ansehen. Dieser Blueprint erzeugt eine sehr einfache NodeJS-Funktion:

'use strict';
console.log('Loading function');
   
exports.handler = (event, context, callback) => {
   console.log('value1 =', event.key1);
   console.log('value2 =', event.key2);
   console.log('value3 =', event.key3);
   callback(null, event.key1); 
};

Nach der Erstellung dieser Funktion kann sie umgehend mit der Konsole ausprobiert werden, indem ein Test-Event angelegt wird. Wenn wir die Funktion synchron aufrufen wollen, müssen wir einen API-Endpoint mit dem AWS API Gateway erzeugen. Der API Gateway generiert APIs, die sich wie eine „Eingangstür“ für die Funktionen verhalten. Um dies mit den Events in unserem „Hello-World“-Beispiel umzusetzen, müssen wir die Ressourcen unseres APIs auswählen:

Screen-Shot-2016-06-30-at-22.04.24-800x257-768x247

Unter „Integration Request“ fügen wir ein Template des Types application/json hinzu:

{ "key3": "$input.params('key3')","key2": "$input.params('key2')","key1": "$input.params('key1')" }

Unter „Method Request“ geben wir drei URL-String Query-Parameter an: key1, key2 und key3. Wenn wir dann das API neu deployen, erzeugt das Drücken des Test-Buttons ein Eingabefeld, um die drei Query-Parameter hinzuzufügen, und die Funktion wird erfolgreich ausgeführt:

Screen-Shot-2016-08-15-at-3.20.37-PM

Möchte man das direkt im Browser testen, muss Auth in „Method Request“ auf „NONE“ gestellt und das API nochmals deployt werden. Die URL kann im „Stage“-Menü gefunden werden.

Weil dieses Beispiel offensichtlich nicht sonderlich anspruchsvoll war, soll noch ein weiterer Blueprint getestet werden: Microservice-Http-Endpoint. Dieser Blueprint erzeugt ein CRUD-Backend unter Verwendung von DynamoDB mit einem RESTful API-Endpoint. Der Code deckt alle gängigen Use Cases ab:

'use strict';
let doc = require('dynamodb-doc');
let dynamo = new doc.DynamoDB();
exports.handler = (event, context, callback) => {
   const operation = event.operation;
   if (event.tableName) {
      event.payload.TableName = event.tableName;
   }
   switch (operation) {
   case 'create':
      dynamo.putItem(event.payload, callback);
      break;
   case 'read':
      dynamo.getItem(event.payload, callback);
      break;
   case 'update':
      dynamo.updateItem(event.payload, callback);
      break;
   case 'delete':
      dynamo.deleteItem(event.payload, callback);
      break;
   case 'list':
      dynamo.scan(event.payload, callback);
      break;
   case 'echo':
      callback(null, event.payload);
      break;
   case 'ping':
      callback(null, 'pong');
      break;
   default:
      callback(new Error(`Unrecognized operation "${operation}"`));
   }
};

Man braucht dabei natürlich noch eine DynamoDB-Instanz mit einigen Daten:

Screen-Shot-2016-07-03-at-17.04.31-800x185-768x178

Die neue Tabelle lässt sich im Lambda mit folgendem Event ansprechen:

{
"tableName": "garage-car-dev",
"operation": "list",
"payload": { }
}

Als einzige schwierige Aufgabe bleibt herauszufinden, welchen Payload die verschiedenen Operationen haben. Wir können nun neue Einträge erstellen:

{
"operation": "create",
"tableName": "garage-car-dev",
"payload": {
   "Item": {
      "id": "1980b61a-f5d7-46e8-b62a-0bbb91e20706",
      "body": "Lamborghini",
      "updatedAt": "1467559284484"
      }
   }
}

Der Blueprint erzeugt auch ein API im API Gateway, das wir mit den obigen Events als Template unter „Integration Request“ aufrufen können, genau wie im ersten Beispiel gezeigt.

DevOps Docker Camp 2017

Das neue DevOps Docker Camp – mit Erkan Yanar

Lernen Sie die Konzepte von Docker und die darauf aufbauende Infrastrukturen umfassend kennen. Bauen Sie Schritt für Schritt eine eigene Infrastruktur für und mit Docker auf!

Das Serverless-Framework

Während der obere Ansatz zwar wie erwartet funktioniert, ist es doch ziemlich aufwändig, die erste eigene Funktion zum Laufen zu bringen, vor allem wenn man bedenkt, dass noch kein richtiger Code in den Beispielen enthalten war. Glücklicherweise gibt es das Serverless Framework (ehemals JAWS), um uns das Leben leichter zu machen. Momentan unterstützt das Serverless Framework nur AWS Lambda, doch Support für andere FaaS-Provider ist auf dem Weg. Ein Pull-Request für Microsoft Azure gibt es bereits, weitere Provider arbeiten an einer Implementierung. Eine anbieterunabhängige FaaS wäre tatsächlich ein Gamechanger!

Ein Problem mit FaaS ist die (so gegebene) Fehlpaarung von Laufzeit-Einheiten und Deploy-Einheiten – dasselbe gilt aber auch für andere Architektur-Muster. Es sollte zwar möglich sein, jeweils nur eine einzelne, spezifische Funktion zu deployen, doch oft sind mehrere Funktionen als Gruppe zusammengefasst. Ich bevorzuge es, eine Anzahl von Funktionen in einem Zug zu deployen, wenn es sinnvoll ist, z.B. verschiedene CRUD-Operationen auf derselben Ressource. Auf diese Weise profitiert man von den Vorteilen der Funktionen (Skalierbarkeit, Kosten, Service-Unabhängigkeit, …), hält aber auch gleichzeitig das Deployment einfach. Genau dies ist ein Schlüssel-Feature des Serverless-Frameworks.

Screen-Shot-2016-08-15-at-3.25.14-PM

Aktuell ist Serverless in der Version 1.0.3 verfügbar. Neue Alphas und Betas werden auf regulärer Basis veröffentlicht. Die Dokumentation kann im  v1.0 Branch auf Github gefunden werden. Serverless führt das „Serverless-Service“-Konzept ein, was eine Gruppe von Funktionen mit einer spezifischen Ressourcen-Anforderung ist.

Im Kern bietet Serverless 1.0 ein mächtiges und einfach zu nutzendes Kommandozeilen-Interface, um Funktionen zu erstellen, zu deployen und aufzurufen. Serverless 1.0 nutzt AWS CloudFormation, um AWS-Ressourcen zu erstellen. Für den Zugriff auf einen AWS Account wird das Default AWS Profil verwendet. Erstellen, Deployen und Starten einer „Hello World“ NodeJS-Funktion mit Serverless funktioniert ganz einfach wie folgt:

serverless create --name cars --provider aws 
serverless deploy 
serverless invoke --function hello --path data.json

Diese Zeilen erzeugen folgendes Lambda:

'use strict'; 
module.exports.hello = (event, context, cb) => cb(null, 
   { message: 'Go Serverless v1.0! Your function executed successfully!', event } 
); 

Die aktuelle Version des Serverless-Frameworks nutzt (leider) nicht die Region der AWS Config, deswegen müssen Sie für Ihre Funktion eventuell in einer anderen Region suchen.

Das Hinzufügen eines API Gateway ist einfach zu machen, indem dieses Http-Event angelegt wird:

events:
  - http:
       path: greet
       method: get

Die URL kann im API Gateway innerhalb der Stages-Sektion gefunden werden, wie bereits weiter oben gezeigt.

Und als nächstes?

Im ersten Teil dieser Serie lag unser Hauptaugenmerk auf AWS. In den nächsten beiden Teilen wollen wir uns andere Anbieter schauen:

  • Auth0 WebTask
  • Microsoft Azure Functions
  • Google Cloud Functions
  • IBM OpenWhisk

Danksagung

Ich möchte mich bei Philipp Müns (unter http://serverless.com/ und http://blog.serverless.com/) sowie Patrick Debois (http://www.devopsdays.org/ und http://www.smalltownheroes.be/) für ihr konstruktives Feedback zu diesem Blogpost bedanken. Die Jungs machen wirklich tolle Sachen, man sollte sich die Links ruhig mal anschauen!

Dieser Artikel wurde zuerst in englischer Sprache auf Bart Blommaerts Blog Daggie.be veröffentlicht.

Geschrieben von
Bart Blommaerts
Bart Blommaerts
Bart ist leidenschaftlicher Architekt von Apps. Er glaubt, es ist essentiell die Lücke der Model-Codes zu schließen, um schnelle, agile Deliveries nachhaltig zu machen. Bart hat einen starken Focus auf API Design, Wiederverwertung, Automatisierung und Sicherheit. Er ist ständig auf der Suche nach technischen Herausforderungen. Außerdem ist Bart im Aufsichtsrat von verschiedenen JWorks Competence Center Leads bei Ordina.
Kommentare
  1. Federico2016-11-14 12:39:05

    Sehr interessanter und nützlicher Blog, dankeschön!!
    Klasse auch die Beispiele, auch wenn die Beschreibung für einen Neuling nicht ausreichend ist, um es nachzuvollziehen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.