lxd: Wechsel des zugrundeliegenden Images für einen Container

  • Hallo,


    Ich spiele gerade ein wenig mit lxd/lxc und einem ZFS Pool herum.


    Bei lxd hat man ja üblicherweise ein Image, aus dem man einen Container startet. Das Image kann z.B. ein Ubuntu-20.04 minimal sein, ich habs aus einem Online Repository geladen. Die Container kann man dann erweitern und u.a. spezifische Software für die jeweiligen Dienste installieren. Dabei wird aber meines Wissens nur die Differenz zum Image gespeichert. Alles, was sich nicht ändert, wird zur Laufzeit des Containers aus dem Image geladen und nicht noch mal separat gespeichert, was die Sache sehr effizient macht.

    Im ZFS Pool kann ich auch sehen, wie unter default/images das Image und unter "default/containers" die Container gespeichert sind, mit ihren jeweiligen Speicherplatz-Anforderungen.


    Nun wurde das Image automatisch aktualisiert. In der Folge wurde das veraltete Image unter "default/deleted/images" geschoben und bleibt da nun auch liegen, da es ja noch die Basis für die Container ist. Entsprechend hat sich der Speicherplatz-Bedarf im Pool deutlich erhöht, da nun eine zweite Instanz des Images gespeichert wurde, die im Grunde (zumindest bislang) nicht benötigt wird.


    Die Frage ist nun: Kann ich die Image Referenz der Container aktualisieren, so dass sie auf das neue Image zeigen und nicht mehr auf das alte? Dann könnte man das alte löschen. Mir ist klar, dass das nicht trivial ist, da der Inhalt der Images nicht 100% identisch ist. Eine Online Recherche hat nichts ergeben. Es gibt offensichtlich nur wenige Leute, die das Problem haben.

  • Die Frage ist nun: Kann ich die Image Referenz der Container aktualisieren, so dass sie auf das neue Image zeigen und nicht mehr auf das alte? Dann könnte man das alte löschen. Mir ist klar, dass das nicht trivial ist, da der Inhalt der Images nicht 100% identisch ist. Eine Online Recherche hat nichts ergeben. Es gibt offensichtlich nur wenige Leute, die das Problem haben.

    Ich würde nicht sagen, dass nur wenige Leute das Problem haben, aber es gibt keine "schöne" Lösung dafür. ;)

    Standardmäßig hat man es hier nicht mit einem "Overlay" der Containerinstanz "über" dem Basisabbild zu tun, welches einen Austausch "einfacher" machen würde, son­dern es wird der Umstand ausgenutzt, dass beim ZFS-Backend im Moment der Instantiierung lediglich Verweise auf die bereits existierenden Dateien im Pool dupliziert werden, anstatt die Dateien selbst zu duplizieren (copy-on-write, cow). [*]

    Möchte man das "Basisabbild" erneuern, sind im Wesentlichen neue Containerinstanzen zu erzeugen, in welchen dieselben Änderungen vorgenommen werden, wie sie bei den alten Containerinstanzen im Rahmen von Anwendungsinstallationen/Konfigurationsanpassungen abgespeichert wurden. Auf Anwenderebene geht das grund­sätz­lich wie folgt:

    • Seien BI1 das veraltete Basisabbild, COn (n=1..N) die darauf basierenden Container(instanz(en)) und BI2 ein neues Basisabbild
    • Generiere CO0 aus BI1, um den "Originalzustand" der COn vor Anpassung als Vergleich im Zugriff zu haben
    • Für alle COm (m=1..n):
      • Erstelle die Liste aller modifizierter Dateien/Verzeichnisse, welche sich gegenüber CO0 geändert haben (rsync kann das im "dry-run-Modus", wenn man sich beispielsweise zwischen CO0 und COm via ssh verbindet); ggf. auch zwischenzeitlich gelöschte Dateien berücksichtigen!
      • Generiere COm' auf Basis von BI2
      • Übertrage alle geänderte Dateien aus obigem Vergleich (etwa in Form eines tar-Archivs) von COm auf COm' (hierbei sollte man ggf. keine Dateien über­schreiben, die in COm' "noch" neuer sind als die Dateien, die man überträgt)
      • Prüfe, ob Container COm' wie erwartet funktioniert; wenn ja, lösche COm
    • Lösche CO0

    (Spezialdateien/Geräte könnten in seltenen Fällen ein Stolperstein sein, aber ich würde u. a. /dev zunächst vom Abgleich ausschließen.)

    Anstelle von rsync und der temporären Generierung von CO0 zum Zeitpunkt des Updates wäre es auch denkbar, einfach eine Prüfsummenliste aller Dateien in ein­em er­sten unveränderten Container basierend auf BI1 zu erzeugen und diese beim späteren Abgleich zu nutzen (Achtung, auch das Dateierstellungsdatum sollte hier als sinn­vol­les Vergleichskriterium mitgesichert werden; analog zu rsync sollten zudem ggf. auch gelöschte Dateien entsprechend vermerkt werden). Das hat den Vor­teil, dass man die Container auch zwi­schen­zeitlich auf andere LXC/LXD-Knoten verschieben kann, ohne auf die Archivierung/"Vorhaltung" von BI1 zu achten (dürfte Platz sparen). b3sum ist hier die schnell­ste mir be­kann­te Möglichkeit für die Erstellung derartiger Prüfsummen.

    Abgesehen vom Effizienzaspekt bei Verwendung des ZFS-Backends ist obiger Ansatz natürlich dateisystemagnostisch und funktioniert, solange eine Erneuerung ei­nes Basis­ab­bilds nicht mit Seiteneffekten einhergeht (Beispiel: ABI-Änderungen bei Basisbibliotheken, wodurch "nachinstallierte" Anwendungen, die hierauf zugreifen (wol­len), ohne Anpassung nicht mehr funktionieren).


    [*] Ein anderer Ansatz wäre natürlich, mit OverlayFS (oder besser: AuFS) zu hantieren, wenn es das zugrundeliegende Dateisystem unterstützt, aber auch das muss man händisch einrichten und dieser Ansatz ist eher noch aufwendiger und es gibt keine adäquaten "Bordmittel" für das ZFS-Backend in Kombination mit LXD.

    (Ich selbst habe testweise mehrere WordPress-Instanzen mit jeweiligen Theme-/Plugin-Schichten und einer einzigen WordPress-Basisinstallation mit AuFS und ZFS rea­li­siert, aber das ist mehr eine Machbarkeitsstudie denn eine "naheliegende" Lösung.)

    VServer IOPS Comparison Sheet: https://docs.google.com/spreadsheets/d/1w38zM0Bwbd4VdDCQoi1buo2I-zpwg8e0wVzFGSPh3iE/edit?usp=sharing