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

Controlador de almacenamiento OverlayFS

OverlayFS es un sistema de archivos de unión (union filesystem).

Esta página se refiere al controlador del kernel Linux como OverlayFS y al controlador de almacenamiento de Docker como overlay2.

Note

Docker Engine 29.0 y versiones posteriores utilizan el almacén de imágenes de containerd de forma predeterminada. El controlador overlay2 es un controlador de almacenamiento heredado (legacy) que ha sido reemplazado por el snapshotter overlayfs de containerd. Para obtener más información, consulta Seleccionar un controlador de almacenamiento.

Note

Para el controlador fuse-overlayfs, consulta la documentación del modo Rootless.

Requisitos previos

El controlador overlay2 es compatible si cumples con los siguientes requisitos previos:

  • Versión 4.0 o superior del kernel Linux, o RHEL o CentOS utilizando la versión 3.10.0-514 del kernel o superior.
  • El controlador overlay2 es compatible con sistemas de archivos de respaldo xfs, pero solo con d_type=true habilitado. Utiliza xfs_info para verificar que la opción ftype esté establecida en 1. Para formatear correctamente un sistema de archivos xfs, usa la bandera -n ftype=1.
  • Cambiar el controlador de almacenamiento hace que los contenedores e imágenes existentes dejen de estar accesibles en el sistema local. Usa docker save para guardar las imágenes que hayas creado o envíalas a Docker Hub o a un registro privado antes de cambiar el controlador de almacenamiento, de modo que no tengas que volver a crearlas más tarde.

Configurar Docker con el controlador de almacenamiento overlay2

Antes de seguir este procedimiento, primero debes cumplir con todos los requisitos previos.

Los siguientes pasos describen cómo configurar el controlador de almacenamiento overlay2.

  1. Detén Docker.

    $ sudo systemctl stop docker
    
  2. Copia el contenido de /var/lib/docker en una ubicación temporal.

    $ cp -au /var/lib/docker /var/lib/docker.bk
    
  3. Si deseas utilizar un sistema de archivos de respaldo independiente del utilizado por /var/lib/, formatea el sistema de archivos y móntalo en /var/lib/docker. Asegúrate de añadir este montaje a /etc/fstab para que sea permanente.

  4. 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": "overlay2"
    }

    Docker no se iniciará si el archivo daemon.json contiene un JSON no válido.

  5. Inicia Docker.

    $ sudo systemctl start docker
    
  6. Verifica que el demonio esté utilizando el controlador de almacenamiento overlay2. Usa el comando docker info y busca Storage Driver y Backing filesystem.

    $ docker info
    
    Containers: 0
    Images: 0
    Storage Driver: overlay2
     Backing Filesystem: xfs
     Supports d_type: true
     Native Overlay Diff: true
    <...>
    

Docker ahora está utilizando el controlador de almacenamiento overlay2 y ha creado automáticamente el montaje overlay con las estructuras requeridas lowerdir, upperdir, merged y workdir.

Continúa leyendo para obtener detalles sobre cómo funciona OverlayFS dentro de tus contenedores de Docker, así como consejos de rendimiento e información sobre las limitaciones de su compatibilidad con diferentes sistemas de archivos de respaldo.

Cómo funciona el controlador overlay2

OverlayFS superpone dos directorios en un único host Linux y los presenta como un solo directorio. Estos directorios se denominan capas y el proceso de unificación se conoce como un montaje de unión (union mount). OverlayFS se refiere al directorio inferior como lowerdir y al directorio superior como upperdir. La vista unificada se expone a través de su propio directorio llamado merged.

El controlador overlay2 admite de forma nativa hasta 128 capas inferiores de OverlayFS. Esta capacidad proporciona un mejor rendimiento para los comandos de Docker relacionados con capas, como docker build y docker commit, y consume menos inodes en el sistema de archivos de respaldo.

Capas de imágenes y contenedores en disco

Después de descargar una imagen de cinco capas utilizando docker pull ubuntu, puedes ver seis directorios bajo /var/lib/docker/overlay2.

Warning

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

$ ls -l /var/lib/docker/overlay2

total 24
drwx------ 5 root root 4096 Jun 20 07:36 223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7
drwx------ 3 root root 4096 Jun 20 07:36 3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b
drwx------ 5 root root 4096 Jun 20 07:36 4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1
drwx------ 5 root root 4096 Jun 20 07:36 e8876a226237217ec61c4baf238a32992291d059fdac95ed6303bdff3f59cff5
drwx------ 5 root root 4096 Jun 20 07:36 eca1e4e1694283e001f200a667bb3cb40853cf2d1b12c29feda7422fed78afed
drwx------ 2 root root 4096 Jun 20 07:36 l

El nuevo directorio l (L minúscula) contiene identificadores de capa acortados en forma de enlaces simbólicos. Estos identificadores se utilizan para evitar alcanzar el límite de tamaño de página en los argumentos del comando mount.

$ ls -l /var/lib/docker/overlay2/l

total 20
lrwxrwxrwx 1 root root 72 Jun 20 07:36 6Y5IM2XC7TSNIJZZFLJCS6I4I4 -> ../3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 B3WWEFKBG3PLLV737KZFIASSW7 -> ../4e9fa83caff3e8f4cc83693fa407a4a9fac9573deaf481506c102d484dd1e6a1/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 JEYMODZYFCZFYSDABYXD5MF6YO -> ../eca1e4e1694283e001f200a667bb3cb40853cf2d1b12c29feda7422fed78afed/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 NFYKDW6APBCCUCTOUSYDH4DXAT -> ../223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff
lrwxrwxrwx 1 root root 72 Jun 20 07:36 UL2MW33MSE3Q5VYIKBRN4ZAGQP -> ../e8876a226237217ec61c4baf238a32992291d059fdac95ed6303bdff3f59cff5/diff

La capa más baja contiene un archivo llamado link, que contiene el nombre del identificador acortado, y un directorio llamado diff que contiene el contenido de la capa.

$ ls /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/

diff  link

$ cat /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/link

6Y5IM2XC7TSNIJZZFLJCS6I4I4

$ ls  /var/lib/docker/overlay2/3a36935c9df35472229c57f4a27105a136f5e4dbef0f87905b2e506e494e348b/diff

bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

La segunda capa más baja, y cada capa superior, contienen un archivo llamado lower que indica su padre (parent), y un directorio llamado diff que contiene su contenido. También contiene un directorio merged, que contiene el contenido unificado de su capa padre y de sí misma, y un directorio work que OverlayFS utiliza internamente.

$ ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7

diff  link  lower  merged  work

$ cat /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/lower

l/6Y5IM2XC7TSNIJZZFLJCS6I4I4

$ ls /var/lib/docker/overlay2/223c2864175491657d238e2664251df13b63adb8d050924fd1bfcdb278b866f7/diff/

etc  sbin  usr  var

Para ver los montajes que existen cuando utilizas el controlador de almacenamiento overlay con Docker, usa el comando mount. La salida a continuación se ha acortado para mayor legibilidad.

$ mount | grep overlay

overlay on /var/lib/docker/overlay2/9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/merged
type overlay (rw,relatime,
lowerdir=l/DJA75GUWHWG7EWICFYX54FIOVT:l/B3WWEFKBG3PLLV737KZFIASSW7:l/JEYMODZYFCZFYSDABYXD5MF6YO:l/UL2MW33MSE3Q5VYIKBRN4ZAGQP:l/NFYKDW6APBCCUCTOUSYDH4DXAT:l/6Y5IM2XC7TSNIJZZFLJCS6I4I4,
upperdir=9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/diff,
workdir=9186877cdf386d0a3b016149cf30c208f326dca307529e646afce5b3f83f5304/work)

El rw en la segunda línea indica que el montaje overlay es de lectura y escritura.

El siguiente diagrama muestra cómo se apilan una imagen de Docker y un contenedor de Docker. La capa de la imagen es el lowerdir y la capa del contenedor es el upperdir. Si la imagen tiene varias capas, se utilizan múltiples directorios lowerdir. La vista unificada se expone a través de un directorio llamado merged, que es efectivamente el punto de montaje del contenedor.

Cómo se asignan las estructuras de Docker a las de OverlayFS

Cuando la capa de la imagen y la capa del contenedor contienen los mismos archivos, la capa del contenedor (upperdir) tiene prioridad y oculta la existencia de los mismos archivos en la capa de la imagen.

Para crear un contenedor, el controlador overlay2 combina el directorio que representa la capa superior de la imagen más un nuevo directorio para el contenedor. Las capas de la imagen son los lowerdirs en el overlay y son de solo lectura. El nuevo directorio para el contenedor es el upperdir y es de escritura.

Capas de imágenes y contenedores en disco (controlador overlay heredado)

El siguiente comando docker pull muestra un host Docker descargando una imagen de Docker que consta de cinco capas.

$ docker pull ubuntu

Using default tag: latest
latest: Pulling from library/ubuntu

5ba4f30e5bea: Pull complete
9d7d19c9dc56: Pull complete
ac6ad7efd0f9: Pull complete
e7491a747824: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:46fb5d001b88ad904c5c732b086b596b92cfb4a4840a3abd0e35dbb6870585e4
Status: Downloaded newer image for ubuntu:latest

Las capas de la imagen

Cada capa de imagen tiene su propio directorio dentro de /var/lib/docker/overlay/, que contiene su contenido, como se muestra en el siguiente ejemplo. Los IDs de las capas de imagen no se corresponden con los IDs de los directorios.

Warning

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

$ ls -l /var/lib/docker/overlay/

total 20
drwx------ 3 root root 4096 Jun 20 16:11 38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8
drwx------ 3 root root 4096 Jun 20 16:11 55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358
drwx------ 3 root root 4096 Jun 20 16:11 824c8a961a4f5e8fe4f4243dab57c5be798e7fd195f6d88ab06aea92ba931654
drwx------ 3 root root 4096 Jun 20 16:11 ad0fe55125ebf599da124da175174a4b8c1878afe6907bf7c78570341f308461
drwx------ 3 root root 4096 Jun 20 16:11 edab9b5e5bf73f2997524eebeac1de4cf9c8b904fa8ad3ec43b3504196aa3801

Los directorios de las capas de imágenes contienen los archivos exclusivos de esa capa, así como enlaces duros (hard links) a los datos compartidos con las capas inferiores. Esto permite un uso eficiente del espacio en disco.

$ ls -i /var/lib/docker/overlay2/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls

19793696 /var/lib/docker/overlay2/38f3ed2eac129654acef11c32670b534670c3a06e483fce313d72e3e0a15baa8/root/bin/ls

$ ls -i /var/lib/docker/overlay2/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls

19793696 /var/lib/docker/overlay2/55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358/root/bin/ls

Las capa del contenedor

Los contenedores también existen en disco en el sistema de archivos del host Docker bajo /var/lib/docker/overlay/. Si listas el subdirectorio de un contenedor en ejecución con el comando ls -l, verás tres directorios y un archivo:

$ ls -l /var/lib/docker/overlay2/<directory-of-running-container>

total 16
-rw-r--r-- 1 root root   64 Jun 20 16:39 lower-id
drwxr-xr-x 1 root root 4096 Jun 20 16:39 merged
drwxr-xr-x 4 root root 4096 Jun 20 16:39 upper
drwx------ 3 root root 4096 Jun 20 16:39 work

El archivo lower-id contiene el ID de la capa superior de la imagen en la que se basa el contenedor, que representa el lowerdir de OverlayFS.

$ cat /var/lib/docker/overlay2/ec444863a55a9f1ca2df72223d459c5d940a721b2288ff86a3f27be28b53be6c/lower-id

55f1e14c361b90570df46371b20ce6d480c434981cbda5fd68c6ff61aa0a5358

El directorio upper contiene el contenido de la capa de lectura y escritura del contenedor, que corresponde al upperdir de OverlayFS.

El directorio merged es el montaje de unión de lowerdir y upperdirs, que constituye la vista del sistema de archivos desde dentro del contenedor en ejecución.

El directorio work es de uso interno para OverlayFS.

Para ver los montajes que existen cuando utilizas el controlador de almacenamiento overlay2 con Docker, usa el comando mount. La siguiente salida se ha acortado para mayor legibilidad.

$ mount | grep overlay

overlay on /var/lib/docker/overlay2/l/ec444863a55a.../merged
type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/55f1e14c361b.../root,
upperdir=/var/lib/docker/overlay2/l/ec444863a55a.../upper,
workdir=/var/lib/docker/overlay2/l/ec444863a55a.../work)

El rw en la segunda línea indica que el montaje overlay es de lectura y escritura.

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

Lectura de archivos

Considera tres escenarios en los que un contenedor abre un archivo para acceso de lectura con overlay.

El archivo no existe en la capa del contenedor

Si un contenedor abre un archivo para acceso de lectura y el archivo aún no existe en el contenedor (upperdir), se lee desde la imagen (lowerdir). Esto incurre en una sobrecarga de rendimiento muy baja.

El archivo solo existe en la capa del contenedor

Si un contenedor abre un archivo para acceso de lectura y el archivo existe en el contenedor (upperdir) y no en la imagen (lowerdir), se lee directamente desde el contenedor.

El archivo existe tanto en la capa del contenedor como en la capa de la imagen

Si un contenedor abre un archivo para acceso de lectura y el archivo existe en la capa de la imagen y en la capa del contenedor, se lee la versión del archivo en la capa del contenedor. Los archivos en la capa del contenedor (upperdir) ocultan los archivos con el mismo nombre en la capa de la imagen (lowerdir).

Modificación de archivos o directorios

Considera algunos escenarios en los que se modifican archivos en un contenedor.

Escribir en un archivo por primera vez

La primera vez que un contenedor escribe en un archivo existente, ese archivo no existe en el contenedor (upperdir). El controlador overlay2 realiza una operación copy_up para copiar el archivo desde la imagen (lowerdir) al contenedor (upperdir). Luego, el contenedor escribe los cambios en la nueva copia del archivo en la capa del contenedor.

Sin embargo, OverlayFS funciona a nivel de archivo en lugar de a nivel de bloque. Esto significa que todas las operaciones copy_up de OverlayFS copian el archivo completo, incluso si el archivo es grande y solo se modifica una pequeña parte de él. Esto puede tener un impacto notable en el rendimiento de escritura del contenedor. Sin embargo, vale la pena señalar dos cosas:

  • La operación copy_up solo ocurre la primera vez que se escribe en un archivo determinado. Las escrituras posteriores en el mismo archivo se realizan sobre la copia del archivo que ya se ha copiado al contenedor.

  • OverlayFS funciona con múltiples capas. Esto significa que el rendimiento se puede ver afectado al buscar archivos en imágenes con muchas capas.

Eliminación de archivos y directorios

  • Cuando se elimina un archivo dentro de un contenedor, se crea un archivo whiteout en el contenedor (upperdir). La versión del archivo en la capa de la imagen (lowerdir) no se elimina (porque el lowerdir es de solo lectura). Sin embargo, el archivo whiteout impide que esté disponible para el contenedor.

  • Cuando se elimina un directorio dentro de un contenedor, se crea un directorio opaco dentro del contenedor (upperdir). Esto funciona de la misma manera que un archivo whiteout e impide de forma efectiva que se acceda al directorio, aunque este siga existiendo en la imagen (lowerdir).

Renombrar directorios

Llamar a rename(2) para un directorio se permite solo cuando tanto la ruta de origen como la de destino están en la capa superior. De lo contrario, devuelve el error EXDEV ("enlace entre dispositivos no permitido"). Tu aplicación debe estar diseñada para manejar EXDEV y recurrir a una estrategia de "copiar y desenlazar".

Rendimiento de OverlayFS y Docker

overlay2 puede funcionar mejor que btrfs. Sin embargo, ten en cuenta los siguientes detalles:

Caché de páginas

OverlayFS admite el uso compartido de la caché de páginas. Varios contenedores que acceden al mismo archivo comparten una única entrada de caché de página para ese archivo. Esto hace que el controlador overlay2 sea eficiente con la memoria y una buena opción para casos de uso de alta densidad como PaaS.

Copy-up

Al igual que con otros sistemas de archivos copy-on-write, OverlayFS realiza operaciones copy-up cada vez que un contenedor escribe en un archivo por primera vez. Esto puede añadir latencia a la operación de escritura, especialmente en archivos grandes. Sin embargo, una vez que el archivo ha sido copiado, todas las escrituras posteriores en ese archivo ocurren en la capa superior, sin necesidad de realizar más operaciones copy-up.

Buenas prácticas de rendimiento

Las siguientes buenas prácticas de rendimiento generales se aplican a OverlayFS.

Utilizar almacenamiento rápido

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

Utilizar volúmenes para cargas de trabajo con uso intensivo de escritura

Los volúmenes ofrecen 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 tus datos incluso si ningún contenedor en ejecución los está utilizando.

Limitaciones en la compatibilidad de OverlayFS

Para resumir los aspectos de OverlayFS que son incompatibles con otros sistemas de archivos:

open(2)
OverlayFS solo implementa un subconjunto de los estándares POSIX. Esto puede provocar que ciertas operaciones de OverlayFS infrinjan los estándares POSIX. Una de esas operaciones es la operación copy-up. Supón que tu aplicación llama a fd1=open("foo", O_RDONLY) y luego a fd2=open("foo", O_RDWR). En este caso, tu aplicación espera que fd1 y fd2 se refieran al mismo archivo. Sin embargo, debido a una operación copy-up que ocurre después de la segunda llamada a open(2), los descriptores se refieren a archivos diferentes. El descriptor fd1 continúa haciendo referencia al archivo en la imagen (lowerdir) y fd2 hace referencia al archivo en el contenedor (upperdir). Una solución para esto es ejecutar touch en los archivos, lo que obliga a que se realice la operación copy-up. Todas las operaciones open(2) posteriores, independientemente del modo de acceso de solo lectura o lectura-escritura, harán referencia al archivo en el contenedor (upperdir).

Se sabe que yum se ve afectado a menos que el paquete yum-plugin-ovl esté instalado. Si el paquete yum-plugin-ovl no está disponible en tu distribución (como en RHEL/CentOS anterior a 6.8 o 7.2), es posible que debas ejecutar touch /var/lib/rpm/* antes de ejecutar yum install. Este paquete implementa la solución alternativa touch mencionada anteriormente para yum.

rename(2)
OverlayFS no admite completamente la llamada al sistema rename(2). Tu aplicación debe detectar este fallo y recurrir a una estrategia de "copiar y desenlazar".