Kubeless – FaaS auf Kubernetes

Kubernetes und Serverless sind zwei der bedeutendsten Trends beim Betrieb von Software. Kubeless verspricht sogar, beides zu vereinen, und lohnt daher eine nähere Betrachtung.

Architektur/Methoden  –  2 Kommentare
Kubeless – FaaS auf Kubernetes

Software in Containern auszuliefern, ist seit ein paar Jahren ein zentraler Trend. Kubernetes hat sich als Mittel der Wahl etabliert, die Container auf vielen Rechnern zu betreiben und zu orchestrieren. Auf welcher konkreten Infrastruktur es läuft, ist dabei zweitrangig. Es kann das Angebot eines der großen Cloud-Providers sein, ein lokales Rechenzentrum oder sogar eigene Hardware vor Ort: Kubernetes empfiehlt sich als universelle Plattform. Für viele ist das ein wichtiges Argument für den Einsatz. Entwicklern verlangt das System jedoch einiges an Wissen ab, wie sich eine Anwendung in einer solchen Umgebung betreiben lässt.

Unter dem Begriff Serverless vereinen sich wiederum Ansätze, bei denen die Infrastruktur in den Hintergrund rückt. Ein Kernbestandteil dieser Architektur ist Function as a Service (FaaS). Es werden nur noch Funktionen definiert, die auf bestimmte Events reagieren. Eine Anwendung entsteht durch die Kombination vieler solcher Funktionen. Bei Serverless-Angeboten bindet man sich jedoch an den jeweiligen Anbieter der Infrastruktur und kann nicht mehr selbst bestimmen, wo die eigene Software läuft. Verträge, Regulierungsbehörden und nicht zuletzt der Datenschutz erlauben es vielen Anwendern häufig nicht, auf Serverless umzusteigen.

Es ist daher naheliegend, eine Anwendung zu suchen, die auf vielen verschiedenen Plattformen funktioniert und gleichzeitig die Details der Infrastruktur für Entwickler so transparent wie möglich gestaltet. Entsprechend vielfältig sind bereits die Angebote, die FaaS auf die Kubernetes-Plattform übertragen. Als Open-Source-Plattformen existieren unter anderem OpenFaaS, Fission, OpenWhisk und Kubeless. Letzteres wird im Folgenden exemplarisch näher betrachtet.

Die zentralen Elemente einer FaaS-Anwendung sind Funktionen und Trigger. Funktionen stellen die eigentliche Logik dar. Sie lassen sich durch unterschiedliche Ereignisse (Trigger) aufrufen, wobei dieselbe Funktion mit verschiedenen Arten von Ereignissen zurechtkommt.

Funktionen lassen sich in Kubeless in unterschiedlichsten Programmiersprachen implementieren. Um dies zu ermöglichen, führt Kubeless ein weiteres Element ein: die Runtime. Das ist ein Container, der sich an bestimmte Konventionen hält, mit denen er den Quellcode der Funktion übersetzen und ausführen kann. Er kümmert sich auch um die Installation etwaiger externer Bibliotheken.

Kubeless liefert in der aktuellen Version (v1.0.0-alpha.8) Runtimes für die folgenden Sprachen und Umgebungen mit:

  • Python
  • NodeJS
  • Ruby
  • PHP
  • Go
  • .NET
  • Java (Quellcode und Bytecode)
  • Ballerina

Das Erstellen eigener Runtime ist gut beschrieben. Sie können dann in der Konfiguration hinterlegt werden und stehen für neue Funktionen zur Verfügung. Dadurch eröffnen sich interessante Optionen für eigene Runtimes, die neben weiteren Programmiersprachen auch zusätzliche Funktionen mitbringen können.

Alle Funktionen verfügen über ein einheitliches, relativ einfach aufgebautes Interface. Beim Aufruf erhält eine Funktion zwei Parameter: Event und Context.

Der Parameter Event enthält eine Reihe von Metadaten wie den Aufrufzeitpunkt, die Art des Events und eine ID. Vor allem sind darin die eigentlichen Daten des Events enthalten. Sie sind üblicherweise sehr individuell, weshalb hier als Typ einfach ein String übergeben wird.

Der Parameter Context liefert eine Reihe weiterer Metadaten der Laufzeitumgebung. Dazu zählen der Name, unter dem die Funktion registriert ist, ihre Runtime und Angaben über Timeouts und Speicherlimits. Der Rückgabewert der Funktion ist wiederum ein String, den die Runtime auswerten kann.

Über Trigger lassen sich die in einer Runtime containerisierten Funktionen aufrufen.

Als Trigger für die Funktionen bietet Kubeless im derzeitigen Release an: HttpTrigger, CronjobTrigger und MessageTrigger. Die HttpTrigger hören auf HTTP-Aufrufe und leiten sie an die entsprechende Funktion weiter. Dabei nutzen sie die Infrastruktur von Kubernetes und richten für den Trigger die entsprechenden HTTP-Routing-Regeln in Kubernetes in Form einer Ingress-Definition ein. Es lassen sich sowohl virtuelle Hostnamen, Pfade und die HTTP-Methoden konfigurieren – somit ist auch eine REST API einfach zu gestalten.

CronjobTrigger benutzen das in Kubernetes bereits vorhandene Objekt des Cronjob, um regelmäßige Aufrufe einer Funktion zu realisieren. Die Definition der Zeitpunkte folgt dabei dem zwar kryptischen, aber auch schon seit Jahrzehnten etablierten Muster der Cron-Expression.

Schließlich lassen sich Funktionen auch über einen Message-Bus auslösen. Dazu existieren aktuell zwei Implementierungen. Die derzeit bevorzugt eingesetzte nutzt Apache Kafka und die andere Implementierung baut auf NATS, das als Projekt der Cloud Native Computing Foundation (CNCF) im Kubernetes-Umfeld zunehmend populärer wird.

Im Vergleich zu vielen Cloud-basierten FaaS-Ansätzen ist die Anzahl der Trigger recht überschaubar. Das Erstellen eigener Trigger ist allerdings ebenfalls recht gut dokumentiert, sodass sich spezifische Anforderungen in der eigenen Umgebung umsetzen lassen.