
LXD — è un gestore di container di nuova generazione, così dice . Propone un'interfaccia utente simile a quella delle macchine virtuali, ma utilizza invece container Linux.
Il nucleo di LXD è un demone privilegiato (servizio eseguito con diritti di root) che fornisce un'API REST tramite un socket unix locale, nonché attraverso la rete, se configurato correttamente. I client, come lo strumento da riga di comando fornito con LXD, inviano richieste attraverso 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, né esploreremo tutte le funzionalità disponibili descritte nella documentazione, inclusa la recente implementazione nelle ultime versioni di LXD che supporta macchine virtuali QEMU insieme ai container. Invece, ci concentreremo solo sulle funzionalità di base per la gestione dei container: configureremo pool di archiviazione, rete, avvieremo un container, applicheremo limiti sulle risorse e vedremo come utilizzare gli snapshot, in modo da fornirti una comprensione di base di LXD e permetterti di utilizzare i container in Linux.
Per informazioni complete, fai riferimento alla fonte ufficiale:
Navigazione
Installazione di LXD
Installazione di LXD sulle distribuzioni Ubuntu
Nella distribuzione 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)Significa che verranno installati contemporaneamente due pacchetti, uno di sistema e l'altro come pacchetto snap. L'installazione di due pacchetti nel sistema può creare un problema, in cui il pacchetto di sistema può diventare orfano se si rimuove il pacchetto snap tramite il gestore di pacchetti snap.
Trova pacchetto lxd nel repository snap 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 - Ipervisore KVM (nova)
distrobuilder 1.0 Costruttore di immagini per LXC e LXD
fabrica 0.1 Crea snap semplicemente puntando un modulo web a...
satellite 0.1.2 Piattaforma avanzata scalabile di intelligence open sourceEseguendo il comando list puoi verificare che il pacchetto lxd non sia ancora installato:
snap list
Nome Versione Rev Tracking Editor Note
core 16-2.43.3 8689 stabile canonical✓ coreNonostante LXD sia un pacchetto snap, deve essere installato tramite il pacchetto di sistema lxd, che creerà nel sistema il gruppo corrispondente, gli strumenti necessari 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 Editor Note
core 16-2.43.3 8689 stabile canonical✓ core
lxd 3.21 13474 stabile\/… canonical✓ -Installazione di LXD sulle distribuzioni Arch Linux
Per installare il pacchetto LXD nel sistema è necessario eseguire i seguenti comandi, il primo aggiorna l'elenco dei pacchetti disponibili nel repository del sistema, 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 al gruppo di sistema lxd:
sudo usermod -a -G lxd user1Verifichiamo 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 è visibile nell'elenco, allora è necessario attivare nuovamente la sessione dell'utente. Per farlo, è necessario disconnettersi e riconnettersi al 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 della inizializzazione, dobbiamo 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 normali directory. Ogni Storage Pool è suddiviso in volumi (Storage Volume) che contengono immagini, contenitori o dati per altri scopi.
- Immagini — sono distribuzioni appositamente assemblate senza il kernel Linux e disponibili da fonti esterne
- Contenitori — sono distribuzioni srotolate da immagini, pronte per l'uso
- 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 è possibile ottenere aiuto specificando la chiave — lxc storage --help
Il comando successivo visualizza un elenco di tutti Storage Pool in LXD storage:
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 si utilizza il comando 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 è stato scelto il file system BTRFS durante la creazione, è possibile ottenere l'elenco Storage Volume o subvolumes in termini di BTRFS utilizzando gli strumenti di questo file system:
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 contenitori, è necessario eseguire l'inizializzazione generale di LXD che crea e configura la rete, oltre allo storage. Questo può essere fatto manualmente utilizzando i comandi standard del client disponibili nell'elenco generato dal comando lxc --help o tramite il wizard di inizializzazione lxd init rispondendo a alcune domande.
Scelta del file system per il Pool di Archiviazione
Durante l'inizializzazione, LXD pone alcune domande, tra cui la definizione del tipo di file system per il predefinito Storage Pool. Per impostazione predefinita, viene scelto il file system BTRFS. Cambiare in un altro FS dopo la creazione sarà impossibile. Per scegliere il FS è proposta :
Caratteristica
Directory
Btrfs
LVM
ZFS
CEPH
Storage immagini ottimizzato
no
sì
sì
sì
sì
Creazione instance ottimizzata
no
sì
sì
sì
sì
Creazione snapshot ottimizzata
no
sì
sì
sì
sì
Trasferimento immagini ottimizzato
no
sì
no
sì
sì
Trasferimento instance 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 storage utilizzabile all'interno di un container
sì
sì
no
no
no
Ripristino da snapshot più vecchi (non gli ultimi)
sì
sì
sì
no
sì
Quote di storage
sì(*)
sì
sì
sì
no
Inizializzazione della rete e del Pool di Archiviazione tramite una procedura guidata
Il prossimo comando che esamineremo offre di configurare i componenti principali di LXD rispondendo a semplici domande tramite una procedura guidata 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 in base alle tue esigenze:
lxd init
Vuoi utilizzare il clustering LXD? (sì/no) [default=no]:
Vuoi configurare un nuovo pool di storage? (sì/no) [default=yes]:
Nome del nuovo pool di storage [default=default]: ssdpool
Nome del backend di storage da usare (lvm, btrfs, dir) [default=btrfs]:
Creare un nuovo pool BTRFS? (sì/no) [default=yes]:
Vuoi utilizzare un dispositivo a blocchi esistente? (sì/no) [default=no]:
Dimensione in GB del nuovo dispositivo loop (1GB minimo) [default=15GB]: 10GB
Vuoi connetterti a un server MAAS? (sì/no) [default=no]:
Vuoi creare un nuovo bridge di rete locale? (sì/no) [default=yes]:
Come deve essere chiamato il nuovo bridge? [default=lxdbr0]:
Quale indirizzo IPv4 deve essere utilizzato? (notazione CIDR, “auto” o “none”) [default=auto]: 10.0.5.1/24
Vuoi che LXD faccia NAT per il traffico IPv4 sul tuo bridge? [default=yes]:
Quale indirizzo IPv6 deve essere utilizzato? (notazione CIDR, “auto” o “none”) [default=auto]: none
Vuoi che LXD sia disponibile in rete? (sì/no) [default=no]:
Vuoi che le immagini memorizzate nella cache obsolete siano aggiornate automaticamente? (sì/no) [default=yes] no
Vuoi che venga stampata una preconfigurazione YAML "lxd init"? (sì/no) [default=no]: Creazione di un Pool di Archiviazione aggiuntivo
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 file system corrisponde al disco SSD fisico nel mio PC.
Nelle prossime azioni, per espandere la comprensione del ruolo che svolge Storage Pool nello storage, creeremo un secondo Storage Pool che sarà fisicamente situato su un altro tipo di disco, su HDD. Il problema è che LXD non permette di creare Storage Pool al di fuori dell'indirizzo /var/lib/lxd/disks/ e nemmeno i collegamenti simbolici funzioneranno, . Possiamo aggirare questa limitazione durante l'inizializzazione/formattazione Storage Pool specificando il valore come dispositivo a blocchi invece del percorso al file di loopback questo nel flag source.
Quindi, prima della creazione Storage Pool è necessario determinare il file loopback o una partizione esistente nel sistema operativo che utilizzerà. A tal fine, creeremo e utilizzeremo un file che limiteremo a 10GB:
dd if=\/dev\/zero of=\/mnt\/work\/lxd\/hddpool.img bs=1MB count=10000
10000+0 record in
10000+0 record 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 sullo schermo il nome del dispositivo al quale è stato collegato il nostro file loopback. Se necessario, possiamo visualizzare l'elenco di tutti i dispositivi occupati di questo tipo, per assicurarci della correttezza delle nostre azioni:
losetup -l
NOME SIZELIMIT OFFSET AUTOCLEAR RO FILE-PRINCIPALE 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ò osservare che nel dispositivo /dev/loop1 è collegato il file loopback /mnt/work/lxd/hddpool.img, e nel dispositivo /dev/loop0 è collegato il 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 file system BTRFS:
lxc storage create hddpool btrfs size=10GB source=\/dev\/loop1Visualizziamo l'elenco di tutti Storage Pool sullo 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 delle dimensioni del Pool di Archiviazione
Dopo la creazione Storage Pool, se necessario, può essere ampliato. Per Storage Pool basato sul 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\/hddpoolInserimento automatico di un file loopback nello slot del dispositivo loopback
Abbiamo un piccolo problema, al riavvio del sistema host, il file /mnt/work/lxd/hddpool.img "uscirà" dal dispositivo /dev/loop1 e il servizio LXD si fermerà all'avvio poiché non lo vedrà in questo dispositivo. Per risolvere questo problema, è necessario creare un servizio di sistema che inserisca questo file nel dispositivo /dev/loop1 all'avvio del sistema host.
Creiamo un unit file di tipo service in /etc/systemd/system/ per il sistema di inizializzazione 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
Creato collegamento simbolico /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 del fornitore: disabilitata)
Attivo: attivo (uscito) da mer 08 apr 2020 03:43:53 MSK; 1min 37s fa
Processo: 711 ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img (codice=uscito, stato=0/SUCCESS)
Main PID: 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 verificare che lo stato del servizio è pari a active, nonostante l'esecuzione del nostro script da un singolo comando sia terminata, questo ci ha permesso di utilizzare l'opzione RemainAfterExit=true.
Sicurezza. Privilegi dei container
Poiché tutti i processi del contenitore vengono effettivamente eseguiti in isolamento sul sistema host utilizzando il suo kernel, per fornire una protezione aggiuntiva per l'accesso dei processi del contenitore al sistema host, LXD offre privilegi ai processi, dove:
Contenitori 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 possiede 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 tutti i diritti non solo nel contenitore, ma anche sul 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 UID e GID con numeri da 0 a 65535, ma per il sistema host il proprietario è mascherato tramite il bit SubUID e SubGID aggiunto. Ad esempio, un utente con UID=0 nel contenitore verrà rilevato nel sistema host come
SubUID + UID. Questo protegge il sistema host, poiché se un processo nel contenitore riesce a uscire dal proprio spazio dei nomi isolato, può interagire con il sistema host solo come processo con un UID/GID sconosciuto e molto elevato.
Per impostazione predefinita, i nuovi contenitori creati hanno lo stato di non privilegiati e pertanto dobbiamo definire SubUID e SubGID.
Creiamo due file di configurazione in cui impostiamo 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 uno switch virtuale di rete
Poiché in precedenza abbiamo inizializzato la rete utilizzando la procedura guidata di inizializzazione lxd init e creato un dispositivo di rete lxdbr0, in questa sezione ci limiteremo a esaminare la rete in LXD e come creare uno switch virtuale (bridge) utilizzando il comando del client.
La seguente illustrazione mostra come lo switch (bridge) collega l'host e i container nella rete:

I container possono comunicare tramite la rete con altri container o con l'host su cui questi container sono in esecuzione. Per questo è necessario collegare le schede di rete virtuali dei container allo switch virtuale. Inizialmente creeremo lo switch e le interfacce di rete del container saranno collegate nei capitoli successivi, dopo che sarà stato creato il container stesso.
Il comando seguente crea uno switch con una sottorete 10.0.5.0/24 e un indirizzo IPv4 10.0.5.1/24, e inoltre abilita ipv4.nat affinché i container possano ottenere Internet tramite l'host utilizzando il servizio NAT:
lxc network create lxdbr0 ipv4.address=10.0.5.1/24 ipv4.nat=true ipv6.address=noneVerifichiamo l'elenco dei dispositivi di rete disponibili in LXD:
lxc network list
+--------+----------+---------+-------------+---------+
| NAME | TYPE | MANAGED | DESCRIPTION | USED BY |
+--------+----------+---------+-------------+---------+
| eno1 | physical | NO | | 0 |
+--------+----------+---------+-------------+---------+
| lxdbr0 | bridge | YES | | 0 |
+--------+----------+---------+-------------+---------+Inoltre, per verificare la creazione del dispositivo di rete, puoi utilizzare lo strumento di sistema del tuo Linux — ip link o 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 0Profilo di configurazione
Ogni container in LXD ha la propria configurazione e può espanderla utilizzando configurazioni globalmente dichiarate che vengono chiamate profili di configurazione. L'applicazione dei profili di configurazione al 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). Il profilo default ha un dispositivo root il cui parametro pool , quindi questa funzione configurerà il socket con l'opzione ssdpool, ma grazie al modello a cascata dell'applicazione della configurazione possiamo applicare al contenitore il profilo hddpool il cui parametro pool sovrascriverà questo 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, è possibile utilizzare il seguente comando:
lxc profile list
+---------+---------+
| NOME | UTILIZZATO DA |
+---------+---------+
| default | 1 |
+---------+---------+
| hddroot | 0 |
+---------+---------+
| ssdroot | 1 |
+---------+---------+L'elenco completo dei comandi disponibili per gestire i profili può essere ottenuto aggiungendo il flag --help:
lxc profile --help
Descrizione:
Gestire i profili
Uso:
lxc profile [comando]
Comandi disponibili:
add Aggiungi profili alle istanze
assign Assegna set di profili alle istanze
copy Copia profili
create Crea profili
delete Elimina profili
device Gestisci i dispositivi delle istanze
edit Modifica le configurazioni dei profili in formato YAML
get Ottieni valori per le chiavi di configurazione dei profili
list Elenca profili
remove Rimuovi profili dalle istanze
rename Rinomina profili
set Imposta le chiavi di configurazione dei profili
show Mostra configurazioni di profili
unset Annulla le chiavi di configurazione dei profiliModifica del profilo
Il profilo di configurazione predefinito default non ha configurazione della scheda di rete per il contenitore e tutti i contenitori appena creati non hanno rete, è necessario creare dispositivi di rete locali (dedicati) con un comando separato, ma possiamo creare nel profilo di configurazione un dispositivo di rete globale che sarà condiviso tra tutti i contenitori che utilizzano questo profilo. In questo modo, subito dopo il comando di creazione di un nuovo contenitore, avranno una rete con accesso alla rete. Non ci sono limiti, possiamo sempre creare successivamente un dispositivo di rete locale se necessario.
Il seguente comando 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, poiché abbiamo effettivamente aggiunto un dispositivo al profilo di configurazione, se avessimo specificato un indirizzo IP statico per il dispositivo, tutti i contenitori che applicano questo profilo condivideranno lo stesso indirizzo IP. Se è necessario creare un contenitore con un indirizzo IP statico dedicato, è allora consigliabile creare una configurazione del dispositivo di rete a livello del contenitore (configurazione locale) con il parametro dell'indirizzo IP, e non 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 contenitori creati verranno creati due dispositivi (devices):
eth0— Dispositivo di tiponiccollegato a uno switch (bridge di rete)lxdbr0root— Dispositivo di tipodiskche utilizza un pool di archiviazionessdpool
Creazione di nuovi profili
Per utilizzare i già creati Storage Pool contenitori, creeremo 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=ssdpoolAnalogamente, creiamo un dispositivo di tipo disk, ma in questo caso utilizzando 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 costruite appositamente prive di kernel Linux. Pertanto, prima di avviare un contenitore, deve essere distribuito da questa immagine. La fonte delle immagini è il repository locale in cui le immagini vengono caricate da repository esterni.
Repository delle immagini remote
Per impostazione predefinita, LXD è configurato per ricevere immagini da tre fonti remote:
- ubuntu: (per le immagini stabili di Ubuntu)
- ubuntu-daily: (per le immagini giornaliere di Ubuntu)
- immagini: (per una serie di altre distribuzioni)
lxc remote list
+-----------------+------------------------------------------+--------+--------+
| NOME | URL | PUBBLICO | STATICO |
+-----------------+------------------------------------------+--------+--------+
| images | https://images.linuxcontainers.org | SÌ | NO |
+-----------------+------------------------------------------+--------+--------+
| local (default) | 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 limitare il numero di colonne, abbiamo utilizzato l'opzione -c con i parametri dasut, e abbiamo anche limitato la lunghezza dell'elenco usando il comando head.
Per visualizzare l'elenco delle immagini, è possibile filtrare. Il comando seguente elencherà tutte le architetture disponibili della distribuzione :
lxc image -c ldast list images:alpine/3.11
+------------------------------+--------------------------------------+--------------+
| ALIAS | DESCRIZIONE | ARCHITETTURA |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11 (3 di più) | Alpine 3.11 amd64 (20200220_13:00) | x86_64 |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/arm64 (1 di più) | Alpine 3.11 arm64 (20200220_13:00) | aarch64 |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/armhf (1 di più) | Alpine 3.11 armhf (20200220_13:00) | armv7l |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/i386 (1 di più) | Alpine 3.11 i386 (20200220_13:01) | i686 |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/ppc64el (1 di più) | Alpine 3.11 ppc64el (20200220_13:00) | ppc64le |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/s390x (1 di più) | 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 local:. Al momento, il repository locale è vuoto, questo ci verrà confermato dal comando lxc image list. Se al metodo list non viene specificato alcun repository, verrà utilizzato per impostazione predefinita il repository locale - local:
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
Gestire gli alias delle immagini
lxc image copy
Copiare immagini tra server
lxc image delete
Eliminare immagini
lxc image edit
Modificare le proprietà delle immagini
lxc image export
Esportare e scaricare immagini
lxc image importa
Importare immagini nel deposito delle immagini
lxc image info
Mostrare informazioni utili sulle immagini
lxc image list
Elencare immagini
lxc image aggiorna
Aggiornare immagini
lxc image mostra
Mostrare le proprietà delle immagini
Copia l'immagine nel repository locale dal globale immagini::
lxc image copy images:alpine/3.11/amd64 local: --alias=alpine3
Immagine copiata con successo!Mostriamo l'elenco di tutte le immagini attualmente disponibili nel repository locale local::
lxc image -c lfdatsu list local:
+---------+--------------+------------------------------------+--------------+
| ALIAS | FINGERPRINT | DESCRIPTION | ARCHITECTURE |
+---------+--------------+------------------------------------+--------------+
| alpine3 | 73a3093d4a5c | Alpine 3.11 amd64 (20200220_13:00) | x86_64 |
+---------+--------------+------------------------------------+--------------+Configurazione di LXD
Oltre alla modalità interattiva, LXD supporta anche la modalità non interattiva per la configurazione, in cui la configurazione viene specificata come file YAML, un formato speciale che consente di impostare l'intera configurazione in una sola volta, bypassando l'esecuzione di numerosi comandi interattivi già trattati in questo articolo, inclusa la configurazione di rete, la creazione di profili di configurazione, ecc. Non tratteremo quest'area qui, puoi informarti autonomamente su di essa .
Il seguente comando interattivo lxc config che esamineremo, consente di impostare la configurazione. Ad esempio, affinché le immagini caricate nel repository locale non vengano aggiornate automaticamente dai repository globali, possiamo attivare questo comportamento con il seguente comando:
lxc config set images.auto_update_cached=falseCreazione e gestione di un container
Per creare un contenitore si utilizza il comando lxc init a cui vengono passati i valori repository:image e poi l'identificatore desiderato per il contenitore. Il repository può essere specificato come locale local: Così come qualsiasi globale. Se il repository non è specificato, per impostazione predefinita, viene utilizzato il repository locale per cercare l'immagine. Se l'immagine è specificata da un repository globale, all'inizio l'immagine verrà caricata 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 nel dettaglio le opzioni del comando che stiamo utilizzando qui:
alpine3— Viene specificato un alias per l'immagine precedentemente caricata nel repository locale. Se l'alias non era stato creato per quest'immagine, è sempre possibile fare riferimento all'immagine tramite il suo Fingerprint che viene visualizzato nella tabella.alp— Viene impostato un identificatore per il contenitore--storage— Questa opzione indica in quale Storage Pool verrà creato il contenitore--profile— Queste opzioni applicano in cascata al contenitore la configurazione dai profili di configurazione creati in precedenza.
Avviamo il contenitore, che inizia a avviare il sistema init della distribuzione:
lxc start alpInoltre, è 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 |
+------+---------+------------------+------+-----------+--------------+Verifichiamo 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 trovare solo un dispositivo, poiché il dispositivo di rete è stato creato a livello di profilo. default. Per vedere tutti i dispositivi utilizzati dal contenitore è necessario aggiungere la chiave --expanded:
lxc config show alp --expanded
architettura: 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:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path:
pool: hddpool
type: disk
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""Impostazione 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 ci informerà che il dispositivo non esiste perché il dispositivo eth0 utilizzato dal contenitore appartiene al profilo default:
lxc config device set alp eth0 ipv4.address 10.0.5.5
Errore: Il dispositivo non esistePossiamo naturalmente 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.5Dobbiamo quindi riavviare il contenitore:
lxc restart alpSe ora guardiamo alla configurazione del contenitore, non dobbiamo applicare l'opzione --expanded per vedere il dispositivo di rete eth0, poiché l'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: RUNNING
devices:
eth0:
ipv4.address: 10.0.5.5
name: eth0
nictype: bridged
parent: lxdbr0
type: nic
root:
path: \
pool: hddpool
type: disk
ephemerale: false
profilo:
- predefinito
- hddroot
stateful: false
descrizione: ""Eliminazione del container
Per eliminare il contenitore si utilizza il comando lxc delete, ma prima di eliminare il contenitore, deve essere fermato utilizzando il comando lxc stop:
lxc stop alplxc list
+------+---------+-------------------+------+-----------+-----------+
| NOME | STATO | IPV4 | IPV6 | TIPO | SNAPSHOT |
+------+---------+-------------------+------+-----------+-----------+
| alp | FERMATO | 10.0.5.10 (eth0) | | CONTENITORE | 0 |
+------+---------+-------------------+------+-----------+-----------+Dopo aver verificato che lo stato del contenitore è diventato STOPPED, può essere eliminato da Storage Pool:
lxc delete alpAccesso al container
Per eseguire comandi all'interno del contenitore, direttamente, bypassando le connessioni di rete, si utilizza il comando lxc exec che esegue comandi nel contenitore senza avviare la shell di sistema. Se hai bisogno di eseguire un comando nella shell, utilizzando pattern di shell, come variabili, reindirizzamenti di file (pipe), ecc., puoi 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 $ in modo che 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 concluso la sessione, eseguire il hotkey CTRL+D:
lxc exec alp -- /bin/shGestione delle risorse del container
In LXD è possibile gestire le risorse del contenitore utilizzando un insieme speciale di configurazione. L'elenco completo dei parametri di configurazione del contenitore è disponibile .
Limitazione delle risorse RAM (memoria)
Parametro limits.memory limita la quantità di RAM disponibile per il contenitore. Come valore viene indicato un numero e uno dei .
Imponiamo al contenitore un limite sulla quantità di RAM pari a 256 MB:
lxc config set alp limits.memory 256MBInoltre, ci sono 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 CPU ci sono diversi :
limit.cpu— lega il contenitore a uno o più core della CPUlimits.cpu.allowance— gestisce o i limiti del pianificatore CFS, quando si supera il limite di tempo, o un meccanismo universale di condivisione delle risorse CPU, quando si supera una certa percentualelimits.cpu.priority— priorità del pianificatore, quando a più istanze condivide lo stesso insieme di processori ed è assegnato lo stesso percentuale di processori
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: ""Limitazione dello spazio su disco
Oltre alle limitazioni come limits.read, limits.write possiamo anche limitare il volume di spazio su disco utilizzato dal contenitore (funziona solo con ZFS o BTRFS):
lxc config device set alp root size=2GBDopo aver impostato, 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 disco utilizzate possiamo ottenere dai comandi lxc info:
lxc info alp
...
Resources:
Processes: 5
Disk usage:
root: 1.05GB
CPU usage:
CPU usage (in seconds): 1
Memory usage:
Memory (current): 5.46MB
Network usage:
eth0:
Bytes received: 802B
Bytes sent: 1.59kB
Packets received: 4
Packets sent: 14
lo:
Bytes received: 0B
Bytes sent: 0B
Packets received: 0
Packets sent: 0Nonostante abbiamo impostato un limite per il dispositivo root del contenitore a 2GB, gli strumenti di sistema come df non vedranno questo limite. Per questo faremo un piccolo test per scoprire come funziona.
Creeremo 2 nuovi contenitori identici nello stesso Storage Pool (hddpool):
lxc init alpine3 alp1 --storage=hddpool --profile=default --profile=hddroot
lxc init alpine3 alp2 --storage=hddpool --profile=default --profile=hddrootlxc list
+------+---------+------------------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+------------------+------+-----------+-----------+
| alp1 | RUNNING | 10.0.5.46 (eth0) | | CONTAINER | 0 |
+------+---------+------------------+------+-----------+-----------+
| alp2 | RUNNING | 10.0.5.30 (eth0) | | CONTAINER | 0 |
+------+---------+------------------+------+-----------+-----------+In uno dei contenitori creeremo un file di dimensione 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 e verifichiamo l'esistenza del file nello stesso percorso, non ci sarà, come ci si aspetta, poiché i contenitori vengono creati nei propri Storage Volume in questo stesso Storage Pool:
lxc exec alp2 -- ls -lh
total 0Ma confrontiamo i valori restituiti 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 root è Storage Pool che questi contenitori utilizzano, quindi lo condividono tra loro.
Statistiche di utilizzo delle risorse
È possibile visualizzare le statistiche di utilizzo delle risorse per il contenitore utilizzando 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: 0Gestione degli snapshot
In LXD c'è la possibilità di creare snapshot e ripristinare lo stato del contenitore da essi.
Per creare uno snapshot, eseguire il seguente comando:
lxc snapshot alp snapshot1Il comando lxc snapshot non ha un'opzione list, quindi, per visualizzare l'elenco degli snapshot è necessario utilizzare il comando che mostra le informazioni generali sul contenitore:
lxc info alp
...
...
Snapshot:
snapshot1 (preso il 2020/04/08 18:18 UTC) (stateless)È possibile ripristinare un contenitore da uno snapshot usando il comando lxc restore indicando il contenitore per cui si desidera effettuare il ripristino e l'alias dello snapshot:
lxc restore alp snapshot1Il comando seguente serve per eliminare uno snapshot. Si noti che la sintassi del comando non somiglia a quella degli altri; è necessario indicare una barra diretta dopo il nome del contenitore. Se la barra viene omessa, il comando di eliminazione dello snapshot viene interpretato come comando di eliminazione del contenitore!
lxc delete alp/snapshot1Nell'esempio sopra abbiamo considerato i cosiddetti snapshot stateless. In LXD esiste un altro tipo di snapshot — stateful, in cui viene salvato lo stato attuale di tutti i processi nel contenitore. Gli snapshot stateful offrono alcune funzioni interessanti e utili.
Cos'altro?
- Per gli sviluppatori Python è disponibile il modulo che fornisce un'API per LXD
AGGIORNAMENTO 10.04.2020 15:00: Aggiunta navigazione
Fonte: habr.com
