Aktuell hosten wir unsere Serverless Applikationen direkt auf AWS Lambda. Da wir jedoch möglichst Provider unabhängig bleiben wollen schauen wir uns in diesem TechUp Knative an. Knative ist eine Kubernetes basierte Platform um Serverless-Anwendungen direkt in Kubernetes bereitzustellen. Dadurch kann eine Serverless Applikation auch auf jeden anderen Provider portiert werden, solange Kubernetes installiert ist.
Knative ist ein Open-Source Projekt und wurde zum ersten Mal 2018 durch Google vorgestellt. Aber nicht nur Google arbeitet an dem Serverless-Framework, sondern auch zahlreiche andere grosse Firmen wie beispielsweise IBM oder RedHat. Die aktuellste Version zum Zeitpunkt dieses Blogbeitrags ist 0.24.
Knative kommt mit 2 Basiskomponenten “Serving” und “Eventing”. Serving ist dafür zuständig, um serverless Container in Kubernetes laufen zu lassen. Eventing bietet eine Schnittstelle um auf Ereignisse zu reagieren wie beispielsweise Github Hooks oder Message Queues.
In manchen Posts liest man noch von einer dritten Komponente “Build”. Diese wurde jedoch mit diesem Issue archiviert, da man zukünfitg auf Tekton Pipelines setzen will.
Knative Serving
Knative Serving nutzt Kubernetes und Istio um serverless Applikationen und Funktionen zu deployen. Dabei werden die folgenden Funktionen unterstützt:
-
Autoscaling inklusive “scale to zero”
-
Unterstützung der gängigsten Netzwerklayer wie Istio, Kourier, Ambassador, …
-
Snapshots von Code und Konfigurationen
Es gibt 4 Kubernetes CRDs (Custom Resource Definitions) um zu definieren, wie sich die serverless Applikationen im Cluster verhalten.
Service
Die Service Resource steuert den kompletten Lifecycle einer Applikation oder Funktion. Er erstellt ausserdem alle Objekte, welche zum Ausführen benötigt werden (Route, Konfiguration, Revisionen). Im Service wird auch geregelt welche Revision genutzt werden soll.
Route
Die Route-Resource verknüpft einen Netzwerk-Endpunkt mit einer oder mehreren Revisionen.
Configuration
Die Konfiguration Resource sorgt für den gewünschten State des Deployments. Es gibt eine strikte Trennung zwischen Code und Konfiguration. Bei jeder Änderung der Konfiguration wird eine neue Revision erstellt.
Revision
Die Revision Resource ist ein Snapshot des Codes und der Konfiguration, welche bei jeder Änderung erstellt wird. Eine Revision kann nach der Erstellung nicht mehr verändert werden. Revisionen können je nach Traffic autoskaliert werden.
Knative Eventing
Knative Eventing stellt Funktionen zur Verwaltung der Ereignisse zur Verfügung. Die Anwendungen werden in einem ereignisgesteuerten Modell ausgeführt.
Über Eventing lassen sich Produzenten (Producer) mit Konsumenten (Consumer) flexibel koppeln. Knative organisiert das Queueing der Ereignisse und liefert diese an die Container-basierten Services. Knative nutzt zum Senden und Empfangen von Events zwischen den Producer und Consumer HTTP Post Requests.
Knative Eventing definiert ein EventType-Objekt um Consumer einfach die Eventtypen, die sie konsumieren können, anzubieten. Diese EventTypes sind in der Event-Registry hinterlegt.
Wer meine TechUp’s verfolgt der weiss, dass ich gerne die Framework’s in der Praxis sehe! 😄 Wollen wir uns nun also Knative mal im Cluster anschauen.
In der Praxis
Als erstes wollen wir Knative Serving in unserem Kubernetes Cluster installieren. Wir folgen hier den Schritten im Administration Guide mit allen Defaults (Kourier, Magic DNS).
Knative Serving Custom Resources und Knative Serving
|
|
Netzwerklayer (Kourier)
|
|
Magic DNS (sslip.io)
Knative bietet einen Kubernetes Job “default-domain” an, welcher Knative Serving so konfiguriert, dass sslip.io als default DNS Suffix genommen wird.
|
|
Nachdem wir Knative Serving installiert haben, installieren wir noch Knative Eventing.
Knative Eventing Custom Resources und Knative Eventing:
|
|
Soweit so gut, Knative ist jetzt in unserem Cluster installiert.
Knative Serving Beispiel
Nun wollen wir unsere erste Serverless Applikation erstellen und mittels Knative deployen. Dazu schreiben wir uns einen ganz simplen Go-Server.
|
|
Anschliessend erstellen wir uns ein Dockerfile, um aus unserer Go-Applikation ein Image bauen zu können.
|
|
Anschliessend noch unser go.mod manifest erzeugen mit
|
|
Daraus erstellen wir uns jetzt ein Image und pushen dies auf https://docker.io .
|
|
Unser Image ist nun fertig um deployed zu werden. Wir erstellen und einen Knative Service. Dazu schreiben wir uns das folgende service.yaml File.
|
|
Jetzt nur noch ein apply und schon sollte unsere erste Serverless Applikation zur Verfügung stehen.
|
|
Nachdem unser Service erstellt wurde, wird Knative die folgenden Schritte für uns ausführen:
-
Eine neue Version unserer Applikation wird erstellt.
-
Es wird eine Route, Ingress, Service und ein LoadBalancer für unsere Applikation erstellt
-
Automatisches Up- und Downscaling unserer Pods.
Schauen wir uns dies im Detail an. Als Erstes wollen wir mal die URL für unseren Service herausfinden. Durch Magic DNS bekommen wir für jeden Service automatisch eine http://sslip.io URL. Durch folgenden Befehl sehen wir diese spezifische Url:
|
|
Wir sehen, dass aktuell keine Pods laufen. Starten wir also ein watch auf get Pods und schauen, was bei einem Request auf die Url passiert.
|
|
|
|
Sobald ein Request gemacht wird, wird automatisch ein Pod gestartet und die Anfrage wird entgegengenommen. Sobald die Response gesendet wurde, fährt der Pod dann automatisch auch wieder nach einem gewissen Timeout (60s) herunter.
Fazit
Wir haben hier an einem einfachen Beispiel gesehen, wie man eine sehr einfache Serverless Applikation mittels Knative zur Verfügung stellen kann. Wir bei b-nova haben uns dazu entschlossen alle bestehenden Lambda Funktionen zu Knative zu migrieren! 🚀 Der Grund dafür ist relativ simpel. AWS Lambda braucht innerhalb der Applikation einen Handler um die Serverless Anfragen entgegenzunehmen.
Eine Go Lambda Applikation sieht beispielsweise so aus:
|
|
Die main()
-Methode muss als Entrypoint die lambda.Start()
-Funktion aufrufen. Wir müssen also unseren Applikationscode verändern, damit wir die Lambda-Funktion deployen können.
Bei Knative können wir unseren Applikationsode unverändert lassen. Es braucht lediglich eine zusätzliche, vom Quellcode unabhängige Konfiguration.
Nächste Schritte
Im heutigen TecUp haben wir uns lediglich Knative Serving angeschaut und dort auch nur die Basics. Es gibt in diesem Umfeld noch viele interessante Themen wie beispielsweise Traffic Splitting.
Für Knative Eventing haben wir momentan keinen Use Case, werden dies aber auf jeden Fall im Auge behalten und für ein weiteres TechUp vormerken.
Den vollständigen Quellcode findet ihr wie immer in unserem TechHub Git https://github.com/b-nova-techhub/knative-hello-bnova
Weiterführende Links: