Isolieren von Entwicklungsumgebungen mit LXD-Containern

Ich werde über einen Ansatz zur Organisation lokaler isolierter Entwicklungsumgebungen auf meiner Workstation sprechen. Der Ansatz wurde unter dem Einfluss folgender Faktoren entwickelt:

  • Unterschiedliche Sprachen erfordern unterschiedliche IDEs und Toolchains;
  • Verschiedene Projekte können unterschiedliche Versionen von Toolchains und Bibliotheken verwenden.

Der Ansatz besteht darin, innerhalb von LXD-Containern zu entwickeln, die lokal auf einem Laptop oder einer Workstation ausgeführt werden, wobei die Grafikausgabe an den Host umgeleitet wird.

Beispielkonfiguration Ubuntu 20.04.

Überlegungen zu Optionen und Gründen finden Sie am Ende des Artikels.

1. LXD-Installation

В Ubuntu 20.04 LXD kann nicht mehr als Deb-Paket installiert werden, sondern nur noch per Snap:

$ snap install lxd

Nach der Installation müssen Sie eine Initialisierung durchführen:

$ lxd init

Der einzige Parameter, den ich ändere, ist storage bakend - ich verwende dir als die einfachste. Da ich keine Bilder und Kopien verwende, gelten die Warnhinweise in Dokumentation Sie machen mir keine Angst:

Ebenso ist das Verzeichnis-Backend als letzte Möglichkeit zu betrachten.
Es unterstützt zwar alle wichtigen LXD-Funktionen, ist jedoch furchtbar langsam und ineffizient, da es keine Leistung erbringt
Sofortkopien oder Snapshots erstellen und daher jedes Mal den gesamten Speicher der Instanz kopieren müssen.

2. Einrichtung des LXD-Profils

Profile in LXD – Hierbei handelt es sich um Parametersätze, die auf mehrere Container angewendet werden. Für meine Bedürfnisse reicht mir das einzige standardmäßig erstellte Profil default mit folgenden Änderungen:

  • $ lxc profile device add default X0 disk source=/tmp/.X11-unix/X0 path=/tmp/.X11-unix/X0 – damit Anwendungen in Containern mit dem Host-X11-Server interagieren können;
  • $ lxc profile set default environment.DISPLAY :0 - damit die Umgebungsvariable DISPLAY wurde korrekt in Container eingebaut;
  • $ lxc profile set default raw.idmap "both 1000 1000" - für das Richtige Identifier-Mapping.

3. Erstellen und Einrichten eines Containers

Erstellen eines Containers basierend auf einem Bild images:ubuntu/20.04:

$ lxc launch images:ubuntu/20.04 dev1

Ich bevorzuge Bilder aus dem Repository https://images.linuxcontainers.org, da sie weniger Software vorinstalliert haben. Aus diesem Grund habe ich das Präfix hinzugefügt images: zum Bildnamen. Das Erstellen eines Containers basierend auf einem Image aus dem Ubuntu-Repository kann wie folgt erfolgen: $ lxc launch ubuntu/20.04 dev1.

Zugriff auf die Root-Shell des Containers:

$ lxc exec dev1 -- bash

Ich werde Firefox und VS Code (aus dem Repository) installieren nach Anleitung):

$ apt update
$ apt install curl gpg firefox

$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
$ install -o root -g root -m 644 packages.microsoft.gpg /usr/share/keyrings/
$ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list

$ apt update
$ apt install code

Der Übersichtlichkeit halber füge ich einen Container hinzu.

poweroff

Bonus! Es ist ganz einfach, eine GPU in einen Container zu werfen, damit darin laufende Anwendungen die Grafikkarte nutzen können. Dazu benötigen Sie:

  • Gerät hinzufügen $ lxc config device add dev1 mygpu gpu;
  • Installieren Sie die Grafikkartentreiber im Container – dieselben, die auf dem Host installiert sind.

4. Verwendung eines Behälters

Wenn der Container noch nicht läuft, müssen Sie ihn starten:

lxc start dev1

Ausführen von VS Code als Nicht-Root-Benutzer ubuntu:

lxc exec dev1 -- sudo --login --user ubuntu code

Starten Sie Firefox:

lxc exec dev1 -- sudo --login --user ubuntu firefox

Anwendungsfenster werden auf dem Host angezeigt, aber innerhalb des Containers ausgeführt – ähnlich wie beim Weiterleiten von Grafiken per SSH.

Ich fahre laufende Container nicht manuell herunter, weil ich darin keinen großen Sinn sehe – ich beschränke mich darauf, die Fenster laufender Anwendungen zu schließen.

5. Заключение

Ich ziehe es vor, kein Host-Betriebssystem für die Entwicklung zu verwenden, da dies die Installation von Entwicklungstools, das Debuggen von Bibliotheksversionen, die spezifische Konfiguration von Systemkomponenten und andere Manipulationen erfordern würde. All dies kann zu unerwartetem Verhalten in anderer Nicht-Entwicklungssoftware oder sogar im gesamten Betriebssystem führen. Beispielsweise können Änderungen in der OpenSSL-Konfiguration dazu führen, dass das Betriebssystem nicht mehr ordnungsgemäß startet.

Ich habe verschiedene Tools ausprobiert, um Entwicklungsumgebungen zu isolieren:

  • virtuelle Maschinen (KVM, VirtualBox usw.) sind die naheliegendste Option, verbrauchen jedoch deutlich mehr Ressourcen, obwohl es keine anderen Optionen für die Entwicklung unter Windows gibt (wenn der Host Linux ist);
  • Cloud-Entwicklungstools, die auf einer lokalen Maschine ausgeführt werden (Cloud9 in einem Container oder einer virtuellen Maschine, Eclipse Che usw.) – sie sind nicht für diesen Betriebsmodus entwickelt, sie erfordern zusätzliche Konfiguration und Wartung, es ist am besten, sie bestimmungsgemäß zu verwenden Zweck - in der Cloud;
  • Docker-Container sind wiederum für etwas anderes gedacht; meiner Meinung nach eignen sie sich nicht sehr gut für die schnelle Prototypenerstellung mit Software, die noch nicht in separaten Containern verpackt ist.

Der gewählte Ansatz überzeugt mich durch seine Einfachheit und niedrige Einstiegshürde. In den Containern selbst können Sie projektspezifische Ansätze nutzen: alles manuell installieren und konfigurieren oder Automatisierung (Puppet, Ansible usw.) nutzen und sogar bereitstellen Docker-basierte Infrastruktur. Ich verwende LXD-Container auch, um bestimmte Software auszuführen, die entweder die Installation einer großen Anzahl von Abhängigkeiten oder einer anderen Betriebssystemversion erfordert – in diesem Fall kann man beispielsweise einen Container mit der gewünschten Betriebssystemversion erstellen $ lxc launch images:ubuntu/16.04 dev16.

Es ist wichtig zu bedenken, dass die Containerisierung im Hinblick auf die Isolation im Vergleich zur Virtualisierung eine größere Angriffsfläche bietet – Host und Container teilen sich einen einzigen Kern, eine Schwachstelle, die es Malware ermöglichen kann, aus dem Container zu entkommen. Beim Experimentieren mit zweifelhafter Software ist es besser, geeignetere Isolationsmechanismen zu verwenden.

Nützliche Links

Source: habr.com

Kommentar hinzufügen