Ahora puede crear imágenes de Docker en werf usando un Dockerfile normal

Mejor tarde que nunca. O cómo casi cometimos un grave error al no tener soporte para Dockerfiles normales para crear imágenes de aplicaciones.

Ahora puede crear imágenes de Docker en werf usando un Dockerfile normal

hablaremos de patio — Utilidad GitOps que se integra con cualquier sistema CI/CD y proporciona gestión de todo el ciclo de vida de la aplicación, permitiendo:

  • recopilar y publicar imágenes,
  • implementar aplicaciones en Kubernetes,
  • elimine las imágenes no utilizadas mediante políticas especiales.


La filosofía del proyecto es recopilar herramientas de bajo nivel en un único sistema unificado que brinde a los ingenieros de DevOps control sobre las aplicaciones. Si es posible, se deben utilizar utilidades existentes (como Helm y Docker). Si no hay solución a un problema, podemos crear y apoyar todo lo necesario para ello.

Antecedentes: tu propio recopilador de imágenes

Esto es lo que pasó con el recopilador de imágenes en werf: el Dockerfile habitual no nos bastó. Si echas un vistazo rápido a la historia del proyecto, este problema ya apareció en las primeras versiones de werf (entonces todavía conocido como dapp).

Mientras creábamos una herramienta para crear aplicaciones en imágenes de Docker, rápidamente nos dimos cuenta de que Dockerfile no era adecuado para algunas tareas muy específicas:

  1. La necesidad de crear pequeñas aplicaciones web típicas de acuerdo con el siguiente esquema estándar:
    • instalar dependencias de aplicaciones en todo el sistema,
    • instalar un paquete de bibliotecas de dependencia de aplicaciones,
    • recoger activos,
    • y lo más importante, actualizar el código de la imagen de forma rápida y eficaz.
  2. Cuando se realizan cambios en los archivos del proyecto, el constructor debe crear rápidamente una nueva capa aplicando un parche a los archivos modificados.
  3. Si ciertos archivos han cambiado, entonces es necesario reconstruir la etapa dependiente correspondiente.

Hoy nuestro coleccionista tiene muchas otras posibilidades, pero estos fueron los deseos e impulsos iniciales.

En general, sin pensarlo dos veces, nos armamos con el lenguaje de programación que utilizamos. (vea abajo) y emprender el camino para implementar propio ADSL! De acuerdo con los objetivos, se pretendió describir el proceso de montaje por etapas y determinar las dependencias de estas etapas con los archivos. Y lo complementó propio coleccionista, que convirtió el DSL en el objetivo final: una imagen ensamblada. Al principio el DSL estaba en Ruby, pero a medida que transición a golang — la configuración de nuestro recopilador comenzó a describirse en un archivo YAML.

Ahora puede crear imágenes de Docker en werf usando un Dockerfile normal
Configuración antigua para dapp en Ruby

Ahora puede crear imágenes de Docker en werf usando un Dockerfile normal
Configuración actual para werf en YAML

El mecanismo del coleccionista también cambió con el tiempo. Al principio, simplemente generamos un Dockerfile temporal sobre la marcha a partir de nuestra configuración, y luego comenzamos a ejecutar instrucciones de ensamblaje en contenedores temporales y a confirmar.

NB: Por el momento, nuestro recopilador, que funciona con su propia configuración (en YAML) y se llama recopilador Stapel, ya se ha convertido en una herramienta bastante poderosa. Su descripción detallada merece artículos aparte, y los detalles básicos se pueden encontrar en documentación.

Conciencia del problema

Pero nos dimos cuenta, y no inmediatamente, de que habíamos cometido un error: no añadimos la capacidad construir imágenes a través de Dockerfile estándar e integrarlos en la misma infraestructura de gestión de aplicaciones de un extremo a otro (es decir, recopilar imágenes, implementarlas y limpiarlas). ¿Cómo podría ser posible crear una herramienta para su implementación en Kubernetes y no implementar la compatibilidad con Dockerfile, es decir? ¿Manera estándar de describir imágenes para la mayoría de los proyectos?

En lugar de responder a esta pregunta, ofrecemos una solución. ¿Qué pasa si ya tienes un Dockerfile (o un conjunto de Dockerfiles) y quieres usar werf?

NB: Por cierto, ¿por qué querrías usar werf? Las características principales se reducen a las siguientes:

  • ciclo completo de gestión de aplicaciones, incluida la limpieza de imágenes;
  • la capacidad de gestionar el montaje de varias imágenes a la vez desde una única configuración;
  • Proceso de implementación mejorado para gráficos compatibles con Helm.

Una lista más completa de ellos se puede encontrar en página del proyecto.

Entonces, si antes nos hubiéramos ofrecido a reescribir el Dockerfile en nuestra configuración, ahora diremos con gusto: "¡Permítanos construir sus Dockerfiles!"

Modo de empleo?

La implementación completa de esta característica apareció en el lanzamiento. werf v1.0.3-beta.1. El principio general es simple: el usuario especifica la ruta a un Dockerfile existente en la configuración werf y luego ejecuta el comando werf build... y eso es todo: werf ensamblará la imagen. Veamos un ejemplo abstracto.

Anunciamos el próximo Dockerfile en la raíz del proyecto:

FROM ubuntu:18.04
RUN echo Building ...

Y lo anunciaremos werf.yamlque usa esto Dockerfile:

configVersion: 1
project: dockerfile-example
---
image: ~
dockerfile: ./Dockerfile

¡Todo! Izquierda correr werf build:

Ahora puede crear imágenes de Docker en werf usando un Dockerfile normal

Además, podrá declarar lo siguiente werf.yaml para crear varias imágenes a partir de diferentes Dockerfiles a la vez:

configVersion: 1
project: dockerfile-example
---
image: backend
dockerfile: ./dockerfiles/Dockerfile-backend
---
image: frontend
dockerfile: ./dockerfiles/Dockerfile-frontend

Finalmente, también admite pasar parámetros de compilación adicionales, como --build-arg и --add-host - a través de la configuración werf. Una descripción completa de la configuración de la imagen Dockerfile está disponible en página de documentación.

Como funciona?

Durante el proceso de construcción, funciona el caché estándar de las capas locales en Docker. Sin embargo, lo importante es que werf también integra la configuración de Dockerfile en su infraestructura. ¿Qué significa esto?

  1. Cada imagen creada a partir de un Dockerfile consta de una etapa llamada dockerfile (puedes leer más sobre qué etapas hay en werf aquí).
  2. Para escenario dockerfile werf calcula una firma que depende del contenido de la configuración de Dockerfile. Cuando cambia la configuración de Dockerfile, la firma de la etapa cambia dockerfile y werf inicia una reconstrucción de esta etapa con una nueva configuración de Dockerfile. Si la firma no cambia, werf toma la imagen del caché (más detalles sobre el uso de firmas en werf se describen en Este reporte).
  3. A continuación, las imágenes recopiladas se pueden publicar con el comando werf publish (o werf build-and-publish) y utilícelo para la implementación en Kubernetes. Las imágenes publicadas en Docker Registry se limpiarán utilizando herramientas de limpieza estándar de werf, es decir, Las imágenes antiguas (más de N días), las imágenes asociadas con ramas de Git inexistentes y otras políticas se limpiarán automáticamente.

Se pueden encontrar más detalles sobre los puntos descritos aquí en la documentación:

Notas y precauciones

1. La URL externa no es compatible con ADD

Actualmente no se admite el uso de una URL externa en una directiva ADD. Werf no iniciará una reconstrucción cuando cambie el recurso en la URL especificada. Planeamos agregar esta función pronto.

2. No puedes agregar .git a la imagen.

En términos generales, agregar un directorio .git en la imagen: una mala práctica viciosa y este es el motivo:

  1. si .git permanece en la imagen final, esto viola los principios Aplicación de 12 factores: Dado que la imagen final debe estar vinculada a una única confirmación, no debería ser posible hacerlo. git checkout compromiso arbitrario.
  2. .git aumenta el tamaño de la imagen (el repositorio puede ser grande debido al hecho de que una vez se le agregaron archivos grandes y luego se eliminaron). El tamaño de un árbol de trabajo asociado únicamente con una confirmación específica no dependerá del historial de operaciones en Git. En este caso, la adición y posterior eliminación .git desde la imagen final no funcionará: la imagen aún adquirirá una capa adicional; así es como funciona Docker.
  3. Docker puede iniciar una reconstrucción innecesaria, incluso si se está creando la misma confirmación, pero desde diferentes árboles de trabajo. Por ejemplo, GitLab crea directorios clonados separados en /home/gitlab-runner/builds/HASH/[0-N]/yourproject cuando el ensamblaje paralelo está habilitado. El reensamblaje adicional se deberá al hecho de que el directorio .git es diferente en diferentes versiones clonadas del mismo repositorio, incluso si se crea la misma confirmación.

El último punto también tiene consecuencias cuando se utiliza werf. Werf requiere que el caché integrado esté presente cuando se ejecutan algunos comandos (p. ej. werf deploy). Cuando se ejecutan estos comandos, werf calcula las firmas de etapa para las imágenes especificadas en werf.yamly deben estar en la caché del ensamblado; de lo contrario, el comando no podrá continuar funcionando. Si la firma del escenario depende del contenido .git, luego obtenemos un caché que es inestable a los cambios en archivos irrelevantes, y werf no podrá perdonar tal descuido (para más detalles, consulte documentación).

En general, los agregando solo ciertos archivos necesarios a través de las instrucciones ADD en cualquier caso aumenta la eficiencia y confiabilidad de los escritos. Dockerfile, y también mejora la estabilidad del caché recopilado para esto. Dockerfile, a cambios irrelevantes en Git.

Total

Nuestro camino inicial para escribir nuestro propio constructor para necesidades específicas fue difícil, honesto y directo: en lugar de usar muletas sobre el Dockerfile estándar, escribimos nuestra solución con una sintaxis personalizada. Y esto tenía sus ventajas: el colector Stapel cumple perfectamente su tarea.

Sin embargo, en el proceso de escribir nuestro propio constructor, perdimos de vista la compatibilidad con los Dockerfiles existentes. Esta falla ahora se ha solucionado y en el futuro planeamos desarrollar soporte para Dockerfile junto con nuestro constructor Stapel personalizado para ensamblaje distribuido y ensamblaje usando Kubernetes (es decir, ensamblaje en corredores dentro de Kubernetes, como se hace en kaniko).

Entonces, si de repente tienes un par de Dockerfiles por ahí... Intentar patio!

PD Lista de documentación sobre el tema.

Lea también en nuestro blog: “werf: nuestra herramienta para CI/CD en Kubernetes (resumen e informe en video)".

Fuente: habr.com

Añadir un comentario