Le funzionalità di base di LXD — sistemi di contenitori in Linux

Le funzionalità di base di LXD — sistemi di contenitori in Linux

LXD — è un gestore di container di nuova generazione, così dice fonte. 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 pacchetto snap:

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 source

Eseguendo 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✓  core

Nonostante 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 lxd

Assicuriamoci 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 lxd

Dopo l'installazione del pacchetto, per gestire LXD come utente normale, è necessario aggiungerlo al gruppo di sistema lxd:

sudo usermod -a -G lxd user1

Verifichiamo che l'utente user1 sia stato aggiunto al gruppo lxd:

id -Gn user1

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

Se 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 lxd

Avviamo il servizio:

sudo systemctl start lxd

Controlliamo lo stato del servizio:

sudo systemctl status lxd

Archiviazione LXD (Storage) ^

Prima della inizializzazione, dobbiamo comprendere come è strutturato logicamente lo storage in LXD.

Lo storage (Storage) è composto 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

Le funzionalità di base di LXD — sistemi di contenitori in Linux

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/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3

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

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

Inizializzazione 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 una tabella comparativa delle funzionalità:

Caratteristica
Directory
Btrfs
LVM
ZFS
CEPH

Storage immagini ottimizzato
no



Creazione instance ottimizzata
no



Creazione snapshot ottimizzata
no



Trasferimento immagini ottimizzato
no

no

Trasferimento instance ottimizzato
no

no

Copy on write
no



Basato su blocchi
no
no

no

Clonazione istantanea
no



Driver di storage utilizzabile all'interno di un container


no
no
no

Ripristino da snapshot più vecchi (non gli ultimi)



no

Quote di storage
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, vedi la risposta dello sviluppatore. 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\/s

Colleghiamo il file loopback a un dispositivo loopback libero:

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

\/dev\/loop1

Grazie 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     512

Dall'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\/loop1

Visualizziamo 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\/hddpool

Inserimento 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
EOF

Attiviamo 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 root

Per applicare le modifiche, il servizio LXD deve essere riavviato:

sudo systemctl restart lxd

Creazione 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:

Le funzionalità di base di LXD — sistemi di contenitori in Linux

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=none

Verifichiamo 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 0

Profilo 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:

Le funzionalità di base di LXD — sistemi di contenitori in Linux

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 profili

Modifica 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 tipo nic collegato a uno switch (bridge di rete) lxdbr0
  • root — Dispositivo di tipo disk che utilizza un pool di archiviazione ssdpool

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 Poolssdpool:

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

Analogamente, creiamo un dispositivo di tipo disk, ma in questo caso utilizzando Storage Poolhddpool:

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

Controlliamo 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 AlpineLinux:

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 nella documentazione.

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=false

Creazione 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=hddroot

Analizziamo 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 alp

Inoltre, è 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 esiste

Possiamo 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.5

Dobbiamo quindi riavviare il contenitore:

lxc restart alp

Se 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 alp

lxc 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 alp

Accesso 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/sh

Gestione 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 nella documentazione.

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 suffissi disponibili.

Imponiamo al contenitore un limite sulla quantità di RAM pari a 256 MB:

lxc config set alp limits.memory 256MB

Inoltre, ci sono altri parametri per limitare la memoria:

  • limits.memory.enforce
  • limits.memory.hugepages
  • limits.memory.swap
  • limits.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 tipi di limitazioni:

  • limit.cpu — lega il contenitore a uno o più core della CPU
  • limits.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 percentuale
  • limits.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=2GB

Dopo 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: 0

Nonostante 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=hddroot

lxc 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=1000

Assicuriamoci 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.img

Se 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 0

Ma 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: 0

Gestione 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 snapshot1

Il 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 snapshot1

Il 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/snapshot1

Nell'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 PyLXD che fornisce un'API per LXD

AGGIORNAMENTO 10.04.2020 15:00: Aggiunta navigazione

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster