Las capacidades básicas de LXD: el sistema de contenedores en Linux

Las capacidades básicas de LXD: el sistema de contenedores en Linux

LXD — es un gestor de contenedores de nueva generación, así está declarado fuente. Ofrece una interfaz de usuario similar a las máquinas virtuales, pero utiliza contenedores de Linux en su lugar.

El núcleo de LXD — es un demonio privilegiado (servicio ejecutado con derechos de root) que proporciona una API REST a través de un socket unix local, así como a través de la red, si se establece la configuración adecuada. Los clientes, como la herramienta de línea de comandos proporcionada con LXD, envían solicitudes a través de esta API REST. Esto significa que, independientemente de si estás accediendo al host local o a uno remoto, todo funciona de la misma manera.

En este artículo no profundizaremos en los conceptos de LXD, ni examinaremos todas las capacidades disponibles descritas en la documentación, incluyendo la reciente implementación en las últimas versiones de LXD que soporta máquinas virtuales QEMU junto con contenedores. En su lugar, solo conoceremos las funciones básicas de gestión de contenedores: configuraremos grupos de almacenamiento, red, iniciaremos un contenedor, aplicaremos límites de recursos y también veremos cómo usar instantáneas, para que puedas obtener una visión básica de LXD y utilizar contenedores en Linux.

Para obtener información completa, se debe consultar la fuente oficial:

Navegación

Instalación de LXD ^

Instalación de LXD en distribuciones de Ubuntu ^

En la distribución Ubuntu 19.10, el paquete lxd tiene traducción a paquete snap:

apt search lxd

lxd/eoan 1:0.7 all
  Paquete de transición - lxd -> snap (lxd)

Esto significa que se instalarán dos paquetes de inmediato, uno del sistema y otro como paquete snap. La instalación de dos paquetes en el sistema puede causar un problema en el que el paquete del sistema puede quedar huérfano si se elimina el paquete snap mediante el gestor de paquetes snap.

Buscar paquete lxd en el repositorio snap se puede hacer con el siguiente comando:

snap find lxd

Nombre            Versión       Resumen
lxd               3.21          Gestor de contenedores del sistema y API
lxd-demo-server   0+git.6d54658  Sesiones de demostración de software en línea usando LXD
nova              ocata         Servicio de computación OpenStack (nova)
nova-hypervisor   ocata         Servicio de computación OpenStack - Hypervisor KVM (nova)
distrobuilder     1.0           Constructor de imágenes para LXC y LXD
fabrica           0.1           Crea snaps simplemente apuntando un formulario web a...
satellite         0.1.2         Plataforma avanzada escalable de inteligencia de código abierto

Al ejecutar el comando list se puede confirmar que el paquete lxd todavía no está instalado:

snap list

Nombre  Versión    Rev   Seguimiento  Publicador   Notas
core  16-2.43.3  8689  estable    canonical✓  core

A pesar de que LXD es un paquete snap, se debe instalar a través del paquete del sistema lxd, el cual creará en el sistema el grupo correspondiente y las utilidades necesarias en /usr/bin etc.

sudo apt update
sudo apt install lxd

Verifiquemos que el paquete esté instalado como paquete snap:

snap list

Nombre  Versión    Rev    Seguimiento  Publicador   Notas
core  16-2.43.3  8689   estable    canonical✓  core
lxd   3.21       13474  estable/...  canonical✓  -

Instalación de LXD en distribuciones de Arch Linux ^

Para instalar el paquete LXD en el sistema, es necesario ejecutar los siguientes comandos; el primero actualizará la lista de paquetes disponibles en el repositorio y el segundo instalará directamente el paquete:

sudo pacman -Syyu && sudo pacman -S lxd

Después de instalar el paquete, para gestionar LXD como usuario normal, debe ser agregado al grupo del sistema lxd:

sudo usermod -a -G lxd user1

Verifiquemos que el usuario user1 haya sido agregado al grupo lxd:

id -Gn user1

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

Si el grupo lxd no aparece en la lista, entonces es necesario reiniciar la sesión del usuario. Para hacer esto, debe cerrar sesión y volver a ingresar al sistema con el mismo usuario.

Activaremos en systemd la carga del servicio LXD al inicio del sistema:

sudo systemctl enable lxd

Iniciamos el servicio:

sudo systemctl start lxd

Verificamos el estado del servicio:

sudo systemctl status lxd

Almacenamiento LXD (Storage) ^

Antes de comenzar la inicialización, necesitamos entender cómo está estructurado lógicamente el almacenamiento en LXD.

El almacenamiento (Almacenamiento) se compone de uno o más Grupo de Almacenamiento que utiliza uno de los sistemas de archivos compatibles como ZFS, BTRFS, LVM o directorios normales. Cada Grupo de Almacenamiento se divide en volúmenes (Storage Volume) que contienen imágenes, contenedores o datos para otros fines.

  • Imágenes son distribuciones especialmente construidas sin núcleo de Linux y disponibles desde fuentes externas
  • Contenedores son distribuciones desplegadas desde imágenes, listas para su uso
  • Instantáneas son capturas del estado de los contenedores a las que se puede regresar

Las capacidades básicas de LXD: el sistema de contenedores en Linux

Para gestionar el almacenamiento en LXD, se utiliza el comando lxc storage cuya ayuda se puede obtener indicando la clave — lxc storage --help

El siguiente comando muestra en pantalla la lista de todos Grupo de Almacenamiento en el almacenamiento de LXD:

lxc storage list

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

Para ver la lista de todos Storage Volume en el elegido Grupo de Almacenamiento se utiliza el 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       |
+-----------+----------------------------------+-------------+---------+

Además, si al crear se eligió el sistema de archivos BTRFS, se puede obtener la lista de Grupo de Almacenamiento subvolúmenes Storage Volume o en la interpretación de BTRFS mediante las herramientas de este sistema de archivos: sudo btrfs subvolume list -p /var/lib/lxd/storage-pools/hddpoolID 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

Antes de crear y usar contenedores, es necesario realizar la inicialización general de LXD que crea y configura la red, así como el almacenamiento. Esto se puede llevar a cabo manualmente mediante los comandos estándar del cliente que están disponibles en la lista llamando al comando

Inicialización de LXD ^

lxc --help o mediante el asistente de inicialización lxd init respondiendo a algunas preguntas. respondí a varias preguntas.

Selección del sistema de archivos para el grupo de almacenamiento ^

Durante la inicialización, LXD hace varias preguntas, entre las cuales se definirá el tipo de sistema de archivos para el predeterminado Grupo de Almacenamiento. Por defecto, se selecciona el sistema de archivos BTRFS. No será posible cambiar a otro sistema de archivos después de la creación. Para seleccionar un sistema de archivos, se ofrece una tabla de comparación de capacidades:

Características
Directorio
Btrfs
LVM
ZFS
CEPH

Almacenamiento de imágenes optimizado
no
yes
yes
yes
yes

Creación de instancias optimizada
no
yes
yes
yes
yes

Creación de instantáneas optimizada
no
yes
yes
yes
yes

Transferencia de imágenes optimizada
no
yes
no
yes
yes

Transferencia de instancias optimizada
no
yes
no
yes
yes

Copia al escribir
no
yes
yes
yes
yes

Basado en bloques
no
no
yes
no
yes

Clonado instantáneo
no
yes
yes
yes
yes

Controlador de almacenamiento utilizable dentro de un contenedor
yes
yes
no
no
no

Restaurar desde instantáneas anteriores (no la más reciente)
yes
yes
yes
no
yes

Cuotas de almacenamiento
sí(*)
yes
yes
yes
no

Inicialización de la red y del grupo de almacenamiento mediante el asistente ^

El siguiente comando que revisaremos permite configurar los componentes básicos de LXD respondiendo a preguntas sencillas mediante un asistente de inicialización.

Ejecute el comando lxc init y dé respuestas a las preguntas después de los dos puntos como se muestra en el ejemplo a continuación o modifíquelas según sus condiciones:

lxd init

¿Te gustaría utilizar la agrupación LXD? (sí/no) [predeterminado=no]: 
¿Quieres configurar un nuevo grupo de almacenamiento? (sí/no) [predeterminado=sí]: 
Nombre del nuevo grupo de almacenamiento [predeterminado=default]: ssdpool         
Nombre del backend de almacenamiento a utilizar (lvm, btrfs, dir) [predeterminado=btrfs]: 
¿Crear un nuevo grupo BTRFS? (sí/no) [predeterminado=sí]: 
¿Te gustaría usar un dispositivo de bloque existente? (sí/no) [predeterminado=no]: 
Tamaño en GB del nuevo dispositivo de bucle (mínimo 1GB) [predeterminado=15GB]: 10GB
¿Te gustaría conectarte a un servidor MAAS? (sí/no) [predeterminado=no]: 
¿Te gustaría crear un nuevo puente de red local? (sí/no) [predeterminado=sí]: 
¿Cómo debería llamarse el nuevo puente? [predeterminado=lxdbr0]: 
¿Qué dirección IPv4 debería utilizarse? (notación de subred CIDR, "auto" o "none") [predeterminado=auto]: 10.0.5.1/24
¿Te gustaría que LXD NATeara el tráfico IPv4 en tu puente? [predeterminado=sí]: 
¿Qué dirección IPv6 debería utilizarse? (notación de subred CIDR, "auto" o "none") [predeterminado=auto]: none
¿Te gustaría que LXD estuviese disponible a través de la red? (sí/no) [predeterminado=no]: 
¿Te gustaría que las imágenes almacenadas en caché caducadas se actualizaran automáticamente? (sí/no) [predeterminado=sí]: no
¿Te gustaría que se imprimiera una preconfiguración YAML para "lxd init"? (sí/no) [predeterminado=no]: 

Creación de un grupo de almacenamiento adicional ^

En el paso anterior, hemos creado Grupo de Almacenamiento al que le dimos el nombre ssdpool y cuyo archivo se encuentra en mi sistema en la dirección /var/lib/lxd/disks/ssdpool.img. Esta dirección del sistema de archivos corresponde al disco SSD físico en mi PC.

Las siguientes acciones, para ampliar la comprensión del papel que juega Grupo de Almacenamiento en el almacenamiento, crearemos un segundo Grupo de Almacenamiento que físicamente estará en otro tipo de disco, en un HDD. El problema es que LXD no permite crear Grupo de Almacenamiento fuera de la dirección /var/lib/lxd/disks/ y ni siquiera los enlaces simbólicos funcionarán, vea la respuesta del desarrollador. Podemos sortear esta limitación al inicializar/formatear Grupo de Almacenamiento especificando el valor como un dispositivo de bloque en lugar de la ruta a un archivo de bucle, indicándolo en la clave source.

Por lo tanto, antes de crear Grupo de Almacenamiento es necesario definir un archivo de loopback o una partición existente en su sistema de archivos que utilizará. Para ello, crearemos y utilizaremos un archivo que limitaremos a 10 GB:

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

10000+0 registros entrantes
10000+0 registros salientes
10000000000 bytes (10 GB, 9,3 GiB) copiados, 38,4414 s, 260 MB/s

Conectaremos el archivo de loopback a un dispositivo de loopback libre:

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

/dev/loop1

Gracias a la clave --show la ejecución del comando devuelve en pantalla el nombre del dispositivo al que se ha conectado nuestro archivo de loopback. Si es necesario, podemos mostrar en pantalla la lista de todos los dispositivos ocupados de este tipo, para asegurarnos de que nuestras acciones son correctas:

losetup -l

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

De la lista se puede observar que en el dispositivo /dev/loop1 se ha conectado un archivo de loopback /mnt/work/lxd/hddpool.img, y en el dispositivo /dev/loop0 se ha conectado un archivo de loopback /var/lib/lxd/disks/ssdpool.img que corresponde al predeterminado Grupo de Almacenamiento.

El siguiente comando crea un nuevo Grupo de Almacenamiento en LXD basado en el archivo de loopback recién preparado. LXD formateará el archivo de loopback /mnt/work/lxd/hddpool.img en el dispositivo /dev/loop1 para el sistema de archivos BTRFS:

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

Mostremos la lista de todos Grupo de Almacenamiento en pantalla:

lxc storage list

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

Aumento del tamaño del grupo de almacenamiento ^

Después de crear Grupo de Almacenamiento, si es necesario, se puede ampliar. Para Grupo de Almacenamiento basado en el sistema de archivos BTRFS, ejecute los siguientes comandos:

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

Autoinserción de un archivo de bucle en el slot de dispositivo de bucle ^

Tenemos un pequeño problema, al reiniciar el sistema host, el archivo /mnt/work/lxd/hddpool.img "se desconectará" del dispositivo /dev/loop1 y el servicio LXD fallará al iniciar ya que no lo verá en este dispositivo. Para resolver este problema, es necesario crear un servicio del sistema que insertará este archivo en el dispositivo /dev/loop1 al iniciar el sistema host.

Crearemos de pruebas unitarias archivo tipo el servicio en /etc/systemd/system/ para el sistema de inicialización 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

Activamos el servicio:

sudo systemctl enable lxd-hddpool

Se creó un enlace simbólico en /etc/systemd/system/local-fs.target.wants/lxd-hddpool.service → /etc/systemd/system/lxd-hddpool.service.

Después de reiniciar el sistema host, comprobamos el estado del servicio:

systemctl status lxd-hddpool.service 

● lxd-hddpool.service - Losetup LXD Storage Pool (hddpool)
     Cargado: cargado (/etc/systemd/system/lxd-hddpool.service; habilitado; ajuste de proveedor: deshabilitado)
     Activo: activo (salió) desde el Wed 2020-04-08 03:43:53 MSK; hace 1min 37s
    Proceso: 711 ExecStart=/sbin/losetup /dev/loop1 /mnt/work/lxd/hddpool.img (código=salió, estado=0/SÉXITO)
   PID principal: 711 (código=salió, estado=0/SÉXITO)

abr 08 03:43:52 manjaro systemd[1]: Iniciando Losetup LXD Storage Pool (hddpool)...
abr 08 03:43:53 manjaro systemd[1]: Finalizado Losetup LXD Storage Pool (hddpool).

De la salida podemos asegurarnos de que el estado del servicio es active, a pesar de que la ejecución de nuestro script de un solo comando finalizó, esto nos permitió hacer la opción RemainAfterExit=true.

Seguridad. Privilegios de los contenedores ^

Dado que todos los procesos del contenedor se ejecutan en aislamiento en el sistema host utilizando su núcleo, para proteger el acceso de los procesos del contenedor al sistema host, LXD ofrece privilegiados procesos, donde:

  • Contenedores privilegiados son contenedores en los que los procesos con UID y GID corresponden al mismo propietario que en el sistema host. Por ejemplo, un proceso ejecutado en un contenedor con UID igual a 0 tiene los mismos derechos de acceso que un proceso del sistema host con UID igual a 0. En otras palabras, el usuario root en el contenedor tiene todos los derechos no solo dentro del contenedor, sino también en el sistema host si puede salir del espacio de nombres aislado del contenedor.

  • Contenedores no privilegiados son contenedores en los que los procesos pertenecen al propietario con UID y GID de 0 a 65535, pero para el sistema host el propietario se enmascara mediante el bit SubUID y SubGID añadidos. Por ejemplo, un usuario con UID=0 en el contenedor será visto en el sistema host como SubUID + UID. Esto protege al sistema host, ya que si algún proceso en el contenedor puede salir de su espacio de nombres aislado, solo puede interactuar con el sistema host como un proceso con UID/GID desconocido y muy alto.

Por defecto, los contenedores recién creados tienen el estado de no privilegiados y por lo tanto debemos definir SubUID y SubGID.

Crearemos dos archivos de configuración en los que establecemos la máscara para SubUID y SubGID respectivamente:

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

Para aplicar los cambios, el servicio LXD debe ser reiniciado:

sudo systemctl restart lxd

Creación de un conmutador virtual de red ^

Dado que anteriormente inicializamos la red utilizando el asistente de inicialización respondiendo a algunas preguntas. y creamos un dispositivo de red lxdbr0, en esta sección solo nos familiarizaremos con la red en LXD y con cómo crear un conmutador virtual (puente de red, bridge) utilizando el comando del cliente.

El siguiente esquema muestra cómo el conmutador (puente de red, bridge) conecta el host y los contenedores en la red:

Las capacidades básicas de LXD: el sistema de contenedores en Linux

Los contenedores pueden interactuar a través de la red con otros contenedores o con el host en el que están alojados. Para ello, es necesario enlazar las tarjetas de red virtuales de los contenedores con el conmutador virtual. Primero crearemos el conmutador, y las interfaces de red del contenedor se enlazarán en capítulos posteriores, después de que se haya creado el propio contenedor.

El siguiente comando crea un conmutador con una subred 10.0.5.0/24 y una dirección IPv4 10.0.5.1/24, y también habilita ipv4.nat para que los contenedores puedan acceder a Internet a través del host utilizando el servicio NAT:

lxc network create lxdbr0 ipv4.address=10.0.5.1/24 ipv4.nat=true ipv6.address=none

Verificamos la lista de dispositivos de red disponibles en LXD:

lxc network list

+--------+----------+---------+-------------+---------+
|  NAME  |   TYPE   | MANAGED | DESCRIPTION | USED BY |
+--------+----------+---------+-------------+---------+
| eno1   | physical | NO      |             | 0       |
+--------+----------+---------+-------------+---------+
| lxdbr0 | bridge   | YES     |             | 0       |
+--------+----------+---------+-------------+---------+

Además, se puede verificar la creación del dispositivo de red utilizando la herramienta estándar del sistema operativo 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

Perfil de configuración ^

Cada contenedor en LXD tiene su propia configuración y puede expandirla mediante configuraciones declaradas globalmente que se denominan perfiles de configuración. La aplicación de perfiles de configuración a un contenedor sigue un modelo en cascada; el siguiente ejemplo lo demuestra:

Las capacidades básicas de LXD: el sistema de contenedores en Linux

En este ejemplo, se han creado tres perfiles en el sistema LXD: default, hddpool y hostfs. Los tres perfiles se aplican a un contenedor que tiene una configuración local (zona gris). El perfil default tiene un dispositivo root que tiene el parámetro pool es igual a ssdpool, pero gracias al modelo en cascada de aplicación de configuración, podemos aplicar al contenedor el perfil hddpool que tiene el parámetro pool sobrescribirá este mismo parámetro del perfil default y el contenedor recibirá la configuración del dispositivo root con el parámetro pool igual a hddpool, mientras que el perfil hostfs simplemente añade un nuevo dispositivo al contenedor.

Para ver la lista de perfiles de configuración disponibles, se utiliza el siguiente comando:

lxc profile list

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

La lista completa de comandos disponibles para trabajar con perfiles se puede obtener agregando la clave --help:

lxc profile --help

Descripción:
  Gestionar perfiles

Uso:
  lxc profile [comando]

Comandos disponibles:
  add         Agregar perfiles a instancias
  assign      Asignar conjuntos de perfiles a instancias
  copy        Copiar perfiles
  create      Crear perfiles
  delete      Eliminar perfiles
  device      Gestionar dispositivos de instancia
  edit        Editar configuraciones de perfil como YAML
  get         Obtener valores para claves de configuración de perfil
  list        Listar perfiles
  remove      Eliminar perfiles de instancias
  rename      Renombrar perfiles
  set         Establecer claves de configuración de perfil
  show        Mostrar configuraciones de perfil
  unset       Desestablecer claves de configuración de perfil

Edición del perfil ^

El perfil de configuración por defecto default no tiene configuración de tarjeta de red para el contenedor y todos los contenedores creados no tienen red. Para ellos, es necesario crear dispositivos de red locales (dedicados) con un comando separado, pero podemos crear en el perfil de configuración un dispositivo de red global que será compartido entre todos los contenedores que usen este perfil. Así, inmediatamente después del comando de creación de un nuevo contenedor, tendrán red con acceso a la red. En este sentido, no hay restricciones; siempre podemos crear más tarde un dispositivo de red local si es necesario.

El siguiente comando añadirá a la configuración del perfil un dispositivo eth0 del tipo nic conectado a la red lxdbr0:

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

Es importante señalar que, dado que hemos agregado un dispositivo al perfil de configuración, si hubiéramos especificado una dirección IP estática para el dispositivo, todos los contenedores que apliquen este perfil compartirían la misma dirección IP. Si es necesario crear un contenedor con una dirección IP estática dedicada, entonces se debe crear una configuración de dispositivo de red a nivel del contenedor (configuración local) con la dirección IP, y no a nivel de perfil.

Verificamos el perfil:

lxc profile show default

config: {}
description: Perfil LXD predeterminado
devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  root:
    path: \/
    pool: ssdpool
    type: disk
name: default
used_by: []

En este perfil podemos ver que se crearán dos dispositivos (devices) para todos los contenedores recién creados:

  • eth0 — Dispositivo del tipo nic conectado a un switch (puente de red) lxdbr0
  • root — Dispositivo del tipo disco que utiliza un pool de almacenamiento ssdpool

Creación de nuevos perfiles ^

Para usar los anteriormente creados Grupo de Almacenamiento contenedores, crearemos un perfil de configuración ssdroot en el que añadiremos un dispositivo del tipo disco con un punto de montaje / (root) usando el ya creado Grupo de Almacenamiento — ssdpool:

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

De manera similar, creamos un dispositivo del tipo disco, pero en este caso utilizando Grupo de Almacenamiento — hddpool:

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

Verificamos los perfiles de configuración:

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: []

Repositorio de imágenes ^

Los contenedores se crean a partir de imágenes que son distribuciones especialmente construidas sin núcleo de Linux. Por lo tanto, antes de ejecutar un contenedor, debe ser desplegado a partir de esta imagen. La fuente de las imágenes es un repositorio local donde se cargan las imágenes desde repositorios externos.

Repositorios de imágenes remotas ^

Por defecto, LXD está configurado para recibir imágenes de tres fuentes remotas:

  • ubuntu: (para imágenes estables de Ubuntu)
  • ubuntu-daily: (para imágenes diarias de Ubuntu)
  • images: (para un conjunto de otras distribuciones)

lxc remote list

+-----------------+------------------------------------------+--------+--------+
|      NOMBRE     |                   URL                    | PÚBLICO | ESTÁTICO |
+-----------------+------------------------------------------+--------+--------+
| imágenes        | https://images.linuxcontainers.org       | SÍ     | NO     |
+-----------------+------------------------------------------+--------+--------+
| local (predeterminado) | unix://                                  | NO     | SÍ     |
+-----------------+------------------------------------------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | SÍ     | SÍ     |
+-----------------+------------------------------------------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | SÍ     | SÍ     |
+-----------------+------------------------------------------+--------+--------+

Por ejemplo, el repositorio ubuntu: tiene las siguientes imágenes:

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

+----------------------------------------------+--------------+----------+------------+
|                   DESCRIPCIÓN                | ARQUITECTURA |   TAMAÑO |   TIPO     |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150728)  | x86_64       | 153.72MB | CONTENEDOR |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150819)  | x86_64       | 152.91MB | CONTENEDOR |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150906)  | x86_64       | 154.69MB | CONTENEDOR |
+----------------------------------------------+--------------+----------+------------+
| ubuntu 12.04 LTS amd64 (release) (20150930)  | x86_64       | 153.86MB | CONTENEDOR |
+----------------------------------------------+--------------+----------+------------+

Para mostrar un número limitado de columnas usamos la opción — el número de paquetes, después de los cuales con los parámetros dasut, y también limitamos la longitud de la lista con el comando head.

Para mostrar la lista de imágenes, está disponible la filtración. El siguiente comando mostrará la lista de todas las arquitecturas disponibles del distribuidor AlpineLinux:

lxc image -c ldast list images:alpine/3.11

+------------------------------+--------------------------------------+--------------+
|            ALIAS             |             DESCRIPCIÓN              | ARQUITECTURA |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11 (3 más)          | Alpine 3.11 amd64 (20200220_13:00)   | x86_64       |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/arm64 (1 más)    | Alpine 3.11 arm64 (20200220_13:00)   | aarch64      |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/armhf (1 más)    | Alpine 3.11 armhf (20200220_13:00)   | armv7l       |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/i386 (1 más)     | Alpine 3.11 i386 (20200220_13:01)    | i686         |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/ppc64el (1 más)  | Alpine 3.11 ppc64el (20200220_13:00) | ppc64le      |
+------------------------------+--------------------------------------+--------------+
| alpine/3.11/s390x (1 más)    | Alpine 3.11 s390x (20200220_13:00)   | s390x        |
+------------------------------+--------------------------------------+--------------+

Repositorio de imágenes local ^

Para comenzar a utilizar el contenedor, es necesario añadir una imagen del repositorio global al local. local:En este momento, el repositorio local está vacío, así que la siguiente orden nos confirmará esto: lxc image listSi no se especifica un repositorio en el método, por defecto se utilizará el repositorio local — list lxc image list local:+-------+-------------+--------+-------------+--------------+------+------+ | ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | +-------+-------------+--------+-------------+--------------+------+------+ local:

La gestión de imágenes en el repositorio se realiza mediante los siguientes métodos:

lxc image

Comando
Descripción

Gestionar alias de imágenes alias
Copiar imágenes entre servidores

Gestionar alias de imágenes copy
Eliminar imágenes

Gestionar alias de imágenes delete
Editar propiedades de la imagen

Gestionar alias de imágenes edit
exportar

Gestionar alias de imágenes Exportar y descargar imágenes
Importar imágenes en el almacén de imágenes

Gestionar alias de imágenes import
Mostrar información útil sobre las imágenes

Gestionar alias de imágenes info
Listar imágenes

Gestionar alias de imágenes list
Actualizar imágenes

Gestionar alias de imágenes -token.
mostrar

Gestionar alias de imágenes Mostrar propiedades de la imagen
Copiamos la imagen al repositorio local desde el global

lxc image copy images:alpine/3.11/amd64 local: --alias=alpine3¡Imagen copiada con éxito! images::

Mostraremos la lista de todas las imágenes disponibles actualmente en el repositorio local

lxc image -c lfdatsu list local:+---------+--------------+------------------------------------+--------------+ | ALIAS | FINGERPRINT | DESCRIPTION | ARCHITECTURE | +---------+--------------+------------------------------------+--------------+ | alpine3 | 73a3093d4a5c | Alpine 3.11 amd64 (20200220_13:00) | x86_64 | +---------+--------------+------------------------------------+--------------+ local::

Además del modo interactivo, LXD también admite un modo no interactivo de configuración, que es cuando la configuración se establece en forma de archivo YAML, un formato especial que permite establecer toda la configuración a la vez, omitiendo la ejecución de múltiples órdenes interactivas que se han tratado anteriormente en este artículo, incluyendo la configuración de red, la creación de perfiles de configuración, etc. Aquí no vamos a tratar este aspecto, puedes informarte sobre esto por ti mismo.

Configuración de LXD ^

El siguiente comando interactivo en la documentación.

lxc config que vamos a revisar permite configurar las opciones. Por ejemplo, para que las imágenes descargadas en el repositorio local no se actualicen automáticamente desde los repositorios globales, podemos habilitar este comportamiento con el siguiente comando: lxc config set images.auto_update_cached=false

Para crear un contenedor, se utiliza el comando

Creación y gestión de un contenedor ^

al que se le pasan los valores lxc init repositorio:imagen y luego el identificador deseado para el contenedor. El repositorio puede ser especificado como local. es local: así como cualquier global. Si no se especifica un repositorio, por defecto, se utiliza el repositorio local para buscar la imagen. Si se indica una imagen del repositorio global, primero se descargará la imagen en el repositorio local y luego se utilizará para crear el contenedor.

Ejecutaremos el siguiente comando para crear nuestro primer contenedor:

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

Desglosemos uno por uno las claves del comando que usamos aquí:

  • alpine3 — Se especifica un alias (seudónimo) para la imagen que se ha descargado anteriormente en el repositorio local. Si no se creó un alias para esta imagen, siempre se puede referir a la imagen por su Huella digital que se muestra en la tabla.
  • alp — Se asigna un identificador para el contenedor
  • --storage — Esta clave indica en qué Grupo de Almacenamiento se creará el contenedor
  • --profile — Estas claves aplican en cascada la configuración del contenedor de los perfiles de configuración creados previamente

Iniciamos el contenedor, que comienza a ejecutar el sistema init de la distribución:

lxc start alp

También se puede usar el comando lxc launch que permite combinar los comandos lxc init y lxc start en una sola operación.

Comprobamos el estado del contenedor:

lxc list -c ns46tb
+------+---------+------------------+------+-----------+--------------+
| NAME |  STATE  |       IPV4       | IPV6 |   TYPE    | STORAGE POOL |
+------+---------+------------------+------+-----------+--------------+
| alp  | RUNNING | 10.0.5.46 (eth0) |      | CONTAINER | hddpool      |
+------+---------+------------------+------+-----------+--------------+

Comprobamos la configuración del contenedor:

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

En la sección perfiles podemos asegurarnos de que este contenedor utiliza dos perfiles de configuración — default y hddroot. En la sección dispositivos solo podemos detectar un dispositivo, ya que el dispositivo de red se creó a nivel de perfil defaultPara ver todos los dispositivos utilizados por el contenedor, es necesario agregar la clave --expanded:

lxc config show alp --expanded

arquitectura: 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: ""

Asignación de una dirección IP estática ^

Si intentamos establecer la dirección IP para el dispositivo de red eth0 con el comando lxc config device set alp destinada a la configuración del contenedor, obtendremos un error que indicará que el dispositivo no existe porque el dispositivo eth0 que usa el contenedor pertenece al perfil default:

lxc config device set alp eth0 ipv4.address 10.0.5.5

Error: El dispositivo no existe

Por supuesto, podemos establecer una dirección IP estática para eth0 el dispositivo en el perfil, pero será única para todos los contenedores que utilicen este perfil. Por lo tanto, agreguemos un dispositivo dedicado para el contenedor:

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

Luego, es necesario reiniciar el contenedor:

lxc restart alp

Si ahora miramos la configuración del contenedor, no necesitamos aplicar la opción --expanded para ver el dispositivo de red eth0, ya que lo creamos a nivel de contenedor y ha cubierto en cascada el mismo dispositivo del perfil default:

lxc config show alp

arquitectura: 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: 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
ephemeral: false
profiles:
- default
- hddroot
stateful: false
description: ""

Eliminación del contenedor ^

Para eliminar el contenedor, se usa el comando lxc delete, pero antes de eliminar el contenedor, debe ser detenido con el comando lxc stop:

lxc stop alp

lxc list

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

Después de asegurarnos de que el estado del contenedor es STOPPED, se puede eliminar de Grupo de Almacenamiento:

lxc delete alp

Acceso al contenedor ^

Para ejecutar comandos en el contenedor directamente, omitiendo las conexiones de red, se usa el comando lxc exec que ejecuta comandos en el contenedor sin iniciar un shell del sistema. Si necesita ejecutar un comando en el shell, utilizando patrones de shell, como variables, redirecciones de archivos (pipe), etc., debe iniciar el shell explícitamente y pasar el comando como argumento, por ejemplo:

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

En el comando se utilizó un símbolo especial de escape para el símbolo especial $ para que la variable $HOME no se interprete en la máquina host, sino que se interprete solo dentro del contenedor.

También es posible iniciar el modo interactivo del shell, y luego finalizar la sesión usando la tecla de acceso rápido CTRL+D:

lxc exec alp -- \/bin\/sh

Gestión de los recursos del contenedor ^

En LXD, se puede gestionar los recursos del contenedor mediante un conjunto especial de configuraciones. La lista completa de parámetros de configuración del contenedor se puede encontrar en la documentación.

Límite de recursos de RAM (memoria) ^

Parámetro limits.memory limita la cantidad de RAM accesible para el contenedor. Como valor, se indica un número y uno de los sufijos disponibles.

Introduzcamos un límite de 256 MB de RAM para el contenedor:

lxc config set alp limits.memory 256MB

Además, existen otros parámetros para limitar la memoria:

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

Comando lxc config show permite mostrar toda la configuración del contenedor, incluyendo la limitación de recursos aplicada:

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

Límite de recursos de CPU ^

Para limitar los recursos de la CPU, existen varios tipos de limitaciones:

  • limit.cpu — asigna el contenedor a uno o varios núcleos de CPU
  • limits.cpu.allowance — gestiona las cuotas del planificador CFS, cuando se ha agotado el límite de tiempo, o un mecanismo universal de uso compartido de recursos de CPU, cuando se ha superado un valor porcentual
  • limits.cpu.priority — prioridad del planificador, cuando se ha asignado el mismo porcentaje de CPU a varias instancias que comparten un conjunto de procesadores

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

Límite de espacio en disco ^

Además de las limitaciones tales como limits.read, limits.write también podemos limitar la cantidad de espacio en disco usado por el contenedor (solo funciona con ZFS o BTRFS):

lxc config device set alp root size=2GB

Después de la configuración, en el parámetro devices.root.size podemos verificar la limitación establecida:

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

Para revisar las cuotas de disco utilizadas, podemos obtenerlo del comando 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

A pesar de que hemos establecido un límite para el dispositivo raíz del contenedor en 2GB, utilidades del sistema como df no verán este límite. Para ello, realizaremos una pequeña prueba y averiguaremos cómo funciona.

Crearemos 2 nuevos contenedores idénticos en el mismo Grupo de Almacenamiento (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         |
+------+---------+------------------+------+-----------+-----------+

En uno de los contenedores, crearemos un archivo de 1GB:

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

Asegurémonos de que el archivo se haya creado:

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

Si miramos en el segundo contenedor y comprobamos la existencia del archivo en el mismo lugar, no habrá dicho archivo, lo cual es esperado, ya que los contenedores se crean en sus propios Storage Volume en este mismo Grupo de Almacenamiento:

lxc exec alp2 -- ls -lh
total 0

Pero comparemos los valores que reporta df en los dos contenedores:

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 montado como la partición raíz es Grupo de Almacenamiento la cual estos contenedores utilizan, por lo que comparten su volumen entre ellos.

Estadísticas de consumo de recursos ^

Puede ver las estadísticas de consumo de recursos para el contenedor usando el siguiente 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

Trabajo con instantáneas ^

En LXD, existe la posibilidad de crear instantáneas y restaurar el estado del contenedor desde ellas.

Para crear una instantánea, ejecute el siguiente comando:

lxc snapshot alp snapshot1

El comando lxc snapshot no tiene la opción list, por lo que, para ver la lista de instantáneas, debes utilizar un comando que muestre información general sobre el contenedor:

lxc info alp
...
...
Instantáneas:
  instantánea1 (tomada el 2020/04/08 18:18 UTC) (sin estado)

Se puede restaurar el contenedor a partir de una instantánea con el comando lxc restore especificando el contenedor para el cual se realizará la restauración y el alias de la instantánea:

lxc restore alp instantánea1

El siguiente comando se utiliza para eliminar una instantánea. Tenga en cuenta que la sintaxis del comando no se parece a todos los demás; aquí es necesario indicar una barra diagonal después del nombre del contenedor. Si se omite la barra, el comando de eliminación de la instantánea se interpretará como un comando de eliminación del contenedor.

lxc delete alp/instantánea1

En el ejemplo anterior, consideramos las llamadas instantáneas sin estado. En LXD hay otro tipo de instantáneas: con estado, en las que se guarda el estado actual de todos los procesos en el contenedor. Las instantáneas con estado están asociadas a una serie de funciones interesantes y útiles.

¿Qué más? ^

  • Para los desarrolladores de Python, está disponible el módulo PyLXD que proporciona una API para LXD

ACTUALIZACIÓN 10.04.2020 15:00: Agregué navegación

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster