Crear imágenes de Docker en Kubernetes
Vitalis Ogbonna
3 de mayo de 2022
0 minutos de lecturaCada vez más ingenieros alojan plataformas de CI/CD en Kubernetes. Este enfoque ahorra tiempo gracias a la automatización, garantiza implementaciones consistentes y facilita la supervisión y el manejo de microservicios. Sin embargo, crear imágenes de contenedores en clústeres de Kubernetes implica algunos desafíos técnicos que requieren soluciones alternativas.
En este artículo, exploraremos algunas formas de crear imágenes de Docker en un clúster de Kubernetes para procesos de CI/CD. También hablaremos sobre las ventajas y desventajas de estos métodos.
Herramientas para crear imágenes de Docker en Kubernetes
Si alguna vez creaste una imagen de contenedor, probablemente ejecutaste un comando como docker build. Luego, cuando llegó el momento de automatizar ese proceso, quizá configuraste tus herramientas de CI/CD para que también usaran docker build. Esto funciona con servidores de CI sencillos, pero quizá más adelante quieras implementar una plataforma de CI basada en Kubernetes.
El desafío es que el daemon de Docker no está disponible libremente desde el clúster de Kubernetes. Por eso, debemos usar alternativas y asegurarnos de no poner en riesgo la integridad de nuestra aplicación ni la infraestructura.
Hay varias herramientas para hacerlo:
Buildah se especializa en crear imágenes de la Open Container Initiative (OCI). Sus comandos replican todos los comandos de un Dockerfile. Permite crear imágenes con o sin Dockerfiles, sin necesidad de privilegios de root.
img es una herramienta independiente para crear imágenes de contenedores compatibles con Dockerfile y OCI, sin daemon ni privilegios. Usa la caché de manera eficiente y puede ejecutar varias etapas de compilación al mismo tiempo, ya que utiliza internamente el solucionador DAG de BuildKit para crear imágenes.
kaniko crea imágenes de contenedores a partir de un Dockerfile, dentro de un contenedor o clúster de Kubernetes. kaniko no depende de un daemon de Docker y ejecuta cada comando del Dockerfile completamente en el espacio de usuario.
Docker in Docker es una receta para ejecutar Docker dentro de Docker. Crea contenedores de Docker en clústeres de Kubernetes al montar el archivo
/var/run/docker.sockcomo volumen en un contenedor de Docker.Sysbox Enterprise Edition (Sysbox-EE), de Nestybox, permite que los contenedores sin privilegios de root ejecuten cargas de trabajo como Docker, systemd y Kubernetes como si fueran máquinas virtuales.
BuildKit CLI crea imágenes OCI y Docker de una o varias arquitecturas en clústeres de Kubernetes. Reemplaza el comando docker build por kubectl build para crear imágenes en clústeres de Kubernetes.
Jib para contenedores Java crea imágenes de contenedores sin usar un Dockerfile ni requerir una instalación de Docker. Hay plugins de Jib para Maven y Gradle. Jib también está disponible como biblioteca de Java.
KO es una herramienta rápida y sencilla para crear imágenes de contenedores para aplicaciones de Go. Crea imágenes básicamente ejecutando go build en tu máquina local, por lo que no requiere instalar Docker.
Veamos dos métodos populares para crear imágenes de Docker en un clúster de Kubernetes: Docker in Docker y kaniko.
Docker in Docker
El método Docker in Docker (DIND) se usa comúnmente en pipelines de CI/CD, donde las imágenes se crean y se suben después de una compilación de código exitosa. También se usa para integrar Jenkins en pipelines de implementación, por ejemplo, durante pruebas en entornos de sandbox.
El enfoque DIND puede parecer práctico y sencillo. Sin embargo, el ex empleado de Docker y colaborador de DIND Jérôme Petazzoni sostiene que Docker creó este enfoque para acelerar los procesos internos, y alude a problemas de seguridad como motivo para no usarlo en entornos de producción.
Originalmente, Docker creó los contenedores para que se ejecutaran en modo privilegiado con el enfoque DIND. El daemon de Docker se ejecuta como root, por lo que el contenedor también se ejecuta como root en el host. Cualquiera que acceda al socket de Docker tiene acceso root, lo que le permite ejecutar cualquier software, crear usuarios nuevos y acceder a todo lo conectado al contenedor. Esto hace que los contenedores sean vulnerables a ataques que podrían propagarse por toda la arquitectura.
Además, como Kubernetes eliminó oficialmente la compatibilidad con Dockershim, es probable que montar docker.sock en el host deje de funcionar en el futuro, a menos que agreguemos Docker a todos los nodos de Kubernetes. AWS ofrece una herramienta útil para detectar el uso del socket de Docker en clústeres.
El método DIND también presenta problemas de compatibilidad con los controladores de almacenamiento. Además, administrar las cachés de imágenes puede ser complicado porque tenemos que descargar las imágenes de Docker cada vez que iniciamos una compilación.
Una forma de resolver estos problemas es usar herramientas que no requieran un entorno de ejecución de contenedores para crear imágenes. Una de ellas es kaniko, la solución de código abierto de Google para crear imágenes de Docker en un clúster de Kubernetes.
kaniko
kaniko crea imágenes de contenedores a partir de un Dockerfile, dentro de un contenedor o clúster de Kubernetes. No depende de un daemon de Docker y ejecuta cada comando del Dockerfile completamente en el espacio de usuario. Esto te permite crear imágenes de contenedores en entornos donde no es fácil ni seguro ejecutar un daemon de Docker, como los clústeres de Kubernetes estándar.
Usaremos herramientas gratuitas y de acceso público para mostrar el flujo de trabajo de kaniko. Para seguir este tutorial, necesitarás:
Docker Desktop instalado en tu PC con Kubernetes habilitado
Una cuenta válida de Docker Hub para que el pod de kaniko se autentique y suba la imagen de Docker
Una cuenta de GitHub para que kaniko acceda al Dockerfile
Usaremos este proyecto de ejemplo en GitHub para mostrar cómo funciona kaniko. Clónalo con git clone https://github.com/agavitalis/kaniko-kubernetes.git para seguir los pasos.
Este proyecto de ejemplo tiene dos archivos y un archivo README.md:
#sample project directory
kaniko-build-demo
dockerfilepod.ymlREADME.md
dockerfile contiene este código para los comandos de creación de imágenes:
En el código de configuración de kaniko, el ejecutor de imágenes de kaniko usa la versión más reciente. También especificamos la ubicación de nuestro Dockerfile y el repositorio de imágenes, así como el nombre de las credenciales del registro de imágenes en Kubernetes.
Cómo funciona kaniko
kaniko funciona de una manera bastante sencilla. La imagen del ejecutor de kaniko gcr.io/kaniko-project/executor:latest ejecuta los comandos del Dockerfile para crear imágenes. Lee el Dockerfile especificado, descarga la imagen base definida en el comando FROM (en este caso, ubuntu) en el sistema de archivos del contenedor definido y luego sube las imágenes a un registro.
Después de descargar la imagen base indicada en la instrucción FROM, kaniko ejecuta por separado cada comando del Dockerfile y toma una instantánea del espacio de usuario después de ejecutar cada uno. Luego, agrega la capa de la instantánea a la capa base en cada ejecución.
Configuramos estos parámetros en el archivo pod.yml:
context: ubicación del Dockerfile. En este caso, el Dockerfile está en el directorio raíz del repositorio. Usa las variablesGIT_USERNAMEyGIT_PASSWORD(token de API) para autenticarte en repositorios privados de Git.destination: Reemplaza <dockerhub-username> por tu nombre de usuario para que kaniko suba la imagen al registro de Docker Hub.docker-file: ruta al Dockerfile relativa al contexto.
Ahora que entendemos cómo funciona kaniko, creemos un Secret de Kubernetes. Luego lo usaremos para crear e implementar una imagen.
Crear un Secret de Kubernetes para Docker Hub
Debemos crear un Secret de Kubernetes para que kaniko pueda acceder a Docker Hub. Para hacerlo, necesitamos la siguiente información:
docker-server: servidor del registro de Docker donde se alojarán tus imágenes. Si usas Docker Hub, este valor debe serhttps://index.docker.io/v1/.docker-username: nombre de usuario de tu registro de Docker.docker-password: contraseña de tu registro de Docker.docker-email: correo electrónico configurado en tu registro de Docker.
Ejecuta los siguientes comandos y reemplaza cada variable según corresponda:
El comando anterior monta este Secret en el pod de kaniko para facilitar la autenticación al subir la imagen creada a un registro de Docker. Deberías recibir un mensaje de confirmación como este:

Implementar el pod de kaniko para crear una imagen de Docker
Ahora, iniciemos la compilación creando el pod en nuestro clúster de Kubernetes. Implementa el pod con el comando:

Esto inicia el proceso de creación de la imagen y luego la sube al registro de Docker especificado.
Puedes listar los pods disponibles en tu clúster de Kubernetes con el comando:

Esto muestra los pods disponibles, su estado y su antigüedad. Ten en cuenta que podrías recibir un error si kaniko usa credenciales incorrectas o intenta subir la imagen al repositorio equivocado.
Si quieres, usa el comando kubectl delete pod <pod-name> para eliminar los pods existentes.
Para obtener información detallada sobre el pod que acabas de implementar, usa el comando:

También puedes consultar el registro de compilación con el comando:

Consulta la hoja de referencia de kubectl para conocer otros comandos que puedes usar para explorar y solucionar problemas, y obtener más información sobre tu clúster.
Después, ve a Docker Hub para confirmar que todo haya funcionado y que hayas implementado correctamente tus imágenes en Docker.

¡Creamos e implementamos correctamente nuestra imagen de Docker desde un clúster de Kubernetes con kaniko!
Snyk para la seguridad de contenedores
kaniko ofrece una forma segura de crear imágenes de Docker en clústeres de Kubernetes. Obtiene el Dockerfile del contexto de compilación definido, crea la imagen y sube el resultado a un registro de imágenes. Su potente sistema de caché permite crear imágenes más rápido.
Aunque no uses un método inseguro para crear tus imágenes de Docker en Kubernetes, podrías seguir expuesto a vulnerabilidades de seguridad de Kubernetes. Snyk Container ofrece una solución confiable de seguridad de contenedores para detectar y corregir vulnerabilidades en aplicaciones nativas de la nube. Snyk se integra sin problemas con Docker, GitHub, Kubernetes, Jenkins y otras herramientas para proteger tu aplicación y tu infraestructura.
Seguridad de contenedores centrada en los desarrolladores
Snyk encuentra y corrige automáticamente vulnerabilidades en imágenes de contenedores y cargas de trabajo de Kubernetes.



