Isolation der Entwicklungsumgebungen mit LXD-Containern

Ich werde über den Ansatz zur Organisation lokaler, isolierter Entwicklungsumgebungen auf meiner Arbeitsstation sprechen. Der Ansatz wurde unter dem Einfluss der folgenden Faktoren entwickelt:

  • für verschiedene Sprachen werden unterschiedliche IDEs und Toolchains benötigt;
  • in verschiedenen Projekten können unterschiedliche Versionen von Toolchains und Bibliotheken verwendet werden.

Der Ansatz besteht darin, die Entwicklung innerhalb von lokal auf dem Laptop oder der Arbeitsstation gestarteten LXD-Containern durchzuführen, wobei die grafische Ausgabe an den Host umgeleitet wird.

Konfiguration am Beispiel Ubuntu 20.04.

Überlegungen zu Optionen und Gründen sind am Ende des Artikels aufgeführt.

1. Installation von LXD

Im Ubuntu 20.04 LXD ist nicht mehr als deb-Paket installiert, sondern nur über snap:

$ snap install lxd

Nach der Installation muss die Initialisierung durchgeführt werden:

$ lxd init

Der einzige Parameter, den ich ändere, ist storage backend — ich benutze dir als die einfachste. Da ich keine Snapshots und Kopien verwende, erschrecken mich die Warnungen in Dokumentation nicht:

Um diesen Backend zu betrachten, sollte es als letzte Option betrachtet werden.
Es unterstützt alle wichtigsten LXD-Features, ist aber schrecklich langsam und ineffizient, da es keine
sofortigen Kopien oder Snapshots erstellen kann und daher bei jedem Zugriff den gesamten Speicher der Instanz kopieren muss.

2. Konfiguration des LXD-Profils

Profile in LXD sind Gruppen von Parametern, die auf mehrere Container angewendet werden. Für meine Bedürfnisse reicht mir das 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 in den Containern korrekt gesetzt wird;
  • $ lxc profile set default raw.idmap "beide 1000 1000" — für eine richtige ID-Mapping..

3. Erstellen und Einrichten des Containers

Einen Container auf Basis des Images images:ubuntu/20.04:

$ lxc launch images:ubuntu/20.04 dev1

Ich bevorzuge die Images aus dem Repository, weil sie weniger vorinstallierte Software enthalten. Aus diesem Grund habe ich ein Präfix https://images.linuxcontainers.orgzum Image-Namen hinzugefügt. Das Erstellen eines Containers aus einem Ubuntu-Repository-Image kann wie folgt erfolgen: images: $ lxc launch ubuntu/20.04 dev1 Zugriff auf die Root-Shell des Containers:.

$ lxc exec dev1 -- bash

Ich werde Firefox und VS Code installieren (aus dem Repository

gemäß Anleitung. gemäß der 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

Ich werde den Container zur Veranschaulichung aktivieren

Ausschalten

Bonus! Es ist ziemlich einfach, die GPU in den Container weiterzuleiten, damit die darin ausgeführten Anwendungen die Grafikkarte nutzen können. Dazu muss man:

  • ein Gerät hinzufügen $ lxc config device add dev1 mygpu gpu;
  • die Treiber der Grafikkarte im Container installieren – dieselben, die auf dem Host installiert sind.

4. Verwendung des Containers

Falls der Container noch nicht gestartet ist, muss er gestartet werden:

lxc start dev1

VS Code unter einem unprivilegierten Benutzer ausführen ubuntu:

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

Firefox starten:

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

Die Fenster der Anwendungen werden auf dem Host angezeigt, während sie im Container ausgeführt werden – ähnlich wie bei der Grafikweiterleitung über ssh.

Ich schalte die laufenden Container nicht manuell aus, da ich darin keinen besonderen Sinn sehe – ich beschränke mich auf das Schließen der Fenster der laufenden Anwendungen.

5. Fazit

Ich ziehe es vor, das Host-Betriebssystem nicht für die Entwicklung zu verwenden, da dies die Installation von Entwicklungstools, Debug-Versionen von Bibliotheken, die spezifische Konfiguration von Systemkomponenten und andere Manipulationen erfordern würde. All dies kann zu unerwartetem Verhalten anderer, nicht entwicklungsbezogener Software und sogar des gesamten Betriebssystems führen. Zum Beispiel können Änderungen in der OpenSSL-Konfiguration dazu führen, dass das Betriebssystem nicht mehr korrekt startet.

Ich habe verschiedene Mittel zur Isolierung von Entwicklungsumgebungen ausprobiert:

  • Virtuelle Maschinen (KVM, VirtualBox usw.) – die naheliegendste Option, verbraucht jedoch deutlich mehr Ressourcen, obwohl es für die Entwicklung unter Windows (wenn der Host Linux ist) keine anderen Optionen gibt;
  • Cloud-Entwicklungstools, die auf einem lokalen Rechner gestartet werden (Cloud9 in einem Container oder einer virtuellen Maschine, Eclipse Che usw.) – sie sind nicht für diesen Betriebsmodus entwickelt, erfordern zusätzliche Konfiguration und Wartung. Am besten nutzt man sie wie vorgesehen – in der Cloud;
  • Docker-Container sind, meiner Meinung nach, nicht ideal, um schnell Prototypen mit Software zu entwickeln, die noch nicht in separaten Containern verpackt ist.

Der gewählte Ansatz spricht mich aufgrund seiner Einfachheit und der geringen Einstiegshürde an. In den Containern können projektspezifische Ansätze angewendet werden: Entweder man installiert und konfiguriert alles manuell oder man nutzt Automatisierungstools (Puppet, Ansible usw.), um sogar das Rollout durchzuführen. Infrastruktur basierend auf Docker.Ich verwende auch LXD-Container, um spezifische Software auszuführen, die entweder viele Abhängigkeiten benötigt oder eine andere Version des Betriebssystems erfordert – in diesem Fall kann man einen Container mit der benötigten Version des Betriebssystems erstellen, zum Beispiel $ lxc launch images:ubuntu/16.04 dev16.

Es ist wichtig, sich daran zu erinnern, dass Containerisierung im Hinblick auf Isolation eine größere Angriffsoberfläche hat als Virtualisierung – der Host und der Container teilen sich denselben Kernel, und eine Schwachstelle darin kann es schadhafter Software ermöglichen, aus dem Container auszubrechen. Für Experimente mit fragwürdiger Software sind geeignetere Isolationsmechanismen die bessere Wahl.

Nützliche Links

Quelle: habr.com

60GB SSD 8Gb DDR4