
Un día, decidí escribir un artículo sobre la entrega de los paquetes Docker y Deb en forma de contenedores, pero cuando comencé, por alguna razón sufrí en los días lejanos de las primeras computadoras personales e incluso calculadoras. En general, en lugar de comparaciones secas de docker y deb, estos son los pensamientos sobre la evolución, que presento a su corte.
Cualquier producto, sea lo que sea, debe llegar de alguna manera a los servidores del producto, debe configurarse y lanzarse. Este artículo será sobre esto.
Reflexionaré en el contexto histórico, "lo que veo, lo que canto", lo que vi cuando comencé a escribir código y lo que estoy observando ahora, lo que nosotros mismos usamos en este momento y por qué. El artículo no pretende ser un estudio completo, faltan algunos puntos, esta es mi opinión personal de lo que fue y lo que es ahora.
Entonces, en los viejos tiempos ... el primer método de entrega que encontré fue con casetes de cinta. Tenía una computadora BK-0010.01 ...
La edad de las calculadoras
No, hubo un punto anterior, también hubo una calculadora
MK-61 y
MK-52 .

Entonces, cuando tenía
MK-61 , la forma de transferir el programa era usar un trozo de papel normal en una caja en la que se grabó el programa, que, si era necesario, se escribió manualmente en la calculadora. Si quieres jugar (sí, incluso había juegos en esta calculadora antediluviana), siéntate e ingresa el programa en la calculadora. Naturalmente, cuando se apagó la calculadora, el programa quedó en el olvido. Además de los códigos de calculadora escritos personalmente en papel, los programas se publicaron en las revistas Radio and Technique of Youth, así como en libros de esa época.
La siguiente modificación fue la calculadora
MK-52 , ya parecía un tipo de almacenamiento de datos no volátil. Ahora el juego o programa no tenía que ser manejado manualmente, pero, después de hacer algunos pases mágicos con botones, se cargó solo.
El volumen del programa más grande en la calculadora fue de 105 pasos, y el tamaño de la memoria permanente en el MK-52 fue de 512 pasos.
Por cierto, si hay fanáticos de estas calculadoras que están leyendo este artículo, en el proceso de escribir el artículo, encontré un emulador de calculadora para Android y un programa para él. ¡Adelante al pasado!
Una pequeña digresión sobre MK-52 (de Wikipedia)
MK-52 voló al espacio en la nave espacial Soyuz TM-7. Se suponía que debía usarse para calcular la trayectoria de aterrizaje en caso de que la computadora a bordo falle.
El MK-52 con la unidad de expansión de memoria "Electronics-Astro" desde 1988 se suministró a los barcos de la Armada como parte de un kit de computación de navegación.
Las primeras computadoras personales

Volvamos a los tiempos de
BK-0010 . Está claro que había más memoria allí, y ya no era una opción para manejar el código de una hoja de papel (aunque al principio lo hice, porque simplemente no había otro medio). Los principales medios de almacenamiento y entrega de software son casetes de audio para grabadoras.

El almacenamiento en un cassette generalmente tenía la forma de uno o dos archivos binarios, todo lo demás estaba contenido dentro. La fiabilidad era muy baja, tuve que guardar 2-3 copias del programa. El tiempo de carga tampoco fue feliz, los entusiastas experimentaron con diferentes codificaciones de frecuencia para superar estas deficiencias. En ese momento, yo todavía no había participado en el desarrollo de software profesional (aparte de los programas básicos simples), por lo tanto, desafortunadamente, no le diré en detalle cómo se organizó todo dentro. El hecho de tener solo RAM en la computadora en su mayor parte determinó la simplicidad del esquema de almacenamiento de datos.
La aparición de medios de almacenamiento confiables y grandes
Más tarde, aparecen los disquetes, el proceso de copia se simplifica y la confiabilidad está creciendo.
Pero la situación cambia dramáticamente solo cuando aparecen almacenamientos locales suficientemente grandes en forma de HDD.
El tipo de entrega cambia fundamentalmente: aparecen los instaladores que controlan el proceso de configuración del sistema, así como la limpieza después de la eliminación, ya que los programas no solo se leen en la memoria, sino que ya se copian en el almacenamiento local, desde el cual debe poder borrar e innecesario si es necesario.
Al mismo tiempo, aumenta la complejidad del software suministrado.
El número de archivos en la entrega aumenta de unidades a cientos y miles, los conflictos de versiones de biblioteca y otras alegrías comienzan cuando diferentes programas usan los mismos datos.

En aquellos días, la existencia de Linux aún no estaba abierta para mí, vivía en el mundo de MS DOS y, más tarde, en Windows, y escribía en Borland Pascal y Delphi, a veces mirando hacia C ++. Para suministrar productos en esos días, muchos utilizaron InstallShield
ru.wikipedia.org/wiki/InstallShield , que resolvió con bastante éxito todas las tareas de implementación y configuración de software.
Era de internet
Gradualmente, la complejidad de los sistemas de software se vuelve aún más complicada, desde un monolito y aplicaciones de escritorio hay una transición a sistemas distribuidos, clientes ligeros y microservicios. Ahora necesita configurar no solo un programa, sino su conjunto, y para que sean amigos todos juntos.
El concepto ha cambiado por completo, ha llegado Internet, ha llegado la era de los servicios en la nube. Hasta ahora, solo se interpreta en la etapa inicial, en forma de sitios, nadie soñaba especialmente con los servicios. pero este fue un punto de inflexión en la industria tanto del desarrollo como de la entrega real de aplicaciones.
Por mi parte, noté que en este momento hubo un cambio en las generaciones de desarrolladores (o solo en mi entorno), y tuve la sensación de que todos los buenos métodos de entrega antiguos se olvidaron en un momento y todo comenzó desde el principio: comenzaron a hacer la entrega completa con guiones hasta la rodilla y orgullosamente lo llamaron "Entrega continua". De hecho, comenzó un período de caos, cuando lo viejo se olvida y no se usa, pero simplemente no hay nada nuevo.
Recuerdo los momentos en que en nuestra empresa, donde trabajaba en ese momento (no llamaré), en lugar de construir a través de hormigas (Maven no era popular todavía o no lo era en absoluto), las personas simplemente recolectaban jar en IDE y se comprometían él en svn. En consecuencia, la implementación consistía en obtener el archivo de SVN y copiarlo a través de SSH en la máquina deseada. Tan simple y torpe.
Al mismo tiempo, la entrega de sitios simples a PHP se hizo bastante primitiva simplemente copiando el archivo corregido a través de FTP a la máquina de destino. A veces no existía tal cosa: el código se editaba en vivo en el servidor del producto, y era especialmente elegante si había copias de seguridad en alguna parte.
Paquetes RPM y DEB

Por otro lado, con el desarrollo de Internet, los sistemas similares a UNIX comenzaron a ganar más y más popularidad, en particular, fue en ese momento que descubrí RedHat Linux 6 por mí mismo, alrededor del año 2000. Naturalmente, había ciertas herramientas para la entrega de software allí, según Wikipedia, RPM como el administrador principal de paquetes apareció ya en 1995, en la versión de RedHat Linux 2.0. Y desde entonces hasta ahora, el sistema se ha entregado en forma de paquetes RPM y existe y se desarrolla con bastante éxito.
Las distribuciones de la familia Debian siguieron un camino similar e implementaron la entrega en forma de paquetes deb, que también se ha modificado hasta el día de hoy.
Los administradores de paquetes le permiten entregar los productos de software ellos mismos, configurarlos durante el proceso de instalación, administrar dependencias entre diferentes paquetes, eliminar productos y limpiar el exceso durante la desinstalación. Es decir en su mayor parte, esto es todo lo que se necesita, por lo que duraron varias décadas con poco o ningún cambio.
Se agregaron nubes a la instalación de los administradores de paquetes no solo desde medios físicos, sino también desde repositorios en la nube, sino que básicamente, poco ha cambiado.
Vale la pena señalar que en la actualidad hay algunos escalofríos para evitar deb y cambiar a paquetes instantáneos, pero más sobre eso más adelante.
Entonces, esta nueva generación de desarrolladores en la nube, que no conocía DEB ni RPM, también creció lentamente, ganó experiencia, los productos se volvieron más complicados y se necesitaban métodos de entrega más razonables que FTP, scripts de bash y trabajos similares de estudiantes.
Y aquí Docker entra en escena, una especie de mezcla de virtualización, asignación de recursos y métodos de entrega. Ahora está de moda, juventud, pero ¿se necesita para todo? ¿Es una panacea?
Según mis observaciones, muy a menudo se ofrece Docker no como una opción razonable, sino simplemente porque, por un lado, se habla en la comunidad, y aquellos que lo ofrecen solo lo saben. Por otro lado, en su mayor parte guardan silencio sobre los viejos y buenos sistemas de embalaje: son y son, están haciendo su trabajo de manera silenciosa e imperceptible. En tal situación, no hay otra opción, la opción es obvia, Docker.
Trataré de compartir mi experiencia sobre cómo implementamos Docker y lo que sucedió como resultado.
Escrituras autoescritas
Inicialmente, había scripts de bash que implementaban archivos jar en las máquinas necesarias. Gestionó este proceso por Jenkins. Esto funcionó con éxito, ya que el archivo jar ya es un ensamblaje que contiene clases, recursos e incluso configuración. Si pone todo al máximo, luego amplíelo con un script, esto no es lo más difícil que necesita
Pero los guiones tienen varios inconvenientes:
- los scripts generalmente se escriben con prisa y, por lo tanto, son tan primitivos que contienen solo uno de los scripts más exitosos. Esto se ve facilitado por el hecho de que el desarrollador está interesado en una entrega rápida, y un script normal requiere una cantidad decente de recursos.
- Como consecuencia del párrafo anterior, los scripts no contienen el procedimiento de desinstalación
- sin procedimiento de actualización establecido
- cuando aparece un nuevo producto, debe escribir un nuevo script
- sin soporte de dependencia
Por supuesto, puedes escribir un script elegante, pero, como escribí anteriormente, este es el tiempo de desarrollo, y no el más pequeño, pero, como sabes, siempre no hay suficiente tiempo.
Obviamente, todo esto limita el alcance de este método de implementación a los sistemas más simples. Ha llegado el momento de cambiar esto.
Docker

En algún momento, los medios recién horneados comenzaron a llegar a nosotros, llenos de ideas y delirando con un estibador. Bueno, la bandera en la mano, ¡hazlo! Hubo dos intentos. Ambos fracasaron, digamos que sí, debido a las grandes ambiciones, pero a la falta de experiencia real. ¿Era necesario forzar y terminar de alguna manera? Es poco probable: el equipo debe crecer evolutivamente al nivel deseado antes de poder usar las herramientas adecuadas. Además de eso, al usar imágenes listas para usar de la ventana acoplable, a menudo nos encontramos con el hecho de que la red funcionaba incorrectamente allí (que, tal vez, también estaba conectada con la humedad de la ventana acoplable) o que era difícil expandir los contenedores de otras personas.
¿Qué inconvenientes hemos encontrado?
- Problemas de red en modo puente
- Es inconveniente mirar los registros en el contenedor (si no se llevan por separado al sistema de archivos de la máquina host)
- Periódicamente extraño ElasticSearch se cuelga dentro del contenedor, la razón no se ha establecido, el contenedor es oficial
- Es incómodo usar la carcasa dentro del contenedor: todo está muy recortado, no hay herramientas familiares
- Grandes contenedores para recolectar - costosos de almacenar
- Debido al gran tamaño de los contenedores, es difícil admitir múltiples versiones
- Compilación más larga, a diferencia de otros métodos (scripts o paquetes deb)
Por otro lado, ¿es peor implementar un servicio Spring en forma de archivo jar a través de la misma deb? ¿Es realmente necesario el aislamiento de los recursos? ¿Vale la pena perder las herramientas convenientes del sistema operativo, llenando el servicio en un contenedor muy recortado?
Como la práctica ha demostrado, en realidad esto no es necesario, un paquete deb es suficiente en el 90% de los casos.
¿Cuándo sigue fallando el viejo deb y cuándo realmente necesitamos un acoplador?
Para nosotros, esta fue una implementación de servicios en Python. Se necesitaban muchas bibliotecas para el aprendizaje automático y no estaban disponibles en la entrega estándar del sistema operativo (y las versiones incorrectas), hacks con configuraciones, la necesidad de diferentes versiones para diferentes servicios que viven en el mismo sistema host condujo a que la única forma razonable de suministrar esta mezcla nuclear era acoplable. La complejidad de ensamblar el contenedor acoplable resultó ser menor que la idea de empaquetarlo todo en paquetes de Deb separados con dependencias, y nadie en su sano juicio lo habría tomado.
El segundo punto donde planea usar Docker es para implementar servicios utilizando el esquema de implementación azul-verde. Pero aquí quiero obtener un aumento gradual de la complejidad: primero, se recopilan los paquetes deb, y luego se ensambla un contenedor acoplable a partir de ellos.
Paquetes Snap

Volver a los paquetes de complemento. Primero aparecieron oficialmente en Ubuntu 16.04. A diferencia de los paquetes deb habituales y los paquetes rpm, snap transporta todas las dependencias. Por un lado, esto evita el conflicto de las bibliotecas, por otro lado, significa tamaños más significativos del paquete resultante. Además, lo mismo puede afectar la seguridad del sistema: en el caso de la entrega rápida, todos los cambios en las bibliotecas incluidas deben ser monitoreados por el desarrollador que crea el paquete. En general, no todo es tan simple y la felicidad general de su uso no llega. Pero, sin embargo, esta es una alternativa bastante razonable, si el mismo Docker se usa solo como un medio de empaquetado, y no como virtualización.
Como resultado, ahora usamos los paquetes deb y los contenedores docker en una combinación razonable, que, quizás, en algunos casos, reemplazaremos con paquetes snap.