Wie Containerless dank WebAssembly-Runtimes geht

13.10.2021 Raffael Schneider
Cloud wasm Rust serverless framework distributed-systems edge-computing handson tutorial howto

Seit 2017 gibt es für Web-Browser einen neuen W3C-Standard, welcher es ermöglicht binären Code direkt im Browser auszuführen und somit quasi-native Performance zu erlangen. Es handelt sich dabei um WebAssembly. Erst kürzlich hat Ricky über WebAssembly ein TechUp-Beitrag geschrieben und aufgezeigt, wie man ein Program in einer beliebigen Ausgangssprache (in seinem Artikel war die Sprache der Wahl Rust) in ein WebAssembly-Format, das sogenannte WASM-Artefakt, bringen kann und im Browser einbindet.

Kurz zusammengefasst kann man in jede beliebige Codebase in ein WASM-Artefakt umwandeln und direkt auf dem Client-Browser laufen lassen. Das hat nicht nur den Vorteil, dass die Ressourcenbeanspruchung direkt auf dem Client-System stattfindet, sondern kann bei entsprechender Architektur auch zur Latenzverminderung kommen, da gewisse Rechenoperationen nicht mehr ans Backend anfallen müssen, sondern direkt vom Client übernommen werden können.

WebAssembly Timeline

WebAssembly ist doch ein recht junge Entwicklung und die Awareness der Möglichkeiten ist noch nicht etabliert. Aus diesem Grund zeigen wir kurz die grossen Meilensteine von WebAssembly auf und verweisen somit auf die junge Entstehungsgeschichte von WebAssembly als revolutionäre, distributive Technologie:

  • März 2017:
    Minimum Viable Product veröffentlicht, erste Browser-Engine adoptierten die erste Spezifikation (Blink, WebKit, Gecko, usw.)

  • März 2019:
    WebAssembly System Interface veröffentlich und ermöglich es WASM ohne Browser zu nutzen

  • Dezember 2019:
    W3C erklärt die WebAssembly Core Specification als neuer Web-Standard

  • Januar 2021:
    Wasmer, als erste universelle WebAssembly Runtime wurde in der Version 1.0 veröffentlicht

  • August 2021:
    wasmCloud, eine für die Cloud konzipierte Runtime, wird ein CNCF-Sandbox-Project

Sandboxing durch WASI

WASI steht für WebAssembly System Interface und ist der W3C-Standard, welcher definiert wie WebAssembly mit dem Betriebssystem interagieren darf. Da WebAssembly nur ein binäres Format darstellt, ist ein zusätzlicher Standard notwendig um zu gewährleisten, dass bei der Ausführung eines WASM-Artefakts auf einer Implementation einer Virtual Machine das darunter liegende Betriebssystem richtig angesprochen wird.

Beim Zugriff auf lokale Dateien denkt man oft, dass bei Programmiersprachen wie C direkt auf die Dateien zugegriffen werden kann. Dem ist aber nicht so. Es gibt eine Abstraktionsebene dazwischen, der User Mode, welcher über System Calls den Kernel fragt, ob der Zugriff legitim ist, genauer gesagt ob die Zugriffsrechte gegeben sind. Da es verschiedene Betriebssysteme gibt, wird beim Kompilieren eines C-Programms unterschiedliche APIs benutzt. Bei Windows wird dabei die Windows-API genutzt, wo hingegen auf Linux oder MacOs die POSIX genutzt wird. Genau die gleiche Ausgangslage präsentiert sich bei WebAssembly. Wenn man den Web-Browser weg abstrahiert, braucht WebAssembly ein Interface womit es das darunter liegende Betriebssystem ansprechen kann. WASI ist der Standard dazu. WASI sorgt für eine OS-unabhängige Interaktion von WebAssembly-Artefakten.

Für WebAssembly und WASI stehen zwei wichtige Merkmale im Vordergrund:

  • Portabilität

  • Security

Der WASI-Standard erlaubt es somit WASM-Artefakte in einer sicheren Sandbox auszuführen. Den Nutzen davon hat Solomon Hykes, Co-Founder und initialer Erfinder von Docker, in einem seiner Tweets wie folgt am besten zum Ausdruck gebracht:

Write Once, Run Anywhere

Die Idee von Write Once, Run Anywhere (WORA) ist nicht neu. Bereits in den 90ern hat Java die Programmierwelt mit dem Slogan erobern können. Das war zu einer Zeit worin noch unterschiedlichste Chipsets in den Rechnern verbaut gewesen waren. Da war es besonders wichtig eine Applikation auf so vielen Rechner wie nur möglich laufen lassen zu können. Die Java Virtual Machine übernimmt dabei die Arbeit und sorgt dafür dass eine Codebase sich auf allen Rechnern und Betriebssystemen gleich verhält, oder so zumindest in der Theorie. Mit dem Aufkommen des Internets wurde JavaScript zur neuen Lingua Franca des Webs und gilt als Quasi-Standardsprache für Webapplikationen.

Es gibt bereits eine Vielzahl von WASI-Implementation, die auf eine WASM-Runtime abzielen. Darunter gehört Wasmer, Wasmtime, Lucet oder SecondState. Wir werden in diesem Beitrag nicht alle Runtimes auf Lunge und Niere prüfen können, versuchen aber ein grundlegendes Bild davon zu geben, was damit gemacht werden kann und wofür eine Runtime sich bei Ihnen im Betrieb eignen könnte.

Kevin Hoffmann, ein Software Architect bei Cosmonic, die Entwickler von wasmCloud, unterscheidet in einem seiner ersten Speeches über WebAssembly-Runtimes 3 Abstraktionsebenen:

  • Low-Level Runtimes
    Interpreters und Compilers, sowie JIT-Compilers. Diese bieten eine Browser-lose Execution von WASM-Artefakten. Beispiele:

    • Wasmer

    • Wasmtime

    • Wasm3

    • Wasmi

  • Mid-Level Runtimes
    Dies sind Runtimes, die zusätzlich zum Interpreter/Compiler auch noch zusätzliche Layers wie Interfaces für Function-/Procedures-Calls oder Payloads mitausliefern. Beispiele:

    • waPC

    • wascap

  • High-Level Runtimes
    Dies sind Runtimes, die weitere Layers bereitstellen und somit ein Actor-Model ausliefern, welcher es erlaubt HTTP-Server, Anbindungen an Message Broker, oder Interfaces per Protobuf als WASM-Module einzubinden. Beispiele:

    • waSCC

    • wasmCloud

Wasmer – Run any code on any client

Wasmer ist eine WASM-Runtime, welche WebAssembly-Artefakte standalone ganz ohne Browser ausführt. Wasmer gehört laut dem Abstraktionsmodel für Runtimes von Hoffmann zu den Low-Level Runtimes, welcher lediglich eine Runtime zur Verfügung stellt.

Installation

Wie man es aus modernen Cloud-Applikationen gewohnt ist, gibt es hier ein Shell-Skript zur Installation welches man sich direkt per curl downloaden kann.

❯ curl https://get.wasmer.io -sSfL | sh
Welcome to the Wasmer bash installer!
downloading: wasmer-darwin-amd64
Latest release: 2.0.0
...

Package Manager und WASM-Repository

Ein weiteres Projekt von Wasmer ist der wapm, der WebAssembly Package Manager. Damit kann man wie bei DockerHub, WASM-Artefakte hosten und diese bei Bedarf herunterladen.

Ein Beispielartefakt, adamz/quickjs, ist eine JavaScript-Engine. Diese kann man direkt per WebAssembly-Shell im Browser ausführen lassen.

Installation eines WASM-Artefakts

❯ wapm install adamz/quickjs
[INFO] Installing adamz/quickjs@0.20210327.0
Package installed successfully to wapm_packages!

Ausführung des WASM-Artefakts

❯ cd ~/wapm_packages/adamz/quickjs@0.20210327.0/build
❯ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > 1+1
1+1
2
qjs > 

WASM-Container in der Cloud

Es gibt ganz grundsätzliche Vorteile WebAssembly-Container anstatt klassische LXC-Container zu nutzen. Obwohl klassische Container-Lösungen auch einen starken Fokus auf Security-relevante Features haben, so stellen die möglichen Security-Kontexte doch eine grosse Angriffsfläche, und somit Gefahrenpotenzial dar. Aus diesem Grund entwickeln Cloud-Anbieter an kleinen Hypervisors und sogenannten Micro-VMs wie gVisor, Firecracker oder Kata-Containern, um die Zugangsmöglichkeiten an den Kernel zu mindern und um für eine bessere Isolation der Applikationsumgebung zu sorgen.

WebAssembly hingegen hat von Grund auf ein auf Sicherheit ausgelegten Standard, welcher ungewollte Zugriffe erst gar nicht ermöglicht. Somit ist WebAssembly eine echte Sandbox. Dazu kommt das WebAssembly-Artefakte nicht die ganzen Libraries, Interpretern oder Virtual Machines ausliefern muss, sondern nur die eigene Applikation als Binary beinhaltet.

Hier zeigt Cosmonic (Quelle der Illustration oben) wie die Containeriesierung vorangeschritten ist und in einer WASM-fähigen Runtime mündet. Klar ist der Trend sichtbar hin zur Entkopplung der Business-Logik vom ganzen Rest. WASM könnte tatsächlich die Lösung sein einen Host in dieser Qualität zur Verfügung zu stellen.

Krustlet – the WASM Kubernetes kubelet

Deis Labs, die Leute hinter bekannten CNCF-Projekten wie Helm oder Brigade haben ein weiteres Projekt am Start, welches Kubernetes um eine interessante Funktion erweitert. Krustlet, abgeleitet von Kubernetes-Rust-Kuebelet, ist ein Kubelet, welches es ermöglicht WebAssembly-Workload auf einem Kubernetes-Cluster auszurollen. Die Idee ist dabei die Upstart-Zeit und den Footprint zu verringern, sowie noch Hardware-unabhängiger zu sein. Auch wenn dies oft keine allzu grosse Rolle spielt, so ist die Container-Runtime (LXC) wie Docker darauf angewiesen, dass das auszuführende Image für das gleiche Chipset ausgeliefert wird, wie das darunterliegende Host-System.

Fazit

WebAssembly ist nicht nur ein neuer Standard, sondern hat das disruptives Potenzial Dinge in der Web- und Cloud-Welt fundamental zu ändern. Hierbei geht es nicht nur um den offensichtlichen Nutzen, nämlich Workload vom Backend auf die Client-Geräte zu verlagern, was für eine bessere Latenz, sowie eine bessere User-Experience sorgt. Somit schafft man mit WebAssembly in Kombination mit WASI eine Laufzeitumgebung womit Codebase auf die Business-Logik reduziert und mit dem kleinstmöglichen Footprint und Ressourceneinsatz sicher ausrollen kann.

Kevin Hoffmann sieht in WebAssembly die Zukunft für Distributed Computing und die Grundlage Browser-unabhängig ‘'Write Once, Deploy Everywhere'' zu erzielen. Erst kürzlich, im August 2021, wurde die erste WebAssembly-Runtime in der Cloud Native Computing Foundation aufgenommen. wasmCloud, die Runtime von Cosmonic, erlaubt es Workload in eine WebAssembly-Umgebung in die Cloud auszurollen. Somit sind bereits die ersten Weichen gestellt für eine Cloud-fähige Lösung dank WebAssembly-Runtimes. Ob sich diese Container-Alternative in der Zukunft etablieren wird können wir jetzt nur beschränkt beurteilen. Sicher ist, dass wir WASM und dessen Runtimes im Auge behalten und bei einer breitflächigen Adoption die Technologie auch selber einsetzen werden. Stay tuned!

Weiterführende Links und Ressourcen

Wasmer – The Universal WebAssembly Runtime

SecondState – Serverless Everywhere with WasmEdge

WebAssembly runtimes compared – LogRocket Blog

WebAssembly-Where is it going? – OpenCredo

Kruslet Brings WebAssembly to Kubernetes with a Rust-Based Kubelet

Rust, WebAssembly, and the future of Serverless by Steve Klabnik – Codegram (Youtube)

Kevin Hoffmann-Building a Containerless Future with WebAssembly – WebAssembly Summit (Youtube)

WebAssembly in the Cloud – kevinhoffmann.medium.com

Cosmonic Contributes WebAssembly Runtime to CNCF

Using WebAssembly and Kubernetes in Combination

Raffael Schneider – crafter, disruptor, free spirit. As a fervent software craftsmanship, Raffael likes to write about programming languages and software resilience in modern distributed systems. Be it DevOps, SRE or systems architecture, he always got a new way of approaching things.