Kubeless – FaaS auf Kubernetes

Seite 3: Hello World

Inhaltsverzeichnis

Das "Hello World"-Beispiel von Kubeless ist eine einfache Python-Funktion, die ihre Parameter loggt und die übergebenen Daten zurückgibt:

def hello(event, context):
print event
return event['data']

Vorausgesetzt, dass diese Funktion in einer Datei namens helloworld.py abgelegt ist, lässt sie sich mit dem folgenden Kommando auf der Kubeless-Kommandozeile als Funktion installieren:

$ kubeless function deploy hello --runtime python2.7 \
--from-file helloworld.py \
--handler helloworld.hello

Kubeless legt damit ein Objekt für die Funktion an und lädt die Datei helloworld.py als ConfigMap in Kubernetes hoch. Daraufhin wird der Kubeless Function Controller aktiv und erzeugt einen Pod, mit dem unter dem Parameter runtime genannten Container. Dieser wiederum liest die Daten aus der ConfigMap und initialisiert sich entsprechend. Anschließend steht die Funktion zum Aufruf bereit. Noch fehlt ein entsprechender Trigger, aber zu Testzwecken lässt sich die Funktion manuell mit folgendem Kommando aufrufen:

$ kubeless function call hello --data "Hello World"

Als Ergebnis gibt sie wiederum "Hello World" aus. Der Aufruf findet sich ebenfalls im Log der Funktion, das sich mittels

$ kubectl logs -l function=hello

aufrufen lässt.

Im nächsten Schritt folgt ein passender Trigger. Der lässt sich beispielsweise für HTTP einrichten. Dazu dient folgendes Kubeless-Kommando:

$ kubeless trigger http create hello-trigger --function-name hello

Basierend auf diesem Trigger wird ein Kubernetes Ingress angelegt. Auf einer minikube-Installation sieht das so aus:

$ kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
hello-trigger hello.192.168.99.101.nip.io 10.0.2.15 80 8m

Kubeless nutzt per default URLs der Form <Funktionsname>.<IP>.nip.io. Nip.io ist ein Dienst, der bei DNS-Abfragen die zuvor notierte IP-Adresse zurückgibt. Was in diesem Fall für einen Kubernetes-Ingress, der einen Hostnamen voraussetzt, recht praktisch ist. Selbstverständlich lassen sich mit der Option —hostname bei der Erstellung des Triggers auch andere Namen angeben. Die Funktion lässt sich anschließend per HTTP beispielsweise mit curl aufrufen:

$ curl hello.192.168.99.101.nip.io -d "Hello World"
Hello World

Die Definition der Funktionen unterscheidet sich je nach Programmiersprache deutlich. Ein guter Ausgangspunkt für die Details der jeweiligen Runtime zu einer Programmiersprache sind die Beispiele auf GitHub.

Komplexere Funktionen benötigen neben dem eigentlichen Quellcode oft noch externe Abhängigkeiten. Wie die einzubinden sind, ist ebenfalls von der jeweiligen Runtime abhängig. Im Falle von Python reicht eine requirements.txt. Sie enthält die Liste aller Python-Pakete, die eingebunden werden sollen. Für Node.js ist es eine package.json, für die Java-Runtime ist es eine pom.xml im Maven-Format, die von einer bestimmten Parent-Pom ableitet. Auch dieses Vorgehen lässt sich gut anhand der genannten Beispiele nachvollziehen.