Compartir comentarios
Las respuestas se generan en base a la documentación.

Controlador de almacenamiento Device Mapper (obsoleto)

Obsoleto (Deprecated)

El controlador Device Mapper está obsoleto y se ha eliminado en Docker Engine v25.0. Si estás utilizando Device Mapper, debes migrar a un controlador de almacenamiento compatible antes de actualizar a Docker Engine v25.0. Lee la página de controladores de almacenamiento de Docker para conocer los controladores compatibles.

Device Mapper es un marco de trabajo basado en el kernel que respalda muchas tecnologías avanzadas de gestión de volúmenes en Linux. El controlador de almacenamiento devicemapper de Docker aprovecha las capacidades de aprovisionamiento dinámico (thin provisioning) y snapshots de este marco para la gestión de imágenes y contenedores. Este artículo se refiere al controlador de almacenamiento de Device Mapper como devicemapper y al marco del kernel como Device Mapper.

Para los sistemas en los que es compatible, el soporte de devicemapper está incluido en el kernel Linux. Sin embargo, se requiere una configuración específica para utilizarlo con Docker.

El controlador devicemapper utiliza dispositivos de bloque dedicados a Docker y opera a nivel de bloque, en lugar de a nivel de archivo. Estos dispositivos se pueden ampliar añadiendo almacenamiento físico a tu host Docker, y ofrecen un mejor rendimiento que el uso de un sistema de archivos a nivel del sistema operativo (OS).

Requisitos previos

  • devicemapper es compatible con Docker Engine - Community en CentOS, Fedora, SLES 15, Ubuntu, Debian o RHEL.
  • devicemapper requiere que los paquetes lvm2 y device-mapper-persistent-data estén instalados.
  • Cambiar el controlador de almacenamiento hace que los contenedores que ya hayas creado dejen de estar accesibles en el sistema local. Usa docker save para guardar los contenedores y envía las imágenes existentes a Docker Hub o a un registro privado para que no tengas que volver a crearlas más tarde.

Configurar Docker con el controlador de almacenamiento devicemapper

Antes de seguir estos procedimientos, primero debes cumplir con todos los requisitos previos.

Configurar el modo loop-lvm para pruebas

Esta configuración solo es adecuada para pruebas. El modo loop-lvm utiliza un mecanismo de bucle de retorno o 'loopback' que permite leer y escribir en archivos del disco local como si fueran un disco físico o dispositivo de bloques real.

Sin embargo, la adición del mecanismo loopback y la interacción con la capa del sistema de archivos del sistema operativo implican que las operaciones de E/S pueden ser lentas y consumir muchos recursos. El uso de dispositivos loopback también puede introducir condiciones de carrera.

No obstante, la configuración del modo loop-lvm puede ayudar a identificar problemas básicos (como la falta de paquetes en el espacio de usuario, controladores del kernel, etc.) antes de intentar la configuración más compleja requerida para habilitar el modo direct-lvm. Por lo tanto, el modo loop-lvm solo debe usarse para realizar pruebas básicas antes de configurar direct-lvm.

Para sistemas de producción, consulta Configurar el modo direct-lvm para producción.

  1. Detén Docker.

    $ sudo systemctl stop docker
    
  2. Edita /etc/docker/daemon.json. Si aún no existe, créalo. Suponiendo que el archivo estuviera vacío, añade el siguiente contenido.

    {
      "storage-driver": "devicemapper"
    }

    Consulta todas las opciones de almacenamiento para cada controlador en la documentación de referencia del demonio

    Docker no se iniciará si el archivo daemon.json contiene un JSON mal formado.

  3. Inicia Docker.

    $ sudo systemctl start docker
    
  4. Verifica que el demonio esté utilizando el controlador de almacenamiento devicemapper. Usa el comando docker info y busca Storage Driver.

    $ docker info
    
      Containers: 0
        Running: 0
        Paused: 0
        Stopped: 0
      Images: 0
      Server Version: 17.03.1-ce
      Storage Driver: devicemapper
      Pool Name: docker-202:1-8413957-pool
      Pool Blocksize: 65.54 kB
      Base Device Size: 10.74 GB
      Backing Filesystem: xfs
      Data file: /dev/loop0
      Metadata file: /dev/loop1
      Data Space Used: 11.8 MB
      Data Space Total: 107.4 GB
      Data Space Available: 7.44 GB
      Metadata Space Used: 581.6 KB
      Metadata Space Total: 2.147 GB
      Metadata Space Available: 2.147 GB
      Thin Pool Minimum Free Space: 10.74 GB
      Udev Sync Supported: true
      Deferred Removal Enabled: false
      Deferred Deletion Enabled: false
      Deferred Deleted Device Count: 0
      Data loop file: /var/lib/docker/devicemapper/data
      Metadata loop file: /var/lib/docker/devicemapper/metadata
      Library Version: 1.02.135-RHEL7 (2016-11-16)
    <...>
    

    Este host se está ejecutando en modo loop-lvm, el cual no es compatible con sistemas de producción. Esto se indica por el hecho de que Data loop file y Metadata loop file son archivos ubicados bajo /var/lib/docker/devicemapper. Estos son archivos dispersos (sparse files) montados en loopback. Para sistemas de producción, consulta Configurar el modo direct-lvm para producción.

Configurar el modo direct-lvm para producción

Los hosts de producción que utilizan el controlador de almacenamiento devicemapper deben usar el modo direct-lvm. Este modo utiliza dispositivos de bloque para crear el thin pool. Esto es más rápido que usar dispositivos loopback, utiliza los recursos del sistema de manera más eficiente y los dispositivos de bloque pueden crecer según sea necesario. Sin embargo, requiere más configuración que el modo loop-lvm.

Una vez que hayas cumplido con los requisitos previos, sigue los pasos a continuación para configurar Docker para usar el controlador de almacenamiento devicemapper en modo direct-lvm.

Warning

Cambiar el controlador de almacenamiento hace que los contenedores que ya hayas creado dejen de estar accesibles en el sistema local. Usa docker save para guardar los contenedores y envía las imágenes existentes a Docker Hub o a un registro privado para que no tengas que volver a crearlas más tarde.

Permitir que Docker configure el modo direct-lvm

Docker puede gestionar el dispositivo de bloques por ti, simplificando la configuración del modo direct-lvm. Esto es adecuado únicamente para instalaciones nuevas de Docker. Solo puedes utilizar un único dispositivo de bloques. Si necesitas utilizar varios dispositivos de bloques, debes configurar el modo direct-lvm manualmente en su lugar. Las siguientes opciones de configuración están disponibles:

OpciónDescripción¿Requerido?PredeterminadoEjemplo
dm.directlvm_deviceLa ruta al dispositivo de bloques a configurar para direct-lvm.dm.directlvm_device="/dev/xvdf"
dm.thinp_percentEl porcentaje de espacio a utilizar para almacenamiento a partir del dispositivo de bloques proporcionado.No95dm.thinp_percent=95
dm.thinp_metapercentEl porcentaje de espacio a utilizar para el almacenamiento de metadatos a partir del dispositivo de bloques proporcionado.No1dm.thinp_metapercent=1
dm.thinp_autoextend_thresholdEl umbral en el que lvm debería extender automáticamente el thin pool, expresado como porcentaje del espacio de almacenamiento total.No80dm.thinp_autoextend_threshold=80
dm.thinp_autoextend_percentEl porcentaje en el que se debe incrementar el thin pool cuando se activa una extensión automática (autoextend).No20dm.thinp_autoextend_percent=20
dm.directlvm_device_forceSi se debe formatear el dispositivo de bloques incluso si ya existe un sistema de archivos en él. Si se establece en false y hay un sistema de archivos presente, se registra un error y el sistema de archivos se deja intacto.Nofalsedm.directlvm_device_force=true

Edita el archivo daemon.json y establece las opciones correspondientes, luego reinicia Docker para que los cambios surtan efecto. La siguiente configuración de daemon.json establece todas las opciones de la tabla anterior.

{
  "storage-driver": "devicemapper",
  "storage-opts": [
    "dm.directlvm_device=/dev/xdf",
    "dm.thinp_percent=95",
    "dm.thinp_metapercent=1",
    "dm.thinp_autoextend_threshold=80",
    "dm.thinp_autoextend_percent=20",
    "dm.directlvm_device_force=false"
  ]
}

Consulta todas las opciones de almacenamiento para cada controlador en la documentación de referencia del demonio

Reinicia Docker para que los cambios surtan efecto. Docker invoca los comandos para configurar el dispositivo de bloques por ti.

Warning

Cambiar estos valores después de que Docker haya preparado el dispositivo de bloques por ti no está admitido y provocará un error.

Aún necesitas realizar tareas de mantenimiento periódicas.

Configurar el modo direct-lvm manualmente

El procedimiento a continuación crea un volumen lógico configurado como un thin pool para usarlo como respaldo para el grupo de almacenamiento. Asume que tienes un dispositivo de bloques libre en /dev/xvdf con suficiente espacio disponible para completar la tarea. El identificador del dispositivo y los tamaños de los volúmenes pueden variar en tu entorno, por lo que debes sustituir tus propios valores a lo largo del procedimiento. El procedimiento también asume que el demonio de Docker está en estado detenido (stopped).

  1. Identifica el dispositivo de bloques que deseas utilizar. El dispositivo se encuentra bajo /dev/ (como /dev/xvdf) y necesita suficiente espacio libre para almacenar las imágenes y las capas de los contenedores para las cargas de trabajo que ejecuta ese host. Una unidad de estado sólido (SSD) es ideal.

  2. Detén Docker.

    $ sudo systemctl stop docker
    
  3. Instala los siguientes paquetes:

    • RHEL / CentOS: device-mapper-persistent-data, lvm2 y todas las dependencias

    • Ubuntu / Debian / SLES 15: thin-provisioning-tools, lvm2 y todas las dependencias

  4. Crea un volumen físico en tu dispositivo de bloques del paso 1, utilizando el comando pvcreate. Sustituye el nombre de tu dispositivo en lugar de /dev/xvdf.

    Warning

    Los siguientes pasos son destructivos, por lo que debes asegurarte de haber especificado el dispositivo correcto.

    $ sudo pvcreate /dev/xvdf
    
    Physical volume "/dev/xvdf" successfully created.
    
  5. Crea un grupo de volúmenes llamado docker en el mismo dispositivo, utilizando el comando vgcreate.

    $ sudo vgcreate docker /dev/xvdf
    
    Volume group "docker" successfully created
    
  6. Crea dos volúmenes lógicos llamados thinpool y thinpoolmeta usando el comando lvcreate. El último parámetro especifica la cantidad de espacio libre permitido para la expansión automática de los datos o metadatos si el espacio escasea, como una medida de contención temporal. Estos son los valores recomendados.

    $ sudo lvcreate --wipesignatures y -n thinpool docker -l 95%VG
    
    Logical volume "thinpool" created.
    
    $ sudo lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VG
    
    Logical volume "thinpoolmeta" created.
    
  7. Convierte los volúmenes en un thin pool y en una ubicación de almacenamiento de metadatos para el thin pool, utilizando el comando lvconvert.

    $ sudo lvconvert -y \
    --zero n \
    -c 512K \
    --thinpool docker/thinpool \
    --poolmetadata docker/thinpoolmeta
    
    WARNING: Converting logical volume docker/thinpool and docker/thinpoolmeta to
    thin pool's data and metadata volumes with metadata wiping.
    THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)
    Converted docker/thinpool to thin pool.
    
  8. Configura la autoextensión de los thin pools a través de un perfil de lvm.

    $ sudo vi /etc/lvm/profile/docker-thinpool.profile
    
  9. Especifica los valores de thin_pool_autoextend_threshold y thin_pool_autoextend_percent.

    thin_pool_autoextend_threshold es el porcentaje de espacio utilizado antes de que lvm intente extender automáticamente el espacio disponible (100 = deshabilitado, no recomendado).

    thin_pool_autoextend_percent es la cantidad de espacio a añadir al dispositivo al extenderse automáticamente (0 = deshabilitado).

    El siguiente ejemplo añade un 20% más de capacidad cuando el uso del disco alcanza el 80%.

    activation {
      thin_pool_autoextend_threshold=80
      thin_pool_autoextend_percent=20
    }

    Guarda el archivo.

  10. Aplica el perfil de LVM utilizando el comando lvchange.

    $ sudo lvchange --metadataprofile docker-thinpool docker/thinpool
    
    Logical volume docker/thinpool changed.
    
  11. Asegúrate de que el monitoreo del volumen lógico esté habilitado.

    $ sudo lvs -o+seg_monitor
    
    LV       VG     Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert Monitor
    thinpool docker twi-a-t--- 95.00g             0.00   0.01                             not monitored
    

    Si la salida en la columna Monitor indica, como se muestra arriba, que el volumen not monitored (no está monitoreado), entonces el monitoreo debe habilitarse explícitamente. Sin este paso, la extensión automática del volumen lógico no se llevará a cabo, independientemente de la configuración del perfil aplicado.

    $ sudo lvchange --monitor y docker/thinpool
    

    Verifica de nuevo que el monitoreo esté habilitado ejecutando el comando sudo lvs -o+seg_monitor por segunda vez. La columna Monitor ahora debería indicar que el volumen lógico está siendo monitoreado (monitored).

  12. Si alguna vez has ejecutado Docker en este host antes, o si /var/lib/docker/ existe, muévelo a otra ubicación para que Docker pueda utilizar el nuevo pool de LVM para almacenar el contenido de las imágenes y los contenedores.

    $ sudo su -
    # mkdir /var/lib/docker.bk
    # mv /var/lib/docker/* /var/lib/docker.bk
    # exit
    

    Si alguno de los siguientes pasos falla y necesitas restaurar la configuración anterior, puedes eliminar /var/lib/docker y reemplazarlo por /var/lib/docker.bk.

  13. Edita /etc/docker/daemon.json y configura las opciones necesarias para el controlador de almacenamiento devicemapper. Si el archivo estaba vacío previamente, ahora debería contener el siguiente contenido:

    {
        "storage-driver": "devicemapper",
        "storage-opts": [
        "dm.thinpooldev=/dev/mapper/docker-thinpool",
        "dm.use_deferred_removal=true",
        "dm.use_deferred_deletion=true"
        ]
    }
  14. Inicia Docker.

    systemd:

    $ sudo systemctl start docker
    

    service:

    $ sudo service docker start
    
  15. Verifica que Docker esté utilizando la nueva configuración mediante docker info.

    $ docker info
    
    Containers: 0
     Running: 0
     Paused: 0
     Stopped: 0
    Images: 0
    Server Version: 17.03.1-ce
    Storage Driver: devicemapper
     Pool Name: docker-thinpool
     Pool Blocksize: 524.3 kB
     Base Device Size: 10.74 GB
     Backing Filesystem: xfs
     Data file:
     Metadata file:
     Data Space Used: 19.92 MB
     Data Space Total: 102 GB
     Data Space Available: 102 GB
     Metadata Space Used: 147.5 kB
     Metadata Space Total: 1.07 GB
     Metadata Space Available: 1.069 GB
     Thin Pool Minimum Free Space: 10.2 GB
     Udev Sync Supported: true
     Deferred Removal Enabled: true
     Deferred Deletion Enabled: true
     Deferred Deleted Device Count: 0
     Library Version: 1.02.135-RHEL7 (2016-11-16)
    <...>
    

    Si Docker está configurado correctamente, Data file y Metadata file estarán vacíos, y el nombre del pool será docker-thinpool.

  16. Una vez que hayas verificado que la configuración es correcta, puedes eliminar el directorio /var/lib/docker.bk que contiene la configuración anterior.

    $ sudo rm -rf /var/lib/docker.bk
    

Gestionar devicemapper

Monitorear el thin pool

No dependas únicamente de la autoextensión de LVM. El grupo de volúmenes se extiende automáticamente, pero el volumen aún puede llenarse. Puedes monitorear el espacio libre en el volumen utilizando lvs o lvs -a. Considera utilizar una herramienta de monitoreo a nivel del sistema operativo, como Nagios.

Para ver los registros (logs) de LVM, puedes utilizar journalctl:

$ sudo journalctl -fu dm-event.service

Si te encuentras con problemas recurrentes con el thin pool, puedes establecer la opción de almacenamiento dm.min_free_space a un valor (que representa un porcentaje) en /etc/docker/daemon.json. Por ejemplo, establecerlo en 10 garantiza que las operaciones fallen con una advertencia cuando el espacio libre esté en el 10% o menos. Consulta las opciones del controlador de almacenamiento en la referencia del demonio de Engine.

Incrementar la capacidad en un dispositivo en ejecución

Puedes incrementar la capacidad del pool en un dispositivo thin-pool en ejecución. Esto es útil si el volumen lógico de datos está lleno y el grupo de volúmenes está a su máxima capacidad. El procedimiento específico depende de si estás utilizando un thin pool loop-lvm o un thin pool direct-lvm.

Redimensionar un thin pool loop-lvm

Para redimensionar un thin pool loop-lvm, puedes utilizar la utilidad device_tool o, en su lugar, utilizar las utilidades del sistema operativo.

Utilizar la utilidad device_tool

Un script aportado por la comunidad llamado device_tool.go está disponible en el repositorio de GitHub moby/moby. Puedes usar esta herramienta para redimensionar un thin pool loop-lvm, evitando el largo proceso mencionado anteriormente. No se garantiza el funcionamiento de esta herramienta, pero de cualquier forma solo deberías usar loop-lvm en sistemas que no sean de producción.

Si no deseas utilizar device_tool, puedes redimensionar el thin pool manualmente en su lugar.

  1. Para usar la herramienta, clona el repositorio de GitHub, accede a contrib/docker-device-tool y sigue las instrucciones en el README.md para compilar la herramienta.

  2. Utiliza la herramienta. El siguiente ejemplo redimensiona el thin pool a 200GB.

    $ ./device_tool resize 200GB
    
Utilizar las utilidades del sistema operativo

Si no deseas utilizar la utilidad device_tool, puedes redimensionar un thin pool loop-lvm manualmente siguiendo este procedimiento.

En el modo loop-lvm, se utiliza un dispositivo loopback para almacenar los datos y otro para almacenar los metadatos. El modo loop-lvm solo se admite para pruebas debido a que presenta importantes inconvenientes de rendimiento y estabilidad.

Si estás utilizando el modo loop-lvm, la salida de docker info muestra las rutas de los archivos para Data loop file y Metadata loop file:

$ docker info |grep 'loop file'

 Data loop file: /var/lib/docker/devicemapper/data
 Metadata loop file: /var/lib/docker/devicemapper/metadata

Sigue estos pasos para aumentar el tamaño del thin pool. En este ejemplo, the thin pool es de 100 GB y se incrementa a 200 GB.

  1. Lista los tamaños de los dispositivos.

    $ sudo ls -lh /var/lib/docker/devicemapper/
    
    total 1175492
    -rw------- 1 root root 100G Mar 30 05:22 data
    -rw------- 1 root root 2.0G Mar 31 11:17 metadata
    
  2. Aumenta el tamaño del archivo data a 200 GB utilizando el comando truncate, el cual sirve para aumentar o disminuir el tamaño de un archivo. Ten en cuenta que disminuir el tamaño es una operación destructiva.

    $ sudo truncate -s 200G /var/lib/docker/devicemapper/data
    
  3. Verifica que el tamaño del archivo haya cambiado.

    $ sudo ls -lh /var/lib/docker/devicemapper/
    
    total 1.2G
    -rw------- 1 root root 200G Apr 14 08:47 data
    -rw------- 1 root root 2.0G Apr 19 13:27 metadata
    
  4. El archivo loopback ha cambiado en disco pero no en memoria. Lista el tamaño del dispositivo loopback en memoria, en GB. Recárgalo y luego vuelve a listar el tamaño. Después de la recarga, el tamaño es de 200 GB.

    $ echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ]
    
    100
    
    $ sudo losetup -c /dev/loop0
    
    $ echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ]
    
    200
    
  5. Recarga el thin pool de devicemapper.

    a. Obtén primero el nombre del pool. El nombre del pool es el primer campo, delimitado por :. Este comando lo extrae.

    $ sudo dmsetup status | grep ' thin-pool ' | awk -F ': ' {'print $1'}
    docker-8:1-123141-pool
    

    b. Vuelca la tabla de device mapper para el thin pool.

    $ sudo dmsetup table docker-8:1-123141-pool
    0 209715200 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing
    

    c. Calcula los sectores totales del thin pool utilizando el segundo campo de la salida. El número se expresa en sectores de 512 bytes. Un archivo de 100 GB tiene 209715200 sectores de 512 bytes. Si duplicas este número a 200 GB, obtienes 419430400 sectores de 512 bytes.

    d. Recarga el thin pool con el nuevo número de sectores utilizando los siguientes tres comandos dmsetup.

    $ sudo dmsetup suspend docker-8:1-123141-pool
    $ sudo dmsetup reload docker-8:1-123141-pool --table '0 419430400 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing'
    $ sudo dmsetup resume docker-8:1-123141-pool
    

Redimensionar un thin pool direct-lvm

Para extender un thin pool direct-lvm, primero debes conectar un nuevo dispositivo de bloques al host Docker y tomar nota del nombre que el kernel le asigne. En este ejemplo, el nuevo dispositivo de bloques es /dev/xvdg.

Sigue este procedimiento para extender un thin pool direct-lvm, sustituyendo tu dispositivo de bloques y otros parámetros para adaptarlos a tu situación.

  1. Recopila información sobre tu grupo de volúmenes.

    Usa el comando pvdisplay para encontrar los dispositivos de bloque físico actualmente en uso por tu thin pool, y el nombre del grupo de volúmenes.

    $ sudo pvdisplay |grep 'VG Name'
    
    PV Name               /dev/xvdf
    VG Name               docker
    

    En los siguientes pasos, sustituye el nombre de tu dispositivo de bloques o grupo de volúmenes según corresponda.

  2. Extiende el grupo de volúmenes utilizando el comando vgextend con el VG Name del paso anterior y el nombre de tu nuevo dispositivo de bloques.

    $ sudo vgextend docker /dev/xvdg
    
    Physical volume "/dev/xvdg" successfully created.
    Volume group "docker" successfully extended
    
  3. Extiende el volumen lógico docker/thinpool. Este comando utiliza el 100% del volumen de inmediato, sin autoextensión. Para extender el thinpool de metadatos en su lugar, utiliza docker/thinpool_tmeta.

    $ sudo lvextend -l+100%FREE -n docker/thinpool
    
    Size of logical volume docker/thinpool_tdata changed from 95.00 GiB (24319 extents) to 198.00 GiB (50688 extents).
    Logical volume docker/thinpool_tdata successfully resized.
    
  4. Verifica el nuevo tamaño del thin pool utilizando el campo Data Space Available en la salida de docker info. Si en su lugar extendiste el volumen lógico docker/thinpool_tmeta, busca Metadata Space Available.

    Storage Driver: devicemapper
     Pool Name: docker-thinpool
     Pool Blocksize: 524.3 kB
     Base Device Size: 10.74 GB
     Backing Filesystem: xfs
     Data file:
     Metadata file:
     Data Space Used: 212.3 MB
     Data Space Total: 212.6 GB
     Data Space Available: 212.4 GB
     Metadata Space Used: 286.7 kB
     Metadata Space Total: 1.07 GB
     Metadata Space Available: 1.069 GB
    <...>

Activar devicemapper después de reiniciar

Si reinicias el host y descubres que el servicio docker no se pudo iniciar, busca el error "Non existing device". Necesitas reactivar los volúmenes lógicos con este comando:

$ sudo lvchange -ay docker/thinpool

Cómo funciona el controlador de almacenamiento devicemapper

Warning

No manipules directamente ningún archivo o directorio dentro de /var/lib/docker/. Docker se encarga de gestionar estos archivos y directorios.

Usa el comando lsblk para ver los dispositivos y sus pools desde el punto de vista del sistema operativo:

$ sudo lsblk

NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda                    202:0    0    8G  0 disk
└─xvda1                 202:1    0    8G  0 part /
xvdf                    202:80   0  100G  0 disk
├─docker-thinpool_tmeta 253:0    0 1020M  0 lvm
│ └─docker-thinpool     253:2    0   95G  0 lvm
└─docker-thinpool_tdata 253:1    0   95G  0 lvm
  └─docker-thinpool     253:2    0   95G  0 lvm

Usa el comando mount para ver el punto de montaje que está utilizando Docker:

$ mount |grep devicemapper
/dev/xvda1 on /var/lib/docker/devicemapper type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

Cuando utilizas devicemapper, Docker almacena el contenido de las imágenes y capas en el thinpool, y lo expone a los contenedores montándolo en subdirectorios de /var/lib/docker/devicemapper/.

Capas de imágenes y contenedores en disco

El directorio /var/lib/docker/devicemapper/metadata/ contiene metadatos sobre la propia configuración de Devicemapper y sobre cada capa de imagen y contenedor existente. El controlador de almacenamiento devicemapper utiliza snapshots, y estos metadatos incluyen información sobre dichos snapshots. Estos archivos están en formato JSON.

El directorio /var/lib/docker/devicemapper/mnt/ contiene un punto de montaje para cada capa de imagen y contenedor existente. Los puntos de montaje de las capas de imagen están vacíos, pero el punto de montaje de un contenedor muestra el sistema de archivos del contenedor tal como aparece desde dentro de este.

Capas de imágenes y uso compartido

El controlador de almacenamiento devicemapper utiliza dispositivos de bloque dedicados en lugar de sistemas de archivos formateados, y opera en los archivos a nivel de bloque para obtener el máximo rendimiento durante las operaciones copy-on-write (CoW).

Snapshots

Otra característica de devicemapper es el uso de snapshots (a veces también llamados dispositivos dinámicos o dispositivos virtuales), que almacenan las diferencias introducidas en cada capa como thin pools muy pequeños y ligeros. Los snapshots ofrecen muchos beneficios:

  • Las capas comunes compartidas entre contenedores se almacenan en el disco una sola vez, a menos que sean de escritura. Por ejemplo, si tienes 10 imágenes diferentes basadas en alpine, la imagen alpine y todas sus imágenes padre se almacenan una sola vez cada una en el disco.

  • Los snapshots son una implementación de la estrategia copy-on-write (CoW). Esto significa que un archivo o directorio determinado solo se copia a la capa de escritura del contenedor cuando ese contenedor lo modifica o lo elimina.

  • Debido a que devicemapper opera a nivel de bloque, se pueden modificar múltiples bloques en una capa de escritura de forma simultánea.

  • Se pueden realizar copias de seguridad de los snapshots utilizando utilidades estándar a nivel del sistema operativo. Basta con hacer una copia de /var/lib/docker/devicemapper/.

Flujo de trabajo de Devicemapper

Cuando inicias Docker con el controlador de almacenamiento devicemapper, todos los objetos relacionados con las capas de imágenes y contenedores se almacenan en /var/lib/docker/devicemapper/, que está respaldado por uno o más dispositivos a nivel de bloque, ya sean dispositivos loopback (solo para pruebas) o discos físicos.

  • El dispositivo base (base device) es el objeto de nivel más bajo. Este es el propio thin pool. Puedes examinarlo mediante docker info. Contiene un sistema de archivos. Este dispositivo base es el punto de partida para cada capa de imagen y contenedor. El dispositivo base es un detalle de implementación de Device Mapper, no una capa de Docker.

  • Los metadatos sobre el dispositivo base y cada capa de imagen o contenedor se almacenan en /var/lib/docker/devicemapper/metadata/ en formato JSON. Estas capas son snapshots copy-on-write, lo que significa que están vacías hasta que divergen de sus capas padres.

  • La capa de escritura de cada contenedor se monta en un punto de montaje en /var/lib/docker/devicemapper/mnt/. Existe un directorio vacío para cada capa de imagen de solo lectura y cada contenedor detenido.

Cada capa de imagen es un snapshot de la capa inferior. La capa más baja de cada imagen es un snapshot del dispositivo base que existe en el pool. Al ejecutar un contenedor, este es un snapshot de la imagen en la que se basa. El siguiente ejemplo muestra un host Docker con dos contenedores en ejecución. El primero es un contenedor ubuntu y el segundo es un contenedor busybox.

Capas de imágenes de Ubuntu y Busybox

Cómo funcionan las lecturas y escrituras de contenedores con devicemapper

Lectura de archivos

Con devicemapper, las lecturas ocurren a nivel de bloque. El siguiente diagrama muestra el proceso general para leer un solo bloque (0x44f) en un contenedor de ejemplo.

Lectura de un bloque con devicemapper

Una aplicación realiza una solicitud de lectura del bloque 0x44f en el contenedor. Debido a que el contenedor es un snapshot dinámico de una imagen, no tiene el bloque, pero tiene un puntero al bloque en la imagen padre más cercana donde sí existe, y lee el bloque desde allí. El bloque ahora reside en la memoria del contenedor.

Escritura de archivos

Escribir un archivo nuevo: Con el controlador devicemapper, la escritura de nuevos datos en un contenedor se realiza mediante una operación allocate-on-demand (asignación bajo demanda). Cada bloque del nuevo archivo se asigna en la capa de escritura del contenedor y el bloque se escribe allí.

Actualizar un archivo existente: El bloque correspondiente al archivo se lee desde la capa más cercana donde exista. Cuando el contenedor escribe en el archivo, solo los bloques modificados se escriben en la capa de escritura del contenedor.

Eliminar un archivo o directorio: Cuando eliminas un archivo o directorio en la capa de escritura de un contenedor, o cuando una capa de imagen elimina un archivo que existe en su capa padre, el controlador de almacenamiento devicemapper intercepta los futuros intentos de lectura sobre ese archivo o directorio y responde que no existe.

Escribir y luego eliminar un archivo: Si un contenedor escribe en un archivo y posteriormente lo elimina, todas esas operaciones ocurren en la capa de escritura del contenedor. En ese caso, si utilizas direct-lvm, los bloques se liberan. Si utilizas loop-lvm, es posible que los bloques no se liberen. Esta es otra razón para no utilizar loop-lvm en producción.

Rendimiento de Device Mapper y Docker

  • Impacto en el rendimiento de allocate-on-demand:

    El controlador de almacenamiento devicemapper utiliza una operación allocate-on-demand para asignar nuevos bloques desde el thin pool a la capa de escritura del contenedor. Cada bloque es de 64 KB, por lo que esta es la cantidad mínima de espacio que se utiliza para una escritura.

  • Impacto en el rendimiento de copy-on-write: La primera vez que un contenedor modifica un bloque específico, ese bloque se escribe en la capa de escritura del contenedor. Debido a que estas escrituras ocurren a nivel del bloque y no del archivo, el impacto en el rendimiento se minimiza. Sin embargo, escribir una gran cantidad de bloques aún puede afectar negativamente al rendimiento, y el controlador de almacenamiento devicemapper podría tener un rendimiento inferior al de otros controladores en este escenario. Para cargas de trabajo con uso intensivo de escritura, debes usar volúmenes de datos, que omiten el controlador de almacenamiento por completo.

Buenas prácticas de rendimiento

Ten en cuenta estos aspectos para maximizar el rendimiento al utilizar el controlador de almacenamiento devicemapper.

  • Utiliza direct-lvm: El modo loop-lvm no es eficiente y nunca debe usarse en producción.

  • Utiliza almacenamiento rápido: Las unidades de estado sólido (SSD) proporcionan lecturas y escrituras más rápidas que los discos mecánicos.

  • Uso de memoria: devicemapper consume más memoria que algunos otros controladores de almacenamiento. Cada contenedor iniciado carga una o más copias de sus archivos en memoria, dependiendo de cuántos bloques del mismo archivo se estén modificando al mismo tiempo. Debido a la presión de memoria, el controlador devicemapper puede no ser la opción adecuada para ciertas cargas de trabajo en casos de uso de alta densidad.

  • Utiliza volúmenes para cargas de trabajo con uso intensivo de escritura: Los volúmenes proporcionan el mejor y más predecible rendimiento para cargas de trabajo con uso intensivo de escritura. Esto se debe a que omiten el controlador de almacenamiento y no incurren en ninguna de las posibles sobrecargas introducidas por el aprovisionamiento dinámico y copy-on-write. Los volúmenes tienen otros beneficios, como permitirte compartir datos entre contenedores y persistir incluso cuando ningún contenedor en ejecución los está utilizando.

    Note

    Al utilizar devicemapper y el controlador de registros json-file, los archivos de registro generados por un contenedor se siguen almacenando en el directorio dataroot de Docker, por defecto /var/lib/docker. Si tus contenedores generan muchos mensajes de registro, esto puede provocar un aumento en el uso del disco o la imposibilidad de administrar tu sistema debido a un disco lleno. Puedes configurar un controlador de registro para almacenar los registros de tus contenedores de forma externa.

Información relacionada