18. Mai 2020 | 8 min lesezeit

Serverless Computing verstehen und anwenden

Beim Serverless Computing stellt ein Cloud-Anbieter eine Laufzeitumgebung zur Ausführung von Programmfunktionen bereit (Function as a Service). Entwickler können sich so ganz auf ihren Code konzentrieren.

Enterprise-Projekte sind in Bezug auf die umzusetzende Fachlichkeit und für die zur Laufzeit benötigte Infrastruktur komplex. Oft bringt man die Entwicklung und Bereitstellung entsprechender Anwendungen daher mit umständlichen Entwicklungsprozessen, übergroßen Projektstrukturen, schwergewichtigen Anwendungsservern, langsamen Test- und Deployment-Zyklen sowie komplexer Provisionierung in Verbindung.

Microservices inklusive Runtimes wie Spring Boot oder Eclipse MicroProfile vereinfachen zwar die Entwicklung, doch optimal wäre es erst, wenn Entwickler sich nur noch um die Implementierung der fachlichen Bausteine und nicht um die Plattform kümmern müssten, auf der sie laufen.

Ein primäres Ziel in der Anwendungsentwicklung sollte es sein, dass sich Entwickler auf die Umsetzung der Anwendung konzentrieren können. In der Realität sieht das oft anders aus. Ein Großteil der Projektzeit verwenden sie nicht dafür, sondern für das korrekte Aufsetzen und Betreiben der zur Laufzeit benötigten Infrastruktur und Backend-Services. Eine Erleichterung sollen die unterschiedlichen Cloud-Angebote liefern. Angefangen bei virtuellen Rechnern (Infrastructure as a Service, IaaS) über Datenbanken, Dateisysteme oder Anwendungsserver (Platform as a Service, PaaS) bis hin zu komplexen Softwareanwendungen (Software as a Service, SaaS) kann sich ein Cloud-affines Entwicklerteam heutzutage einer breiten Palette an Diensten innerhalb der Cloud bedienen.

Mithilfe der Cloud-Dienste lässt sich in allen Phasen des Softwarelebenszyklus ein großer Teil des Entwicklungs- und operationalen Aufwands einsparen. Ein weiterer Vorteil ist die automatische Skalierung. Durch die Verlagerung von Infrastruktur in die Cloud kann eine Anwendung on the fly skalieren. Die Provisionierung von Ressourcen wird zum Kinderspiel. Die Bereitstellung zusätzlicher Rechnerinstanzen erfolgt binnen Minuten statt Tagen oder Wochen. Das gilt auch für Datenbanken und Plattenplatz. Auch die fachliche Anwendung selbst lässt sich durch automatische Replikation der Anwendungsserver binnen Minuten um weitere Instanzen erweitern – Routing und Load Balancing inklusive. Die Abrechnung erfolgt in der Regel nach den belegten Ressourcen. Hohe Initialkosten und somit ein nur schwer kalkulierbares Projektrisiko gehören der Vergangenheit an. Wie aber passt nun Serverless Computing in dieses Bild? Serverless Computing versucht, das Paradigma der automatischen Provisionierung und bedarfsgerechten Skalierung auf die fachliche Logik einer Anwendung auszuweiten. Dies umfasst zwei Varianten: Backend as a Service (BaaS) und Function as a Service (FaaS).

Bei Backend as a Service stellt der Cloud-Anbieter fachliche Rundum-sorglos-Pakete – zum Beispiel User-Management, Social-Media-Integration oder ein Chatsystem – in Form von Backend-Services zur Verfügung. Mit API oder SDK sind sie in die eigene Anwendung einbindbar und von dort aus ansprechbar. Dabei ist es egal, ob die eigene Anwendung ebenfalls in der Cloud des BaaS-Anbieters, in der Cloud eines anderen Anbieters oder als On-Premises-Lösung im eigenen Rechenzentrum läuft. BaaS erfreut sich insbesondere im Umfeld mobiler Lösungen großer Beliebtheit, da sich durch die geschickte Kombination von angebotenen Backend-Diensten auf ein eigenes Backend verzichten lässt.

Bei Function as a Service, das einige als das „echte“ Serverless ansehen, geht der Cloud-Anbieter noch einen Schritt weiter und bietet voll gemanagte, automatisch skalierbare Laufzeitumgebungen für die individuelle Anwendungslogik an. Der Anwendungsentwickler programmiert nur noch die gewünschte Logik in Form einzelner Funktionen – Serverless Functions (Abbildung 1). Alles Weitere liegt in der Verantwortung des Cloud-Anbieters. Damit die Funktion in der Cloud aufrufbar ist, muss der Entwickler noch ein Event konfigurieren, das die Funktion aktiviert. Ein solches Event kann ein über ein API-Gateway an die Funktion weitergeleiteter REST-Call sein, ein Ereignis innerhalb einer Cloud-Komponente (wie das Hinzufügen eines Bildes in einen vorab definierten Ablageort des Cloud-Storage) innerhalb einer bestimmten Tabelle einer Cloud-Datenbank. Diese Beispiele zeigen, dass eine Serverless Function selten allein dasteht, sondern als Bindeglied zwischen mehreren Cloud-Komponenten fungiert.

Im Gegensatz zu Iaas und PaaS beschränkt sich beim FaaS-Modell die Zuständigkeit des Entwicklers auf das Programmieren der Logik in Form von Funktionen (Abb. 1).

Serverless im Einsatz

Was wie Platform as a Service klingt, unterscheidet sich in der Praxis sehr von diesem Ansatz. Stellt PaaS eine langlebige Ablaufumgebung für die gesamte Laufzeit – vom Start bis zum gezielten Herunterfahren – eines Anwendungsservers oder eines (Micro-)Services zur Verfügung, bietet Function as a Service eine kurzlebige Runtime, die lediglich für die Ausführungszeit eines einzelnen Funktionsaufrufs existiert. Laufzeiten von wenigen Sekunden oder gar Millisekunden sind das Maß der Dinge.

Das Inanspruchnehmen und Bezahlen der Cloud-Ressourcen ergibt sich aus der Nutzungsdauer von Backend-Service und Funktion. Auch die Skalierung im Serverless-Umfeld ist effizient. Lastspitzen, ob geplant oder ungeplant, lassen sich über zusätzliche Instanzen des gewünschten Backend-Services (BaaS) und zusätzliche Laufzeitumgebungen für die Serverless Functions abfangen und somit temporär und verursachungsgerecht skalieren.

Im Hintergrund laufen natürlich weiterhin physikalische und virtuelle Server sowie minimalistische Server-Runtimes zur Ausführung der Funktionen. Der Begriff Serverless soll lediglich ausdrücken, dass die Anwendungsentwickler sich darum keine Gedanken mehr machen müssen.

Neben kommerziellen Plattformen wie Microsoft Azure Functions, Google Cloud Functions, IBM Cloud Functions und AWS Lambda gibt es Open-Source-Varianten wie OpenFaaS [1], Apache OpenWhisk [2] und Fn Project.

Serverless Computing spielt seine Stärken immer dann aus, wenn es einen Bedarf an „Off the Shelf“-Anwendungslogik gibt (BaaS) oder sich spezifische Anwendungslogik effizient durch eine einzelne Funktion oder durch Kombination weniger Funktionen abbilden lässt. Beispiele sind das automatische Erzeugen eines Vorschaubilds nach einem Bildupload und das Erzeugen eines PDFs nach dem Befüllen einer Tabelle.

Durch die automatische Skalierung und das damit verbundene Pay-per-Use-Zahlungsmodell eignet sich das FaaS-Modell für Szenarien, in denen das Lastverhalten einzelner Businessmethoden extremen Schwankungen unterliegt. Monatliche Rechnungsläufe oder Ticketverkäufe für begehrte Events stehen dabei ebenso auf der Liste der potenziellen Kandidaten wie die Annahme von Lotto-Spielscheinen oder die Bestellabwicklung eines Onlineshops zur Weihnachtszeit. Und auch der klassische Batch-Job ist ein typischer Kandidat für FaaS. Vorausgesetzt, der Batch-Job lässt sich aus fachlicher Sicht gänzlich oder zumindest in Teilen parallelisieren, dann ließe sich die Abarbeitung des Jobs in der Cloud auf mehrere parallellaufende Instanzen einer Serverless Function verteilen und so Zeit sparen.

Neben den eben genannten Szenarien bieten sich zusätzlich Aufgabenstellungen an, in denen im Hintergrund fortlaufend Daten in nahezu Echtzeit zu analysieren sind. Dies können während der Produktion von Fahrzeugen generierte Kennzahlen zur Qualitätsprüfung, Messwerte von IoT-Devices zur Erfassung von Verbräuchen oder Social-Media-Streams zur Durchführung von Trendanalysen sein.

Die aufgeführten Beispiele zeigen, dass sich überschaubare, punktuelle Szenarien gut für die Umsetzung mittels Serverless Functions eignen. Wie sieht es aber mit umfangreichen (Web-)Anwendungen aus? Lassen sie sich genauso gut und einfach auf Serverless Computing umstellen? Für einfache Anwendungen wie eine Webanwendung zur Pflege von Kundendaten ist das vorstellbar. Schwieriger wird es dagegen bei komplexen Anwendungen mit einer Vielzahl fachlicher Use Cases. Hier kommen schnell etliche Hundert Funktionen zusammen, mit dem Resultat eines stark verteilten, eventgetriebenen und asynchron arbeitenden Systems in der Cloud. Theoretisch denkbar, praktisch aber eine nicht zu unterschätzende Herausforderung. Nicht umsonst schreibt Martin Fowler: „My First Law of Distributed Object Design: Don’t distribute your objects.“ [3]

Lokal und in der Cloud testen

Wie bereits angedeutet, stellt die starke Verteiltheit bei komplexen Anwendungsszenarien eine Herausforderung dar. Da Serverless Functions in der Regel asynchron arbeiten, ist ein ausgereiftes Monitoring der einzelnen Funktionen – inklusive automatischem Recovery und Alarming – zwingend notwendig. Nur so lässt sich zur Laufzeit sicherstellen, dass jede Funktion für sich, aber auch im Zusammenspiel mit den anderen Cloud-Komponenten das tut, was von ihr erwartet wird.

Die Herausforderungen treten allerdings nicht erst zur Laufzeit auf. Möchte man eine Funktion, deren Trigger und etwaiges Fallback-Verhalten (wie Dead Letter Queues für nicht verarbeitete Events) testen, können diese Tests nur zu kleinen Teilen auf dem Rechner des Entwicklers erfolgen. Gleiches gilt für die notwendigen Integrationstests, die das Zusammenspiel einer Funktion mit anderen Cloud-Komponenten prüfen. Denn in der Regel stehen nicht alle Cloud-Komponenten auch als lokale Variante zur Verfügung. Tun sie das, verhalten sie sich lokal bezüglich Antwortzeitverhalten und damit verbundenen Time-outs anders als in der Cloud. Nur einen kleinen Teil der notwendigen Tests kann man lokal durchführen, der weitaus größere Teil muss dagegen zwingend in der Cloud erfolgen (Abbildung 2).

Das Testen von Serverless Functions kann nur teilweise auf dem eigenen Rechner erfolgen. Die meisten Tests müssen innerhalb der Cloud ausgeführt werden (Abb. 2).

Ein weiteres Problem ergibt sich durch das Runtime-Modell der Serverless Functions. Wie bereits beschrieben, startet die Laufzeitumgebung erst beim Aufruf und der Aktivierung der Funktion und fährt im Anschluss wieder herunter. Was aus Sicht der belegten Ressourcen optimal klingt, bringt zur Laufzeit einen zeitlichen Overhead mit sich, auch Cold Start genannt. Kein Problem ist es, wenn die Funktion asynchron im Hintergrund läuft. Wartet dagegen ein synchroner Aufrufer auf eine Antwort, sieht die Situation anders aus und der zeitliche Overhead ist möglicherweise nicht akzeptabel. Dieses Problem ist auch den Cloud-Anbietern bewusst, die es durch Optimierungen entschärfen. So versuchen nahezu alle Anbieter, die Anzahl der Cold-Start-Situationen zu minimieren, indem eine nicht mehr benötigte Instanz der Laufzeitumgebung noch eine gewisse Zeit lang erhalten bleibt, um sie so für einen direkt folgenden Funktionsaufruf wiederverwenden zu können. Zusätzlich werten einige Cloud-Anbieter das Nutzungsprofil der verschiedenen Funktionen aus und versuchen so vorherzusagen, zu welchem Zeitpunkt wie viele Instanzen der Laufzeitumgebung der jeweiligen Funktionen nötig sind, um diese zur Verfügung zu stellen. Man kann auch selbst dafür sorgen, dass ausreichend Instanzen der Laufzeitumgebung einer Serverless Function zur Verfügung stehen, indem man die zugehörige Funktion regelmäßig aufruft. Allerdings muss man beim Aufruf darauf achten, dass die Funktion durch einen Parameter signalisiert bekommt, dass es sich um einen „Fake“-Aufruf handelt und sie somit ihre Logik nicht ausführen soll – eine eher unschöne, wenn auch pragmatische Lösung des Problems. AWS bietet daher mittlerweile die Möglichkeit an die gewünschte Anzahl an parallelen Instanzen via Konfiguration am Leben zu halten. Ein sinnvoller Service, der allerdings mit Kosten verbunden ist.

Ein ebenfalls vielbeschworenes Damoklesschwert des Serverless Computings stellt das mit der Auswahl eines Cloud-Anbieters einhergehende Vendor-Lock-in dar. Denn nur die Bindung an den gesamten Technologiestack des Anbieters ermöglicht eine effiziente Entwicklung einer auf Serverless Functions basierenden Anwendung. Dieses Problem lässt sich zwar nicht vollständig aus dem Weg räumen, die gegebenen Abhängigkeiten zum Cloud-Anbieter lassen sich aber minimieren. So kann man auf das Abstraktions-Framework mit dem passenden Namen Serverless zurückgreifen. Ursprünglich angetreten, die Entwicklung in der AWS-Cloud zu vereinfachen, unterstützt es mittlerweile auch Plattformen wie Azure Functions, Google Cloud Functions, IBM Cloud Functions und Fn Project. Dass es generell einen Bedarf an Harmonisierung und Standardisierung der verschiedenen am Markt existierenden Serverless-Lösungen gibt, erkennt man am Engagement der Cloud Native Computing Foundation. Dort findet sich unter anderem das Projekt CloudEvents. Es hat sich zum Ziel gesetzt, ein providerneutrales Eventformat zu spezifizieren, das sich Cloud-übergreifend als Trigger für Serverless Functions verwenden lässt.

An dieser Stelle muss die Frage erlaubt sein, wie realistisch der Wechsel von einer Serverless-Plattform zu einer anderen ist und wie hoch der damit einhergehende Aufwand ins Gewicht fällt. Serverless Functions sind letztendlich nicht viel mehr als das Bindeglied zwischen den verschiedenen proprietären Komponenten eines Cloud-Anbieters. Der zu erwartende Aufwand beim Wechsel von einem Anbieter zu einem anderen fällt daher vor allem bei der Migration der genutzten Cloud-Komponenten und weniger bei der Migration der Serverless Functions an.

Fazit

In großen Projekten liegt der Fokus der Entwicklung oft mehr auf Infrastruktur und Technologie als auf der Umsetzung der Fachlichkeit. Eine Verlagerung einzelner Komponenten in die Cloud schafft Abhilfe. Neben der Nutzung Cloud-basierter Infrastruktur und Plattformkomponenten lässt sich mittlerweile auch die eigene Fachlichkeit, aufgeteilt in Funktionen (FaaS), als Services in der Cloud hinterlegen. Der Aufruf der Funktionen erfolgt von außen über ein API-Gateway oder Cloud-intern über ein Event einer anderen Cloud-Komponente. Die Skalierung zur Laufzeit findet automatisch statt, bezahlt wird pro Aufruf. Aus Sicht des Anwendungsentwicklers existiert keine Infrastruktur mehr – Serverless ist das Schlagwort.

Allerdings bringt der serverlose Ansatz auch neue Herausforderungen mit sich. Eine Strategie zur Erkennung und Behandlung von Ausnahmesituationen innerhalb der lose gekoppelten Cloud-Funktionen ist erforderlich. Gleiches gilt für ein automatisiertes Test- und Deployment-Konzept. Die Cloud-basierte Ablaufumgebung lässt sich nur schwer lokal simulieren. Dank stetig wachsender Community steht man aber nicht alleine mit diesen Herausforderungen da, sondern kann auf eine Reihe von in der Praxis erprobter Best Practices und Frameworks zurückgreifen.

Quellen:

[1] Henry-Norbert Cocos; Christian Baun; Gekapselter Aufruf; OpenFaaS als leichtgewichtige Basis für eigene Functions as a Service, iX 9/2018, S. 122

[2] Henry-Norbert Cocos; Marcus Legendre; Christian Baun; Funktional verquirlt; Functions as a Service mit OpenWhisk, iX 12/2018, S. 126

[3] Martin Fowler; Patterns of Enterprise Application Architecture, Addison-Wesley, 2002

Der Artikel ist Teil des aktuellen Sonderhefts iXkompakt 2020 – Container, S.12 – S.15. Das vollständige Magazin ist hier zu finden: https://shop.heise.de/katalog/ix-kompakt-container-2020


Keine Kommentare

Kontakt

OPEN KNOWLEDGE GmbH

Standort Oldenburg:
Poststraße 1, 26122 Oldenburg

Standort Essen:
II. Hagen 7, 45127 Essen