Mejores prácticas de Kubernetes. Creando pequeños contenedores

Mejores prácticas de Kubernetes. Creando pequeños contenedores

El primer paso para implementar Kubernetes es colocar su aplicación en un contenedor. En esta serie, veremos cómo se puede crear una imagen de contenedor pequeña y segura.
Gracias a Docker, crear imágenes de contenedores nunca ha sido tan fácil. Especifique una imagen base, agregue sus cambios y cree un contenedor.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Si bien esta técnica es excelente para comenzar, el uso de imágenes base predeterminadas puede generar un trabajo inseguro con imágenes grandes llenas de vulnerabilidades.

Además, la mayoría de las imágenes en Docker usan Debian o Ubuntu para la imagen base y, si bien esto proporciona una excelente compatibilidad y una fácil personalización (un archivo Docker requiere solo dos líneas de código), las imágenes base pueden agregar cientos de megabytes de carga adicional a su contenedor. Por ejemplo, un archivo node.js simple para una aplicación Go "hello-world" tiene aproximadamente 700 megabytes, mientras que su aplicación real tiene solo unos pocos megabytes de tamaño.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Entonces, toda esta carga de trabajo adicional es un desperdicio de espacio digital y un gran escondite para vulnerabilidades y errores de seguridad. Entonces, veamos dos formas de reducir el tamaño de una imagen de contenedor.

El primero es el uso de imágenes base pequeñas, el segundo es el uso del patrón Builder. Usar imágenes base más pequeñas es probablemente la forma más fácil de reducir el tamaño de su contenedor. Lo más probable es que el idioma o la pila que está utilizando proporcione una imagen de aplicación original que sea mucho más pequeña que la imagen predeterminada. Echemos un vistazo a nuestro contenedor node.js.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

De forma predeterminada en Docker, el tamaño de la imagen base del nodo:8 es de 670 MB, y el tamaño de la imagen del nodo:8-alpine es de solo 65 MB, es decir, 10 veces más pequeño. Al utilizar la imagen base de Alpine más pequeña, reducirá significativamente el tamaño de su contenedor. Alpine es una distribución de Linux pequeña y liviana que es muy popular entre los usuarios de Docker porque es compatible con muchas aplicaciones y mantiene los contenedores pequeños. A diferencia de la imagen de "nodo" estándar de Docker, "node:alpine" elimina muchos archivos y programas de servicio, dejando solo aquellos que son suficientes para ejecutar su aplicación.

Para pasar a una imagen base más pequeña, simplemente actualice el Dockerfile para comenzar a trabajar con la nueva imagen base:

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Ahora, a diferencia de la antigua imagen de compilación, debes copiar tu código en el contenedor e instalar las dependencias. En un nuevo Dockerfile, el contenedor comienza con una imagen de nodo:alpine, luego crea un directorio para el código, instala dependencias usando el administrador de paquetes NPM y finalmente ejecuta server.js.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Esta actualización da como resultado un contenedor que es 10 veces más pequeño. Si su lenguaje de programación o pila no tiene la funcionalidad de reducción de imágenes base, utilice Alpine Linux. También brindará la capacidad de gestionar completamente el contenido del contenedor. Usar imágenes base pequeñas es una excelente manera de crear rápidamente contenedores pequeños. Pero se puede lograr una reducción aún mayor utilizando el patrón Builder.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

En los lenguajes interpretados, el código fuente primero se pasa al intérprete y luego se ejecuta directamente. En los lenguajes compilados, el código fuente se convierte primero en código compilado. Sin embargo, la compilación suele utilizar herramientas que en realidad no son necesarias para ejecutar el código. Esto significa que puedes eliminar completamente estas herramientas del contenedor final. Puedes usar Builder Pattern para esto.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

El código se crea en el primer contenedor y se compila. Luego, el código compilado se empaqueta en un contenedor final sin los compiladores ni las herramientas necesarias para compilar ese código. Ejecutemos una aplicación Go a través de este proceso. Primero, pasaremos de la imagen de compilación a Alpine Linux.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

En el nuevo Dockerfile, el contenedor comienza con una imagen golang:alpine. Luego crea un directorio para el código, lo copia en el código fuente, crea ese código fuente y ejecuta la aplicación. Este contenedor es mucho más pequeño que el contenedor de compilación, pero aún contiene el compilador y otras herramientas de Go que realmente no necesitamos. Entonces simplemente extraigamos el programa compilado y pongámoslo en su propio contenedor.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Quizás notes algo extraño en este archivo Docker: contiene dos líneas FROM. La primera sección de 4 líneas tiene exactamente el mismo aspecto que el Dockerfile anterior, excepto que utiliza la palabra clave AS para nombrar esta etapa. La siguiente sección tiene una nueva línea FROM para comenzar una nueva imagen, donde en lugar de la imagen golang:alpine usaremos Raw alpine como imagen base.

Raw Alpine Linux no tiene ningún certificado SSL instalado, lo que provocará que la mayoría de las llamadas API a través de HTTPS fallen, así que instalemos algunos certificados CA raíz.

Ahora viene la parte divertida: para copiar el código compilado del primer contenedor al segundo, simplemente puedes usar el comando COPY ubicado en la línea 5 de la segunda sección. Sólo copiará un archivo de aplicación y no afectará a las herramientas de utilidad Go. El nuevo archivo Docker de varias etapas contendrá una imagen contenedora de solo 12 megabytes de tamaño, en comparación con la imagen contenedora original que tenía 700 megabytes, ¡lo cual es una gran diferencia!
Por lo tanto, usar imágenes base pequeñas y Builder Pattern son excelentes maneras de crear contenedores mucho más pequeños sin mucho trabajo.
Es posible que, dependiendo de la pila de aplicaciones, existan formas adicionales de reducir el tamaño de la imagen y del contenedor, pero ¿los contenedores pequeños realmente tienen un beneficio mensurable? Veamos dos áreas en las que los contenedores pequeños son extremadamente eficaces: rendimiento y seguridad.

Para evaluar el aumento del rendimiento, considere la duración del proceso de crear un contenedor, insertarlo en el registro (push) y luego recuperarlo desde allí (pull). Puede ver que un contenedor más pequeño tiene una clara ventaja sobre un contenedor más grande.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Docker almacenará en caché las capas para que las compilaciones posteriores sean muy rápidas. Sin embargo, muchos sistemas de CI utilizados para crear y probar contenedores no almacenan en caché las capas, por lo que suponen un importante ahorro de tiempo. Como puede ver, el tiempo para construir un contenedor grande, dependiendo de la potencia de su máquina, es de 34 a 54 segundos, y cuando se usa un contenedor, se reduce usando el patrón Builder, de 23 a 28 segundos. Para operaciones de este tipo, el aumento de la productividad será del 40-50%. Así que piense cuántas veces construye y prueba su código.

Una vez creado el contenedor, debe insertar su imagen (imagen del contenedor de inserción) en el registro del contenedor para luego poder usarlo en su clúster de Kubernetes. Recomiendo usar Google Container Registry.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Con Google Container Registry (GCR), solo paga por el almacenamiento sin formato y las redes, y no hay tarifas adicionales de administración de contenedores. Es privado, seguro y muy rápido. GCR utiliza muchos trucos para acelerar la operación de extracción. Como puede ver, insertar un contenedor Docker Container Image usando go:onbuild tomará de 15 a 48 segundos, dependiendo del rendimiento de la computadora, y la misma operación con un contenedor más pequeño tomará de 14 a 16 segundos, y para máquinas menos productivas. la ventaja en la velocidad de operación aumenta 3 veces. Para máquinas más grandes, el tiempo es aproximadamente el mismo, ya que GCR utiliza un caché global para una base de datos compartida de imágenes, lo que significa que no es necesario cargarlas en absoluto. En una computadora de bajo consumo, la CPU es el cuello de botella, por lo que la ventaja de usar contenedores pequeños aquí es mucho mayor.

Si está utilizando GCR, le recomiendo utilizar Google Container Builder (GCB) como parte de su sistema de compilación.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Como puede ver, su uso le permite lograr resultados mucho mejores en la reducción de la duración de la operación Build+Push que incluso una máquina productiva; en este caso, el proceso de construcción y envío de contenedores al host se acelera casi 2 veces. . Además, obtienes 120 minutos de construcción gratuitos todos los días, lo que cubre tus necesidades de construcción de contenedores en la mayoría de los casos.

Luego viene la métrica de rendimiento más importante: la velocidad de recuperación o descarga de contenedores Pull. Y si no le importa mucho el tiempo dedicado a una operación de inserción, entonces la duración del proceso de extracción tiene un impacto grave en el rendimiento general del sistema. Supongamos que tiene un grupo de tres nodos y uno de ellos falla. Si está utilizando un sistema de gestión como Google Kubernetes Engine, reemplazará automáticamente el nodo inactivo por uno nuevo. Sin embargo, este nuevo nodo estará completamente vacío y tendrás que arrastrar todos tus contenedores hacia él para que comience a funcionar. Si la operación de extracción demora lo suficiente, su clúster se ejecutará con un rendimiento menor todo el tiempo.

Hay muchos casos en los que esto puede suceder: agregar un nuevo nodo a un clúster, actualizar nodos o incluso cambiar a un nuevo contenedor para su implementación. Por lo tanto, minimizar el tiempo de extracción del pull se convierte en un factor clave. Es innegable que un contenedor pequeño se descarga mucho más rápido que uno grande. Si ejecuta varios contenedores en un clúster de Kubernetes, el ahorro de tiempo puede ser significativo.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

Mire esta comparación: una operación de extracción en contenedores pequeños lleva entre 4 y 9 veces menos tiempo, dependiendo de la potencia de la máquina, que la misma operación con go:onbuild. El uso de imágenes base de contenedores pequeños y compartidos acelera significativamente el tiempo y la velocidad a la que se pueden implementar y conectar nuevos nodos de Kubernetes.

Veamos el tema de la seguridad. Los contenedores más pequeños se consideran mucho más seguros que los más grandes porque tienen una superficie de ataque más pequeña. ¿Es realmente? Una de las funciones más útiles de Google Container Registry es la capacidad de escanear automáticamente sus contenedores en busca de vulnerabilidades. Hace unos meses creé contenedores onbuild y multietapa, así que veamos si hay alguna vulnerabilidad allí.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

El resultado es sorprendente: solo se detectaron 3 vulnerabilidades medianas en un contenedor pequeño, y en un contenedor grande se encontraron 16 vulnerabilidades críticas y otras 376. Si miramos el contenido de un contenedor grande, podemos ver que la mayoría de los problemas de seguridad no tienen nada que ver con nuestra aplicación, sino que están relacionados con programas que ni siquiera utilizamos. Entonces, cuando la gente habla de una gran superficie de ataque, eso es lo que quieren decir.

Mejores prácticas de Kubernetes. Creando pequeños contenedores

La conclusión es clara: cree contenedores pequeños porque brindan beneficios reales de rendimiento y seguridad a su sistema.

Mejores prácticas de Kubernetes. Organización de Kubernetes con espacio de nombres.

Algunos anuncios 🙂

Gracias por estar con nosotros. ¿Te gustan nuestros artículos? ¿Quieres ver más contenido interesante? Apóyanos haciendo un pedido o recomendándonos a amigos, VPS en la nube para desarrolladores desde $4.99, un análogo único de servidores de nivel de entrada, que fue inventado por nosotros para usted: Toda la verdad sobre VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps desde $19 o como compartir servidor? (disponible con RAID1 y RAID10, hasta 24 núcleos y hasta 40GB DDR4).

Dell R730xd 2 veces más barato en el centro de datos Equinix Tier IV en Amsterdam? Solo aqui 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV desde $199 ¡en los Paises Bajos! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - ¡desde $99! Leer acerca de Cómo construir infraestructura corp. clase con el uso de servidores Dell R730xd E5-2650 v4 por valor de 9000 euros por un centavo?

Fuente: habr.com

Añadir un comentario