Respalda tu migración con la expansión de malla de Istio: Conceptos

Este artículo es la primera parte de una serie en la que se analiza el uso de una malla de servicios para migrar función por función de un entorno heredado, como un centro de datos local que ejecuta aplicaciones en máquinas virtuales a Google Kubernetes Engine (GKE).

La serie consta de este artículo conceptual y del instructivo adjunto. En este artículo, se explica la lógica de la migración y se describen sus pasos de alto nivel. En el instructivo, se te guiará a través de un ejemplo de migración.

Introducción

Este artículo está dirigido a los profesionales de TI a cargo de una infraestructura compleja que deseas migrar y modernizar de forma gradual y, al mismo tiempo, minimizar lo siguiente:

  • Tiempo de inactividad
  • Refactoriza el esfuerzo
  • Complejidad operativa de la red

Los conceptos que se explican se aplican a cualquier nube, por lo que en el artículo, suponemos que estás familiarizado con las tecnologías de la nube, los contenedores y los microservicios.

Como se describe en Patrones y prácticas de nubes híbridas y múltiples, existen tres patrones principales para migrar a la nube: lift-and-shift, mejorar y migrar, y extraer y reemplazar. En este artículo, se describe un patrón de mejora y migración, en el que el patrón se aplica a cada función de la aplicación, en lugar de a toda la aplicación.

Durante la migración, la aplicación tiene una arquitectura híbrida en la que algunas funciones están en Google Cloud y otras todavía están en el entorno heredado. Cuando se finaliza la migración, la aplicación completa se aloja en Google Cloud.

Terminología

aplicación
En este artículo, una aplicación es un sistema de software completo con muchas funciones. Los usuarios perciben a la aplicación como una unidad única. Por ejemplo, un sitio web que vende libros es una aplicación.
función

Una función es una unidad de funcionalidad de una aplicación, como la función de reseñas de libros de una aplicación de librería. Las funciones constan de microservicios.

Pueden ser sin estado, que son las que no dependen de ningún tipo de datos, o con estado, que son las que dependen de los datos.

microservicio

Un microservicio es un componente independiente que se compila para adaptarse a una función de la aplicación. En este artículo, una aplicación se compone de diferentes microservicios que los usuarios no pueden distinguir. Por ejemplo, un componente que controla las reseñas de libros es un microservicio.

En el patrón de microservicios, la aplicación es el agregado de varios microservicios, cada uno con un objetivo específico. Por ejemplo, puedes tener un microservicio que controle las calificaciones de los libros y otro que controle las reseñas de los libros. Esos microservicios deben estar vinculados de forma flexible y deben interactuar entre sí a través de las API bien definidas. Se pueden escribir en diferentes lenguajes y frameworks (como en las aplicaciones políglotas), y pueden tener ciclos de vida distintos.

Para definir mejor los límites de cada microservicio, puedes colocarlos en contenedores mediante las siguientes herramientas:

malla de servicios

Una malla de servicios es un software que vincula diferentes servicios y que proporciona funciones de red de alto valor, como el descubrimiento de servicios, comunicaciones seguras, el balanceo de cargas, la administración del tráfico, la supervisión y la observabilidad.

Una implementación típica de las mallas de servicios es vincular cada servicio con un proxy que proporciona esas funciones. Se conoce al proxy de servicio como archivo adicional. La función del archivo adicional es aumentar y mejorar la aplicación a la que se conecta, a menudo sin el conocimiento de la aplicación.

migración

Una migración es un proceso para migrar funciones de una o más aplicaciones que se ejecutan en un entorno heredado a un entorno de destino, como Google Cloud. En este artículo, una migración puede ser cualquiera de los siguientes tipos:

  • Migración Big Bang: Cuando migras todas las funciones de una aplicación a la vez.
  • Migración gradual, función por función: Cuando migras una función a la vez.
conjunto de pruebas de cumplimiento

Un conjunto de pruebas de cumplimiento es un grupo de pruebas que se pueden ejecutar en un entorno para comprobar si este cumple con un conjunto de requisitos determinado. Si el entorno es válido, cumple con los requisitos. Por ejemplo, puedes validar la respuesta a una solicitud de prueba o comprobar si las dependencias de la aplicación se instalaron.

Puedes comenzar con la supervisión, el seguimiento y las herramientas de visualización de la malla de servicios para obtener una validación manual. Luego, puedes implementar el conjunto de pruebas y desarrollarlo con el tiempo:

  • Prueba de carga. Puedes hacer que el conjunto de pruebas evolucione si envías el tráfico de prueba al entorno de forma automática y evalúas los resultados.
  • Herramienta de pruebas de cumplimiento. Puedes diseñar y desarrollar un conjunto de pruebas mediante una herramienta dedicada.

¿Por qué elegir una estrategia de migración gradual?

Una migración Big Bang es difícil debido a los desafíos y riesgos que implica migrar una o más aplicaciones en un solo ejercicio. Cuando tienes limitaciones en el tiempo y el presupuesto, enfocarte en una migración Big Bang no deja mucha capacidad para trabajar en las funciones nuevas de la aplicación.

Por el contrario, una migración gradual y por funciones tiene una complejidad general más baja debido al menor tamaño de la carga de trabajo que se migrará: una función única tiene una huella más pequeña en comparación con una aplicación completa. Una migración gradual te permite repartir el riesgo entre eventos de migración más pequeños, en lugar de en un solo ejercicio de alta prioridad. Una migración gradual también permite que el equipo de migración planifique, diseñe y desarrolle varias estrategias de migración a fin de adaptarse a diferentes tipos de funciones.

Puedes encontrar asesoramiento sobre cómo elegir qué funciones migrar primero y cómo migrar funciones con estado en Migra una aplicación monolítica a microservicios en Google Kubernetes Engine.

¿Por qué usar una malla de servicios?

Una malla de servicios separa las funciones de servicio (cómo se implementa la lógica empresarial) de funciones de red (cómo y cuándo enrutar el tráfico a las funciones de servicio).

En el entorno heredado, la mayoría de las llamadas de servicio no incluyen la red, ya que se generan en una plataforma monolítica. En las arquitecturas de microservicios, las comunicaciones entre servicios se realizan a través de una red y los servicios deben ocuparse de este modelo diferente. Una malla de servicios abstrae las funciones para manejar las comunicaciones de red, por lo que no tienes que implementarlas en cada aplicación. Una malla de servicios también reduce la complejidad operativa de la red, y que proporciona canales de comunicación seguros, el balanceo de cargas, la administración del tráfico, la supervisión y funciones de observabilidad listas para usar.

En el instructivo adjunto, usarás Istio como la malla de servicios. Las funciones de Istio incluyen lo siguiente:

  • Administración del tráfico: control detallado del tráfico con reglas de enrutamiento enriquecidas para el tráfico HTTP, gRPC, WebSocket y TCP.
  • Funciones de solicitud de resiliencia: reintentos, conmutaciones por error, inyección de fallas y disyuntores.
  • Una capa de política conectable y una API de configuración que admiten el control de acceso y el límite de frecuencia.
  • Métricas, registros y seguimientos automáticos para todo el tráfico dentro de un clúster, que incluye el ingreso y la salida del clúster.
  • Comunicación segura entre servicios con autenticación y autorización basadas en cuentas de servicio.
  • Asesoramiento en las tareas de implementación y prueba, como las pruebas A/B, los lanzamientos canary, la inyección de fallas y el límite de frecuencia.

También puedes visualizar tu malla de servicios. Las herramientas como Kiali se integran a Istio para mostrar qué servicios forman parte de una malla de servicios y cómo se conectan.

En la siguiente captura de pantalla, se muestra un gráfico de servicio de Kiali de ejemplo que representa una malla de Istio.

Gráfico de servicio de Kiali que representa una malla de Istio

Si implementas y configuras una malla de servicios, puedes enrutar el tráfico de forma dinámica al entorno heredado o al entorno de destino. No necesitas modificar la configuración de la aplicación a fin de admitir tu migración, ya que la administración del tráfico es transparente para los servicios en la malla.

Aunque este enfoque funciona bien para las funciones sin estado, debes planificar y refactorizar de manera adicional las funciones con estado, sensibles a la latencia o muy vinculadas con otras:

  • Con estado. Cuando migras funciones con estado, también debes migrar los datos, lo que minimiza el tiempo de inactividad y aborda los problemas de integridad y sincronización durante la migración. Puedes obtener más información sobre las estrategias de migración de datos en Migra una aplicación monolítica a microservicios en Google Kubernetes Engine.
  • Sensible a la latencia. Si una función es sensible a la latencia cuando se comunica con otras funciones, es posible que debas implementar componentes adicionales durante el proceso de migración. Los proxies que pueden cargar de forma previa datos o capas de almacenamiento en caché, por lo general, se usan para mitigar esta sensibilidad.
  • Muy vinculadas a otras funciones. Si dos o más funciones están muy vinculadas, es posible que tengas que migrarlas al mismo tiempo. Aunque este enfoque es más fácil que migrar una aplicación completa, puede ser más difícil que migrar una sola función.

El plan de migración

En esta sección, se presenta un plan para realizar una migración gradual por funciones mediante una malla de servicios. El plan se compone de las siguientes fases:

  1. Evaluar el entorno heredado
  2. Crear una base en el entorno de destino
  3. Implementar servicios en el entorno de destino y comenzar a enrutar el tráfico al entorno de destino
  4. Detener el enrutamiento de tráfico al entorno heredado
  5. Retirar el entorno heredado

Evalúa el entorno heredado

Antes de cualquier actividad de implementación o diseño de migración, debes evaluar el entorno heredado a fin de recopilar información y establecer un conjunto de requisitos del entorno de destino y un modelo de referencia de las pruebas y la validación. Puedes empezar por compilar un catálogo de todas las funciones de la aplicación que se migrarán. Para cada función, deberías poder responder a este conjunto de preguntas (no exhaustivas):

  • ¿Cuáles son los requisitos del entorno de ejecución y del rendimiento?
  • ¿Existen dependencias en otras funciones?
  • ¿Esta función es fundamental para la empresa?
  • ¿Esta función es sin estado o con estado?
  • ¿Cuánto se espera refactorizar para migrarla?
  • ¿Esta función puede permitir un período de migración?

Puedes obtener más información sobre el proceso de evaluación y qué funciones migrar. Luego, ejecuta el conjunto de pruebas de cumplimiento en el entorno heredado como modelo de referencia y, también, en el entorno de destino durante y después de la migración.

Tus conjuntos de pruebas estar enfocados para validar los siguientes aspectos durante la migración:

  • Aprovisionamiento. Aprovisiona los recursos que necesitas en tu entorno antes de configurarlos.
  • Configuración. Después de aprovisionar los recursos en el entorno, configúralos según las necesidades de tu aplicación. Tener un conjunto de pruebas de configuración garantiza que el entorno esté listo para alojar la aplicación.
  • Lógica empresarial. Después de validar el aprovisionamiento y la configuración del entorno, valida la lógica empresarial de la aplicación. Por ejemplo, puedes validar las respuestas a las solicitudes.

InSpec, RSpec y Serverspec son herramientas para desarrollar paquetes de prueba de cumplimiento automático. Son independientes de la plataforma y extensibles, por lo que puedes implementar tus propios controles a partir de los integrados.

En el siguiente diagrama, se muestra un ejemplo de un entorno heredado:

Entorno heredado

Aprovisiona el entorno de destino

Ahora que tienes suficiente información sobre los entornos y las aplicaciones que migrarás, puedes aprovisionar el entorno de destino según los requisitos que establezcas durante la evaluación.

Durante esta fase, puedes usar el conjunto de pruebas de cumplimiento para validar el entorno de destino. Es posible que tengas que actualizar el conjunto de pruebas para tener en cuenta las diferencias eventuales entre el entorno heredado y el de destino, como el hardware y la topología de red. Ten en cuenta que migras de un entorno local, en el que tienes control total, a un entorno de nube pública, en el que, por lo general, no tienes acceso completo a toda la pila.

Debido a que aprovisionas un entorno nuevo, te recomendamos aplicar una metodología de infraestructura como código para que tu infraestructura se pueda auditar, repetir y aprovisionar de forma automática.

En el siguiente diagrama, se muestra el entorno heredado y el entorno de destino que recién se aprovisionó (y que en este momento está vacío).

Entorno heredado y entorno de destino (vacío)

Configura una malla de servicios

En el siguiente paso, se configura una malla de servicios que abarque el entorno heredado y el entorno de destino. La malla de servicios se encarga de conectar los diversos microservicios que se ejecutan en el entorno heredado y que se migrarán al entorno de destino. En esta fase, la malla de servicios está vacía, a la espera de que se registren los servicios. La malla de servicios aún no recibe tráfico de producción.

En el siguiente diagrama, se muestra el entorno heredado y la malla de servicios vacía en el entorno de destino.

Entorno heredado y malla de servicios vacía

Agrega servicios del entorno heredado a la malla

En este ejemplo, el entorno heredado no está integrado directamente a la malla de servicios. Esa integración requiere que registres de forma manual todos los servicios que se ejecutan en el entorno heredado con la malla de servicios. Si tu entorno ya se ejecuta en Kubernetes, puedes automatizar el registro gracias a la integración nativa con las API de malla de servicios.

En esta etapa, los clientes aún usan las interfaces del entorno heredado para acceder a los microservicios que migras. La malla de servicios aún no recibe tráfico de producción.

En el siguiente diagrama, se muestra que los servicios que se ejecutan en el entorno heredado se agregan a la malla de servicios.

Los servicios que se ejecutan en el entorno heredado se agregan a la malla de servicios.

Expón servicios a través de la malla de servicios

Con el entorno heredado registrado, usa la malla de servicios para exponer los microservicios que se ejecutan en el entorno heredado. En esta etapa también enrutas el tráfico de forma gradual a los microservicios desde las interfaces del entorno heredado hasta las interfaces del entorno de destino.

Los clientes no ven ninguna interrupción del servicio, ya que acceden a las interfaces de los dos entornos a través de una capa de balanceo de cargas. Además, el enrutamiento del tráfico dentro de la malla de servicios es transparente para los clientes. Los clientes no sabrán que se produjo un cambio en la configuración del enrutamiento.

En el siguiente diagrama, se muestra que los servicios que se ejecutan en el entorno heredado se exponen a través de la malla de servicios.

Los servicios que se ejecutan en el entorno heredado se exponen a través de la malla de servicios.

Implementa servicios en el entorno de destino

En esta fase, implementarás microservicios en el entorno de destino. Aquí se supone que estos microservicios ya se encuentran en contenedores. Por lo tanto, con ese proceso finalizado, puedes elegir una estrategia de implementación para inicializar la carga de trabajo que migrarás en el entorno de destino:

  • Implementación masiva: Todas las instancias de microservicios se implementan al mismo tiempo.
  • Implementación gradual: Se implementa un microservicio a la vez.

Las instancias de microservicios en el entorno de destino todavía no reciben tráfico de producción.

Cuando migras microservicios con estado, también debes migrar los datos relacionados, lo que minimiza el tiempo de inactividad y aborda los problemas de integridad y sincronización. Obtén más información sobre las estrategias de migración de datos.

Los microservicios que se ejecutan en el entorno de destino se registran en la malla de servicios de forma automática, gracias a la integración nativa con Istio y Kubernetes. En esta etapa, los clientes aún usan los microservicios que se ejecutan en el entorno heredado y que se exponen a través de la malla de servicios. Los microservicios que se ejecutan en el entorno de destino aún no recibirán tráfico de producción.

En el siguiente diagrama, se muestran los servicios expandidos que no reciben tráfico de producción y los que se exponen en el entorno heredado mediante la malla de servicios.

Servicios expandidos que no reciben tráfico de producción y servicios que se exponen en el entorno heredado mediante la malla de servicios

Configura reglas de enrutamiento para dividir el tráfico

Ahora puedes configurar reglas de enrutamiento para dividir el tráfico de producción entre los servicios que se ejecutan en el entorno heredado y los que se ejecutan en el entorno de destino mediante la malla de servicios. Puedes comenzar por enrutar una parte pequeña del tráfico de producción a instancias de microservicios que se ejecutan en el entorno de destino. A medida que desarrollas la confianza en el entorno de destino mediante el conjunto de pruebas y la supervisión sólida, puedes ir aumentando esa parte del tráfico total.

Debido a que las solicitudes de los clientes se enrutan en ambos entornos, necesitas planificación y coordinación adicionales para los microservicios con estado, ya que los datos relacionados también se deben migrar y, durante la migración, podría haber una fase transitoria con varias fuentes de información.

En el siguiente diagrama, se muestra cómo se divide el tráfico entre los microservicios que se ejecutan en el entorno de destino y los que se ejecutan en el entorno heredado.

División del tráfico entre los microservicios que se ejecutan en el entorno de destino y los que se ejecutan en el entorno heredado

También recomendamos que definas mejor las reglas de enrutamiento para inhabilitar las solicitudes entre entornos, de modo que cuando una solicitud del cliente llegue a un entorno, ya sea heredado o de destino, permanezca en ese entorno.

Configura reglas para enrutar el tráfico al entorno de destino

En esta fase, actualizarás las reglas de enrutamiento para enrutar el tráfico de forma gradual solo a los servicios que se ejecuten en el entorno de destino.

En el siguiente diagrama, se muestra cómo el tráfico ahora se enruta solo al entorno de destino, mientras que el entorno heredado se guarda como una copia de seguridad.

El tráfico ahora se enruta solo al entorno de destino, mientras que el entorno heredado se guarda como una copia de seguridad.

Retira el entorno heredado

En esta fase, debes retirar el entorno heredado.

Antes de retirar el entorno heredado, asegúrate de lo siguiente:

  • El tráfico no se enruta a instancias de microservicios que se ejecutan en el entorno heredado.
  • No hay tráfico que provenga de las interfaces del entorno heredado.
  • El entorno de destino se validó por completo.

Cuando se cumplan estas condiciones, podrás actualizar tus registros DNS para apuntar al balanceador de cargas que configuraste durante la fase de aprovisionamiento del entorno de destino.

En el siguiente diagrama, solo se muestra el entorno de destino, ya que se retiró el entorno heredado.

Entorno de destino (sin el entorno heredado)

¿Qué sigue?