
LXD — è un gestore di container di nuova generazione, così si afferma . Offre un'interfaccia utente simile a quella delle macchine virtuali, ma utilizza invece i container Linux.
Il kernel LXD — è un demone privilegiato (servizio eseguito con diritti di root), che fornisce un'API REST tramite un socket unix locale, così come attraverso la rete, se configurato di conseguenza. Clienti come l'utility da riga di comando fornita con LXD inviano richieste tramite questa API REST. Ciò significa che, indipendentemente dal fatto che tu stia accedendo all'host locale o a uno remoto, tutto funziona allo stesso modo.
In questo articolo non approfondiremo i concetti di LXD e non esamineremo tutte le funzionalità disponibili nella documentazione, inclusa la recente implementazione del supporto per macchine virtuali QEMU parallele ai contenitori nelle ultime versioni di LXD. Invece, ci concentreremo solo sulle funzionalità di base della gestione dei contenitori: configureremo i pool di archiviazione, la rete, avvieremo un contenitore, applicheremo limiti sulle risorse e vedremo come utilizzare gli snapshot, in modo da ottenere una comprensione di base di LXD e utilizzare i contenitori in Linux.
Per informazioni complete, consultare la fonte ufficiale:
Navigazione
Installazione di LXD
Installazione di LXD nelle distribuzioni Ubuntu
Nel pacchetto di Ubuntu 19.10, il pacchetto lxd ha una transizione verso :
apt search lxd
lxd/eoan 1:0.7 all
Pacchetto di transizione - lxd -> snap (lxd)Ciò significa che saranno installati due pacchetti contemporaneamente, uno di sistema e l'altro come pacchetto snap. L'installazione di due pacchetti nel sistema può creare alcuni problemi, in cui il pacchetto di sistema potrebbe diventare orfano se il pacchetto snap viene rimosso dal gestore di pacchetti snap.
Trovare il pacchetto lxd nel repository snap è possibile con il seguente comando:
snap find lxd
Nome Versione Riepilogo
lxd 3.21 Gestore di contenitori di sistema e API
lxd-demo-server 0+git.6d54658 Sessioni di demo software online utilizzando LXD
nova ocata Servizio di calcolo OpenStack (nova)
nova-hypervisor ocata Servizio di calcolo OpenStack - Hypervisor KVM (nova)
distrobuilder 1.0 Costruttore di immagini per LXC e LXD
fabrica 0.1 Costruisci snap indicando semplicemente un modulo web a...
satellite 0.1.2 Piattaforma avanzata di intelligence open source scalabileEsegui il comando list è possibile verificare che il pacchetto lxd non è ancora installato:
snap list
Nome Versione Rev Tracking Editore Note
core 16-2.43.3 8689 stable canonical✓ coreNonostante LXD sia un pacchetto snap, deve essere installato tramite il pacchetto di sistema lxd, che creerà nel sistema il gruppo corrispondente, le utility necessarie in /usr/bin ecc.
sudo apt update
sudo apt install lxdAssicuriamoci che il pacchetto sia installato come pacchetto snap:
snap list
Nome Versione Rev Tracking Editore Note
core 16-2.43.3 8689 stable canonical✓ core
lxd 3.21 13474 stable/… canonical✓ -Installazione di LXD nelle distribuzioni Arch Linux
Per installare il pacchetto LXD nel sistema, è necessario eseguire i seguenti comandi; il primo attualizza l'elenco dei pacchetti disponibili nel repository, il secondo installa direttamente il pacchetto:
sudo pacman -Syyu && sudo pacman -S lxdDopo l'installazione del pacchetto, per gestire LXD come utente normale, è necessario aggiungerlo nel gruppo di sistema lxd:
sudo usermod -a -G lxd user1Assicuriamoci che l'utente user1 sia stato aggiunto al gruppo lxd:
id -Gn user1
user1 adm dialout cdrom floppy sudo audio dip video plugdev netdev lxdSe il gruppo lxd non appare nell'elenco, allora è necessario riattivare la sessione dell'utente. Per fare ciò, esci e rientra nel sistema con lo stesso utente.
Attiviamo systemd il caricamento del servizio LXD all'avvio del sistema:
sudo systemctl enable lxdAvviamo il servizio:
sudo systemctl start lxdControlliamo lo stato del servizio:
sudo systemctl status lxdArchiviazione LXD (Storage)
Prima di iniziare l'inizializzazione, è necessario comprendere come è strutturato logicamente lo storage in LXD.
Lo storage (Storage) da uno o più Storage Pool che utilizza uno dei file system supportati, come ZFS, BTRFS, LVM o directory normali. Ogni Storage Pool è suddiviso in volumi (Storage Volume) che contengono immagini, contenitori o dati per altri scopi.
- Le immagini sono distribuzioni costruite appositamente senza il kernel Linux e disponibili da fonti esterne.
- Container sono distribuzioni distribuite dalle immagini, pronte per l'uso.
- Gli snapshot sono istantanee dello stato dei contenitori a cui è possibile tornare.

Per gestire lo storage in LXD, si utilizza il comando lxc storage di cui si può ottenere aiuto specificando il flag — lxc storage --help
Il comando seguente visualizza un elenco di tutti Storage Pool nei storage di LXD:
lxc storage list
+---------+-------------+--------+--------------------------------+---------+
| NAME | DESCRIPTION | DRIVER | SOURCE | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool | | btrfs | /dev/loop1 | 2 |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool | | btrfs | /var/lib/lxd/disks/ssdpool.img | 4 |
+---------+-------------+--------+--------------------------------+---------+Per visualizzare l'elenco di tutti Storage Volume nel selezionato Storage Pool la seguente comando è disponibile 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 |
+-----------+----------------------------------+-------------+---------+Inoltre, se per Storage Pool se è stata scelta la filesystem BTRFS durante la creazione, puoi ottenere un elenco Storage Volume o subvolumi nell'interpretazione di BTRFS puoi utilizzare gli strumenti di questo filesystem:
sudo btrfs subvolume list -p /var/lib/lxd/storage-pools/hddpool
ID 257 gen 818 parent 5 top level 5 path images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3sudo 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/alp3Inizializzazione di LXD
Prima di creare e utilizzare i contenitori, è necessaria un'inizializzazione generale di LXD, che crea e configura la rete, così come lo storage. Questo può essere fatto manualmente con i comandi standard del client disponibili nell'elenco chiamando il comando lxc --help oppure tramite la procedura guidata di inizializzazione lxd init rispondendo a qualche domanda.
Scelta del filesystem per il Pool di Archiviazione
Durante l'inizializzazione, LXD pone alcune domande, tra cui la determinazione del tipo di filesystem per il predefinito Storage Pool. Per impostazione predefinita, viene selezionato il filesystem BTRFS. Cambiare in un altro FS dopo la creazione sarà impossibile. Per scegliere il FS viene proposta :
Caratteristica
Directory
Btrfs
LVM
ZFS
CEPH
Storage delle immagini ottimizzato
no
sì
sì
sì
sì
Creazione dell'istanza ottimizzata
no
sì
sì
sì
sì
Creazione di snapshot ottimizzata
no
sì
sì
sì
sì
Trasferimento immagine ottimizzato
no
sì
no
sì
sì
Trasferimento istanza ottimizzato
no
sì
no
sì
sì
Copy on write
no
sì
sì
sì
sì
Basato su blocchi
no
no
sì
no
sì
Clonazione istantanea
no
sì
sì
sì
sì
Driver di archiviazione utilizzabile all'interno di un contenitore
sì
sì
no
no
no
Ripristina da snapshot precedenti (non l'ultimo)
sì
sì
sì
no
sì
Quote di archiviazione
sì(*)
sì
sì
sì
no
Inizializzazione della rete e del Pool di Archiviazione tramite il wizard
Il prossimo comando che esamineremo consente di configurare i componenti principali di LXD rispondendo a semplici domande tramite il wizard di inizializzazione.
Esegui il comando lxc init e inserisci le risposte alle domande dopo i due punti come mostrato nell'esempio qui sotto o modificale secondo le tue esigenze:
lxd init
Vuoi utilizzare il clustering LXD? (sì/no) [predefinito=no]:
Vuoi configurare un nuovo pool di archiviazione? (sì/no) [predefinito=sì]:
Nome del nuovo pool di archiviazione [predefinito=default]: ssdpool
Nome del backend di archiviazione da utilizzare (lvm, btrfs, dir) [predefinito=btrfs]:
Vuoi creare un nuovo pool BTRFS? (sì/no) [predefinito=sì]:
Vuoi utilizzare un dispositivo a blocchi esistente? (sì/no) [predefinito=no]:
Dimensione in GB del nuovo dispositivo a loop (minimo 1GB) [predefinito=15GB]: 10GB
Vuoi connetterti a un server MAAS? (sì/no) [predefinito=no]:
Vuoi creare un nuovo ponte di rete locale? (sì/no) [predefinito=sì]:
Come dovrebbe chiamarsi il nuovo ponte? [predefinito=lxdbr0]:
Quale indirizzo IPv4 dovrebbe essere utilizzato? (notazione CIDR, “auto” o “nessuno”) [predefinito=auto]: 10.0.5.1/24
Vuoi che LXD NAT sia il traffico IPv4 sul tuo ponte? [predefinito=sì]:
Quale indirizzo IPv6 dovrebbe essere utilizzato? (notazione CIDR, “auto” o “nessuno”) [predefinito=auto]: nessuno
Vuoi che LXD sia disponibile sulla rete? (sì/no) [predefinito=no]:
Vuoi che le immagini memorizzate nella cache obsolete vengano aggiornate automaticamente? (sì/no) [predefinito=sì] no
Vuoi che venga stampato un preseed YAML "lxd init"? (sì/no) [predefinito=no]: Creazione di un ulteriore Pool di Archiviazione
Nel passaggio precedente abbiamo creato Storage Pool a cui abbiamo dato il nome ssdpool e il cui file si trova nel mio sistema all'indirizzo /var/lib/lxd/disks/ssdpool.img. Questo indirizzo del filesystem corrisponde al disco SSD fisico nel mio PC.
Per comprendere meglio il ruolo che gioca Storage Pool nello storage, creeremo un secondo Storage Pool che si troverà fisicamente su un altro tipo di disco, l'HDD. Il problema è che LXD non consente di creare Storage Pool fuori dall'indirizzo /var/lib/lxd/disks/ e nemmeno i link simbolici funzioneranno, . Possiamo aggirare questa limitazione durante l'inizializzazione/formatting Storage Pool specificando il valore come dispositivo a blocchi invece che come percorso a un file loopback specificandolo nella chiave source.
Quindi, prima di creare Storage Pool è necessario determinare il file loopback o una partizione esistente nel filesystem che utilizzerà. Per fare ciò, creeremo e useremo un file limitato a 10GB:
dd if=/dev/zero of=/mnt/work/lxd/hddpool.img bs=1MB count=10000
10000+0 records in
10000+0 records out
10000000000 bytes (10 GB, 9,3 GiB) copiati, 38,4414 s, 260 MB/sColleghiamo il file loopback a un dispositivo loopback libero:
sudo losetup --find --show /mnt/work/lxd/hddpool.img
/dev/loop1Grazie alla chiave --show L'esecuzione del comando restituisce a schermo il nome del dispositivo a cui è collegato il nostro file loopback. Se necessario, possiamo visualizzare a schermo l'elenco di tutti i dispositivi di questo tipo per verificare la correttezza delle nostre azioni:
losetup -l
NOME SIZELIMIT OFFSET AUTOCLEAR RO FILE-INDIRIZZO 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 512Dall'elenco si può notare che nel dispositivo /dev/loop1 è collegato un file loopback /mnt/work/lxd/hddpool.img, e nel dispositivo /dev/loop0 è collegato un file loopback /var/lib/lxd/disks/ssdpool.img che corrisponde al predefinito Storage Pool.
Il comando successivo crea un nuovo Storage Pool in LXD basato sul file loopback appena preparato. LXD formatterà il file loopback /mnt/work/lxd/hddpool.img nel dispositivo /dev/loop1 sotto il filesystem BTRFS:
lxc storage create hddpool btrfs size=10GB source=/dev/loop1Visualizziamo l'elenco di tutti Storage Pool a schermo:
lxc storage list
+---------+-------------+--------+--------------------------------+---------+
| NOME | DESCRIZIONE | DRIVER | SOURCE | USED BY |
+---------+-------------+--------+--------------------------------+---------+
| hddpool | | btrfs | /dev/loop1 | 0 |
+---------+-------------+--------+--------------------------------+---------+
| ssdpool | | btrfs | /var/lib/lxd/disks/ssdpool.img | 0 |
+---------+-------------+--------+--------------------------------+---------+Aumento della dimensione del Pool di Archiviazione
Dopo aver creato Storage Pool, se necessario, può essere ampliato. Per Storage Pool basato su file system BTRFS, eseguire i seguenti comandi:
sudo truncate -s +5G /mnt/work/lxd/hddpool.img
sudo losetup -c /dev/loop1
sudo btrfs filesystem resize max /var/lib/lxd/storage-pools/hddpoolAuto-inserimento del file loopback nello slot del dispositivo loopback
Abbiamo un piccolo problema: al riavvio del sistema host, il file /mnt/work/lxd/hddpool.img "scomparirà" dal dispositivo /dev/loop1 e il servizio LXD non si avvierà al boot, poiché non lo troverà in questo dispositivo. Per risolvere questo problema, è necessario creare un servizio di sistema che monti questo file nel dispositivo /dev/loop1 al boot del sistema host.
Creiamo un'unità file di tipo service in /etc/systemd/system/ per il sistema di init 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
EOFAttiviamo il servizio:
sudo systemctl enable lxd-hddpool
Created symlink /etc/systemd/system/local-fs.target.wants/lxd-hddpool.service → /etc/systemd/system/lxd-hddpool.service.Dopo il riavvio del sistema host, controlliamo lo stato del servizio:
systemctl status lxd-hddpool.service
● lxd-hddpool.service - Losetup LXD Storage Pool (hddpool)
Caricato: caricato (/etc/systemd/system/lxd-hddpool.service; abilitato; impostazione predefinita del fornitore: disabilitata)
Attivo: attivo (uscito) dal Wed 2020-04-08 03:43:53 MSK; 1min 37s fa
Processo: 711 ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img (codice=uscito, stato=0/SUCCESS)
PID principale: 711 (codice=uscito, stato=0/SUCCESS)
apr 08 03:43:52 manjaro systemd[1]: Avvio di Losetup LXD Storage Pool (hddpool)...
apr 08 03:43:53 manjaro systemd[1]: Completato Losetup LXD Storage Pool (hddpool).Dall'output possiamo assicurarci che lo stato del servizio è active, nonostante l'esecuzione del nostro script da un comando singolo sia terminata, ci ha permesso di effettuare l'opzione RemainAfterExit=true.
Sicurezza. Privilegi dei contenitori
Poiché tutti i processi del container vengono effettivamente eseguiti in isolamento sul sistema host utilizzando il suo kernel, per una protezione aggiuntiva dell'accesso dei processi del container al sistema host, LXD offre privilegi per i processi, dove:
Container privilegiati — sono contenitori in cui i processi con UID e GID corrispondono allo stesso proprietario del sistema host. Ad esempio, un processo avviato in un contenitore con UID pari a 0 ha gli stessi diritti di accesso di un processo del sistema host con UID pari a 0. In altre parole, l'utente root nel contenitore ha pieni diritti non solo all'interno del contenitore, ma anche nel sistema host, se riesce a uscire dallo spazio dei nomi isolato del contenitore.
Contenitori non privilegiati — sono contenitori in cui i processi appartengono a un proprietario con UID e GID numerati da 0 a 65535, ma per il sistema host il proprietario è nascosto tramite il bit SubUID e SubGID aggiunto. Ad esempio, un utente con UID=0 nel contenitore sarà riconosciuto nel sistema host come
SubUID + UID. Questo protegge il sistema host, poiché, se un processo all'interno del contenitore riesce a uscire dal suo spazio dei nomi isolato, può interagire con il sistema host solo come un processo con un UID/GID sconosciuto e molto elevato.
Per impostazione predefinita, i contenitori appena creati hanno lo stato di non privilegiati e quindi dobbiamo definire SubUID e SubGID.
Creeremo due file di configurazione in cui imposteremo la maschera per SubUID e SubGID rispettivamente:
sudo touch /etc{subuid,subgid}
sudo usermod --add-subuids 1000000-1065535 root
sudo usermod --add-subgids 1000000-1065535 rootPer applicare le modifiche, il servizio LXD deve essere riavviato:
sudo systemctl restart lxdCreazione di un virtual switch di rete
Poiché abbiamo precedentemente inizializzato la rete utilizzando il master di inizializzazione lxd init e creato un dispositivo di rete lxdbr0, in questa sezione ci limiteremo a esplorare la rete in LXD e a come creare uno switch virtuale (bridge) utilizzando il comando del client.
Il seguente schema dimostra come uno switch (bridge) collega l'host e i contenitori nella rete:

I contenitori possono interagire tramite la rete con altri contenitori o con l'host su cui questi contenitori sono ospitati. A tal fine, è necessario collegare le schede di rete virtuali dei contenitori allo switch virtuale. Inizialmente creeremo lo switch, e le interfacce di rete del contenitore saranno collegate nei capitoli successivi, dopo che il contenitore stesso sarà stato creato.
Il comando seguente crea uno switch con una subnet 10.0.5.0/24 e un indirizzo IPv4 10.0.5.1/24, e attiva ipv4.nat affinché i contenitori possano accedere a Internet tramite l'host utilizzando il servizio NAT:
lxc network create lxdbr0 ipv4.address=10.0.5.1/24 ipv4.nat=true ipv6.address=noneControlliamo l'elenco delle interfacce di rete disponibili in LXD:
lxc network list
+--------+----------+---------+-------------+---------+
| NOME | TIPO | GESTITO | DESCRIZIONE | UTILIZZATO |
+--------+----------+---------+-------------+---------+
| eno1 | fisico | NO | | 0 |
+--------+----------+---------+-------------+---------+
| lxdbr0 | bridge | SÌ | | 0 |
+--------+----------+---------+-------------+---------+Inoltre, è possibile verificare la creazione del dispositivo di rete usando lo strumento standard del sistema operativo Linux — ip link o ip addr:
ip addr
1: lo: mtu 65536 qdisc noqueue stato UNKNOWN gruppo 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 stato UP gruppo 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 stato UP gruppo 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 stato UP gruppo default qlen 1000
link/ether ca:c3:5c:1d:22:26 brd ff:ff:ff:ff:ff:ff link-netnsid 0Profilo di configurazione
Ogni contenitore in LXD ha la propria configurazione e può ampliarla tramite configurazioni dichiarate globalmente che vengono chiamate profili di configurazione. L'applicazione dei profili di configurazione a un contenitore segue un modello a cascata, il seguente esempio lo dimostra:

In questo esempio, nel sistema LXD sono stati creati tre profili: default, hddpool e hostfs. Tutti e tre i profili sono applicati a un contenitore che ha una configurazione locale (zona grigia). Profilo default ha un dispositivo root che ha il parametro pool è uguale a ssdpool, ma grazie al modello a cascata di applicazione della configurazione possiamo applicare un profilo al contenitore hddpool che ha il parametro pool sovrascriverà lo stesso parametro dal profilo default e il contenitore riceverà la configurazione del dispositivo root con il parametro pool uguale a hddpool, mentre il profilo hostfs aggiunge semplicemente un nuovo dispositivo al contenitore.
Per vedere l'elenco dei profili di configurazione disponibili, si utilizza il seguente comando:
lxc profile list
+---------+---------+
| NOME | USATO DA |
+---------+---------+
| default | 1 |
+---------+---------+
| hddroot | 0 |
+---------+---------+
| ssdroot | 1 |
+---------+---------+L'elenco completo dei comandi disponibili per gestire il profilo può essere ottenuto aggiungendo il flag --help:
lxc profile --help
Descrizione:
Gestire i profili
Uso:
lxc profile [comando]
Comandi disponibili:
add Aggiungi profili a istanze
assign Assegna set di profili a istanze
copy Copia profili
create Crea profili
delete Elimina profili
device Gestisci dispositivi delle istanze
edit Modifica configurazioni del profilo come YAML
get Ottieni valori per le chiavi di configurazione del profilo
list Elenca profili
remove Rimuovi profili dalle istanze
rename Rinomina profili
set Imposta chiavi di configurazione del profilo
show Mostra configurazioni del profilo
unset Disattiva chiavi di configurazione del profiloModifica del profilo
Profilo di configurazione predefinito default non è configurata alcuna scheda di rete per il contenitore e tutti i nuovi contenitori non hanno accesso alla rete. Per questi è necessario creare dispositivi di rete locali (dedicati) tramite un comando separato, ma possiamo creare un dispositivo di rete globale nel profilo di configurazione che sarà condiviso da tutti i contenitori che utilizzano questo profilo. In questo modo, subito dopo il comando di creazione di un nuovo contenitore, avranno accesso alla rete. Non ci sono limitazioni, possiamo sempre creare in seguito un dispositivo di rete locale se necessario.
Il comando successivo aggiungerà al profilo di configurazione un dispositivo eth0 di tipo nic collegato alla rete lxdbr0:
lxc profile device add default eth0 nic network=lxdbr0 name=eth0È importante notare che, dato che abbiamo effettivamente aggiunto un dispositivo al profilo di configurazione, se avessimo specificato un indirizzo IP statico per il dispositivo, tutti i container che utilizzeranno questo profilo condivideranno lo stesso indirizzo IP. Se è necessario creare un container con un indirizzo IP statico dedicato, è necessario creare una configurazione di dispositivo di rete a livello di container (configurazione locale) con il parametro dell'indirizzo IP, piuttosto che a livello di profilo.
Controlliamo il profilo:
lxc profile show default
config: {}
description: Profilo LXD predefinito
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: ssdpool
type: disk
name: default
used_by: []In questo profilo possiamo vedere che per tutti i nuovi container creati verranno creati due dispositivi (devices):
eth0— Dispositivo di tiponiccollegato a uno switch (bridge di rete)lxdbr0root— Dispositivo di tipodiskche utilizza il pool di archiviazionessdpool
Creazione di nuovi profili
Per utilizzare i precedentemente creati Storage Pool container, creiamo un profilo di configurazione ssdroot in cui aggiungeremo un dispositivo di tipo disk con punto di montaggio / (root) che utilizza il già creato Storage Pool — ssdpool:
lxc profile create ssdroot
lxc profile device add ssdroot root disk path=/ pool=ssdpoolAllo stesso modo, creiamo un dispositivo di tipo disk, ma in questo caso utilizzare Storage Pool — hddpool:
lxc profile create hddroot
lxc profile device add hddroot root disk path=/ pool=hddpoolControlliamo i profili di configurazione:
lxc profile show ssdroot
config: {}
description: ""
devices:
root:
path: /
pool: ssdpool
type: disk
name: ssdroot
used_by: []lxc profile show hddroot
config: {}
description: ""
devices:
root:
path: /
pool: hddpool
type: disk
name: hddroot
used_by: []Repository delle immagini
I contenitori vengono creati da immagini che sono distribuzioni specialmente realizzate senza un kernel Linux. Pertanto, prima di avviare un contenitore, deve essere estratto da questa immagine. Le immagini provengono da un repository locale in cui vengono caricate da repository esterni.
Repository delle immagini remote
Per impostazione predefinita, LXD è configurato per ricevere immagini da tre fonti remote:
- ubuntu: (per immagini Ubuntu stabili)
- ubuntu-daily: (per immagini quotidiane di Ubuntu)
- images: (per molte altre distribuzioni)
lxc remote list
+-----------------+------------------------------------------+--------+--------+
| NOME | URL | PUBBLICO | STATICO |
+-----------------+------------------------------------------+--------+--------+
| immagini | https://images.linuxcontainers.org | SÌ | NO |
+-----------------+------------------------------------------+--------+--------+
| locale (predefinito) | unix:// | NO | SÌ |
+-----------------+------------------------------------------+--------+--------+
| ubuntu | https://cloud-images.ubuntu.com/releases | SÌ | SÌ |
+-----------------+------------------------------------------+--------+--------+
| ubuntu-daily | https://cloud-images.ubuntu.com/daily | SÌ | SÌ |
+-----------------+------------------------------------------+--------+--------+Ad esempio, il repository ubuntu: ha le seguenti immagini:
lxc image -c dasut list ubuntu: | head -n 11
+----------------------------------------------+--------------+----------+------------+
| DESCRIZIONE | ARCHITETTURA | DIMENSIONE | TIPO |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150728) | x86_64 | 153.72MB | CONTENITORE |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150819) | x86_64 | 152.91MB | CONTENITORE |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150906) | x86_64 | 154.69MB | CONTENITORE |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150930) | x86_64 | 153.86MB | CONTENITORE |
+----------------------------------------------+--------------+----------+------------+Per visualizzare un numero limitato di colonne abbiamo utilizzato l'opzione -c con i parametri dasut, e abbiamo anche limitato la lunghezza dell'elenco con il comando head.
Per l'output dell'elenco delle immagini è disponibile un filtro. Il seguente comando visualizzerà l'elenco di tutte le architetture disponibili per la distribuzione :
lxc image -c ldast list images:alpine/3.11
+------------------------------+--------------------------------------+--------------+
| ALIAS | DESCRIPTION | ARCHITECTURE |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11 (3 more) | Alpine 3.11 amd64 (20200220_13:00) | x86_64 |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/arm64 (1 more) | Alpine 3.11 arm64 (20200220_13:00) | aarch64 |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/armhf (1 more) | Alpine 3.11 armhf (20200220_13:00) | armv7l |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/i386 (1 more) | Alpine 3.11 i386 (20200220_13:01) | i686 |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/ppc64el (1 more) | Alpine 3.11 ppc64el (20200220_13:00) | ppc64le |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/s390x (1 more) | Alpine 3.11 s390x (20200220_13:00) | s390x |
+------------------------------+--------------------------------------+--------------+Repository locale delle immagini
Per iniziare a utilizzare il contenitore, è necessario aggiungere un'immagine dal repository globale a quello locale locale:. Al momento, il repository locale è vuoto, e lo verifichiamo con il comando lxc image list. Se non viene specificato alcun repository per il metodo list , per impostazione predefinita verrà utilizzato il repository locale — locale:
lxc image list local:
+-------+-------------+--------+-------------+--------------+------+------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE |
+-------+-------------+--------+-------------+--------------+------+------+La gestione delle immagini nel repository avviene tramite i seguenti metodi:
Team
Descrizione
lxc image alias
Gestisci alias delle immagini
lxc image copy
Copia immagini tra server
lxc image elimina
Elimina immagini
lxc image modifica
Modifica proprietà dell'immagine
lxc image esporta
Esporta e scarica immagini
lxc image importa
Importa immagini nel deposito delle immagini
lxc image info
Mostra informazioni utili sulle immagini
lxc image list
Elenca immagini
lxc image aggiorna
Aggiorna immagini
lxc image mostra
Mostra proprietà dell'immagine
Copiaamo l'immagine nel repository locale da globale images::
lxc image copy images:alpine/3.11/amd64 local: --alias=alpine3
Immagine copiata con successo!Elenco di tutte le immagini attualmente disponibili nel repository locale locale::
lxc image -c lfdatsu list local:
+---------+--------------+------------------------------------+--------------+
| ALIAS | FINGERPRINT | DESCRIPTION | ARCHITECTURE |
+---------+--------------+------------------------------------+--------------+
| alpine3 | 73a3093d4a5c | Alpine 3.11 amd64 (20200220_13:00) | x86_64 |
+---------+--------------+------------------------------------+--------------+Configurazione LXD
Oltre alla modalità interattiva, LXD supporta anche la modalità non interattiva per la configurazione, in cui la configurazione viene fornita in un file YAML, un formato speciale che consente di impostare tutta la configurazione in un colpo solo, evitando di eseguire numerosi comandi interattivi esaminati in precedenza in questo articolo, inclusa la configurazione della rete, la creazione di profili di configurazione, ecc. In quest'area non ci soffermeremo, potete esplorare autonomamente. .
Il prossimo comando interattivo lxc config che esamineremo, consente di impostare la configurazione. Ad esempio, per evitare che le immagini scaricate nel repository locale vengano aggiornate automaticamente dai repository globali, possiamo attivare questo comportamento con il seguente comando:
lxc config set images.auto_update_cached=falseCreazione e gestione del contenitore
Per creare un contenitore, utilizziamo il comando lxc init a cui vengono passati i valori repository:image e quindi l'identificatore desiderato per il contenitore. Il repository può essere specificato come locale. locale: così come qualsiasi repository globale. Se non viene specificato un repository, per impostazione predefinita verrà utilizzato il repository locale per cercare l'immagine. Se l'immagine è specificata da un repository globale, verrà prima scaricata nel repository locale e poi utilizzata per creare il contenitore.
Eseguiamo il seguente comando per creare il nostro primo contenitore:
lxc init alpine3 alp --storage=hddpool --profile=default --profile=hddrootAnalizziamo i parametri del comando che stiamo utilizzando qui:
alpine3— Viene specificato un alias (pseudonimo) per l'immagine precedentemente scaricata nel repository locale. Se non fosse stato creato un alias per quest'immagine, è possibile sempre fare riferimento all'immagine tramite il suo Fingerprint che viene visualizzato nella tabella.alp— Viene assegnato un identificatore per il contenitore--storage— Questo parametro indica in quale Storage Pool verrà creato il contenitore--profile— Questi parametri applicano a cascata al contenitore la configurazione dai profili di configurazione precedentemente creati.
Avviamo il contenitore, che inizia a lanciare il sistema init della distribuzione:
lxc start alpIn alternativa, è possibile utilizzare il comando lxc launch che consente di combinare i comandi lxc init e lxc start in un'unica operazione.
Controlliamo lo stato del contenitore:
lxc list -c ns46tb
+------+---------+------------------+------+-----------+--------------+
| NAME | STATE | IPV4 | IPV6 | TYPE | STORAGE POOL |
+------+---------+------------------+------+-----------+--------------+
| alp | RUNNING | 10.0.5.46 (eth0) | | CONTAINER | hddpool |
+------+---------+------------------+------+-----------+--------------+Controlliamo la configurazione del contenitore:
lxc config show alp
architecture: x86_64
config:
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: RUNNING
devices:
root:
path: /
pool: hddpool
type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""Nella sezione profiles possiamo assicurarci che questo contenitore utilizzi due profili di configurazione — default e hddroot. Nella sezione devices possiamo rilevare solo un dispositivo, poiché il dispositivo di rete è stato creato a livello di profilo default. Per visualizzare tutti i dispositivi utilizzati dal contenitore è necessario aggiungere la chiave --expanded:
lxc config show alp --expanded
architettura: x86_64
configurazione:
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: RUNNING
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: hddpool
type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""Assegnazione di un indirizzo IP statico
Se proviamo a impostare un indirizzo IP per il dispositivo di rete eth0 comando lxc config device set alp destinato alla configurazione del contenitore, riceveremo un errore che indica che il dispositivo non esiste perché il dispositivo eth0 che è utilizzato dal contenitore appartiene al profilo default:
lxc config device set alp eth0 ipv4.address 10.0.5.5
Errore: il dispositivo non esistePossiamo certamente impostare un indirizzo IP statico per eth0 il dispositivo nel profilo, ma sarà unico per tutti i contenitori che utilizzeranno questo profilo. Pertanto, aggiungiamo un dispositivo dedicato per il contenitore:
lxc config device add alp eth0 nic name=eth0 nictype=bridged parent=lxdbr0 ipv4.address=10.0.5.5Poi bisogna riavviare il contenitore:
lxc restart alpSe ora guardiamo la configurazione del contenitore, non è necessario applicare l'opzione --expanded per vedere il dispositivo di rete eth0, poiché lo abbiamo creato a livello di contenitore e ha sovrascritto a cascata lo stesso dispositivo dal profilo default:
lxc config show alp
architettura: x86_64
configurazione:
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: veth2a1dc59d
volatile.eth0.hwaddr: 00:16:3e:0e:e2:71
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: IN CORSO
devices:
eth0:
ipv4.address: 10.0.5.5
nome: eth0
nictype: bridged
parent: lxdbr0
type: nic
root:
path: /
pool: hddpool
type: disk
ephemeral: false
profili:
- predefinito
- hddroot
stateful: false
descrizione: ""Rimozione del contenitore
Per rimuovere il contenitore si utilizza il comando lxc delete, ma prima di rimuovere il contenitore, deve essere fermato utilizzando il comando lxc stop:
lxc stop alplxc list
+------+---------+-------------------+------+-----------+-----------+
| NOME | STATO | IPV4 | IPV6 | TIPO | SNAPSHOTS |
+------+---------+-------------------+------+-----------+-----------+
| alp | FERMATO | 10.0.5.10 (eth0) | | CONTENITORE | 0 |
+------+---------+-------------------+------+-----------+-----------+Dopo aver verificato che lo stato del contenitore sia FERMATO, può essere rimosso da Storage Pool:
lxc delete alpAccesso al contenitore
Per eseguire comandi nel contenitore, direttamente, bypassando le connessioni di rete, si usa il comando lxc exec , che esegue comandi nel contenitore senza avviare la shell di sistema. Se hai bisogno di eseguire un comando nella shell, usando modelli di shell, come variabili, redirect di file (pipe), ecc., è necessario avviare esplicitamente la shell e passare il comando come chiave, ad esempio:
lxc exec alp -- /bin/sh -c "echo $HOME"Nel comando è stato utilizzato un carattere speciale di escape per il carattere speciale $ , affinché la variabile $HOME non venga interpretata sulla macchina host, ma sia interpretata solo all'interno del contenitore.
È anche possibile avviare la modalità interattiva della shell e, dopo aver terminato la sessione, eseguire il hotkey CTRL+D:
lxc exec alp -- /bin/shGestione delle risorse del contenitore
In LXD puoi gestire le risorse del contenitore tramite un insieme speciale di configurazioni. L'elenco completo dei parametri di configurazione del contenitore può essere trovato .
Limitazione delle risorse RAM
Caratteristica limits.memory limita la quantità di RAM disponibile per il contenitore. Come valore, si indica un numero e uno dei .
Impostiamo un limite alla quantità di RAM per il contenitore pari a 256 MB:
lxc config set alp limits.memory 256MBEsistono anche altri parametri per limitare la memoria:
limits.memory.enforcelimits.memory.hugepageslimits.memory.swaplimits.memory.swap.priority
Team lxc config show permette di visualizzare l'intera configurazione del contenitore, inclusa la limitazione delle risorse applicata:
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.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: ""Limitazione delle risorse CPU
Per limitare le risorse della CPU esistono diversi :
limit.cpu— associa il contenitore a uno o più core della CPUlimits.cpu.allowance— gestisce sia i limiti dei scheduler CFS, quando si è raggiunto il limite di tempo, sia un meccanismo universale di condivisione delle risorse CPU, quando viene superata una percentualelimits.cpu.priority— priorità del pianificatore, quando più istanze condividono un insieme di processori con la stessa percentuale di CPU assegnata
lxc config set alp limits.cpu.allowance 40%lxc config show alp
architettura: x86_64
configurazione:
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: ""Limitazione dello spazio su disco
Oltre a restrizioni come limits.read, limits.write possiamo anche limitare la quantità di spazio su disco utilizzata dal contenitore (funziona solo con ZFS o BTRFS):
lxc config device set alp root size=2GBDopo la configurazione, nel parametro devices.root.size possiamo verificare il limite impostato:
lxc config show alp
...
devices:
root:
path: /
pool: hddpool
size: 2GB
type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""Per visualizzare le quote di spazio su disco utilizzate, possiamo ottenere le informazioni con il comando lxc info:
lxc info alp
...
Risorse:
Processi: 5
Utilizzo disco:
root: 1.05GB
Utilizzo CPU:
Utilizzo CPU (in secondi): 1
Utilizzo memoria:
Memoria (attuale): 5.46MB
Utilizzo rete:
eth0:
Byte ricevuti: 802B
Byte inviati: 1.59kB
Pacchetti ricevuti: 4
Pacchetti inviati: 14
lo:
Byte ricevuti: 0B
Byte inviati: 0B
Pacchetti ricevuti: 0
Pacchetti inviati: 0Nonostante abbiamo impostato un limite per il dispositivo radice del container a 2GB, utilità di sistema come df non vedranno questo limite. Per questo faremo un piccolo test per capire come funziona.
Creiamo 2 nuovi container identici nella stessa Storage Pool (hddpool):
lxc init alpine3 alp1 --storage=hddpool --profile=default --profile=hddroot
lxc init alpine3 alp2 --storage=hddpool --profile=default --profile=hddrootlxc list
+------+---------+------------------+------+-----------+-----------+
| NOME | STATO | IPV4 | IPV6 | TIPO | SNAPSHOT |
+------+---------+------------------+------+-----------+-----------+
| alp1 | IN FUNZIONE | 10.0.5.46 (eth0) | | CONTENITORE | 0 |
+------+---------+------------------+------+-----------+-----------+
| alp2 | IN FUNZIONE | 10.0.5.30 (eth0) | | CONTENITORE | 0 |
+------+---------+------------------+------+-----------+-----------+In uno dei container creiamo un file di dimensioni 1GB:
lxc exec alp1 -- dd if=/dev/urandom of=file.img bs=1M count=1000Assicuriamoci che il file sia stato creato:
lxc exec alp1 -- ls -lh
total 1000M
-rw-r--r-- 1 root root 1000.0M Mar 27 10:16 file.imgSe guardiamo nel secondo contenitore, controllando l'esistenza del file nello stesso posto, questo file non sarà presente, come ci si aspetta, poiché i contenitori vengono creati nei loro ambienti separati. Storage Volume in questo stesso Storage Pool:
lxc exec alp2 -- ls -lh
total 0Ma confrontiamo i valori che restituisce df in entrambi i contenitori:
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% /
...Dispositivo /dev/loop1 montato come partizione radice è Storage Pool quella che questi contenitori utilizzano, quindi suddividono il suo spazio in due.
Statistiche di utilizzo delle risorse
Puoi visualizzare le statistiche sulle risorse consumate dal contenitore con il comando:
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: 0Lavorare con gli snapshot
Con LXD è possibile creare snapshot e ripristinare lo stato di un contenitore da essi.
Per creare uno snapshot, eseguire il seguente comando:
lxc snapshot alp snapshot1Il comando lxc snapshot non ha una chiave list, quindi, per visualizzare l'elenco degli snapshot, è necessario utilizzare un comando che fornisca informazioni generali sul contenitore:
lxc info alp
...
...
Snapshots:
snapshot1 (preso il 2020/04/08 18:18 UTC) (senza stato)È possibile ripristinare il contenitore da uno snapshot con il comando lxc restore specificando il contenitore per il quale si desidera effettuare il ripristino e il nome dello snapshot:
lxc restore alp snapshot1Il seguente comando serve ad eliminare uno snapshot. Si noti che la sintassi del comando è diversa da tutti gli altri; qui è necessario specificare una barra inclinata dopo il nome del contenitore. Se si omette la barra, il comando di eliminazione dello snapshot viene interpretato come un comando di eliminazione del contenitore!
lxc delete alp/snapshot1Nell'esempio sopra abbiamo considerato i cosiddetti snapshot senza stato. In LXD esiste anche un altro tipo di snapshot — stateful, in cui viene salvato lo stato attuale di tutti i processi nel contenitore. Gli snapshot stateful presentano una serie di funzionalità interessanti e utili.
Cosa altro?
- Per gli sviluppatori Python è disponibile un modulo che fornisce un'API per LXD
AGGIORNAMENTO 10.04.2020 15:00: Aggiunta navigazione
Fonte: habr.com
