Echa un vistazo a las imágenes de contenedores más rápido con pagos parciales

¿Se ha preguntado alguna vez por qué se tarda tanto en extraer una imagen de contenedor de un registro de contenedor con una herramienta de contenedor como Podman?

$ time podman pull fedora
Re "fedora" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull registry.fedoraproject.org/fedora:latest...
Getting image source signatures
Copying blob 944c4b241113 done   
Copying config 191682d672 done   
Writing manifest to image destination
Storing signatures
191682d6725209667efcfd197c4dc93be5ab33729b7a4a2a45d5cf2bc1f589e0
 
real    0m19.329s
user    0m4.213s
sys    0m0.829s

Esta imagen base de Fedora es bastante pequeña y tarda 20 segundos con una conexión a Internet de alta velocidad. He oído hablar de imágenes enormes que tardan unos minutos en extraerse. Peor aún, cada vez que se actualiza la imagen de Fedora, o cualquier imagen, debe verificar la imagen completa nuevamente, no solo las diferencias.

Las imágenes grandes también causan problemas de almacenamiento. ¿Alguna vez ha mirado el espacio que ocupan las imágenes de su contenedor en el disco? Algunos usuarios se están quedando sin espacio en sus directorios de inicio solo porque han extraído cientos o miles de imágenes de contenedores. Estas imágenes a menudo contienen muchos archivos duplicados.

Otra cosa a considerar es la memoria del núcleo. El kernel de Linux es lo suficientemente inteligente como para saber que si dos procesos diferentes cargan el mismo contenedor (como una biblioteca compartida) en la memoria, solo necesitan cargarlo en la memoria una vez. Por ejemplo, si tiene 10 programas diferentes ejecutándose simultáneamente que usan libc, el /usr/lib/libc.so.6 el código se carga en la memoria del núcleo una vez. Al ejecutar contenedores con imágenes, si es el mismo /usr/lib/libc.so.6 está en varias imágenes diferentes, entonces el kernel se confunde y carga múltiples versiones del mismo contenido en la memoria, desperdiciando recursos. Debido a la forma en que actualmente almacenamos imágenes de contenedores, esto es muy común.

Este artículo presenta nuevas tecnologías que se han fusionado en herramientas de contenedores para:

  • Haz que las imágenes se disparen mucho más rápido
  • Haz que el almacenamiento de archivos en el disco sea mucho más ligero
  • Informe al kernel de Linux cuándo se puede compartir contenido en la memoria

Los administradores de contenedores pueden hacer todo esto utilizando el contenido previamente almacenado en el disco en lugar de extraerlo y duplicarlo.

Índice

    Cómo extrajimos las imágenes del contenedor

    Iniciativa de contenedores abiertos Las imágenes de contenedor (OCI) se distribuyen como una serie de capas. Cada capa contiene un subconjunto de los archivos de imagen. Estas capas se almacenan en un registro como un archivo tar comprimido.

    Cuando se usa el backend de superposición, el tiempo de ejecución del contenedor obtiene y extrae cada capa en un directorio diferente.

    En tiempo de ejecución, cada capa se utiliza como capa inferior para la edición final del sistema de archivos de superposición del contenedor.

    Un Containerfile (Dockerfile) formado por las siguientes líneas genera una serie de capas diferentes:

    • FROM fedora da como resultado la capa de imagen base de Fedora
    • RUN yum install -y nginx contiene todos los archivos nuevos creados por yum
    • COPY ./config/foo /etc/nginx contiene archivo /etc/nginx/foo

    Actualmente, los usuarios solo pueden realizar la deduplicación en capas. Las imágenes pueden compartir capas, pero eso requiere disciplina. Tener más capas puede facilitar la deduplicación, pero tiene un costo de ejecución porque el sistema de archivos de superposición tiene que analizar más capas para cada búsqueda y crear una lista de directorios.

    Lo que el nuevo modelo está tratando de resolver

    El nuevo modelo de almacenamiento intenta abordar una serie de problemas realizando los siguientes cambios:

    • Los autores de Containerfile no tienen que preocuparse por cómo el registro almacenará la imagen y la optimizará para la deduplicación. También pueden crear imágenes sobrescritas sin preocuparse por la deduplicación.
    • Un motor de contenedor no necesita extraer archivos que ya están presentes localmente.
    • Los archivos en varias capas solo se pueden almacenar una vez (esto requiere compatibilidad con el sistema de archivos).
    • Los archivos de solo lectura utilizados por varias capas o contenedores se pueden asignar a la memoria solo una vez.

    [ Learn more about the Red Hat OpenShift Container Platform. ]

    Opciones de formato de imagen para el nuevo modelo

    El formato de imagen actual que utilizan los motores de contenedores, un archivo tar comprimido con gzip, no tiene suficiente información para permitir estas optimizaciones.

    El primer paso es crear las capas de forma que permitan la recuperación de archivos individuales.

    Actualmente se admiten dos candidatos: eStargz y zstd: fragmentado. Estos nuevos formatos conservan los metadatos de cada archivo contenido en el archivo, incluida su suma de verificación.

    eStargz

    eStargz es un formato de archivo utilizado por containerd para impresiones de imágenes perezosas. Se basa en el proyecto de prueba de concepto de Google. CRFS.

    El formato eStargz transforma una capa comprimida con gzip en un archivo tar equivalente donde cada archivo se comprime individualmente. El sistema puede recuperar cada archivo sin tener que recuperar y descomprimir todo el archivo tar.

    Los metadatos de la capa se agregan al propio archivo tarball como parte del flujo tar. Este es un gran cambio ya que el archivo tar resultante, cuando se descomprime, tiene un resumen diferente y contiene un archivo adicional.

    Debido a algunas limitaciones de las API de contenedores e imágenes, nuestras herramientas de contenedores ya pueden usar estas imágenes, pero aún no pueden crearlas.

    zstd: fragmentado

    Hemos creado una nueva solución llamada zstd: fragmentado para resolver el problema con el formato eStargz que cambia el DiffID y agrega los metadatos como parte del archivo tar. zstd: chunked aprovecha zstd formato comprimido.

    En el formato zstd: chunked, los mismos metadatos utilizados por eStargz se agregan en el flujo de compresión. El descompresor zstd ignora los metadatos adicionales para que el resumen del archivo sin comprimir no cambie. Además, zstd es mucho más rápido y se comprime mejor que gzip.

    Sin embargo, la adopción de este formato plantea algunos problemas:

    • El proyecto Moby se fusionó recientemente esta solicitud de sorteo, que agregará soporte para zstd en la próxima versión de Docker. Las imágenes que usan zstd no funcionarán en versiones anteriores de Docker.
    • Quay.io aún no acepta imágenes OCI, pero el problema se está resolviendo.

    Cómo implementar los nuevos formatos

    Cuando se desprotege una capa almacenada en uno de estos dos formatos, el motor del contenedor sigue estos pasos:

    • Recupera los metadatos de la capa del registro. Este es un archivo JSON que describe el contenido de la capa de imagen y los archivos que contiene.
    • Los archivos ya conocidos localmente se duplican mediante reflinks. Actualmente, esto es compatible con XFS y BTRFS. Si no se admiten los enlaces de referencia, el archivo se copia y no se realiza la deduplicación del almacenamiento.
    • El motor del contenedor prepara una solicitud de multiplicación HTTP que especifica los archivos que aún no se conocen localmente y los solicita del registro.
    • Los nuevos archivos se crean a partir de los datos enviados por el registro.

    Por lo tanto, la deduplicación se produce en el momento de la salida (porque los archivos conocidos no se recuperan) y con el almacenamiento porque los mismos archivos se deduplican con reflinks (cuando se admiten).

    La función de desprotección parcial no requiere almacenamiento adicional para los archivos de objetos, ya que los lee directamente desde el directorio de desprotección final donde están almacenados.

    Cómo extraer el archivo tar

    Actualmente, la búsqueda de tarball ocurre en un proceso separado que se ejecuta en un chroot. Esto evita que las imágenes especialmente diseñadas se aprovechen de la resolución de enlaces simbólicos y creen archivos fuera del directorio de destino.

    Debido a que la nueva característica de deduplicación debe acceder a los archivos fuera del directorio de destino, el entorno de tiempo de ejecución del contenedor no puede usar el código de pago existente.

    [ You might also be interested in reading about the principles of container-based application design. ]

    Se utiliza un nuevo extractor cuando se utiliza la función de tiro parcial. debe ser openat2 syscall que se agregó al kernel de Linux 5.6. openat2 le permite restringir las búsquedas de archivos con el mismo comportamiento que chroot Acaso. Si el extractor no puede utilizar el openat2 syscall, el código vuelve al antiguo mecanismo para extraer toda la capa.

    Cómo deduplicar el host

    En los sistemas que usan OSTree, puede realizar la deduplicación con archivos del sistema ya procesados. Para que esta función funcione, debe habilitar el seguimiento de OSTree mediante la suma de comprobación de carga útil, como:

    $ ostree --repo=/ostree/repo config set core.payload-link-threshold 100

    Cómo deduplicar la memoria

    Los enlaces de referencia tienen diferentes inodos y la capa del sistema de archivos virtual (VFS) de Linux no los conoce porque son administrados directamente por el sistema de archivos.

    Cuando se accede a dos inodos que usan reflinks, el kernel finalmente cargará los mismos datos en la memoria dos veces, incluso si solo se almacenan una vez en el sistema de archivos.

    Cuando necesite deduplicación de memoria, puede configurarla para usar enlaces duros en lugar de enlaces ref.

    Sugerimos usar la deduplicación de enlace duro solo para casos de uso limitado donde la memoria es escasa. Es un cambio radical en el modelo de almacenamiento. Algunas imágenes pueden comportarse de manera diferente porque todos los metadatos del inodo se comparten (como atime, mtime, ctime) entre los archivos deduplicados con el mismo inodo. también n_link El atributo rastreará cuántas veces se ha deduplicado el archivo.

    Evite el bloqueo al extraer

    Un problema de larga data con el almacenamiento de contenedores es que mantiene un bloqueo mientras se extrae el archivo tar y se crea la nueva capa. Esto sucede porque los controladores de almacenamiento necesitan conocer el resumen de cada capa extraída para poder aplicar la siguiente.

    Como efecto secundario de la nueva funcionalidad de pago, este problema se solucionó porque el pago se crea en un directorio de preparación separado. Cada capa se puede extraer en paralelo. El bloqueo solo es necesario para el movimiento atómico del directorio de ensayo hasta su destino final.

    Construya un zstd: imagen fragmentada

    Buildah obtuvo nuevas opciones para crear una zstd: imagen fragmentada. El formato de compresión se especifica cuando la imagen se transmite a un registro.

    $ buildah bud --squash --format oci -t example.com/my-new-zstd-chunked-image
    $ buildah push --compression-format zstd:chunked example.com/my-new-zstd-chunked-image

    Activar y utilizar sorteos parciales

    La función de extracción parcial aún es experimental y no está habilitada de forma predeterminada.

    Para activarlo, debe agregar la siguiente configuración en el storage.conf archivar bajo storage.options:

    pull_options = {enable_partial_images = "true", use_hard_links = "false", ostree_repos = “”}

    Estos indicadores adicionales controlan cómo se realiza la deduplicación:

    • use_hard_links le dice al motor del contenedor que use enlaces duros para la deduplicación.
    • ostree_repos es una lista separada por columnas de repositorios de OSTree para usar al buscar archivos.

    Concluir

    El nuevo modelo de almacenamiento intenta hacer un mejor uso del espacio en disco y reducir el consumo de memoria. Las dominadas pueden ser más eficientes y, por lo tanto, también más rápidas. Para más información, mira esta demostración esto muestra cómo las impresiones parciales pueden mejorar las impresiones de Podman.

    Artículos de interés

    Subir