Hannes Mehnert über MirageOS und OCaml: „Bei der funktionalen Programmierung geh
Vorwort
Unser Backend-Ingenieur Pavel Argentov ist dieses Jahr nach Marrakesch in Marokko gereist, um am neunten MirageOS-Retreat teilzunehmen, das vom 13. bis 19. März 2020 stattfand. Ziel des Events ist es, sowohl erfahrene als auch unerfahrene MirageOS-Benutzer an einem Ort zusammenzubringen, um gemeinsam an verschiedenen MirageOS-Projekten zu arbeiten, neue Projekte zu starten und sich gegenseitig bei Bugfixes zu helfen.
MirageOS ist ein Bibliotheksbetriebssystem, das Unikernels für sichere, hochleistungsfähige Netzwerkanwendungen über eine Vielzahl von Cloud-Computing- und mobilen Plattformen hinweg konstruiert. Der Code kann unter Linux oder Mac OS X entwickelt und dann in einen vollständig eigenständigen, spezialisierten Unikernel kompiliert werden, der unter einem Xen- oder KVM-Hypervisor läuft.
Pavel hat bei dem Event mit Hannes Mehnert, Co-Autor von MirageOS und Event-Host, über seine Arbeit mit MirageOS und OCaml gesprochen. Er hat uns einige Einzelheiten über seine Beiträge zu MirageOS verraten und erzählt, warum er sich dem Projekt angeschlossen hat. Er hat auch die Vorteile der funktionalen Programmierung erläutert, und warum er sich anfangs zu ihr hingezogen gefühlt hat. Darüber hinaus hat er das Potenzial und die Grenzen von MirageOS und OCaml aufgeschlüsselt und uns einige Informationen über neue und zukünftige Entwicklungen gegeben. Wir haben die vollständige Abschrift des Interviews unten beigefügt, damit wir Ihnen nichts vorenthalten.
Das Interview
Pavel: Wir sollten uns zunächst über OCaml unterhalten. Wie und warum haben Sie mit OCaml angefangen?
Hannes: Vor sechs Jahren, als ich gerade meinen Doktortitel in formaler Verifikation von Software abgeschlossen hatte, war ich es gewohnt, zufällige, bereits entwickelte Software zu nehmen, einige Spezifikationen darauf anzuwenden und dann einige Beweise zu schreiben, die zeigen, dass das Programm tatsächlich korrekt läuft. Das hat sich aufgrund der häufigen Verwendung von gemeinsamen, veränderbaren Zuständen als ziemlich komplex und arbeitsintensiv erwiesen. Seit geraumer Zeit interessiere ich mich sehr für Systemprogrammierung, was normalerweise heißt, dass man C verwendet, um das Betriebssystem darin zu schreiben. Aber angesichts meines semantischen Hintergrunds hatte ich eher gehofft, eine höhere Programmiersprache zum Schreiben von Betriebssystemen verwenden zu können. Nachdem ich meine Doktorarbeit abgeschlossen hatte, bin ich zusammen mit meinem Freund David Kaloper über MirageOS gestolpert.
MirageOS ist in OCaml geschrieben, einer Multi-Paradigma-Sprache, die über ein Modulsystem verfügt und für die funktionale Programmierung verwendet wird. Das bedeutet, dass man gemeinsame veränderliche Zustände vermeidet und die Programme tatsächlich auf den Betriebssystemen verifizieren kann. Als ich vor etwa sechs Jahren zu MirageOS gekommen bin, hat das Ganze bereits zu einem gewissen Grad funktioniert, und mein erster Beitrag war der TLS-Stack und kryptographische Algorithmen.
Pavel: Wie wird MirageOS verwendet, und was können wir aus der Verwendung gewinnen?
Hannes: MirageOS hat als Forschungsprojekt begonnen. Wir hatten einen Prototyp und eine Idee, wie man verschiedene Programmierstile für Betriebssysteme verwenden könnte. Mein Hintergrund ist auch sehr stark im Bereich der Security verwurzelt, und das war meine Hauptmotivation für meinen Beitrag zu MirageOS und den Versuch, es voranzutreiben. Aus der Security-Perspektive hat man damit einen weniger veränderlichen Zustand und kann HTTPS oder Webserver mit TLS betreiben. Und man hat viel weniger Code, was weniger Bugs und weniger Ressourcenverbrauch bedeutet, denn wer nicht viel Code ausführen muss, verschwendet weniger CPU-Zyklen und Speicher.
Pavel: Lassen Sie uns über TLS sprechen. Sehr oft stößt man an die Grenzen der Hardware, und alles fängt an, langsamer zu laufen, weil die Kryptoalgorithmen langsam sind. Wie löst OCaml dieses Problem, und löst es das Problem der Geschwindigkeit überhaupt? Beschleunigt OCaml den Code?
Hannes: Ja, OCaml selbst hat eine sehr schnelle Laufzeit. Wir haben einen Garbage Collector (einen Speicherverwalter), der sehr schnell sammelt. Die Frage ist im Grunde, ob OCaml es ermöglicht, eine Schnittstelle zu schreiben, die gut genug ist, um die Argumente korrekt weiterzugeben, und die nicht zu viel CPU-Zeit verschwendet. Tatsächlich ist OCaml schnell genug. Ich verwende gerne eine vernünftige Programmiersprache anstelle eines Low-Level-Mikro-Assemblers.
Und auf der anderen Seite der TLS haben wir die Handshakes. Es handelt sich dabei um asymmetrische Kryptographie, und um das schnell zu machen, verwenden wir die GMP/GNU-Multipräzisionsbibliothek. In OCaml haben wir dafür Bindings, aber das sind die Ausnahmen. Normalerweise versuchen wir, keine Bindings zu schreiben und nicht zu viel C-Code zu verwenden. Die meisten komplexen Teile der Entschlüsselung und Verschlüsselung befinden sich in OCaml, nicht in C.
Pavel: Haskell- und andere Programmierer von höheren Sprachen sind besorgt über die Leistung des Garbage Collectors und sagen, dass er den Code verlangsamt. In Haskell können sie keine „weichen Echtzeitanwendungen“ schreiben. Denken Sie, OCaml kann das? Ist der Garbage Collector von OCaml schnell genug, um in Anwendungsfällen zu funktionieren, die Geschwindigkeit erfordern?
Hannes: Ja, ich denke schon. Haskell hat eine völlig andere Laufzeit und verfügt standardmäßig über eine Lazy Evaluation bzw. faule Auswertung. OCaml ist dahingehend relativ strikt. Wir machen die Berechnung einfach im weiteren Verlauf. Der Garbage Collector ist sehr gut auf Workloads abgestimmt. Er ist wirklich schnell, und ich denke, dass in OCaml „weiche Echtzeitanwendungen“ durchaus realisierbar sind.
Pavel: Soweit ich weiß, ist der „Unikernel“ als Konzept nicht mehr nur bei OCaml anzutreffen. Was ist die Geschichte der Unikernels? War der Name dieser Idee schon immer der gleiche? Wie sind die Leute überhaupt auf die Idee von Unikernels gekommen?
Hannes: Ich denke, das alles begann an der Universität Cambridge mit den theoretischen Abhandlungen über den so genannten Exokernel. Es wurde ein Werkzeug gebraucht; ein System, das aufgabenorientiert, weniger ressourcenintensiv, leicht zu schreiben und leicht anzupassen war.
Pavel: Okay. Soweit mir bekannt ist, verwendet MirageOS die Lwt-Bibliothek. Ist Lwt performant genug, um eine vernünftigen Load zu bewältigen, wenn man einen DNS-Server hat, der schnell in mehrere Richtungen gleichzeitig antworten muss? Arbeitet die Bibliothek schnell genug?
Hannes: Meiner Meinung nach funktioniert sie ziemlich gut. Ein gutes Anwendungsbeispiel für MirageOS ist die Firewall, die in Qubes OS integriert ist. Qubes OS ist ein Betriebssystem, das Xen verwendet. Das Ziel von Qubes OS ist es zum Beispiel, die Mail-Anwendung vom PDF-Renderer zu trennen. Wenn man also eine E-Mail mit einer böswilligen PDF-Datei erhält, sollte diese, sobald man sie geöffnet hat, nicht mehr auf den gesamten Posteingang zugreifen können. Stattdessen wird die PDF-Datei gespeichert und auf eine andere, virtuelle Maschine verschoben. Und diese virtuelle Maschine verfügt über den Code, der den PDF-Renderer ausführt.
Die PDF-Datei wird also nur in einer isolierten Umgebung geöffnet und gerendert. MirageOS eignet sich dafür ziemlich gut, weil es einen viel kleineren Speicherbedarf hat. Wir können die Firewall einfach als eine der Komponenten innerhalb einer der virtuellen Maschinen innerhalb der Qubes OS-Umgebung einrichten und Pakete von anderen VMs empfangen, die Zugriff auf das Netzwerk haben. Der MirageOS-Unikernel arbeitet als Router, der die Pakete weiterleitet.
Pavel: Sie haben den Speicherverbrauch von MirageOS erwähnt. Wie viel Speicher kann das Betriebssystem tatsächlich haben? Wo liegen Ober- und Untergrenze? Ich habe gehört, dass MirageOS nicht für Speicher über 1 GB konfiguriert werden kann. Gibt es solche Einschränkungen tatsächlich?
Hannes:Im Moment gibt es diese. Die minimale Speichermenge der OCaml-Laufzeit und des MirageOS-Unikernels beträgt 10 Megabyte, und die obere Grenze liegt derzeit bei 1 GB. Aber das lässt sich im Grunde leicht anpassen, wenn Bedarf an mehr Speicher besteht. Meine DNS-Dienste benötigen zum Beispiel etwa 14–24 Megabyte Speicherplatz. Das sind nicht Millionen von Datensätzen, sondern eher Hunderte. Und die von mir betriebenen Webdienste haben in der Regel zwischen 32 und 128 Megabyte Speicher. Und das ist ausreichend, um die Daten zu speichern.
Pavel: Haben Sie mit dem Irmin-Datenspeicher gearbeitet? Soweit ich weiß, ist Irmin eine Art Git und der einzige Datenspeicher, der für MirageOS in OCaml geschrieben wurde.
Hannes: Genau. Irmin ist ein unveränderlicher Speicher, der mehrere Branches haben kann. Normalerweise benutze ich Irmin nicht direkt, aber ich verwendet es über die Git-Implementierung, bei der es im Hintergrund läuft. Zum Beispiel speichert mein DNS-Server seine Zonendatei in einem entfernten Git-Repository. Er holt sich einfach das Repository, klont es in den Speicher und stellt dann die Daten von dort aus bereit. Im Jahr 2019 ist eine nennenswerte neue Version erschienen, Irmin 2.0.
Pavel: Lassen Sie uns nun ein wenig über Ihre Treffen sprechen. Könnten Sie uns ein paar Dinge darüber erzählen, was MirageOS-Retreats sind? Wie sind Sie auf diese Idee gekommen?
Hannes: Ich wurde durch verschiedene Konferenzen und auch von den OpenBSD-Hackathons ziemlich inspiriert. Die Grundidee besteht darin, eine nette Gruppe von Menschen zusammenzubringen. Das Treffen findet an einem schönen Ort statt, der dazu einlädt die Zeit dort zu genießen. Für mich ist es enorm wichtig, dass die Menschen die meiste Zeit des Tages zusammen verbringen und miteinander kommunizieren. Es gibt keinen strengen Zeitplan. Es gibt eine tägliche Runde mit Updates darüber, wer was getan hat, wer sich für was interessiert und wer an welchem bestimmten Punkt stecken geblieben ist. Dort können sich die Teilnehmer austauschen und gegenseitig bei Fehlerbehebungen unter die Arme greifen. Die Einen diskutieren Probleme und deren Lösungen, während andere fleißig Programmieren.
Einerseits versuche ich, Leute hierher zu holen, die schon lange in der Community etabliert sind und viel Erfahrung und Ideen im Bezug auf die verschiedenen Bibliotheken und das Ökosystem haben. Dadurch bietet sich die Möglichkeit, vor Ort über fundamentale Veränderungen des Ökosystems zu diskutieren. Ich schätze es allerdings auch immer, einige neue Leute dabei zu haben. Sie bringen einen frischen Wind, können sich in die bestehende Gruppe integrieren und ein wenig mit OCaml und MirageOS programmieren, um einen Beitrag zur Community zu leisten. Das Retreat ist nicht nur für Leute, die MirageOS bereits kennen oder seit mehreren Jahren in OCaml schreiben, sondern steht allen offen, die Lust haben, eine Reise nach Marrakesch zu unternehmen.
Pavel: Das klingt großartig! Denken Sie, dass funktionale Programmierung die Denkweise des Programmierers beeinflusst? Als ich angefangen habe, OCaml-Code zu schreiben, wurde mir langsam klar, dass es Typen gibt, die transformiert werden können. Das hat mich dazu veranlasst, zuerst über die Arten und die Bedeutung der Daten nachzudenken, mit denen ich arbeite. Ich weiß, dass funktionales Programmieren in Europa ein Teil des Programmierstipendiums ist. Soweit mir bekannt ist, lernen die meisten Studenten in Russland das Programmieren anfangs mit imperativen Techniken, und dabei bleibt es überwiegend auch.
Hannes: Richtig. Ich denke viel über Typen nach und wende ziemlich viel typgesteuerte Denkweisen an, bevor ich den eigentlichen Code schreibe. Wenn ich also Programme in einer funktionalen Sprache schreibe, denke ich zuerst darüber nach, wie die Typen aussehen sollten. Sobald ich die Typen in die richtige Form gebracht habe, wird die gesamte Implementierung viel einfacher. Für mich geht es bei der funktionalen Programmierung um eine bessere Codepflege und ein besseres Programmverständnis. Und ich denke, mein Code ist in fünf Jahren einfacher zu verstehen, wenn er in einer funktionalen Sprache mit wenig syntaktischen Eigenheiten und Funktionen geschrieben ist. Das scheint mir sinnvoller, als einen Code mit imperativer Sprache zu schreiben, bei dem jede Funktion hunderte von Zeilen enthält. Ich versuche die Funktionen eher kurz und verständlich zu halten. Ja, funktionelle Programmierung bringt einen dazu, über das Programm nachzudenken.
Pavel: Mir ist aufgefallen, dass Monaden mittlerweile in vielen Sprachen zu finden sind. Es gibt sie in Ruby und in C++. Ist das nur eine Art, wie sich akademisches Wissen in der täglichen Programmierung umsetzen lässt?
Hannes:Ich glaube, Monaden sind ein brauchbares Instrument, aber unter Umständen schwer zu verstehen. Einem neuen imperativen Programmierer Monaden zu erklären, ist sehr schwierig. Wir verwenden nach wie vor Monaden in MirageOS und OCaml, aber mit dem Multicore-Branch, der irgendwann in diesem Jahr Teil der OCaml-Laufzeit wird, werden wir das hoffentlich hinter uns lassen.
Pavel: Lassen Sie uns ein bisschen über Open Source sprechen. Alles, worüber wir bisher gesprochen haben, ist Open Source. Es gibt den Standpunkt, dass eine Technologie nur dann erfolgreich ist, wenn genügend Geld in sie gepumpt wird. Während Open Source unsere Anstrengungen und unsere Zeit verschlingt, bringt es nicht wirklich Geld ein. Wenn man eine neue Technologie in einer öffentlichen Community preisgibt, landet man früher oder später bei einer Open-Source-Zusammenarbeit. Wie wichtig ist Open Source Ihrer Meinung nach?
Hannes: Ich denke, Open Source ist ein entscheidender Faktor. Der Großteil von dem, was wir eigentlich machen, ist das Entwickeln von OCaml-Bibliotheken, die dann in MirageOS-Unikernels verwendet werden. Und jeder sollte in der Lage sein, sie frei miteinander zu kombinieren. Wenn ich einen TLS-Stack oder eine DNS-Implementierung schreibe, habe ich einen starken Anreiz, all das als Open Source zu veröffentlichen, weil es dann andere Leute wiederverwenden können. Ich schreibe gerne Software, und es macht mich glücklich, wenn jemand meine Software benutzt, sei es eine Einzelperson oder ein Unternehmen, das sie für kommerzielle Zwecke nutzt. Das ist kein Problem für mich.
In MirageOS steht der größte Teil der Software unter einer BSD-Lizenz, so dass jeder sie benutzen und damit machen kann, was er will. Es ist meiner Meinung nach sehr wichtig, eine Lizenz zu haben. Jeder kann die GPL verstehen, aber sie besteht aus Unmengen von Textseiten, während die BSD zwei oder drei Absätze hat und normalerweise in 25 Textzeilen geschrieben ist. Und will man eine ganze Branche davon überzeugen, einen Teil seiner Software zu verwenden, ist es besser, wenn man eine freizügige Lizenz verwendet. Verwendet man eine GPL-Lizenz, kann man schwer jemanden davon überzeugen, die Software zu nutzen, vor allem keine Anwälte. In MirageOS zum Beispiel haben wir Code, der von IBM Research geschrieben wurde, und es ist uns gelungen, sie davon zu überzeugen, eine ziemlich freizügige Lizenz zu verwenden. Das war natürlich nicht einfach, weil Anwälte grundsätzlich an der Marke festhalten wollen.
Pavel: Ich habe gelesen, dass Sie für ein Unternehmen arbeiten, das Unikernel-Entwicklungen verkauft. Wie ist es, an einer Technologie zu arbeiten, die keine, sagen wir, etablierte, bekannte imperative Programmierung verkauft?
Hannes: Ich arbeite in einem gemeinnützigen Unternehmen namens Robur. Wir erhalten Zuschüsse, Spenden und kommerzielle Verträge zur Verbesserung des MirageOS-Ökosystems und zur Entwicklung von Unikernels.
Im vergangenen Jahr haben wir einige Gelder durch die Öffentlichkeit erhalten. Von Deutschland und der Europäischen Union wurden wir für die Entwicklung bestimmter Anwendungen wie z. B. OpenVPN Gateway bezuschusst, und aktuell finanziert die EU die Arbeit an einem DNSmasq, was eine der entscheidenden Komponenten aller Netzwerke ist. Und das ist wunderbar.
Pavel: Wie schnell hat sich MirageOS im Laufe der Zeit weiterentwickelt? Läuft die Entwicklung schnell ab, mit einer wachsenden Anzahl an Funktionen?
Hannes: Die Entwicklung geht immer recht langsam voran, aber wir leisten auch recht viel Arbeit. Wir versuchen, uns von unserer technischen Verschuldung zu befreien und uns an moderne Bausysteme anzupassen, was manchmal mehr Zeit in Anspruch nimmt als die anderen Projekte. Was die Funktionen betrifft, geht es vor allem darum, neue Bibliotheken zu entwickeln. Wir haben kurz über den Irmin DataStore gesprochen, und seine Version 2.0 war ein wichtiger Meilenstein, der erst im letzten Jahr veröffentlicht wurde. Es gibt auch einen kommenden TLS 1.3-Stack. Was MirageOS anbelangt, so sind wir jetzt auf dem Weg zu Version 4.0, und diese wird das Programmieren damit radikal verbessern, indem das alte „ocamlbuild“ abgeschafft und durch ein neues Build-System mit dem Namen „dune“ ersetzt wird, das inkrementelle Builds bietet.
Pavel: Lassen Sie uns unser Gespräch mit einer ermutigenden Erklärung an all die Programmierer abschließen, die MirageOS lernen, OCaml mit offenen Armen begrüßen und aufhören können, funktionale Programmierung als theoretischen Gedankenfresser zu fürchten. Wie würden Sie diese Leute ermutigen?
Hannes:Das Gute an FP ist der Grad der Kontrolle, den man über den ziemlich komplexen Code hat. Bei der funktionalen Programmierung könnte man, wenn man einen Fehler auf einer höheren Ebene entdeckt, diesen bis auf die niedrigste Ebene debuggen und innerhalb eines einzigen Wochenendes beheben. Auf gängigen Betriebssystemen ist das aufgrund der Größe der Codebasis und der beteiligten Bibliotheken schlicht unmöglich.
Man hat die Kontrolle über den gesamten Stack. Es handelt sich um eine Full-Stack-Entwicklung, vom Layer der Netzwerkgerätekarte bis hin zur Ausführung der Geschäftslogik und der realen Anwendung.
Hier bei Evrone sind wir bestrebt, auf dem neuesten Stand der technischen Entwicklung zu bleiben und innovative neue Tools und Methoden einzusetzen. So können wir die optimalen Ressourcen nutzen, um unseren Kunden die besten Lösungen für ihre individuellen Bedürfnisse zu bieten. Wir arbeiten mit einer Vielzahl von Programmiersprachen und -tools, und wir ermutigen unsere Teammitglieder, an technischen Konferenzen und Events, wie z. B. dem MirageOS-Retreat, teilzunehmen und Beiträge dazu zu leisten. Wenn Sie eine Idee haben, die Sie entwickeln möchten, lassen Sie uns wissen, wie wir Sie kontaktieren können. Wir werden uns bald mit Ihnen in Verbindung setzen, um Ihr Projekt zu besprechen und mit Ihnen gemeinsam herauszufinden, womit wir Ihnen weiterhelfen können.