Microservicios Unificación y por qué es tan importante. Parte 1 - Configuración



Introduccion


Buen dia a todos. Soy un desarrollador de Python en una empresa que se ocupa de soluciones complejas para automatizar procesos de negocios, desarrollando para resolver tareas individuales, análisis y consultoría. Mis responsabilidades incluyen el desarrollo y mantenimiento de la arquitectura de microservicios. Y hoy me gustaría decir cómo estamos luchando con los microservicios y por qué la unificación es tan importante para ellos.

No es ningún secreto que este enfoque para el desarrollo de productos está capturando cada vez más el mercado. Y cuanto más nos sumergimos en ellos, más es necesario no olvidar las reglas básicas para trabajar con ellos. Para estructurar nuestra experiencia en la escritura de productos de microservicios, se decidió escribir una serie de artículos sobre cómo generalizar algunos aspectos del desarrollo a todos los servicios.

Una de esas reglas es la unificación. En nuestra empresa, la mayoría de los productos consisten en un montón de idiomas y tecnologías multicolores. En todo este stand, debe pensar en cómo generalizar los principios básicos a todos los microservicios para su fácil soporte, configuración y desarrollo conveniente. Esto se discutirá en la serie de estos artículos.

Le pregunto a todos los interesados ​​bajo cat.

El problema


Quizás lo primero que encuentre al desarrollar un servicio son sus métodos de configuración. En la arquitectura de microservicios, este problema se agudiza aún más.

Imagine que tiene dos docenas de servicios y necesita cambiar un parámetro en cada uno. Por ejemplo, deshabilite el uso de CORS. Dado que el sistema es multicomponente y está construido sobre microservicios, para una gestión conveniente es mejor utilizar un enfoque uniforme para la configuración de todos los módulos. Por lo tanto, debe usar el mismo enfoque al configurar cada módulo.

Puede decir que el desarrollador de cada servicio debería hacer esto, pero ¿qué pasa si todas sus configuraciones se almacenan en el mismo Kubernetes, donde no se puede dar a todos los desarrolladores? Los pobres DevOps se verán obligados a pasar mucho tiempo simplemente aprendiendo los servicios y sus métodos de configuración. Y este procedimiento se repetirá con la actualización de los servicios, especialmente si alguien quiere probar algo nuevo en la configuración del servicio. Con este enfoque, el equipo pasará constantemente parte del tiempo trabajando con configuraciones y no desarrollando nuevas funciones, reparando errores, etc.

Solo para este caso, se requiere un método de configuración general que no estará vinculado a un lenguaje o tecnología específicos y le permitirá configurar todos los servicios con diferencias mínimas en la estructura general de la configuración. Para esta tarea, desarrollamos un sistema para configurar "módulos" (servicios) usando archivos yaml, la capacidad de almacenar configuraciones para diferentes etapas (dev / prod / local, etc.) y dividir todo en diferentes bloques relacionados con ciertas cosas.

Especificación


Puede hablar mucho sobre dónde y cómo usarlo, pero propongo ir directamente a la especificación de este método de configuración. Como dicen, la teoría es buena y la práctica es aún mejor.

Requisitos del sistema


Comencemos definiendo nuestro sistema y los requisitos para él.
  • Cada módulo es un componente independiente en el contenedor.
  • Podemos pasar variables de entorno al contenedor
  • No podemos cambiar la configuración sobre la marcha sin reiniciar el servicio (creando un nuevo contenedor).
  • Todas las acciones de reserva (como cambiar a la base de datos de respaldo) se realizan fuera del componente y son transparentes.


Requisitos del método de configuración


Ahora decidamos qué queremos ver de nuestro método de configuración para satisfacer todos los requisitos.

  1. El tipo de archivo de configuración es el YAML de la estructura especificada. YAML fue elegido por nosotros por varias razones:
    • Capacidad para escribir comentarios y una estructura conveniente, a diferencia de JSON
    • Capacidad para describir matrices en contraste con ENV
    • Fuera de la caja se puede utilizar para la inclusión de values.yaml en helm (Kubernetes)

  2. Los archivos de configuración deben fusionarse en el árbol de configuración
  3. La configuración debe ser específica de la etapa. Cada etapa tiene su propio conjunto completo. Aquí vale la pena hacer algunas reservas para aclarar:
    • No puede reutilizar los valores de las variables de otra etapa , excepto la etapa predeterminada , que está reservada para los valores predeterminados.
    • Al cargar la configuración, debe hacer una fusión recursiva de la capa de configuración desde la etapa especificada además de los valores predeterminados con la prioridad de capa de la etapa especificada. Los valores (matrices, etc.) no deben combinarse.
    • Si hay varios archivos de configuración para una etapa, las claves en ellos deben fusionarse y, en consecuencia, deben ser únicos entre sí.

  4. La etapa actual utilizada debe determinarse por el valor de la variable de entorno "ETAPA". No se pretende cambiar una variable en una instancia en ejecución de un servicio.
  5. La ruta absoluta al directorio de configuración debe determinarse por el valor de la variable de entorno "CONFIG_PATH". Por conveniencia, es posible un retroceso si no hay una variable en una determinada ruta predeterminada, que debe indicarse en la documentación del módulo. En este caso, la ruta especificada debe ser relativa a la raíz del directorio de la aplicación.


Ejemplos de configuración


Supongamos que tenemos un servicio que necesita almacenar configuraciones para conectarse a Postgres, así como cierta información sobre nosotros mismos

Primero debe definir una configuración para STAGE = por defecto. En él describiremos la estructura general, así como también haremos que los datos sean independientes de la etapa.

valores predeterminados


# configuration/defaults/service.yaml defaults: version: 1.0.0 name: "config-example" # configuration/defaults/redis.yaml defaults: redis: host: "host" db: 0 port: 6379 password: "password" 


dev


 # configuration/dev/redis.yaml dev: redis: host: "localhost" password: "hard_pwd" 


Config resultante


 version: 1.0.0 name: "config-example" redis: host: "localhost" db: 0 port: 6379 password: "hard_pwd" 


Conclusiones



De una manera tan complicada, resolvimos el problema de configurar los servicios en nuestro zoológico y llevamos todo a una vista común. Este ejemplo es solo un punto de partida y puede modificarse según los detalles de su proyecto.

Para aquellos que estén interesados ​​en este método de configuración en una "forma básica":
Nuestros paquetes para diferentes lenguajes de programación.


Para que la ayuda en la escritura se convierta en un agradecimiento especial a Roque , SMGladkovskiy

Source: https://habr.com/ru/post/es436630/


All Articles