
Hola Habr! Mi nombre es Dmitry, soy desarrollador en ISPsystem. Recientemente, lanzamos en versión beta una nueva versión del panel de control de la máquina virtual. Hoy les contaré cómo decidimos qué tomar de un producto antiguo y qué es mejor rechazar. Revisaré los problemas más importantes para nosotros: una biblioteca para trabajar con libvirt, soporte para varios sistemas operativos durante la instalación del producto, la transición de monolitos a microservicios y la implementación de máquinas virtuales.
El artículo trata sobre
VMmanager . Este es un sistema para administrar, implementar y monitorear máquinas virtuales basadas en virtualización KVM y OVZ. La quinta generación salió en 2012. Desde entonces, la interfaz se ha vuelto muy desactualizada y la arquitectura centralizada ha impedido el desarrollo del producto. Es hora de hacer una nueva versión.
La primera historia Usamos el trabajo de los elfos domésticos
Trabaje con libvirt: considere opciones, seleccione bibliotecas
Como herramienta para administrar la virtualización de KVM, nuestro producto usa libvirt. En 2012, se eligió una biblioteca escrita en C para trabajar con ella, por lo que era más conveniente para ese equipo de desarrollo. Como resultado, una gran cantidad de código escrito en C ++, que llama a la biblioteca C, que implementa el trabajo directo con libvirt.
Y ahora, en el umbral de un nuevo proyecto, miramos hacia atrás y examinamos nuestro producto, evaluamos si vale la pena tomar una solución / tecnología en particular; lo que ha demostrado y lo que necesita ser recordado y nunca repetido.
Nos sentamos y hacemos una retrospectiva de muchos años de trabajo en la versión anterior del producto. Somos pacientes, tomamos calcomanías y escribimos tres tipos de hojas de papel:
- ¿Qué tuvo éxito en el producto? ¿Qué elogiaron los usuarios? ¿Qué nunca has escuchado quejas? ¿Qué te gustó a ti mismo?
- ¿Qué falló? ¿Cuáles fueron los problemas constantemente? ¿Qué obstaculizó el trabajo y por qué comenzaron una nueva sucursal?
- ¿Qué se puede cambiar? ¿Qué piden los usuarios? ¿Qué quieren cambiar los miembros del equipo?
El grupo de personas que estropea celosamente el papel debe incluir tanto a aquellos que han estado en contacto cercano con el producto durante siglos, como a aquellos que pueden tener una nueva visión del producto. No olvide la Solicitud de funciones y el gerente de producto. Las pegatinas ya hechas están pegadas al tablero, definitivamente nos ayudarán.

De vuelta a la historia. Examinamos un fragmento de código donde el estándar C ++ 98 coexiste pacíficamente con las llamadas de la biblioteca C. Recordamos que 2018 es el año y decidimos dejarlo solo. Pero, ¿cómo repetir la funcionalidad de trabajar con máquinas virtuales (VM), haciendo que el código sea más compacto y conveniente para el trabajo?
Estudiamos el problema, entendemos que no importa qué solución y en qué idioma elijamos, será un contenedor sobre la biblioteca C. Como una opción interesante, vale la pena señalar la
biblioteca en Go desde DigitalOcean , utiliza el protocolo RPC para comunicarse directamente con libvirt, pero tiene sus inconvenientes. Nos instalamos en la
biblioteca Python .
Como resultado, obtuvimos la velocidad de escribir código, facilidad de uso y lectura. Vale la pena explicar estas hermosas palabras.
- Velocidad . Ahora podemos crear rápidamente un prototipo de una determinada parte del trabajo con el dominio directamente desde la consola en el servidor de depuración, sin reconstruir la aplicación principal.
- Simplicidad En lugar de llamar a muchos métodos de C ++ en un determinado controlador, tenemos una llamada de secuencia de comandos Python con paso de parámetros.
- La depuración también es lo más rápida e indolora posible. En mi opinión, a la larga esto puede llevar una experiencia de usuario interesante. Imagínese, el administrador del sistema, descontento de que sus máquinas virtuales estén esperando un apagado antes de destruir, va y redefine el script para el método host_stop.
¿Puedo también escribir un panel para ti?
Como resultado, obtuvimos una herramienta simple y conveniente para trabajar con máquinas virtuales a nivel de servidor.
La segunda historia. Un producto bien embalado no necesita caricias adicionales
Distribución del producto: rechazamos muchos paquetes y pasamos a Docker

VMmanager 5 se distribuye como un conjunto de paquetes de Linux. CentOS 6/7 y, hasta hace poco, Debian 7 son compatibles ¿Qué significa esto? Esto significa más servidores de compilación para CI / CD, más pruebas, más atención al código. Debemos recordar que cuando en el repositorio oficial de CentOS 7 qemu versión 1.5.3, en CentOS 6 es 0.12.1. Al mismo tiempo, el usuario puede usar repositorios en los que la versión de este paquete es mucho más alta. Esto significa que debe admitir diferentes versiones de api cuando trabaje con máquinas virtuales, en particular, durante la migración. Debemos recordar la diferencia entre inicializadores (init, systemd), tener en cuenta la diferencia en los nombres de paquetes y utilidades. Las utilidades que funcionan en CentOS no funcionarán en Debian, o sus versiones en los repositorios oficiales varían ampliamente. Para cada inserción, debe recopilar paquetes para todas las versiones, y es aconsejable no olvidar probarlos también.
Todo esto en el nuevo producto no nos conviene. Para no admitir una lógica diferente, abandonamos varios sistemas y dejamos solo CentOS 7. ¿Se resolvió el problema? En realidad no
Tampoco queremos verificar la versión del sistema operativo antes de la instalación, si las utilidades necesarias están disponibles, qué reglas están instaladas en SELinux, y no queremos reconfigurar el firewall y las listas de repositorios. Me gustaría una vez, y eso es todo, haciendo clic para
destruir cada segundo para implementar todo el entorno y el producto en sí. Se dice: hecho, el proyecto está envuelto en un contenedor acoplable.
Ahora es suficiente hacer:
El panel está en funcionamiento.
Por supuesto, estoy exagerando, el usuario debe instalar Docker por sí mismo, y tenemos más de un contenedor, y actualmente VMmanager se ejecuta en modo enjambre como un servicio SaaS. Sobre lo que encontramos al elegir Docker y cómo resolverlo, puede escribir un artículo por separado.
El hecho en sí mismo es lo importante que es simplificar el desarrollo, y lo más importante, la implementación de su producto, install.sh, que una vez ocupó
2097 líneas .
Como resultado:
- Un entorno de instalación de producto homogéneo simplifica el código del programa y reduce los costos de montaje y prueba.
- La distribución de la aplicación como un contenedor acoplable hace que la implementación sea simple y predecible.
La tercera historia. Primera relación con microservicios.
Arquitectura: abandonamos el monolito en favor de microservicios, o no

La quinta versión del producto es un gran sistema monolítico con el estándar C ++ obsoleto. Como resultado, la implementación problemática de nuevas tecnologías y la dificultad de refactorizar el código heredado, escalado horizontal deficiente. En la nueva sucursal, decidieron utilizar el enfoque de microservicio como una de las formas de evitar tales problemas.
Los microservicios son una tendencia moderna que tiene ventajas y desventajas. Intentaré presentar mi visión de las fortalezas de esta arquitectura y hablar sobre la solución de los problemas que trae al proyecto. Vale la pena señalar que este será el primer vistazo a la arquitectura de microservicios en la práctica desde el lado de un desarrollador ordinario. Los aspectos que probablemente no mencionaré están cubiertos en un
buen artículo de revisión .
Lado positivo
El pequeño servicio brinda muchas oportunidades.Además de la conveniencia de escribir, probar y depurar, los microservicios introdujeron un nuevo lenguaje de programación para el proyecto. Cuando su proyecto es un monolito, es difícil imaginar que algún día tratará de reescribir parte de él en otro idioma que le interese. En arquitectura de microservicios, por favor. Además del lenguaje de programación, también puede probar nuevas tecnologías, con la única advertencia de que todo esto estará justificado para el negocio. Por ejemplo, escribimos algunos de los microservicios en Golang, mientras ahorramos una buena cantidad de tiempo.
Escalado del equipoPodemos dividir a muchas personas que solían comprometerse con un repositorio e intentaron mantener la estructura del monolito en su cabeza en varios equipos. Cada equipo se dedicará a su servicio. Además, la entrada de una nueva persona en el trabajo es mucho más simple y rápida, debido al contexto limitado en el que trabajará. Por otro lado, hay menos personas que agregan conocimiento mundial, y siempre se puede conocer cualquier aspecto de un sistema enorme. Quizás con el tiempo reconsidere mi actitud a este punto.
Degradación independienteAtribuiría la degradación independiente a los lados positivo y negativo de los microservicios, porque ¿quién necesita su aplicación si, por ejemplo, se encuentra un servicio de autorización? Sin embargo, esto sigue siendo un lado positivo. Anteriormente, la recopilación de estadísticas de varios cientos de máquinas virtuales hacía que nuestro monolito trabajara duro, en el momento de la carga máxima, la espera para que la solicitud de un usuario aumente aumentó significativamente. Un servicio de recopilación de estadísticas separado puede recopilarlo sin afectar a otros servicios, mientras que aún puede escalarse agregando nuevo hardware o aumentando el número de recopiladores de las mismas estadísticas. E incluso podemos seleccionar un servidor separado para Graphite, donde este servicio registra estadísticas. Con un monolito, donde hay una base, esto es imposible.
Lado negativo
Contexto de solicitudToda mi depuración en el monolito se redujo a dos consultas en la consola:
Hecho Puedo rastrear toda la solicitud, desde su recepción hasta el sistema hasta que se produzca un error.
Pero, ¿qué pasa ahora, cuando la solicitud viaja del microservicio al microservicio, acompañada de llamadas adicionales a los servicios y registros vecinos en varias bases de datos? Para hacer esto, implementamos información de solicitud, que contiene el identificador de solicitud e información sobre el usuario o servicio que la produjo. Por lo tanto, se hace más fácil rastrear toda la cadena de eventos, pero el deseo es escribir un servicio de agregación de registros, porque, después de todo, tenemos una arquitectura de microservicio. También puede mirar hacia Elasticsearch, este problema está abierto y se resolverá pronto.
Inconsistencia de datosLos datos en microservicios están descentralizados, no existe una base de datos única en la que se almacene toda la información. Reflexionando sobre este artículo, revisé las principales interacciones entre microservicios en mi mente, donde podemos obtener duplicados, donde usamos transacciones entre redes, y me di cuenta de que resolvimos el problema de la inconsistencia con un monolito.
Realmente construimos un monolito con una base principal, envolviendo la mayoría de las acciones transaccionales en él. Y alrededor del monolito se recopilaron todos los microservicios que no afectan la consistencia de los datos principales. La excepción es un montón de autorización de servicio + monolito. El problema en este caso es que la base de datos de la aplicación base no contiene usuarios como tales, sus roles y parámetros adicionales, todo esto está en el servicio de autorización.
El usuario del sistema puede trabajar con máquinas virtuales en un monolito, mientras que en el servicio de autorización sus derechos pueden cambiar o quedará completamente bloqueado. El sistema debe responder a esto de manera oportuna. En esta situación, la consistencia de los datos se logra al verificar los parámetros del usuario antes de ejecutar cualquier solicitud.
En cuanto a los microservicios restantes, la imposibilidad de registrarse en el servicio de estadísticas no afecta el funcionamiento de la máquina virtual, y esta acción siempre se puede repetir. Bueno, estamos haciendo un microservicio de recopilación de estadísticas. Pero el servicio de dominio definido (crear una máquina virtual usando libvirt) nunca verá la luz, ya que quién necesita un espacio en blanco de la máquina sin su existencia real.
La cuarta historia. Fresco es enemigo de lo bueno
Implementación de VM: instalación desde imágenes en lugar de instalación sobre una red
En la quinta versión del producto, el despliegue de una máquina virtual lleva bastante tiempo según los estándares reales. La razón de esto es instalar el sistema operativo en la red.
Para Centos, Fedora, RedHat es el
método kickstart :
1. Cree un archivo kickstart.
2. Especifique el enlace al archivo de respuesta en los parámetros del kernel linux inst.ks = <enlace al archivo kickstart>.
3. Ejecute la instalación kickstart.
Kickstart-file es bastante flexible, en él puede describir todos los pasos de la instalación, comenzando por su método y configurando la zona horaria, terminando con la partición del disco y configurando la red. El parámetro url en nuestras plantillas indica que la instalación es desde un servidor remoto.
Para Debian y Ubuntu, el método
preestablecido :
Es similar al anterior, este método también se basa en el archivo de configuración y sus contenidos. En él, también configuramos la instalación a través de la red.
La instalación de FreeBSD es similar, pero en lugar de un archivo kickstart, hay un script de shell de nuestra propia producción.
Aspectos positivos del enfoque.
Esta opción de instalación le permite utilizar una plantilla en nuestros dos productos: VMmanager y
DCImanager (gestión de servidores dedicados).
La implementación de máquinas virtuales es bastante flexible, el administrador del panel puede simplemente copiar la plantilla del sistema operativo y cambiar el archivo de configuración como lo considere conveniente.
Todos los usuarios siempre tienen versiones actualizadas de los sistemas operativos si se actualizan de manera oportuna en un servidor remoto.

Lado negativo
Como ha demostrado la práctica, los usuarios de VMmanager no necesitaban flexibilidad de instalación: en comparación con los servidores dedicados, pocas personas se preocupaban por la configuración específica de los archivos kickstart para máquinas virtuales. Pero esperar la instalación del sistema operativo fue realmente un lujo inadmisible. La otra cara de la relevancia de los sistemas operativos es que parte del instalador está en la red y parte es local para
initrd . Y sus versiones deben coincidir.
Estos son problemas solucionables. Puede crear un grupo de máquinas instaladas y crear su propio repositorio para sistemas operativos, pero esto conlleva costos adicionales.
¿Cómo resolver estos problemas sin crear repositorios y grupos? Seleccionamos archivos de imagen del sistema operativo. Ahora el proceso de instalación se ve así:
1. Copiar la imagen del sistema operativo en el disco de la máquina virtual.
2. Aumente la sección principal de la imagen en el tamaño del espacio libre después de la copia.
3. Configuración básica (configuración de una contraseña, zona horaria, etc.).
Todo lo nuevo está bien olvidado de lo viejo. Utilizamos imágenes del sistema operativo en VDSmanager-Linux, el progenitor de VMmanager.
Pero, ¿qué pasa con la flexibilidad de instalación? La práctica ha demostrado que la mayoría de los usuarios no están interesados en configuraciones de red específicas y mapeo de disco en máquinas virtuales.
¿Y la relevancia de los datos? Se puede lograr mediante la presencia de imágenes con las últimas versiones del sistema operativo en el repositorio, y se pueden instalar actualizaciones menores en el script de configuración inicial. Por lo tanto, la máquina virtual ya estará creada y ejecutándose, y yendo a ella, encontrará la actualización yum condicional ejecutándose.
A cambio, obtenemos una máquina virtual lista para usar, cuya implementación depende solo de copiar el disco, aumentar la partición del disco e iniciar el sistema operativo. La implementación de este enfoque para trabajar con máquinas nos da la oportunidad de crear nuestras propias imágenes y compartirlas. El usuario puede instalar un paquete
LAMP o algún entorno complejo en la máquina virtual, luego hacer una imagen de esta máquina. Ahora, otras personas no tendrán que perder el tiempo instalando las utilidades necesarias.
Implementamos la configuración y modificación de particiones usando las utilidades de la
suite libguestfs . Por ejemplo, cambiar una contraseña en una máquina Linux cambió de 40 líneas de código, que consisten en mount, chroot y usermod, en una sola línea:
command = "/usr/bin/virt-customize --root-password password:{password} --domain '{domain_name}'".format(password=args.password, domain_name=args.domain_name)
Como resultado, hicimos que la máquina virtual terminada fuera lo más rápida posible. Vale la pena hacer un comentario de que con la configuración de la red y la instalación de scripts internos, el tiempo de implementación ha aumentado ligeramente. Resolvimos este problema mostrando los pasos de instalación en el extremo frontal, completando así la pausa formada entre la creación y la preparación completa de la máquina.
También obtuvimos un enfoque más flexible para implementar máquinas virtuales, en función del cual es conveniente crear sus propias imágenes con el entorno necesario.
¿Qué lograste hacer?
En la sexta versión del producto, tratamos de tener en cuenta el principal inconveniente de la quinta: la complejidad de la interacción del usuario con el producto. Hemos reducido el tiempo de entrega de acciones clave. Junto con una interfaz sin bloqueo, esto permite trabajar con el panel sin una espera forzada. La contenedorización ha hecho que el proceso de instalación del producto sea más fácil y más conveniente. El uso de tecnologías modernas y varios lenguajes de programación ha simplificado el soporte y el mantenimiento tanto para programadores como para especialistas en soporte técnico. El cambio a microservicios permitió agregar nuevas funciones rápidamente y con restricciones menores.
En conclusión, quiero decir que el nuevo producto es una buena oportunidad para probar otros enfoques de desarrollo, nuevas tecnologías. Vale la pena recordar por qué está haciendo esto, qué cosas nuevas traerá a usted y a sus usuarios. ¡A por ello!
Invitamos a la comunidad Habr a ver la versión beta de VMmanager 6 y dejar sus comentarios. Para hacer esto, vaya a my.saasvm.com , inicie sesión y conecte un servidor dedicado (CentOS 7 x64, acceso a Internet, dirección IP pública).
Si no tiene un servidor, escríbanos a help@ispsystem.com o chatee en el sitio , le proporcionaremos equipos de prueba de nuestro socio, Selectel.
Lea más en las noticias en el sitio web del ISPsystem .