
A medida que creces en tu carrera en TI, comienzas a notar que los sistemas tienen su propio carácter. Pueden ser complacientes, silenciosos, temperamentales o severos. Pueden atraerte o repelerte. De una forma u otra, tienes que "negociar" con ellos, maniobrar entre los "escollos" y construir las cadenas de su interacción.
Así que nos ha tocado la tarea de construir una plataforma en la nube, y para ello necesitábamos "convencer" a un par de subsistemas para que trabajaran con nosotros. Afortunadamente, tenemos un "lenguaje API", manos hábiles y un montón de entusiasmo.
En este artículo no habrá hardcore técnico, pero sí una descripción de los problemas que enfrentamos al construir la nube. Decidí narrar nuestro camino como una suave fantasía técnica sobre cómo buscamos un lenguaje común con los sistemas y qué resultó de ello.
Bienvenido debajo del corte.
El comienzo del camino
Hace algún tiempo, nuestro equipo enfrentó el desafío de lanzar una plataforma en la nube para nuestros clientes. Contábamos con el apoyo de la dirección, recursos, una infraestructura de hardware y libertad en la elección de tecnologías para implementar la parte de software del servicio.
También había una serie de requisitos:
- el servicio necesita un panel de usuario conveniente;
- la plataforma debe estar integrada en el sistema de facturación existente;
- la parte de software y hardware: OpenStack + Tungsten Fabric (Open Contrail), que nuestros ingenieros aprendieron a "preparar" bastante bien.
Sobre cómo se formó el equipo, se desarrolló la interfaz del panel de usuario y se tomaron decisiones de diseño, hablaremos en otra ocasión, si la comunidad de Habr tiene interés.
Las herramientas que decidimos usar:
- Python + Flask + Swagger + SQLAlchemy: un conjunto de Python bastante estándar;
- Vue.js para el frontend;
- decidimos gestionar la interacción entre componentes y servicios usando Celery sobre AMQP.
Anticipando preguntas sobre por qué elegimos Python, aclaro. El lenguaje ha encontrado su nicho en nuestra empresa y alrededor de él se ha formado una pequeña, pero significativa cultura. Por lo tanto, se decidió empezar a construir el servicio precisamente en él. Además, la velocidad de desarrollo en tales tareas, a menudo, es decisiva.
Así que, comencemos nuestra introducción.
Silencioso Bill - facturación
Con este chico nos conocíamos desde hace tiempo. Siempre se sentaba al lado y contaba algo en silencio. A veces nos reenviaba las solicitudes de los usuarios, emitía las facturas a los clientes, gestionaba los servicios. Un chico trabajador normal. Sin embargo, había complicaciones. Era callado, a veces pensativo y a menudo — en su mundo.

La facturación fue el primer sistema con el que intentamos establecer una relación. Y la primera dificultad se nos presentó al procesar los servicios.
Por ejemplo, al crear o eliminar, la tarea se coloca en la cola interna de facturación. De este modo se implementa un sistema de trabajo asíncrono con los servicios. Para procesar nuestros tipos de servicios, necesitábamos "apilar" nuestras tareas en esta cola. Y aquí nos encontramos con el problema: la falta de documentación.

Según la descripción de la API del software, la tarea se puede resolver, pero no teníamos tiempo para realizar ingeniería inversa, así que sacamos la lógica al exterior y organizamos una cola de tareas sobre RabbitMQ. La operación sobre el servicio es iniciada por el cliente desde su panel personal, se envuelve en una "tarea" de Celery en el backend y se ejecuta en el lado de facturación y OpenStack. Celery permite gestionar las tareas de forma bastante cómoda, organizar repeticiones y seguir el estado. Se puede leer más sobre "Celery", por ejemplo, .
Además, la facturación no detuvo el proyecto cuando se acabaron los fondos. Al hablar con los desarrolladores, descubrimos que al calcular la estadística (y necesitamos implementar exactamente esta lógica) hay una compleja interrelación de las reglas de detención. Pero estos modelos no se ajustan bien a nuestra realidad. También lo implementamos a través de tareas en Celery, llevando la lógica de gestión de servicios al backend.
Ambos problemas mencionados anteriormente llevaron a que el código se inflara un poco y en el futuro tendremos que hacer refactorización para separar la lógica del trabajo con las tareas en un servicio independiente. También necesitamos almacenar parte de la información sobre los usuarios y sus servicios en nuestras tablas para mantener esta lógica.
Otro problema es el silencio.
A algunas solicitudes a la API, Billy simplemente responde "Ok". Por ejemplo, esto sucedió cuando realizamos ingresos de pagos prometidos durante la prueba (de la que hablaremos más adelante). Las solicitudes se ejecutaron correctamente y no vimos errores.

Tuve que estudiar los registros mientras trabajaba con el sistema a través de la interfaz de usuario. Resultó que la facturación realiza tales consultas modificando el ámbito a un usuario específico, como admin, pasando este como parámetro su.
En general, a pesar de las brechas en la documentación y algunos errores menores en la API, todo salió bastante bien. Los registros se pueden leer incluso bajo alta carga, si se entiende cómo están estructurados y qué se necesita buscar. La estructura de la base de datos es enrevesada, pero bastante lógica y en algunos aspectos incluso atractiva.
Por lo tanto, resumiendo, los principales problemas que enfrentamos en la etapa de interacción están relacionados con las peculiaridades de la implementación de un sistema específico:
- características no documentadas que nos afectaron de una forma u otra;
- código fuente cerrado (la facturación está escrita en C++), como consecuencia, la imposibilidad de resolver el problema 1 de ninguna manera, excepto mediante el 'método de prueba y error'.
Afortunadamente, el producto cuenta con una API bastante extensa y hemos integrado en nuestro panel personal los siguientes subsistemas:
- módulo de soporte técnico: las solicitudes desde el panel personal se 'proporcionan' a la facturación de manera transparente para los clientes del servicio;
- módulo financiero: permite emitir facturas a los clientes actuales, realizar deducciones y generar documentos de pago;
- módulo de gestión de servicios: para esto tuvimos que implementar nuestro propio procesador. La ampliabilidad del sistema jugó a nuestro favor y 'enseñamos' a Billy un nuevo tipo de servicio.
Tuve que dedicarle tiempo, pero de una forma u otra, creo que con Billy nos llevaremos bien.
Paseos por campos de tungsteno — Tungsten Fabric
Campos de tungsteno, cubiertos por cientos de cables que transportan miles de bits de información. La información se agrupa en 'paquetes', se analiza y se construyen rutas complejas, como por arte de magia.

Este es el dominio de un segundo sistema con el que tuvimos que familiarizarnos — Tungsten Fabric (TF), anteriormente OpenContrail. Su misión es gestionar el hardware de red, proporcionando una abstracción programática a nosotros, los usuarios. TF — SDN, encapsula una lógica compleja para trabajar con el hardware de red. Hay un buen artículo sobre la tecnología en sí, por ejemplo, .
El sistema está integrado con OpenStack (del cual hablaremos más adelante) a través del plugin de Neutron.

Interacción de los servicios de OpenStack.
Este sistema fue presentado por los chicos del departamento de operaciones. Utilizamos la API del sistema para gestionar el stack de red de nuestros servicios. Hasta ahora, no hemos tenido serios problemas o inconvenientes con él (no me atrevo a hablar por los chicos de Operaciones), aunque ha habido algunos curiosos malentendidos en la interacción.
El primero se veía así: los comandos que requerían la salida de una gran cantidad de datos en la consola de la instancia al conectarse por SSH simplemente «colgaban» la conexión, mientras que por VNC todo funcionaba correctamente.

Para quienes no están familiarizados con el problema, esto resulta bastante divertido: ls /root funciona correctamente, mientras que, por ejemplo, top se «congela» por completo. Afortunadamente, ya habíamos enfrentado problemas similares. Se resolvió ajustando el MTU en la ruta desde los nodos de computación hasta los enrutadores. Cabe decir que esto no representa un problema para TF.
El siguiente problema estaba a la vuelta de la esquina. En un «hermoso» momento, la magia del enrutamiento desapareció, así, de la nada. TF dejó de gestionar el enrutamiento en el hardware.

Trabajamos con OpenStack desde el nivel de admin y después pasamos al nivel de usuario requerido. SDN, al parecer, «intercepta» el alcance del usuario con el que se realizan las acciones. El problema es que esta misma cuenta de administrador se utiliza para la comunicación entre TF y OpenStack. En el paso de cambiar al usuario, la «magia» desaparecía. Se decidió crear una cuenta separada para trabajar con el sistema. Esto permitió trabajar sin romper la funcionalidad de integración.
Formas de vida de silicona — OpenStack
Una entidad de silicona de forma peculiar habita cerca de los campos de tungsteno. Se parece más a un niño gigante que con un solo movimiento podría aplastarnos, pero no emite agresión evidente. No causa miedo, pero su tamaño inspira inquietud. Al igual que la complejidad de lo que ocurre a su alrededor.

OpenStack es el núcleo de nuestra plataforma.
OpenStack cuenta con varios subsistemas, de los cuales hasta ahora hemos utilizado más activamente Nova, Glance y Cinder. Cada uno tiene su propia API. Nova se encarga de los recursos de computación y la creación de instancias, Cinder gestiona volúmenes y sus instantáneas, Glance es el servicio de imágenes que maneja las plantillas del sistema operativo y la meta información relacionada.
Cada servicio se ejecuta en un contenedor, y el broker de mensajes es el «conejo blanco» — RabbitMQ.
Este sistema nos ha presentado más problemas inesperados.
Y el primer problema no tardó en aparecer cuando intentamos conectar un volumen adicional al servidor. La API de Cinder se negó a llevar a cabo esta tarea. Más bien, si creemos en OpenStack, la conexión se establece, pero dentro del servidor virtual el dispositivo de disco está ausente.

Decidimos "tomar un desvío" y solicitamos la misma acción a la API de Nova. El resultado: el dispositivo se conecta correctamente y está disponible dentro del servidor. Parece que el problema surge cuando el almacenamiento en bloque no responde a Cinder.
Otra dificultad nos esperaba al trabajar con discos. No fue posible desconectar el volumen del sistema del servidor.
Una vez más, OpenStack "jura" que la conexión ha sido eliminada y ahora se puede trabajar correctamente con el volumen por separado. Pero la API se negaba categóricamente a realizar operaciones en el disco.

Aquí decidimos no pelear demasiado y cambiar nuestra perspectiva sobre la lógica de funcionamiento del servicio. Si hay una instancia, debe haber un volumen del sistema. Por lo tanto, el usuario no puede eliminar o desconectar el "disco" del sistema sin eliminar primero el "servidor".
OpenStack es un complejo sistema bastante complicado con su propia lógica de interacción y una API intrincada. Nos ayuda la documentación bastante detallada y, por supuesto, el método de prueba y error (¿cómo podría ser de otro modo?).
Ejercicio de prueba
Realizamos el ejercicio de prueba en diciembre del año pasado. El objetivo principal era verificar en modo real nuestro proyecto desde el punto de vista técnico y de experiencia de usuario (UX). La audiencia fue invitada de manera selectiva y la prueba fue cerrada. Sin embargo, también dejamos la posibilidad de solicitar acceso a la prueba en nuestro sitio web.
La prueba, por supuesto, no estuvo exenta de momentos curiosos, ya que nuestras aventuras apenas comienzan.
En primer lugar, subestimamos el interés en el proyecto y tuvimos que agregar nodos de computación rápidamente durante la prueba. Un caso habitual para un clúster, aunque también hubo matices. En la documentación para la versión específica de TF se indica una versión específica del núcleo, en la que se probó el trabajo con vRouter. Decidimos lanzar nodos con núcleos más recientes. Como resultado, TF no recibió rutas de los nodos. Tuvimos que revertir los núcleos de emergencia.

Otro momento curioso está relacionado con la funcionalidad del botón "cambiar contraseña" en el panel de usuario.
Decidimos utilizar JWT para organizar el acceso al panel personal, para no trabajar con sesiones. Dado que los sistemas son diversos y están ampliamente distribuido, gestionamos nuestro propio token, en el que "envuelvemos" las sesiones del billing y el token de OpenStack. Al cambiar la contraseña, el token, por supuesto, "caduca", ya que los datos del usuario ya no son válidos y necesita ser reemitido.

Pasamos por alto este aspecto y no tuvimos recursos para escribir este fragmento rápidamente. Tuvimos que recortar funcionalidad justo antes del lanzamiento de la prueba.
Actualmente estamos desconectando al usuario si se cambia la contraseña.
A pesar de estos matices, las pruebas transcurrieron bien. Durante un par de semanas, alrededor de 300 personas nos visitaron. Pudimos ver el producto desde la perspectiva de los usuarios, probarlo en acción y recopilar comentarios de calidad.
Continuará
Para muchos de nosotros, este es el primer proyecto de tal magnitud. Hemos aprendido varias lecciones valiosas sobre cómo trabajar en equipo, tomar decisiones arquitectónicas y de diseño. Cómo integrar sistemas complejos con recursos limitados y lanzarlos a producción.
Por supuesto, hay mucho que mejorar tanto en el código como en las interfaces de integración de sistemas. El proyecto es bastante joven, pero estamos llenos de ambición para convertirlo en un servicio confiable y conveniente.
Ya hemos conseguido convencer a los sistemas. Bill se encarga obedientemente de los cálculos, la emisión de facturas y las solicitudes de usuarios en su pequeño espacio. La "magia" de los campos de tungsteno nos proporciona una conexión estable. Y solo OpenStack a veces se comporta de manera caprichosa, gritando algo así como "'WSREP no ha preparado aún el nodo para el uso de la aplicación". Pero esa es una historia completamente diferente...
Hace poco lanzamos el servicio.
Puedes encontrar todos los detalles en nuestro .

Equipo de desarrollo de CLO
Enlaces útiles
OpenStack
Tungsten Fabric
Fuente: habr.com
