Die Grundfunktionen von LXD — dem Container-System in Linux

Die Grundfunktionen von LXD — dem Container-System in Linux

LXD ist ein System-Container-Manager der nächsten Generation, so wird gesagt Quelle. Er bietet eine Benutzeroberfläche, die virtualisierten Maschinen ähnelt, nutzt jedoch stattdessen Linux-Container.

Der LXD-Kern ist ein privilegierter Daemon (ein Dienst, der mit Root-Rechten läuft), der eine REST-API über einen lokalen Unix-Socket sowie über das Netzwerk bereitstellt, wenn die entsprechende Konfiguration eingerichtet ist. Clients, wie das Kommandozeilen-Tool, das mit LXD geliefert wird, senden Anfragen über diese REST-API. Das bedeutet, dass es unabhängig davon, ob Sie auf den lokalen Host oder auf einen entfernten zugreifen, alles gleich funktioniert.

In diesem Artikel werden wir nicht ausführlich auf die Konzepte von LXD eingehen und nicht alle verfügbaren Möglichkeiten behandeln, die in der Dokumentation beschrieben sind, einschließlich der neuesten Implementierung in den letzten LXD-Versionen für die Unterstützung von QEMU-VMs parallel zu Containern. Stattdessen konzentrieren wir uns auf die grundlegenden Funktionen der Containerverwaltung — wir konfigurieren Storage-Pools, Netzwerke, starten Container, setzen Ressourcengrenzen und betrachten, wie man Snapshots erstellt, damit Sie ein grundlegendes Verständnis von LXD erlangen und Container in Linux verwenden können.

Für umfassende Informationen wenden Sie sich bitte an die offizielle Quelle:

Navigation

Installation von LXD ^

Installation von LXD in Ubuntu-Distributionen ^

Im Ubuntu 19.10-Paket lxd gibt es eine Übersetzung zu Snap-Paket:

apt search lxd

lxd/eoan 1:0.7 all
  Übergangspaket - lxd -> snap (lxd)

Das bedeutet, dass zwei Pakete installiert werden, eines systembezogen und das andere als Snap-Paket. Die Installation von zwei Paketen im System kann ein Problem verursachen, bei dem das systemabhängige Paket ein Waisenkind wird, wenn das Snap-Paket vom Snap-Paket-Manager entfernt wird.

Paket finden lxd im Snap-Repository kann mit folgendem Befehl erfolgen:

snap find lxd

Name             Version        Summary
lxd              3.21           Systemcontainer-Manager und API
lxd-demo-server  0+git.6d54658  Online-Software-Demo-Sitzungen unter Verwendung von LXD
nova             ocata          OpenStack Compute Service (nova)
nova-hypervisor  ocata          OpenStack Compute Service - KVM Hypervisor (nova)
distrobuilder    1.0            Image-Bildersteller für LXC und LXD
fabrica          0.1            Snaps erstellen, indem man einfach ein Webformular anzeigt...
satellite        0.1.2          Fortgeschrittene skalierbare Open-Source-Intelligenzplattform

Führen Sie den Befehl aus Liste so kann man sicherstellen, dass das Paket lxd noch nicht installiert ist:

snap list

Name  Version    Rev   Tracking  Publisher   Notes
core  16-2.43.3  8689  stable    canonical✓  core

Obwohl LXD ein Snap-Paket ist, muss es über das Systempaket installiert werden lxd, das in der Systemumgebung die entsprechende Gruppe und benötigte Utilities erstellt /usr/bin usw.

sudo apt update
sudo apt install lxd

Überprüfen wir, dass das Paket als Snap-Paket installiert ist:

snap list

Name  Version    Rev    Tracking  Publisher   Notes
core  16-2.43.3  8689   stable    canonical✓  core
lxd   3.21       13474  stable/…  canonical✓  -

Installation von LXD in Arch Linux-Distributionen ^

Um das LXD-Paket im System zu installieren, müssen die folgenden Befehle ausgeführt werden: Der erste aktualisiert die Liste der im Repository verfügbaren Pakete, der zweite installiert das Paket direkt:

sudo pacman -Syyu && sudo pacman -S lxd

Nach der Installation des Pakets muss der Benutzer zur Systemgruppe hinzugefügt werden, um LXD zu verwalten lxd:

sudo usermod -a -G lxd user1

Lassen Sie uns sicherstellen, dass der Benutzer user1 der Gruppe hinzugefügt wurde lxd:

id -Gn user1

user1 adm dialout cdrom floppy sudo audio dip video plugdev netdev lxd

Wenn die Gruppe lxd nicht in der Liste sichtbar ist, muss die Benutzersitzung neu aktiviert werden. Dazu müssen Sie sich abmelden und wieder unter demselben Benutzer anmelden.

Aktivieren wir systemd den LXD-Dienst beim Systemstart:

sudo systemctl enable lxd

Starten Sie den Dienst:

sudo systemctl start lxd

Überprüfen Sie den Status des Dienstes:

sudo systemctl status lxd

LXD-Speicher (Storage) ^

Vor der Initialisierung müssen wir verstehen, wie der Speicher in LXD logisch organisiert ist.

Der Speicher (Speicher) besteht besteht aus einem oder mehreren Storage-Pool die ein unterstütztes Dateisystem wie ZFS, BTRFS, LVM oder normale Verzeichnisse verwenden. Jedes Storage-Pool wird in Volumes (Storage Volume) unterteilt, die Images, Container oder Daten für andere Zwecke enthalten.

  • Images sind speziell gebaute Distributionen ohne den Linux-Kernel und sind aus externen Quellen erhältlich
  • Container sind installierte Distributionen aus Images, die betriebsbereit sind
  • Snapshots sind Zustandsbilder von Containern, auf die zurückgegriffen werden kann

Die Grundfunktionen von LXD — dem Container-System in Linux

Zur Verwaltung des Speichers in LXD wird der Befehl lxc storage verwendet, dessen Hilfe Sie mit dem Schlüssel — lxc storage --help

Der folgende Befehl gibt eine Liste aller Storage-Pool im LXD Speicher aus:

lxc storage list

+---------+-------------+--------+--------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |             SOURCE             | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool |             | btrfs  | /dev/loop1                     | 2       |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool |             | btrfs  | /var/lib/lxd/disks/ssdpool.img | 4       |
+---------+-------------+--------+--------------------------------+---------+

Um die Liste aller Storage Volume im ausgewählten Storage-Pool zu sehen, verwenden Sie den Befehl lxc storage volume list:

lxc storage volume list hddpool

+-------+----------------------------------+-------------+---------+
| TYPE  |          NAME                    | DESCRIPTION | USED BY |
+-------+----------------------------------+-------------+---------+
| image | ebd565585223487526ddb3607f515... |             | 1       |
+-------+----------------------------------+-------------+---------+

lxc storage volume list ssdpool

+-----------+----------------------------------+-------------+---------+
|   TYPE    |            NAME                  | DESCRIPTION | USED BY |
+-----------+----------------------------------+-------------+---------+
| container | alp3                             |             | 1       |
+-----------+----------------------------------+-------------+---------+
| container | jupyter                          |             | 1       |
+-----------+----------------------------------+-------------+---------+
| image     | ebd565585223487526ddb3607f515... |             | 1       |
+-----------+----------------------------------+-------------+---------+

Außerdem, wenn für Storage-Pool Wenn das Dateisystem BTRFS bei der Erstellung ausgewählt wurde, um die Liste zu erhalten Storage Volume oder Subvolumes kann man in der BTRFS-Interpretation mit den Werkzeugen dieses Dateisystems:

sudo btrfs subvolume list -p /var/lib/lxd/storage-pools/hddpool

ID 257 gen 818 parent 5 top level 5 path images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3

sudo btrfs subvolume list -p /var/lib/lxd/storage-pools/ssdpool

ID 257 gen 1820 parent 5 top level 5 path images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
ID 260 gen 1819 parent 5 top level 5 path containers/jupyter
ID 263 gen 1820 parent 5 top level 5 path containers/alp3

Initialisierung von LXD ^

Vor der Erstellung und Verwendung von Containern ist es notwendig, eine allgemeine Initialisierung von LXD durchzuführen, die das Netzwerk sowie den Speicher erstellt und konfiguriert. Dies kann manuell mit den Standardbefehlen des Clients durchgeführt werden, die in der Liste durch den Befehl verfügbar sind lxc --help oder mithilfe des Initialisierungsassistenten lxd init nach Beantwortung einiger Fragen.

Auswahl des Dateisystems für den Storage-Pool ^

Während der Initialisierung stellt LXD mehrere Fragen, darunter die Bestimmung des Dateisystems für das Standard- Storage-Pool. Standardmäßig wird das Dateisystem BTRFS ausgewählt. Nach der Erstellung wird ein Wechsel zu einem anderen FS nicht möglich sein. Zur Auswahl des FS wird eine Vergleichstabelle der Funktionen angeboten:

Funktion
Verzeichnis
Btrfs
LVM
ZFS
CEPH

Optimierter Bildspeicher
nein
yes
yes
yes
yes

Optimierte Instanzenerstellung
nein
yes
yes
yes
yes

Optimierte Snapshot-Erstellung
nein
yes
yes
yes
yes

Optimierte Bildübertragung
nein
yes
nein
yes
yes

Optimierter Instanztransfer
nein
yes
nein
yes
yes

Copy on Write
nein
yes
yes
yes
yes

Blockbasiert
nein
nein
yes
nein
yes

Sofortiges Klonen
nein
yes
yes
yes
yes

Speicherfahrer innerhalb eines Containers nutzbar
yes
yes
nein
nein
nein

Wiederherstellung aus älteren Snapshots (nicht die neuesten)
yes
yes
yes
nein
yes

Speicherquoten
ja(*)
yes
yes
yes
nein

Netzwerk- und Storage-Pool-Initialisierung mit dem Assistenten ^

Die nächste Kommando, das wir betrachten, bietet die Möglichkeit, die grundlegenden LXD-Komponenten durch einfache Fragen mithilfe des Initialisierungsassistenten zu konfigurieren.

Führen Sie den Befehl aus lxc init und geben Sie die Antworten auf die Fragen nach dem Doppelpunkt ein, wie im folgenden Beispiel gezeigt, oder ändern Sie diese gemäß Ihren Anforderungen:

lxd init

Möchten Sie LXD-Cluster verwenden? (ja/nein) [Standard=no]: 
Möchten Sie einen neuen Speicherpool konfigurieren? (ja/nein) [Standard=ja]: 
Name des neuen Speicherpools [Standard=default]: ssdpool         
Name des zu verwendenden Speicher-Backends (lvm, btrfs, dir) [Standard=btrfs]: 
Möchten Sie einen neuen BTRFS-Pool erstellen? (ja/nein) [Standard=ja]: 
Möchten Sie ein bestehendes Blockgerät verwenden? (ja/nein) [Standard=nein]: 
Größe in GB des neuen Loop-Geräts (min. 1GB) [Standard=15GB]: 10GB
Möchten Sie sich mit einem MAAS-Server verbinden? (ja/nein) [Standard=nein]: 
Möchten Sie eine neue lokale Netzwerkbrücke erstellen? (ja/nein) [Standard=ja]: 
Wie sollte die neue Brücke genannt werden? [Standard=lxdbr0]: 
Welche IPv4-Adresse sollte verwendet werden? (CIDR-Subnetznotation, „auto“ oder „none“) [Standard=auto]: 10.0.5.1/24
Möchten Sie, dass LXD IPv4-Verkehr über Ihre Brücke NAT? [Standard=ja]: 
Welche IPv6-Adresse sollte verwendet werden? (CIDR-Subnetznotation, „auto“ oder „none“) [Standard=auto]: none
Soll LXD im Netzwerk verfügbar sein? (ja/nein) [Standard=nein]: 
Wünschen Sie, dass veraltete zwischengespeicherte Bilder automatisch aktualisiert werden? (ja/nein) [Standard=ja] nein
Möchten Sie, dass ein YAML-Vorabgenehmigungs-„lxd init“ ausgedruckt wird? (ja/nein) [Standard=nein]: 

Erstellung eines zusätzlichen Storage-Pools ^

Im vorherigen Schritt haben wir Storage-Pool einen Namen gegeben: ssdpool und die Datei befindet sich in meinem System unter der Adresse /var/lib/lxd/disks/ssdpool.img. Diese Adresse im Dateisystem entspricht der physischen SSD in meinem PC.

Um ein besseres Verständnis der Rolle zu erlangen, die Storage-Pool im Speicher spielt, werden wir einen zweiten Storage-Pool erstellen, der physisch auf einem anderen Typ von Festplatte, nämlich einer HDD, gespeichert werden soll. Das Problem ist, dass LXD keine Storage-Pool außerhalb der Adresse zulässt /var/lib/lxd/disks/ und selbst symbolische Links werden nicht funktionieren, siehe die Antwort des Entwicklers. Wir können diese Einschränkung umgehen, indem wir bei der Initialisierung/Formatierung Storage-Pool den Wert als Blockgerät angeben, anstatt einen Pfad zur Loopback-Datei in den Schlüssel einzutragen. source.

Um also Storage-Pool zu erstellen, müssen wir zuerst eine Loopback-Datei oder eine vorhandene Partition in Ihrem Dateisystem bestimmen, die sie verwenden wird. Dazu werden wir eine Datei erstellen und sie auf 10GB begrenzen:

dd if=/dev/zero of=/mnt/work/lxd/hddpool.img bs=1MB count=10000

10000+0 Datensätze eingelesen
10000+0 Datensätze ausgegeben
10000000000 Bytes (10 GB, 9,3 GiB) kopiert, 38,4414 s, 260 MB/s

Wir verbinden die Loopback-Datei mit einem freien Loopback-Gerät:

sudo losetup --find --show /mnt/work/lxd/hddpool.img

/dev/loop1

Dank des Schlüssels --show Die Ausführung des Befehls zeigt den Namen des Geräts an, mit dem unsere Loopback-Datei verbunden ist. Falls nötig, können wir eine Liste aller belegten Geräte dieses Typs anzeigen, um die Richtigkeit unserer Aktionen zu überprüfen:

losetup -l

NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                      DIO LOG-SEC
/dev/loop1         0      0         0  0 /mnt/work/lxd/hddpool.img        0     512
/dev/loop0         0      0         1  0 /var/lib/lxd/disks/ssdpool.img   0     512

Aus der Liste ist zu erkennen, dass auf dem Gerät /dev/loop1 die Loopback-Datei verbunden ist /mnt/work/lxd/hddpool.img, und auf dem Gerät /dev/loop0 die Loopback-Datei verbunden ist /var/lib/lxd/disks/ssdpool.img das dem Standard entspricht Storage-Pool.

Der nächste Befehl erstellt einen neuen Storage-Pool in LXD basierend auf der gerade vorbereiteten Loopback-Datei. LXD wird die Loopback-Datei /mnt/work/lxd/hddpool.img auf dem Gerät /dev/loop1 mit dem BTRFS-Dateisystem formatieren:

lxc storage create hddpool btrfs size=10GB source=/dev/loop1

Lassen Sie uns eine Liste aller Storage-Pool anzeigen:

lxc storage list

+---------+-------------+--------+--------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |             SOURCE             | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool |             | btrfs  | /dev/loop1                     | 0       |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool |             | btrfs  | /var/lib/lxd/disks/ssdpool.img | 0       |
+---------+-------------+--------+--------------------------------+---------+

Erhöhung der Größe des Storage-Pools ^

Nach der Erstellung Storage-Pool, wenn nötig, kann es erweitert werden. Für Storage-Pool führen Sie die folgenden Befehle aus, um das auf dem BTRFS-Dateisystem basierende System zu konfigurieren:

sudo truncate -s +5G /mnt/work/lxd/hddpool.img
sudo losetup -c /dev/loop1
sudo btrfs filesystems resize max /var/lib/lxd/storage-pools/hddpool

Automatisches Einfügen einer Loopback-Datei in den Loopback-Geräteslot ^

Wir haben ein kleines Problem: Wenn das Host-System neu gestartet wird, wird die Datei /mnt/work/lxd/hddpool.img "vom Gerät entfernt" /dev/loop1 und der LXD-Dienst wird beim Starten abstürzen, da er sie nicht in diesem Gerät findet. Um dieses Problem zu lösen, müssen wir einen Systemdienst erstellen, der diese Datei beim Systemstart in das Gerät einfügt. /dev/loop1 beim Booten des Host-Systems.

Lassen Sie uns unit eine Datei vom Typ service in /etc/systemd/system/ für das Systeminit-System SystemD:

cat << EOF | sudo tee -a /etc/systemd/system/lxd-hddpool.service
[Unit]
Description=Losetup LXD Storage Pool (hddpool)
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img
RemainAfterExit=true

[Install]
WantedBy=local-fs.target
EOF

Aktivieren Sie den Dienst:

sudo systemctl enable lxd-hddpool

Erstellt Symlink /etc/systemd/system/local-fs.target.wants/lxd-hddpool.service → /etc/systemd/system/lxd-hddpool.service.

Nach dem Neustart des Host-Systems überprüfen wir den Status des Dienstes:

systemctl status lxd-hddpool.service 

● lxd-hddpool.service - Losetup LXD Speicherpool (hddpool)
     Geladen: geladen (/etc/systemd/system/lxd-hddpool.service; aktiviert; Werkseinstellung: deaktiviert)
     Aktiv: aktiv (beendet) seit Mi 2020-04-08 03:43:53 MSK; vor 1min 37s
    Prozess: 711 ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img (Code=beendet, Status=0/ERFOLG)
   Haupt-PID: 711 (Code=beendet, Status=0/ERFOLG)

apr 08 03:43:52 manjaro systemd[1]: Starte Losetup LXD Speicherpool (hddpool)...
apr 08 03:43:53 manjaro systemd[1]: Losetup LXD Speicherpool (hddpool) abgeschlossen.

Aus der Ausgabe können wir schließen, dass der Status des Dienstes aktiv, auch wenn die Ausführung unseres Skripts aus einem einzigen Befehl beendet wurde, ermöglichte uns die Option RemainAfterExit=true.

Sicherheit. Berechtigungen von Containern ^

Da alle Prozesse des Containers tatsächlich isoliert im Host-System unter Verwendung seines Kernels ausgeführt werden, bietet LXD zur zusätzlichen Sicherung des Zugriffs der Containerprozesse auf das Host-System die Privilegierung der Prozesse, wobei:

  • Privilegierte Container — das sind Container, in denen Prozesse mit UID und GID dem gleichen Eigentümer entsprechen wie auf dem Hostsystem. Zum Beispiel hat ein Prozess, der in einem Container mit UID gleich 0 läuft, die gleichen Zugriffsrechte wie ein Prozess des Hostsystems mit UID gleich 0. Mit anderen Worten, der Root-Benutzer im Container hat alle Rechte nicht nur im Container, sondern auch auf dem Hostsystem, wenn er außerhalb des isolierten Namensraums des Containers gelangen kann.

  • Unprivilegierte Container — das sind Container, in denen die Prozesse einem Eigentümer mit UID und GID im Bereich von 0 bis 65535 gehören. Für das Hostsystem wird der Eigentümer jedoch durch das Hinzufügen des SubUID- und SubGID-Bits maskiert. Beispielsweise wird ein Benutzer mit UID=0 im Container im Hostsystem als SubUID + UIDsichtbar. Dies schützt das Hostsystem, da, wenn ein Prozess im Container sein isoliertes Namensraum verlassen kann, er nur als ein Prozess mit unbekannter, sehr hoher UID/GID mit dem Hostsystem interagieren kann.

Standardmäßig haben neu erstellte Container den Status unprivilegiert, daher müssen wir SubUID und SubGID definieren.

Wir erstellen zwei Konfigurationsdateien, in denen wir die Maske für SubUID und SubGID festlegen:

sudo touch /etc{/subuid,/subgid}
sudo usermod --add-subuids 1000000-1065535 root 
sudo usermod --add-subgids 1000000-1065535 root

Um die Änderungen anzuwenden, muss der LXD-Dienst neu gestartet werden:

sudo systemctl restart lxd

Erstellung eines virtuellen Netzwerk-Switches ^

Da wir zuvor das Netzwerk mit dem Initialisierungsassistenten eingerichtet haben lxd init und ein Netzwerkgerät erstellt haben lxdbr0, werden wir in diesem Abschnitt einfach das Netzwerk in LXD kennenlernen und wie man mit dem Client-Befehl einen virtuellen Switch (Bridge) erstellt.

Das folgende Schema zeigt, wie der Switch (Bridge) den Host und die Container im Netzwerk vereint:

Die Grundfunktionen von LXD — dem Container-System in Linux

Container können über das Netzwerk mit anderen Containern oder dem Host, auf dem diese Container gehostet werden, interagieren. Dazu müssen die virtuellen Netzwerkkarten der Container mit dem virtuellen Switch verbunden werden. Zunächst erstellen wir den Switch, und die Netzwerkinterfaces der Container werden in den folgenden Kapiteln verbunden, nachdem der Container selbst erstellt wurde.

Der folgende Befehl erstellt einen Switch mit einem Subnetz 10.0.5.0/24 und einer IPv4-Adresse 10.0.5.1/24, und aktiviert ipv4.nat damit Container über den Host mit Hilfe des NAT-Dienstes auf das Internet zugreifen können:

lxc netzwerk erstellen lxdbr0 ipv4.adresse=10.0.5.1/24 ipv4.nat=true ipv6.adresse=none

Überprüfen der Liste der verfügbaren Netzwerkgeräte für LXD:

lxc netzwerk liste

+--------+----------+---------+-------------+---------+
|  NAME  |   TYPE   | VERWALTET | BESCHREIBUNG | VERWENDET VON |
+--------+----------+---------+-------------+---------+
| eno1   | physisch | NEIN      |             | 0       |
+--------+----------+---------+-------------+---------+
| lxdbr0 | brücke   | JA      |             | 0       |
+--------+----------+---------+-------------+---------+

Das Erstellen des Netzwerkgeräts kann auch mit dem Standardwerkzeug der Linux-Distribution überprüft werden — ip link oder ip addr:

ip addr

1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eno1:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether bc:ee:7b:5a:6b:44 brd ff:ff:ff:ff:ff:ff
    altname enp0s25
    inet6 fe80::9571:11f3:6e0c:c07b/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: lxdbr0:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether c2:38:90:df:cb:59 brd ff:ff:ff:ff:ff:ff
    inet 10.0.5.1/24 scope global lxdbr0
       valid_lft forever preferred_lft forever
    inet6 fe80::c038:90ff:fedf:cb59/64 scope link 
       valid_lft forever preferred_lft forever
5: veth3ddab174@if4:  mtu 1500 qdisc noqueue master lxdbr0 state UP group default qlen 1000
    link/ether ca:c3:5c:1d:22:26 brd ff:ff:ff:ff:ff:ff link-netnsid 0

Konfigurationsprofil ^

Jeder Container in LXD verfügt über eine eigene Konfiguration, die durch global deklarierte Konfigurationen ergänzt werden kann, die als Konfigurationsprofilebezeichnet werden. Die Anwendung von Konfigurationsprofilen auf einen Container folgt einem kaskadierenden Modell, das folgendes Beispiel veranschaulicht:

Die Grundfunktionen von LXD — dem Container-System in Linux

In diesem Beispiel wurden im LXD-System drei Profile erstellt: default, hddpool und hostfs. Alle drei Profile werden auf den Container angewendet, der eine lokale Konfiguration (graue Zone) hat. Profil default verfügt über ein Gerät root bei dem der Parameter pool gleich ist ssdpool, aber dank des kaskadierenden Modells zur Anwendung von Konfigurationen können wir für den Container ein Profil anwenden hddpool bei dem der Parameter pool dieses gleiche Parameter aus dem Profil überschreiben default und der Container erhält die Gerätekonfiguration root mit dem Parameter pool gleich hddpool, während das Profil hostfs ein neues Gerät einfach zum Container hinzufügt.

Um die Liste der verfügbaren Konfigurationsprofile anzuzeigen, dient der folgende Befehl:

lxc profile list

+---------+---------+
| NAME    | USED BY |
+---------+---------+
| default | 1       |
+---------+---------+
| hddroot | 0       |
+---------+---------+
| ssdroot | 1       |
+---------+---------+

Eine vollständige Liste der verfügbaren Befehle zur Arbeit mit Profilen erhalten Sie mit dem Schlüssel --help:

lxc profile --help

Beschreibung:
  Profile verwalten

Verwendung:
  lxc profile [Befehl]

Verfügbare Befehle:
  add         Profile zu Instanzen hinzufügen
  assign      Profile-Sets Instanzen zuweisen
  copy        Profile kopieren
  create      Profile erstellen
  delete      Profile löschen
  device      Geräte von Instanzen verwalten
  edit        Profilkonfigurationen als YAML bearbeiten
  get         Werte für Profilkonfigurationsschlüssel abrufen
  list        Profile auflisten
  remove      Profile von Instanzen entfernen
  rename      Profile umbenennen
  set         Profilkonfigurationsschlüssel setzen
  show        Profilkonfigurationen anzeigen
  unset       Profilkonfigurationsschlüssel zurücksetzen

Profil bearbeiten ^

Standardkonfigurationsprofil default Es gibt keine Netzwerkkonfiguration für den Container, und alle neu erstellten Container haben kein Netzwerk. Daher müssen separate lokale (dedizierte) Netzwerkgeräte mit einem eigenen Befehl erstellt werden. Wir können jedoch ein globales Netzwerkgerät im Konfigurationsprofil erstellen, das von allen Containern, die dieses Profil verwenden, gemeinsam genutzt wird. Somit haben die Container sofort nach dem Befehl zur Erstellung eines neuen Containers Zugang zum Netzwerk. Es gibt dabei keine Einschränkungen; wir können immer später ein lokales Netzwerkgerät erstellen, falls dies erforderlich ist.

Der nächste Befehl fügt dem Konfigurationsprofil ein Gerät hinzu. eth0 Typ nic das zum Netzwerk verbunden ist. lxdbr0:

lxc profile device add default eth0 nic network=lxdbr0 name=eth0

Es ist wichtig zu beachten, dass wir, da wir ein Gerät in das Konfigurationsprofil eingefügt haben, wenn wir eine statische IP-Adresse im Gerät angeben, alle Container, die dieses Profil anwenden, die gleiche IP-Adresse teilen würden. Wenn es notwendig ist, einen Container mit einer dedizierten statischen IP-Adresse zu erstellen, sollte eine Netzwerkkonfigurationsdatei auf Containerebene (lokale Konfiguration) mit der IP-Adresse als Parameter erstellt werden, und nicht auf Profilebene.

Überprüfen wir das Profil:

lxc profile show default

config: {}
description: Standard LXD-Profil
devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  root:
    path: /
    pool: ssdpool
    type: disk
name: default
used_by: []

In diesem Profil können wir sehen, dass für alle neu erstellten Container zwei Geräte (devices) erstellt werden:

  • eth0 — Gerätetyp nic verbunden mit dem Switch (Netzwerkbrücke) lxdbr0
  • root — Gerätetyp disk das den Speicherkreis verwendet ssdpool

Neue Profile erstellen ^

Um die zuvor erstellten Storage-Pool Container zu nutzen, erstellen wir ein Konfigurationsprofil ssdroot in dem wir einen Gerätetyp hinzufügen disk mit dem Mount-Punkt / (root), das das zuvor erstellte Storage-Poolssdpool:

lxc profile create ssdroot
lxc profile device add ssdroot root disk path=/ pool=ssdpool

Ebenso erstellen wir einen Gerätetyp disk, aber in diesem Fall verwendet Storage-Poolhddpool:

lxc-profile create hddroot
lxc-profile device add hddroot root disk path=/ pool=hddpool

Überprüfen der Konfigurationsprofile:

lxc profile show ssdroot

config: {}
beschreibung: ""
geräte:
  root:
    pfad: /
    pool: ssdpool
    typ: disk
name: ssdroot
used_by: []

lxc profile show hddroot

config: {}
beschreibung: ""
geräte:
  root:
    pfad: /
    pool: hddpool
    typ: disk
name: hddroot
used_by: []

Image-Repository ^

Container werden aus Images erstellt, die speziell zusammengestellte Distributionen sind und keinen Linux-Kernel enthalten. Daher muss der Container, bevor er gestartet werden kann, aus diesem Image erstellt werden. Die Quelle der Images ist ein lokales Repository, in das die Images aus externen Repositories geladen werden.

Remote Image-Repositories ^

Standardmäßig ist LXD so konfiguriert, dass es Images aus drei entfernten Quellen bezieht:

  • ubuntu: (für stabile Ubuntu-Images)
  • ubuntu-daily: (für tägliche Ubuntu-Images)
  • images: (für eine Reihe anderer Distributionen)

lxc remote list

+-----------------+------------------------------------------+--------+--------+
|      NAME       |                   URL                    | ÖFFENTLICH | STÁTISCH |
+-----------------+------------------------------------------+--------+--------+
| images          | https://images.linuxcontainers.org       | JA     | NEIN   |
+-----------------+------------------------------------------+--------+--------+
| local (default) | unix://                                  | NEIN   | JA     |
+-----------------+------------------------------------------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | JA     | JA     |
+-----------------+------------------------------------------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | JA     | JA     |
+-----------------+------------------------------------------+--------+--------+

Zum Beispiel hat das Repository ubuntu: die folgenden Images:

lxc image -c dasut list ubuntu: | head -n 11

+----------------------------------------------+--------------+----------+------------+
|                   BESCHREIBUNG              | ARCHITEKTUR  |   GRÖSSE  |   TYP      |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150728)  | x86_64       | 153.72 MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150819)  | x86_64       | 152.91 MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150906)  | x86_64       | 154.69 MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150930)  | x86_64       | 153.86 MB | CONTAINER  |
+----------------------------------------------+--------------+----------+------------+

Um eine begrenzte Anzahl von Spalten anzuzeigen, haben wir die Option verwendet -c mit den Parametern dasut, und außerdem haben wir die Länge der Liste mit dem Befehl begrenzt head.

Für die Ausgabe der Liste von Bildern steht eine Filterung zur Verfügung. Der folgende Befehl gibt eine Liste aller verfügbaren Architekturen des Distributionen aus AlpineLinux:

lxc image -c ldast liste images:alpine/3.11

+------------------------------+--------------------------------------+--------------+
|            ALIAS             |             BESCHREIBUNG              | ARCHITEKTUR  |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11 (3 weitere)      | Alpine 3.11 amd64 (20200220_13:00)   | x86_64       |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/arm64 (1 weiteres) | Alpine 3.11 arm64 (20200220_13:00)   | aarch64      |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/armhf (1 weiteres) | Alpine 3.11 armhf (20200220_13:00)   | armv7l       |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/i386 (1 weiteres)  | Alpine 3.11 i386 (20200220_13:01)    | i686         |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/ppc64el (1 weiteres) | Alpine 3.11 ppc64el (20200220_13:00) | ppc64le      |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/s390x (1 weiteres)  | Alpine 3.11 s390x (20200220_13:00)   | s390x        |
+------------------------------+--------------------------------------+--------------+

Lokales Image-Repository ^

Um mit dem Betrieb des Containers zu beginnen, müssen Sie ein Image aus dem globalen Repository in das lokale hinzufügen. local:. Das lokale Repository ist derzeit leer, was uns der Befehl lxc image list. Wenn das Repository im Liste nicht angegeben wird, wird standardmäßig das lokale Repository verwendet — local:

lxc image list local:

+-------+-------------+--------+-------------+--------------+------+------+
| ALIAS | FINGERPRINT | PUBLIC | BESCHREIBUNG | ARCHITEKTUR | TYP | GRÖSSE |
+-------+-------------+--------+-------------+--------------+------+------+

Die Verwaltung von Images im Repository erfolgt durch die folgenden Methoden:

Der Befehl
Beschreibung

lxc image alias
Alias von Images verwalten

lxc image copy
Bilder zwischen Servern kopieren

lxc image löschen
Images löschen

lxc image bearbeiten
Bildeigenschaften bearbeiten

lxc image exportieren
Images exportieren und herunterladen

lxc image importieren
Images in das Image-Repository importieren

lxc image info
Nützliche Informationen über Images anzeigen

lxc image Liste
Images auflisten

lxc image aktualisieren
Images aktualisieren

lxc image anzeigen
Bildeigenschaften anzeigen

Wir kopieren das Image aus dem globalen Repository in das lokale Repository. images::

lxc image copy images:alpine/3.11/amd64 local: --alias=alpine3

Image erfolgreich kopiert!

Lass uns die Liste aller derzeit im lokalen Repository verfügbaren Images anzeigen. local::

lxc image -c lfdatsu list local:

+---------+--------------+------------------------------------+--------------+
|  ALIAS  | FINGERPRINT  |            BESCHREIBUNG            | ARCHITEKTUR |
+---------+--------------+------------------------------------+--------------+
| alpine3 | 73a3093d4a5c | Alpine 3.11 amd64 (20200220_13:00) | x86_64       |
+---------+--------------+------------------------------------+--------------+

LXD-Konfiguration ^

Neben dem interaktiven Modus unterstützt LXD auch den nicht-interaktiven Installationsmodus, bei dem die Konfiguration in Form einer YAML-Datei festgelegt wird. Dieses spezielle Format ermöglicht es, die gesamte Konfiguration auf einmal einzurichten, ohne dass mehrere interaktive Befehle ausgeführt werden müssen, wie in diesem Artikel bereits erläutert, einschließlich Netzwerkkonfiguration, Erstellung von Konfigurationsprofilen usw. Diese Aspekte werden hier nicht weiter behandelt; Sie können sich jedoch eigenständig darüber informieren. in der Dokumentation.

Der nächste interaktive Befehl lxc config den wir betrachten werden, ermöglicht es, die Konfiguration festzulegen. Um beispielsweise zu verhindern, dass die heruntergeladenen Images im lokalen Repository automatisch aus globalen Repositories aktualisiert werden, können wir dieses Verhalten mit dem folgenden Befehl aktivieren:

lxc config set images.auto_update_cached=false

Container erstellen und verwalten ^

Der Befehl zum Erstellen eines Containers lautet lxc init dem die Werte übergeben werden repository:image und anschließend die gewünschte ID für den Container. Das Repository kann als lokal angegeben werden. local: so wie jedes globale. Wenn kein Repository angegeben ist, wird standardmäßig das lokale Repository zur Suche nach dem Image verwendet. Wenn das Image aus einem globalen Repository angegeben ist, wird es zunächst in das lokale Repository geladen und dann zur Erstellung des Containers verwendet.

Führen Sie den folgenden Befehl aus, um unseren ersten Container zu erstellen:

lxc init alpine3 alp --storage=hddpool --profile=default --profile=hddroot

Lassen Sie uns die Schlüssel der Befehlszeile, die wir hier verwenden, der Reihe nach aufschlüsseln:

  • alpine3 — Dies ist der Alias (Pseudonym) für das Image, das zuvor im lokalen Repository gespeichert wurde. Wenn für dieses Image kein Alias erstellt wurde, kann immer auf das Image über dessen Fingerprint zugegriffen werden, der in der Tabelle angezeigt wird.
  • alp — Dies ist die Kennung für den Container.
  • --storage — Dieser Schlüssel gibt an, in welchem Storage-Pool Container erstellt wird.
  • --profile — Diese Schlüssel wenden die Konfiguration früherer erstellter Konfigurationsprofile kaskadierend auf den Container an.

Starten Sie den Container, der das Init-System der Distribution startet:

lxc start alp

Sie können auch den Befehl lxc launch verwenden, der es ermöglicht, die Befehle lxc init und lxc start in eine Operation zu kombinieren.

Überprüfen des Containerstatus:

lxc list -c ns46tb
+------+---------+------------------+------+-----------+--------------+
| NAME |  STATUS |       IPV4       | IPV6 |   TYPE    | STORAGE POOL |
+------+---------+------------------+------+-----------+--------------+
| alp  | LÄUFT  | 10.0.5.46 (eth0) |      | CONTAINER | hddpool      |
+------+---------+------------------+------+-----------+--------------+

Überprüfen der Containerkonfiguration:

lxc config show alp

architektur: x86_64
konfiguration:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200326_13:39)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200326_13:39"
  image.type: squashfs
  volatile.base_image: ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
  volatile.eth0.host_name: vethb1fe71d8
  volatile.eth0.hwaddr: 00:16:3e:5f:73:3e
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.power: LÄUFT
geräte:
  root:
    path: /
    pool: hddpool
    type: disk
ephemeral: false
profile:
- default
- hddroot
stateful: false
beschreibung: ""

Im Abschnitt profile wir können prüfen, dass dieser Container zwei Konfigurationsprofile verwendet — default und hddroot. In dem Abschnitt geräte Wir können nur ein Gerät erkennen, da das Netzwerkgerät auf Profilebene erstellt wurde. defaultUm alle vom Container verwendeten Geräte zu sehen, muss der Schlüssel hinzugefügt werden. --expanded:

lxc config show alp --expanded

architektur: x86_64
konfiguration:
  image.architektur: amd64
  image.beschreibung: Alpine 3.11 amd64 (20200326_13:39)
  image.betriebssystem: Alpine
  image.version: "3.11"
  image.serial: "20200326_13:39"
  image.typ: squashfs
  volatile.base_image: ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
  volatile.eth0.host_name: vethb1fe71d8
  volatile.eth0.hwaddr: 00:16:3e:5f:73:3e
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.power: RUNNING
geräte:
  eth0:
    name: eth0
    netzwerk: lxdbr0
    typ: nic
  root:
    pfad: /
    pool: hddpool
    typ: disk
ephemeral: false
profile:
- default
- hddroot
zustand: false
beschreibung: ""

Statische IP-Adresse einrichten ^

Wenn wir versuchen, eine IP-Adresse für das Netzwerkgerät einzurichten, eth0 mit dem Befehl lxc config device set alp der zur Konfiguration des Containers dient, erhalten wir einen Fehler, der besagt, dass das Gerät nicht existiert, weil das Gerät eth0 das von dem Container verwendete gehört zum Profil default:

lxc config device set alp eth0 ipv4.address 10.0.5.5

Fehler: Das Gerät existiert nicht

Selbstverständlich können wir eine statische IP-Adresse für eth0 das Gerät im Profil festlegen, aber sie wird für alle Container, die dieses Profil verwenden, gleich sein. Daher fügen wir ein dediziertes Gerät für den Container hinzu:

lxc config device add alp eth0 nic name=eth0 nictype=bridged parent=lxdbr0 ipv4.address=10.0.5.5

Dann müssen wir den Container neu starten:

lxc restart alp

Wenn wir uns jetzt die Konfiguration des Containers anschauen, müssen wir die Option nicht anwenden --expanded um das Netzwerkgerät zu sehen eth0, da wir es auf Containerebene erstellt haben und es dieses Gerät aus dem Profil kaskadierend überdeckt. default:

lxc config show alp

architektur: x86_64
konfiguration:
  bild.architektur: amd64
  bild.beschreibung: Alpine 3.11 amd64 (20200326_13:39)
  bild.os: Alpine
  bild.version: "3.11"
  bild.serial: "20200326_13:39"
  bild.typ: squashfs
  volatile.basisebild: ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
  volatile.eth0.host_name: veth2a1dc59d
  volatile.eth0.hwaddr: 00:16:3e:0e:e2:71
  volatile.idmap.bas: "0"
  volatile.idmap.aktuell: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.idmap.nächster: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":65536}]'
  volatile.last_state.leistung: LÄUFT
geräte:
  eth0:
    ipv4.adresse: 10.0.5.5
    name: eth0
    nictype: bridged
    parent: lxdbr0
    typ: nic
  root:
    pfad: /
    pool: hddpool
    typ: disk
ephemer: false
profile:
- standard
- hddroot
zustandsbehaftet: false
beschreibung: ""

Container entfernen ^

Um einen Container zu entfernen, verwenden Sie den Befehl lxc delete, aber bevor Sie den Container löschen, muss er mit dem Befehl lxc stop:

lxc stop alp

lxc list

+------+---------+-------------------+------+-----------+-----------+
| NAME |  STATE  |       IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+------+---------+-------------------+------+-----------+-----------+
| alp  | STOPPED | 10.0.5.10 (eth0)  |      | CONTAINER | 0         |
+------+---------+-------------------+------+-----------+-----------+

Nachdem wir sichergestellt haben, dass der Zustand des Containers STOPPED, kann es entfernt werden von Storage-Pool:

lxc delete alp

Zugriff auf den Container ^

Um Befehle direkt im Container auszuführen, ohne die Netzverbindungen zu nutzen, wird der Befehl lxc exec verwendet, der Befehle im Container ohne die Ausführung einer Shell erfüllt. Wenn Sie einen Befehl in einer Shell ausführen möchten, unter Verwendung von Shell-Mustern wie Variablen, Dateiweiterleitungen (Pipe) usw., müssen Sie die Shell explizit starten und den Befehl als Schlüssel übergeben, zum Beispiel:

lxc exec alp -- /bin/sh -c "echo $HOME"

In dem Befehl wurde ein Escape-Zeichen verwendet für das Sonderzeichen $ damit die Variable $HOME nicht auf der Hostmaschine interpretiert wird, sondern nur innerhalb des Containers.

Es ist auch möglich, den interaktiven Modus der Shell zu starten und die Sitzung dann mit der Hotkey-Taste zu beenden CTRL+D:

lxc exec alp -- /bin/sh

Containerressourcen verwalten ^

In LXD können die Ressourcen des Containers mittels einer speziellen Konfiguration verwaltet werden. Eine vollständige Liste der Konfigurationsparameter für Container finden Sie in der Dokumentation.

RAM-Ressourcenbeschränkung ^

Parameter limits.memory beschränkt den verfügbaren RAM für den Container. Der Wert sollte eine Zahl und einen der verfügbaren Suffixe.

festlegen. Lassen Sie uns dem Container ein RAM-Limit von 256 MB zuweisen:

lxc config set alp limits.memory 256MB

Es gibt auch andere Parameter zur Einschränkung des Arbeitsspeichers:

  • limits.memory.enforce
  • limits.memory.hugepages
  • limits.memory.swap
  • limits.memory.swap.priority

Der Befehl lxc config show zeigt die gesamte Konfiguration des Containers an, einschließlich der angewendeten Ressourcenschränkung, die gesetzt wurde:

lxc config show alp

architektur: x86_64
konfiguration:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200220_13:00)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200220_13:00"
  image.type: squashfs
  limits.memory: 256MB
  volatile.base_image: 73a3093d4a5ce0148fd84b95369b3fbecd19a537ddfd2e2d20caa2eef0e8fd60
  volatile.eth0.host_name: veth75b6df07
  volatile.eth0.hwaddr: 00:16:3e:a1:e7:46
  volatile.idmap.base: "0"
  volatile.idmap.current: '[]'
  volatile.idmap.next: '[]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
geräte: {}
ephemeral: false
profile:
- standard
zustandsgebunden: false
beschreibung: ""

CPU-Ressourcenbeschränkung ^

Für die Einschränkung der CPU-Ressourcen gibt es mehrere Arten von Beschränkungen:

  • limit.cpu verknüpft den Container mit einem oder mehreren CPU-Kernen
  • limits.cpu.allowance reguliert entweder die CFS-Planungskontingente, wenn das Zeitlimit überschreitet, oder einen allgemeinen Mechanismus zur gemeinsamen Nutzung der CPU-Ressourcen, wenn der Prozentsatz überschreitet
  • limits.cpu.priority — Priorität des Planers, wenn mehrere Instanzen, die einen gemeinsamen CPU-Satz nutzen, denselben Prozentsatz an CPUs zugewiesen bekommen.

lxc config set alp limits.cpu.allowance 40%

lxc config show alp

architecture: x86_64
config:
  image.architecture: amd64
  image.description: Alpine 3.11 amd64 (20200220_13:00)
  image.os: Alpine
  image.release: "3.11"
  image.serial: "20200220_13:00"
  image.type: squashfs
  limits.cpu.allowance: 40%
  limits.memory: 256MB
  volatile.base_image: 73a3093d4a5ce0148fd84b95369b3fbecd19a537ddfd2e2d20caa2eef0e8fd60
  volatile.eth0.host_name: veth75b6df07
  volatile.eth0.hwaddr: 00:16:3e:a1:e7:46
  volatile.idmap.base: "0"
  volatile.idmap.current: '[]'
  volatile.idmap.next: '[]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
devices: {}
ephemeral: false
profiles:
- default
stateful: false
description: ""

Speicherplatzbeschränkung ^

Neben Einschränkungen wie limits.read, limits.write können wir auch den von einem Container genutzten Speicherplatz begrenzen (funktioniert nur mit ZFS oder BTRFS):

lxc config device set alp root size=2GB

Nach der Einrichtung im Parameter devices.root.size können wir die gesetzte Beschränkung überprüfen:

lxc config show alp
...
devices:
  root:
    path: /
    pool: hddpool
    size: 2GB
    type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""

Um die verwendeten Disk-Quoten einzusehen, können wir den Befehl verwenden lxc info:

lxc info alp
...
Ressourcen:
  Prozesse: 5
  Speicherplatz:
    Root: 1,05 GB
  CPU-Nutzung:
    CPU-Nutzung (in Sekunden): 1
  Speicher-Nutzung:
    Speicher (aktuell): 5,46 MB
  Netzwerk-Nutzung:
    eth0:
      Empfangen Bytes: 802 B
      Gesendet Bytes: 1,59 kB
      Empfangen Pakete: 4
      Gesendet Pakete: 14
    lo:
      Empfangen Bytes: 0 B
      Gesendet Bytes: 0 B
      Empfangen Pakete: 0
      Gesendet Pakete: 0

Trotz der Tatsache, dass wir das Limit für das Root-Gerät des Containers auf 2 GB festgelegt haben, werden System-Utilities wie df dieses Limit nicht erkennen. Dafür werden wir einen kleinen Test durchführen und herausfinden, wie das funktioniert.

Lassen Sie uns 2 identische Container im selben Storage-Pool (hddpool):

lxc init alpine3 alp1 --storage=hddpool --profile=default --profile=hddroot
lxc init alpine3 alp2 --storage=hddpool --profile=default --profile=hddroot

lxc list
+------+---------+------------------+------+-----------+-----------+
| NAME |  STATUS  |       IPV4       | IPV6 |   TYP     | SNAPSHOTS |
+------+---------+------------------+------+-----------+-----------+
| alp1 | LÄUFT   | 10.0.5.46 (eth0) |      | CONTAINER | 0         |
+------+---------+------------------+------+-----------+-----------+
| alp2 | LÄUFT   | 10.0.5.30 (eth0) |      | CONTAINER | 0         |
+------+---------+------------------+------+-----------+-----------+

In einem der Container erstellen wir eine Datei mit einer Größe von 1 GB:

lxc exec alp1 -- dd if=/dev/urandom of=file.img bs=1M count=1000

Lassen Sie uns sicherstellen, dass die Datei erstellt wurde:

lxc exec alp1 -- ls -lh
total 1000M  
-rw-r--r--    1 root     root     1000,0M Mär 27 10:16 file.img

Wenn wir den zweiten Container betrachten und die Existenz der Datei am gleichen Ort überprüfen, wird diese Datei nicht vorhanden sein, was zu erwarten ist, da die Container ihre eigenen Umgebungen erstellen. Storage Volume am gleichen Ort Storage-Pool:

lxc exec alp2 -- ls -lh
total 0

Lassen Sie uns jedoch die Werte vergleichen, die ausgegeben werden df in den beiden Containern:

lxc exec alp1 -- df -hT
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/loop1           btrfs           9.3G   1016.4M      7.8G  11% /
...

lxc exec alp2 -- df -hT
Filesystem           Type            Size      Used Available Use% Mounted on
/dev/loop1           btrfs           9.3G   1016.4M      7.8G  11% /
...

Gerät /dev/loop1 das als Root-Partition gemountet ist, ist Storage-Pool welches diese Container verwenden, daher teilen sie sich dessen Speicherplatz.

Ressourcenverbrauchsstatistik ^

Die Ressourcennutzung für den Container kann mit dem folgenden Befehl angezeigt werden:

lxc info alp

Name: alp
Location: none
Remote: unix://
Architecture: x86_64
Created: 2020/04/08 18:05 UTC
Status: Running
Type: container
Profiles: default, hddroot
Pid: 19219
Ips:
  eth0: inet    10.0.5.5        veth2a1dc59d
  eth0: inet6   fe80::216:3eff:fe0e:e271        veth2a1dc59d
  lo:   inet    127.0.0.1
  lo:   inet6   ::1
Resources:
  Processes: 5
  Disk usage:
    root: 495.62kB
  CPU usage:
    CPU usage (in seconds): 1
  Memory usage:
    Memory (current): 4.79MB
  Network usage:
    eth0:
      Bytes received: 730B
      Bytes sent: 1.59kB
      Packets received: 3
      Packets sent: 14
    lo:
      Bytes received: 0B
      Bytes sent: 0B
      Packets received: 0
      Packets sent: 0

Mit Snapshots arbeiten ^

In LXD besteht die Möglichkeit, Snapshots zu erstellen und den Zustand des Containers daraus wiederherzustellen.

Um einen Snapshot zu erstellen, führen Sie den folgenden Befehl aus:

lxc snapshot alp snapshot1

Der Befehl lxc snapshot verfügt nicht über einen Schalter Liste, daher müssen Sie den Befehl verwenden, der allgemeine Informationen über den Container anzeigt, um die Liste der Snapshots anzuzeigen:

lxc info alp
...
...
Snapshots:
  snapshot1 (aufgenommen am 2020/04/08 18:18 UTC) (stateless)

Den Container aus einem Snapshot können Sie mit dem Befehl wiederherstellen lxc restore indem Sie den Container angeben, für den die Wiederherstellung durchgeführt werden soll, und den Alias des Snapshots:

lxc restore alp snapshot1

Der folgende Befehl dient dazu, einen Snapshot zu löschen. Beachten Sie, dass die Syntax des Befehls von allen anderen abweicht; hier muss ein direkter Schrägstrich nach dem Containernamen angegeben werden. Wenn der Schrägstrich weggelassen wird, wird der Befehl zum Löschen des Snapshots als Befehl zum Löschen des Containers interpretiert!

lxc delete alp/snapshot1

Im obigen Beispiel haben wir die sogenannten stateless-Snapshots betrachtet. In LXD gibt es auch einen anderen Typ von Snapshots — stateful, bei denen der aktuelle Zustand aller Prozesse im Container gespeichert wird. Mit stateful-Snapshots sind eine Reihe interessanter und nützlicher Funktionen verbunden.

Was noch? ^

  • Für Python-Entwickler ist das Modul PyLXD verfügbar, das eine API zu LXD bereitstellt.

UPDATE 10.04.2020 15:00: Navigation hinzugefügt.

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster