Cómo convertir en contenedor una aplicación heredada

Shutterstock.com/Sergey Novikov

La contenedorización ha transformado la forma en que se desarrollan e implementan nuevas aplicaciones. Sin embargo, muchas organizaciones conservan un catálogo anterior de sistemas más antiguos que necesitan un enfoque diferente. Esta desconexión entre lo nuevo y lo antiguo no tiene que perpetuarse: también puede empaquetar sistemas más antiguos como contenedores, lo que facilita su evolución con métodos de desarrollo más modernos.

En este artículo, veremos un proceso que puede utilizar para comenzar a contener el software "heredado". Si bien no hay dos productos iguales, y el término "heredado" es subjetivo, nos centraremos en pasos ampliamente aplicables para empaquetar sistemas estrechamente acoplados actualmente vinculados a entornos individuales.

Índice de contenidos
  1. 1. Identificar los sistemas candidatos
  2. 2. Componentes del sistema
  3. 3. Prepare sus componentes
    1. Almacenamiento persistente
    2. Gestión de la configuración
    3. Enlaces entre servicios
  4. 4. Escribe tus Dockerfiles
  5. 5. Configurar la orquestación
  6. 6. Después de la mudanza: Monitoreo y expansión de su flota de contenedores
  7. ¿Vale la pena?
  8. Conclusión

1. Identificar los sistemas candidatos

Vale la pena preparar primero un inventario de sistemas que le permita identificar buenos candidatos para la contenedorización. En algunos casos, puede llegar a la conclusión de que una aplicación en particular simplemente no se puede contener. Esto suele ser cuando tiene requisitos de hardware profundamente arraigados o se basa en características del kernel y lenguajes de programación obsoletos.

Los mejores candidatos son los sistemas de uso frecuente que se beneficiarán inmediatamente de un desarrollo futuro acelerado. Busque aplicaciones que ya sean bastante autónomas si es completamente nuevo en la creación de contenedores. Seleccionar un sistema que esté bien utilizado pero que no sea de misión crítica le dará margen de maniobra si las cosas salen mal y le permitirá reconocer los beneficios de una migración exitosa.

2. Componentes del sistema

pudo Contenga su sistema candidato escribiendo un Dockerfile, incluidas todas las dependencias de la aplicación, y llámelo por día. Si bien esta es una forma válida de colocar rápidamente un sistema en un contenedor, no debería ser el objetivo final de sus esfuerzos. Un contenedor monolítico dará como resultado compilaciones largas, tamaños de imagen enormes y escalabilidad deficiente.

En su lugar, debe buscar oportunidades para dividir cada uno de sus sistemas en componentes individuales. Esos componentes deben terminar en sus propios contenedores, evitando que una sola pieza se vuelva demasiado grande. Podrá escalar los componentes individualmente creando réplicas adicionales de contenedores con recursos limitados.

Este paso también es importante para establecer la modularidad general y fomentar una mayor adopción de contenedores. A medida que separa más sistemas en sus componentes, comenzará a encontrar superposiciones que le permitirán reutilizar imágenes de contenedores que ya ha creado. Notará que gradualmente se vuelve más fácil continuar con la creación de contenedores.

Decidir dónde dividir los componentes no debería parecer demasiado exigente. Comience por identificar dónde se basa el sistema en servicios que ya son externos a su código fuente. Las conexiones de bases de datos, las colas de mensajes, los servidores de correo electrónico, los servidores proxy y las puertas de enlace deben ser independientes del componente que aumentan. Los separará en sus propios contenedores que se encuentran junto a la instancia que ejecuta su código.

También vale la pena buscar oportunidades para refactorizar lo que queda. ¿Su servicio tiene demasiadas responsabilidades que podrían dividirse en unidades funcionales separadas? Es posible que tenga una API de perfil de usuario que acepte cargas de fotos; el servicio que cambia el tamaño de esas fotos podría ser un buen candidato para ejecutarse de forma autónoma en su propio contenedor.

3. Prepare sus componentes

Después de separar los componentes, debe prepararlos para operar en un entorno en contenedores. Los contenedores tienen varias diferencias clave en comparación con las máquinas virtuales tradicionales. El almacenamiento persistente, la configuración y los vínculos entre los componentes son los tres aspectos más importantes a tener en cuenta por adelantado.

Almacenamiento persistente

Los contenedores son entornos efímeros. Las modificaciones del sistema de archivos se pierden cuando los contenedores se detienen. Usted es responsable de administrar los datos persistentes de su aplicación mediante los mecanismos que proporciona el tiempo de ejecución de su contenedor.

En el caso de Docker, los volúmenes se utilizan para almacenar datos fuera de las instancias de su contenedor. Los volúmenes se montan en rutas específicas dentro de los contenedores. Para evitar tener que montar docenas de volúmenes, es mejor concentrar los datos de su aplicación en unos pocos directorios de nivel superior. El montaje de volúmenes en esas ubicaciones garantizará la persistencia de los archivos que almacena su aplicación.

Es importante auditar las interacciones del sistema de archivos de su aplicación para comprender qué volúmenes necesita y los problemas que encontrará. No prestar atención a este paso podría resultar costoso si los datos que supone que persisten se pierden cada vez que se reinicia un contenedor.

Gestión de la configuración

Muchas aplicaciones heredadas se configuran mediante archivos de configuración estáticos. Estos pueden estar en un formato dedicado, como XML, JSON o INI, o codificados con el lenguaje de programación del sistema.

Los contenedores normalmente se configuran mediante variables de entorno externas. Las variables se definen cuando se crean los contenedores, utilizando mecanismos como el de Docker. -e bandera con docker run. Se inyectan en el entorno del contenedor en ejecución.

El uso de este sistema garantiza que pueda confiar en la cadena de herramientas de su contenedor para establecer y cambiar los parámetros de configuración. Es posible que primero deba refactorizar su aplicación para admitir la lectura de configuraciones de variables de entorno. Una forma común de facilitar la transición es colocar un pequeño script dentro del punto de entrada del contenedor. Esto puede enumerar las variables de entorno en la creación del contenedor y escribirlas en un archivo de configuración para su aplicación.

Enlaces entre servicios

La contenedorización también lo hace pensar en la creación de redes entre servicios. Los servicios generalmente no están expuestos entre sí, excepto mediante una configuración explícita. Puede configurar la vinculación automática en Docker uniendo varios contenedores a la misma red de Docker. Esto ofrece una función de descubrimiento de servicios que permite que los contenedores se comuniquen entre sí por su nombre.

Otras tecnologías de contenedorización utilizan diferentes enfoques para la creación de redes y el descubrimiento de servicios. Después de haber separado sus sistemas en componentes individuales, debe unirlos nuevamente usando las facilidades que ofrece su tiempo de ejecución. La naturaleza de las implementaciones en contenedores significa que a menudo hay más complejidad que la creación de redes entre máquinas virtuales o hosts físicos. El tráfico debe enrutarse y equilibrarse la carga entre todas las réplicas de contenedores y sus dependencias, por lo que debe reconocer estos requisitos desde el principio.

4. Escribe tus Dockerfiles

Una vez que haya planificado su arquitectura, puede comenzar el trabajo físico asociado con la creación de contenedores. El primer paso es escribir Dockerfiles para los componentes de su aplicación. Estos definen la secuencia de comandos y acciones que crean un sistema de archivos que contiene todo lo que el componente necesita para ejecutarse.

Los Dockerfiles comienzan con una imagen base apropiada a la que hace referencia un FROM declaración. Esto es comúnmente un sistema operativo (ubuntu:20.04, alpine:3) o un entorno de lenguaje de programación preconstruido (php:8, node:16). Puede elegir la imagen que mejor se adapte al entorno existente de su aplicación. Es posible comenzar desde un sistema de archivos vacío, pero generalmente no es necesario, a menos que necesite un control extremadamente granular.

El contenido adicional se superpone a la imagen base mediante instrucciones como COPY y RUN. Estos le permiten copiar archivos desde su host y ejecutar comandos en el sistema de archivos temporal de la compilación. Una vez que haya escrito su Dockerfile, puede compilarlo con el docker build -t my-image:latest . dominio.

5. Configurar la orquestación

Suponiendo que haya dividido en componentes su sistema, terminará con una imagen de contenedor para cada pieza. Ahora necesita una forma de abrir todos los contenedores simultáneamente para que pueda iniciar convenientemente una instancia de aplicación en funcionamiento.

Las instalaciones de producción más grandes suelen utilizar Kubernetes para este propósito. Es un sistema de orquestación dedicado que agrega sus propios conceptos de alto nivel para crear implementaciones replicadas en contenedores. Los sistemas más pequeños y los entornos de desarrollo suelen estar bien atendidos por Docker Compose, una herramienta que se basa en archivos YAML más simples para iniciar una "pila" de varios contenedores:

version: "3"

app:
  image: my-web-app:latest
  ports:
    - 80:80
database:
  image: mysql:8.0
  ports:
    - 3306:3306

A docker-compose.yml le permite iniciar todos sus servicios usando el docker-compose binario:

docker-compose up -d

La configuración de algún tipo de orquestación hace que su flota de contenedores sea más manejable y facilita el escalado a través de la replicación. Tanto Kubernetes como Docker Compose pueden iniciar múltiples instancias de sus servicios, una capacidad que no se puede lograr con aplicaciones heredadas formadas a partir de componentes estrechamente acoplados.

6. Después de la mudanza: Monitoreo y expansión de su flota de contenedores

La creación de contenedores no termina con el inicio de una instancia de su aplicación. Para aprovechar al máximo la tecnología, debe monitorear adecuadamente sus contenedores para mantenerse informado de los errores y la utilización de recursos.

Los sistemas más grandes están mejor atendidos por una plataforma de observabilidad dedicada que puede agregar registros y métricas de toda su flota. Es posible que ya esté utilizando una solución similar con sus implementaciones de aplicaciones heredadas, pero es aún más importante para los contenedores. Una buena observabilidad le permitirá rastrear los problemas hasta la instancia del contenedor en la que se originaron, lo que revelará los conocimientos que importan cuando tenga cientos o miles de réplicas.

Para seguir ampliando su flota, duplique la documentación y la estandarización. Ya hemos visto cómo la división de sistemas en componentes ayuda a la futura reutilización. Sin embargo, esto solo funciona de manera efectiva si ha documentado lo que tiene y cómo encaja cada pieza. Tomarse el tiempo para escribir sobre su sistema y el proceso por el que ha pasado agilizará el trabajo futuro. También ayudará a los nuevos miembros del equipo a comprender las decisiones que ha tomado.

¿Vale la pena?

La contenedorización vale la pena cuando siente que el desarrollo de un sistema se ve frenado por sus procesos actuales. Poder implementarlo como un conjunto de contenedores simplifica la experiencia de desarrollo y le brinda más versatilidad en la implementación. Ahora puede lanzar el servicio en cualquier lugar donde haya disponible un tiempo de ejecución de contenedor, ya sea una instancia en su computadora portátil o 1000 en un proveedor de nube pública.

Apostar por los contenedores hace que sea más fácil aprovechar el poder de la nube, consolidar sus implementaciones y reducir los costos de infraestructura local. Sin embargo, estas ganancias aparentes pueden verse contrarrestadas por la necesidad de volver a capacitar a los ingenieros, contratar nuevos talentos especializados y mantener sus contenedores a lo largo del tiempo.

La decisión de contener un sistema heredado debe considerar el valor de ese sistema para su negocio, el tiempo actual dedicado a mantenerlo y la posible reducción como resultado del uso de contenedores. Es posible que sea mejor dejar solos los servicios de baja prioridad si los procesos asociados con ellos no están causando problemas inmediatos.

Debe reconocerse que no todas las aplicaciones heredadas necesitarán o podrán usar todos los beneficios promocionados de la contenedorización. La adopción es un espectro, desde la ejecución del sistema en un único contenedor monolítico, hasta la creación de componentes, orquestación e integración completas con suites de observabilidad. El último modelo es el objetivo ideal para las aplicaciones críticas para el negocio que los ingenieros evolucionan todos los días; por el contrario, el primero puede ser adecuado para servicios que rara vez se tocan, donde el principal obstáculo es el tiempo dedicado a aprovisionar nuevos entornos de desarrollo basados ​​en máquinas virtuales.

Conclusión

La migración de aplicaciones heredadas a flujos de trabajo en contenedores puede parecer un desafío en la superficie. Por lo general, dividir el proceso en pasos distintos ayuda a definir dónde se encuentra y dónde quiere estar. En este artículo, analizamos seis etapas granulares que puede utilizar para abordar la creación de contenedores de los sistemas existentes. También hemos discutido algunas de las consideraciones que debe hacer al decidir si continuar.

Desde un punto de vista conceptual, contener una aplicación heredada es un poco diferente a trabajar con una nueva. Está aplicando los mismos principios de creación de componentes, servicios vinculados y configuración que se inyectan desde el entorno exterior. La mayoría de los sistemas son relativamente fáciles de contener cuando se ven desde esta perspectiva. Centrarse en estos aspectos lo ayudará a desacoplar sus aplicaciones, crear componentes escalables y diseñar una metodología de contenedorización efectiva.

Descubre más contenido

Subir Change privacy settings