Wir haben ChatGPT verwendet, um die Grammatik und Syntax des Transkripts zu verbessern.
Hallo, hallo zusammen! Ich hoffe, Sie hatten eine gute Kaffeepause. Danke, dass Sie an diesem Vortrag teilgenommen haben. Heute werde ich über Nix sprechen und ein wenig über die Zähmung der Container-Wartung.
Wer ich bin? Ich bin Jérôme Vieilledent, ein Produktmanager bei Platform.sh. Ja, ich weiß, dass es viele Platform.sh-Sprecher gibt, aber Sie können sich jederzeit an mich wenden, wenn Sie über das Produkt, Platform.sh oder einfach nur plaudern wollen. Ich bin hier am Stand.
Um diesen Vortrag einzuleiten, muss ich erklären, wie wir zu dieser Technologie gekommen sind, was manche vielleicht als unangenehm empfinden, aber eigentlich ist es großartig. Wir werden über Nix und seine Rolle bei der Verwaltung von Containern auf Platform.sh sprechen.
Lassen Sie uns zunächst über Container bei Platform.sh sprechen. Wir verwenden Container, aber wir verwenden nicht Docker, sondern LXC (Linux-Container). Diese Entscheidung wurde aus historischen Gründen getroffen. Als Platform.sh anfing, war Docker kaum experimentell, aber LXC war stabiler und bekannter, ähnlich wie BSD Jails oder Solaris Zonen.
Ja, wir verwenden Container, aber wir haben auch ein industrialisiertes Orchestrierungssystem. Wir verwenden nicht Kubernetes, sondern eine Software namens "Manufacturer", die wir hoffentlich eines Tages als Open Source veröffentlichen werden. Damit wird alles auf unserer Plattform orchestriert.
Eine weitere Tatsache ist, dass wir eine horizontale Plattform-as-a-Service (PaaS) betreiben. Unser Ziel ist es, eine Plattform zu sein, die jede Art von Anwendung hosten kann, unabhängig von der Laufzeit. In diesem Vortrag wird es hauptsächlich um PHP gehen, aber unsere Plattform unterstützt auch viele andere Laufzeiten. Die Wartung dieser Container ist eine Herausforderung. Allein für PHP haben wir 11 verschiedene Images, jedes mit unterschiedlichen Versionen von Debian und deren Abhängigkeiten. Es ist sogar möglich (wenn auch nicht empfohlen), eine PHP 5.4-Anwendung zu hosten.
Insgesamt unterstützt Platform.sh viele Laufzeiten - 71 Images allein für Anwendungen und 95 weitere für Dienste wie Datenbanken(Redis, Memcached), Suchmaschinen (Solr, Elasticsearch) und mehr. Insgesamt sind das 166 Images, die gewartet werden müssen. Wir haben drei Mitarbeiter, die sich hauptberuflich um all diese Dinge kümmern, und sie sind sehr gut in dem, was sie tun.
Aber das ist noch nicht alles. Ihre Anwendungen brauchen mehr als nur PHP. Zum Beispiel brauchen Sie vielleicht Tools wie ImageMagick für die Bildbearbeitung oder etwas, um Dateien in PDFs zu konvertieren. Lassen Sie uns über die zusätzlichen Pakete sprechen, die Sie in Ihren Containern benötigen.
Hier ist mein Wunschzettel für Weihnachten: Ich möchte PHP 8.3, das ich immer verwende, weil ich gerne auf dem neuesten Stand bin. Aber ich brauche auch PHP 7.2 für ein altes Build-Skript, das ich seit einem Jahrzehnt benutze. Ich will ImageMagick, aber ich will Version 6, nicht Version 7, weil ich zu faul bin, mich mit den Änderungen zu beschäftigen. Und ich brauche LibreOffice, um PDFs zu erzeugen.
Aber da gibt es ein Problem. Diese verschiedenen Abhängigkeiten arbeiten nicht immer gut zusammen. Das Ergebnis ist etwas, das wir "Abhängigkeitshölle" nennen. Stellen Sie sich vor, Sie versuchen, all diese verschiedenen PHP-Versionen und ihre Erweiterungen - zusammen mit älteren Python-Versionen - auf einmal zu kompilieren. Das würde wahrscheinlich scheitern und zu dem führen, was wir einen XKCD-Moment nennen, in dem Sie feststellen, dass Sie eine enorme Kette von Abhängigkeiten aufbauen, nur um sich selbst zu unterstützen.
Was ist also die Lösung? Nun, es gibt eine: Sie heißt Nix.
Okay, was ist Nix, und warum ist es so großartig? Nix ist ein funktionaler Paketmanager. Was bedeutet das? Zunächst einmal wird es von einer funktionalen Programmiersprache unterstützt. Dadurch können Pakete wie Werte behandelt werden, und da es funktional ist, können alle Funktionen, die zur Erzeugung von Paketen verwendet werden (die wir in Nix "Ableitungen" nennen), keine Seiteneffekte haben. Alles wird in völliger Isolation aufgebaut.
Wie erreichen wir das? Erstens ist es nicht möglich, nicht deklarierte Abhängigkeiten zu haben. Wenn Sie schon einmal .deb- oder .rpm-Dateien verwendet haben, sind Sie vielleicht schon einmal auf das Problem gestoßen, dass Abhängigkeiten nicht richtig deklariert sind. Das kann auch bei Paketmanagern wie Homebrew vorkommen. Aber in Nix ist es unmöglich, etwas zu bauen, ohne es explizit zu deklarieren.
Das Gute an Nix ist, dass man endlich sagen kann: "Das funktioniert auf meinem Rechner", und es auch so meinen kann. Wenn es auf Ihrem Rechner funktioniert, wird es auch auf einem anderen Rechner funktionieren. Es bietet Konsistenz über verschiedene Umgebungen hinweg.
Ein weiterer wichtiger Aspekt ist, dass alle Pakete in völliger Isolation erstellt werden. Wie das geht? Nix verwendet einen so genannten Nix-Speicher, der sich normalerweise unter /nix/store befindet. Alle Pakete werden dort gespeichert, und jedes Paket ist mit einem Hash verknüpft, der es und seine Abhängigkeiten eindeutig identifiziert. Dieser Hash basiert auf einer SHA-256-Prüfsumme und erfasst das Paket und alle seine Abhängigkeiten, wodurch die Isolierung gewährleistet wird.
Dieser Ansatz ermöglicht auch die Koexistenz mehrerer Versionen desselben Pakets. Sie könnten PHP 5.4 neben PHP 8.3 laufen lassen, ohne dass es zu Konflikten kommt. Das ist mit traditionellen Paketmanagern unglaublich schwierig zu erreichen.
Nix wird von einer funktionalen Sprache unterstützt, aber man muss nicht viel über sie lernen, um sie zu benutzen. Je mehr man sich jedoch mit Nix beschäftigt, desto mehr stößt man auf "Nix-Ausdrücke", d.h. Dateien, die in dieser funktionalen Sprache geschrieben sind. Es handelt sich um eine einfache Sprache, die JSON ähnelt, aber leistungsfähiger ist. Diese Nix-Ausdrücke werden ausgewertet, um Ableitungen zu erstellen. Jedes Mal, wenn Sie ein Nix-Paket erstellen, wird der Nix-Ausdruck, den Sie geschrieben haben (unter Angabe Ihrer Pakete und aller benötigten Shell-Hooks), zu einer neuen Ableitung im Nix-Speicher.
Nix wird auch von Nixpkgs unterstützt, dem größten Paket-Repository der Welt mit über 80.000 Paketen. Es ist im Wesentlichen ein riesiges GitHub-Repository, das Nix abfragt, wenn Sie etwas installieren möchten. Standardmäßig wird alles von Grund auf gebaut (kompiliert), aber es gibt auch einen Zwischenspeicher mit vorgefertigten Binärdateien für die meisten Plattformen, so dass Sie nicht immer alles selbst kompilieren müssen.
Um Ihnen ein Beispiel zu geben, sehen Sie hier ein altes Bild von Subversion und seinen Abhängigkeiten. Auf der linken Seite sehen Sie, wie es eigentlich funktionieren sollte. Sie wollen das Paket "hello", das von libc abhängt (weil alles von libc abhängt), und dann gibt es noch eine Abhängigkeit für eine bestimmte Version von libgmp. Das Problem ist, dass Sie, wenn Sie sich auf die libc Ihres Betriebssystems verlassen, Probleme bekommen könnten, wenn Sie versuchen, etwas zu kompilieren, das eine andere Version erwartet.
Diese Art von Abhängigkeitskonflikten kommt häufig vor, insbesondere bei Paketen wie Subversion, die eine bestimmte Version von OpenSSL oder Berkeley DB benötigen. Aber mit Nix ist alles isoliert und versioniert, so dass Sie diese Art von Konflikten vollständig vermeiden. Jedes Paket erhält seine eigene isolierte Umgebung, und dank des Hash-basierten Systems kann Nix mühelos mit mehreren Versionen desselben Pakets umgehen.
So, und jetzt wollen wir etwas Praktisches ausprobieren, eine kleine Demo. Ich will immer noch mein PHP 8.3, weil es rockt, und ich will meine "unheimliche" Erweiterung. Ich habe mich für eine namens SOAP entschieden - niemand benutzt mehr SOAP, richtig? Außer unter der Dusche, natürlich. Aber es ist ein gutes Beispiel.
Da ich mit einem Mac arbeite, möchte ich immer noch Python 2.7 (auch wenn es veraltet ist). Spoiler-Alarm: Wenn Sie versuchen, es mit Nix zu installieren, werden Sie gewarnt, dass es nicht sicher ist, und Sie müssen es außer Kraft setzen. Also habe ich eine spezielle Umgebungsvariable dafür hinzugefügt. Ich möchte auch ImageMagick, aber ich habe beschlossen, LibreOffice für diese Demo wegzulassen, weil es zu lange dauert, es zu bauen.
Versuchen wir es mal. Hierfür werde ich die Nix-Shell verwenden. Nix-shell ist ein Befehl, mit dem man eine temporäre Umgebung in seinem Terminal mit den gewünschten Paketen erstellen kann. Ich schalte es in den Verbose-Modus, damit Sie sehen können, was passiert. Ich habe alles vorab heruntergeladen, damit wir nicht 10 Minuten auf die Installation warten müssen.
Ich habe gesagt, dass ich PHP 8.3 möchte. Ich brauche also das PHP 8.3-Paket zusammen mit der SOAP-Erweiterung. Außerdem möchte ich Composer, weil ich das brauchen werde, und ich füge Python 2.7 und ImageMagick 6 hinzu.
Nix wertet hier alle Nix-Ausdrücke für jede Abhängigkeit der wenigen Pakete aus, die ich installiere. Wie Sie sehen können, gibt es eine Menge Abhängigkeiten. Das ist es, was hinter den Kulissen Ihres Betriebssystems passiert, wenn Sie versuchen, etwas zu bauen.
Schauen wir uns an, was ich im Moment auf meinem System ohne Nix habe. Ich habe PHP 8.2 installiert, aber ich habe nur Python 3, und es ist kein Python-Befehl verfügbar. Ich habe auch kein ImageMagick, das wir später brauchen werden.
Jetzt, nach der Verwendung von Nix, habe ich PHP 8.3, ImageMagick 6.7 (was sehr lange zum Kompilieren brauchte) und Python 2. Außerdem habe ich die SOAP-Erweiterung installiert, so dass wir jetzt eine metaphorische "Dusche" nehmen können.
Das ist im Grunde das, was Nix macht - es richtet eine Arbeitsumgebung mit allen Paketen ein, die man braucht. Aber es kann mühsam sein, jedes Paket für jede Shell-Sitzung manuell zu spezifizieren. Für das Testen neuer Software ist das großartig, aber Sie werden es irgendwann automatisieren wollen. Es gibt mehrere Möglichkeiten, dies zu tun, aber eine der einfachsten Methoden ist, ein Skript zu erstellen, das alles für Sie lädt.
Ich habe ein sehr einfaches Nix-Shell-Skript erstellt, das alle meine Eingaben und Abhängigkeiten deklariert. Es enthält sogar einen Shell-Hook, der "Hello Symfony" ausgibt, wenn es ausgeführt wird. Anstatt alle Optionen manuell einzugeben, kann ich jetzt einfach nix-shell ausführen, und alles wird automatisch für mich eingerichtet.
Das war der schicke Teil der Demo. Wir könnten es mit LibreOffice ausprobieren, aber dafür haben wir heute keine Zeit. Was das alles bedeutet, ist, dass wir mit Nix für unsere eigenen Systeme die Anzahl der Images, die wir pflegen müssen, von 166 auf ein einziges zusammensetzbares Image reduzieren können. Das ist ein großer Gewinn für uns.
Natürlich könnten wir immer noch ein paar verschiedene Images für bestimmte Dienste verwalten, aber der Punkt ist, dass Nix uns erlaubt, alles mit einem einzigen Image zu verwalten, das für verschiedene Bedürfnisse angepasst werden kann. Und wenn Sie Docker verwenden, können Sie mit Nix sogar richtige Docker-Images erzeugen, die aus Ihren Paketen erstellt werden, anstatt mit einem Docker-Image zu beginnen und später Dinge hinzuzufügen. Es gibt auch ein Nix-Image für Docker selbst, was das Hinzufügen von Paketen und Werkzeugen zu Ihrem Stack sehr viel einfacher macht.
Das ist nicht nur für uns bei der Wartung unserer Infrastruktur mit all den Containern nützlich, sondern auch für jeden, der mit der Abhängigkeitshölle zu kämpfen hat. Ich bin mir sicher, dass Sie alle schon einmal das Problem erlebt haben, dass Sie versuchen, etwas zu kompilieren, aber dafür eine bestimmte Bibliotheksversion benötigen, die wiederum von einer anderen Bibliotheksversion abhängt, und so weiter, bis Sie schließlich aufgeben. Dafür wurde Docker erfunden, oder? Um mit der Hölle der Abhängigkeiten fertig zu werden. Aber das kann immer noch passieren, sogar in Docker.
Das war's also im Grunde. Wir haben uns damit beschäftigt, wie Nix die Verwaltung von Abhängigkeiten und die Wartung von Containern vereinfachen kann. Nun, ich bin ein wenig früher fertig, also würde ich mich freuen, Fragen zu beantworten.
Wir haben noch etwas Zeit für Fragen. Oh, wir haben den Würfel, um das Mikrofon weiterzureichen.
Frage: Welches Basis-Image verwenden Sie für Ihre LXC-Container? Gibt es ein bestimmtes Basis-Image?
Antwort: Gute Frage! Wir verwenden Debian als Basis-Image. Wir verwenden LXC, und das Basis-Image ist so ziemlich das unbearbeitete Debian, es wird also von Grund auf neu erstellt.
Frage: Sie haben erwähnt, dass man eine Nix-Konfiguration von einer Maschine aus erstellen kann. Bedeutet das, dass die Versionen aller Pakete, die Sie auf dieser Maschine installiert haben, auf unbestimmte Zeit beibehalten werden?
Antwort: Ja, das ist genau richtig - bis Sie sich für ein Upgrade entscheiden. Nix erlaubt es Ihnen, Ihre Pakete so zu verwalten, dass Konsistenz gewährleistet ist. Und das bringt mich zu etwas, das ich vorhin nicht erwähnt habe: Nix kann auch als vollwertiges Betriebssystem verwendet werden. Sie können es benutzen, um alle Ihre Pakete zu verwalten und zu aktualisieren, wann immer Sie wollen.
Ihre Frage bezieht sich auf das Versions-Pinning. Wenn Sie z. B. PHP 8.3 angeben, wird PHP 8.3 bis zum Ende seines Lebenszyklus verwendet. Dann müssen Sie ein Upgrade auf PHP 8.4 oder die nächste Version durchführen. Das Gleiche gilt für andere Pakete. LibreOffice zum Beispiel hat zwei Kanäle: den frischen Kanal (mit den neuesten Funktionen) und den stabilen Kanal. Sie können wählen, welchem Kanal Sie folgen wollen.
Und selbst wenn Sie dem Hauptkanal für Nix-Pakete folgen, können Sie jederzeit eine bestimmte Paketversion anheften. Dazu verweisen Sie einfach auf den Commit in Nixpkgs, der der gewünschten Version entspricht, und schon sind Sie fertig. Das Paket wird nicht aktualisiert, es sei denn, Sie ändern die gepinnte Version manuell.
Frage: Wie teilen Sie Ihre Konfigurationen mit anderen Entwicklern? Übergeben Sie eine Nix-Datei, die alles enthält, oder erstellen Sie etwas und geben es dann als Paket weiter?
Antwort: Am einfachsten ist es, einen Nix-Ausdruck zu schreiben, wie ich es in der Demo getan habe. Aber anstatt dies nur für die Nix-Shell
zu tun, würden Sie eine umfangreichere Datei erstellen, die wahrscheinlich default.nix
heißt. Diese Datei würde Ihren gesamten Stack definieren. Dann kann jeder in Ihrem Team einfach nix-build
oder ein anderes Kommando ausführen, das Sie eingerichtet haben, und es wird alles entsprechend der Datei default.nix
gebaut.
Sie können es sogar noch einfacher machen, indem Sie ein Makefile erstellen, das den Nix-Befehl ausführt. Auf diese Weise kann jeder einfach make up
oder etwas Ähnliches eingeben und hat den gleichen Stack wie Sie. Es ist sehr einfach, es mit anderen Teams zu teilen.
Eine Frage: Gibt es einen Kompatibilitätsprozess mit Docker-Images oder Docker-Dateien?
Antwort: Nein: Nicht direkt, soweit ich weiß. Aber Nix hat Tools, die Ihnen helfen können, Docker-Images zu generieren, so dass alle Schichten des Images für Sie von Nix erstellt werden. Das ist eine Möglichkeit, dies zu tun. Es gibt zwar keine direkte Konvertierung von Docker-Dateien, aber Sie können Nix trotzdem verwenden, um Docker-Images zu erstellen.
Frage: Wie stellen Sie Nix bereit? Gibt es eine Plattform als Service für Nix?
Antwort: Ja: Für Platform.sh sind wir dabei, Nix als experimentelles Feature einzuführen. In ein paar Wochen werden Sie in der Lage sein, Ihren Stack in Ihrer YAML-Datei mit Nix zu definieren. Anstatt alle Abhängigkeiten manuell festzulegen, werden Sie einfach sagen: "Ich möchte PHP 8.3 und diese anderen Pakete", und es wird automatisch das Nix-Image verwendet.
Wir arbeiten noch daran, aber in Zukunft werden Sie vielleicht sogar in der Lage sein, eigene Nix-Ausdrücke direkt in Ihre YAML-Datei zu schreiben. Und ja, es gibt auch die Möglichkeit, Docker zusammen mit Nix zu verwenden. Es ist noch in der Entwicklung, aber Nix wird sehr bald in Platform.sh integriert.
Frage: Wenn ich Nix sowohl in meiner Entwicklungs- als auch in meiner Produktionsumgebung verwenden möchte, wie kann ich es dann am besten einsetzen? Soll ich einfach meine default.nix-Datei
pushen, oder gibt es einen anderen Ansatz?
Antwort: Im Moment wird Nix noch nicht vollständig für den Produktionseinsatz unterstützt. Ich würde das aber gerne mit Ihnen besprechen, denn wir sind sehr daran interessiert, Nix-basierte Bereitstellungen in der Produktion zu ermöglichen. Wir würden es gerne ermöglichen, Nix-Ausdrücke für Ihre Container zur Build-Zeit zu evaluieren, also lassen Sie uns nachher darüber sprechen, wie wir das möglich machen können.
Frage: Wie funktioniert Nix unter der Haube? Verwendet es eine Art von Preload-Magie oder statische Binärdateien für Abhängigkeiten?
Antwort: Gute Frage! Nix benutzt den Cache von cache.nixos.org. Dort gibt es eine riesige Plattform, die alle gängigen Pakete und Abhängigkeiten vorfertigt. Wenn das Paket, das Sie benötigen, nicht im Cache vorhanden ist, wird es einfach für Sie kompiliert. Und wenn Sie mehr Kontrolle haben wollen, können Sie jederzeit Ihren eigenen Cache einrichten. Damit können Sie alle Ihre Abhängigkeiten vorkompilieren und Ihre lokale Infrastruktur diese zuerst abholen lassen, bevor der Cache von NixOS sie aufnimmt.
Jérôme: In Ordnung, vielen Dank für die vielen Fragen. Das war's für den heutigen Vortrag. Nochmals vielen Dank für Ihre Teilnahme, und denken Sie daran, wenn Sie tiefer in Nix eintauchen wollen, finden Sie mich oder die anderen Mitglieder des Platform.sh-Teams hier. Und vergessen Sie nicht, der PHP-Stack-Maintainer für Nix ist auch im Raum - er versteckt sich, aber er ist hier und hat einige tolle Geschichten zu erzählen!
Vielen Dank, und ich hoffe, Sie genießen den Rest der Veranstaltung!