¡Hola! Quiero hablar de por qué las grandes corporaciones tecnológicas están obsesionadas con crear soluciones patentadas para su infraestructura. La respuesta parece obvia: no es más que el síndrome NIH. Pero esta respuesta está lejos de ser completa, por no decir objetiva.
Soy el CTO del equipo de Ingeniería de Plataforma Yandex y nuestro objetivo es ayudar a los ingenieros a construir todo el ciclo de desarrollo, desde la escritura del código hasta los servicios operativos, para hacerlo más eficiente. Esto incluye la optimización de los procesos: no solo desarrollamos ofertas como servicio, sino que también ayudamos a implementarlas dentro de la empresa. Esto funciona a la escala de Yandex: nuestros servicios son utilizados por miles de desarrolladores en toda la empresa.
Para resolver un problema, a menudo desarrollamos herramientas patentadas en lugar de implementar herramientas ya preparadas. Por ejemplo, cuando todavía era programador en el equipo, trabajé en un sistema de monitoreo cuantitativo en C++ y Python y ayudé a escalarlo a decenas de miles de millones de métricas procesadas. Entonces, basándome en mi propia experiencia, sé qué motivaciones y vías de desarrollo conducen al surgimiento de herramientas internas: a continuación intentaré identificar las razones fundamentales de su creación utilizando nuestras soluciones como ejemplos.
Estableciendo la tarea. El objetivo de nuestra Runtime Cloud interna, o RTC, es proporcionar a los usuarios internos herramientas sencillas de implementación y gestión del tráfico. Los usuarios de RTC son los mismos ingenieros que desarrollan los servicios de Yandex. Y necesitan lanzar decenas de miles de aplicaciones que han creado en algún lugar, enviar solicitudes de usuarios allí, equilibrar la carga y gestionar incidencias, entre otras cosas.
La necesidad de una nube interna surgió a principios de la década de 2010, cuando el número de servicios ya era de cientos y el número total de núcleos asignados crecía decenas de por ciento al año. Tener servidores dedicados para cada servicio se volvió prohibitivamente costoso y necesitábamos herramientas que nos permitieran ejecutar aplicaciones desde múltiples servicios en un solo servidor. Al principio teníamos varios requisitos para estas herramientas:
Básicamente, necesitábamos Kubernetes (y, con el tiempo, RTC estuvo muy cerca). Pero aquí está el problema: k8s no se anunció hasta 2014. Apache Mesos existía en ese momento, pero estaba en su infancia.
Implementación de funciones básicas. Comenzamos a resolver el problema con una especie de MVP: un conjunto simple de herramientas, que se parecía más a un conjunto de bloques de construcción que automatizan acciones rutinarias, por ejemplo:
Con el tiempo, fue posible elaborar un gráfico de diseño de servicio completo utilizando estos componentes básicos (similar a la entrega continua). Después de un cierto número de iteraciones, en 2013 apareció Nanny, un sistema para gestionar servicios que se ejecutan en RTC.
Otro aspecto fundamental de Nanny fue la implementación del aislamiento de aplicaciones en función del consumo de recursos. Inicialmente lanzamos aplicaciones desde varios servicios sin aislamiento de recursos, lo que resultó en una gran cantidad de problemas operativos e incidentes.
En ese momento, las únicas soluciones listas para usar eran LXC, que para entonces ya había dejado de desarrollarse, y Docker, que no podía usar solo IPv6 y reiniciaba todos los contenedores al actualizar Dockerd, lo que hacía imposible actualizar Dockerd sin afectar al usuario. Como resultado, comenzamos a desarrollar nuestra
Resolver problemas de utilización. En ese momento, la gestión de recursos en la nube interna se lograba mediante confirmaciones en el repositorio. Sin embargo, esto ralentizó el desarrollo de Yandex y entró en conflicto con la tarea de aumentar la utilización: para solucionarlo, necesitábamos colocar nuestro sistema de reducción de mapas en las nubes, es decir,
Para llevar YTsaurus a RTC, se requería la capacidad de administrar pods dinámicamente en lugar de mediante confirmaciones del repositorio. Por eso, en 2018, creamos
Nuevos dolores de crecimiento. Durante el mismo período, k8s evolucionó hasta convertirse en una solución mucho más madura y se convirtió en uno de los servicios de AWS en 2017. Pero aún no cumplía con todos nuestros requisitos:
YTsaurus utilizó activamente la capacidad de crear contenedores Porto anidados en lugar de crear un único programador. Por supuesto, nosotros mismos podríamos agregar soporte para la misma pila dual en k8. Sin embargo, la experiencia en el desarrollo del kernel de Linux ha demostrado que no todo se puede enviar a código abierto, y nos esforzamos por mantener al mínimo el delta del kernel ascendente para simplificar la actualización a nuevas versiones.
Nuestra solución hoy. La arquitectura de RTC es muy similar a la de Kubernetes. El usuario describe declarativamente su servicio en forma de alguna especificación que describe cómo iniciar la aplicación especificada y en qué centros de datos. Cada centro de datos tiene su propia instalación de Yandex Planner, que sirve, por un lado, como base de datos para todos los objetos del clúster y, por otro, como programador de pods. Cada servidor en el centro de datos ejecuta un agente que recibe las especificaciones de los pods de Yandex Planner y las lanza utilizando nuestro sistema de contenedorización patentado Porto.
Actualmente, RTC ha lanzado decenas de miles de servicios, asignando más de 5 millones de núcleos a más de 100.000 servidores. Cada día se realizan más de 100.000 cambios en las especificaciones de servicio.
Planes. ¿Qué pasa si los k8 pueden soportar nuestra báscula? Especialmente porque el ecosistema k8s comenzó a superarnos en términos de funcionalidad en algún momento. ¿No sería mejor cambiar a k8 y esperar que las herramientas listas para usar eventualmente proporcionen el volumen que necesitamos? En la práctica, seguimos siendo un consumidor de nicho para k8 porque solo un pequeño porcentaje de empresas opera a tan gran escala, cada una de las cuales tiene sus propias soluciones en la nube internas.
Otro punto crítico a recordar es el tema migratorio. Según julio de 2018
En 2021, estimamos cuánto costaría pasar de un sistema de implementación a otro al elegir nuestra estrategia de desarrollo. La migración de Yandex a los k8 básicos sería una tarea extremadamente costosa, que costaría cientos de años-hombre.
De esta forma tan sencilla hemos acabado con nuestra nube interior, que difícilmente podremos abandonar en los próximos 5 años, incluso si nos fijamos ese objetivo.
¿Qué se debe hacer ante la falta de funcionalidad de la nube interna en comparación con los k8? En la práctica, nuestros clientes pueden utilizar Kubernetes administrado en Yandex Cloud. Esta opción se utiliza principalmente para proyectos donde se deben cumplir estrictos requisitos de cumplimiento; se trata de una pequeña proporción de equipos, menos del 1%. Por las razones expuestas anteriormente, el resto de la población no ve muchos beneficios en mudarse.
Al mismo tiempo, estamos analizando activamente los k8 y considerando cómo acercarnos a los estándares generalmente aceptados. Ya estamos experimentando activamente con k8 en algunas tareas, como el arranque en la nube o la organización de IaaC a escala de todo Yandex. Idealmente, nos gustaría reutilizar la interfaz k8s manteniendo nuestra propia implementación lo más adaptada posible a nuestras necesidades. Todo lo que queda es descubrir cómo hacerlo en la práctica.
Problemas y requisitos de solución . Nuestro monorepositorio, Arcadia, comparte el mismo objetivo principal que nuestra nube interna: proporcionar herramientas de desarrollo convenientes. Esto incluye todo un ecosistema de desarrollo en el caso del repositorio:
Arcadia surgió casi al mismo tiempo que la nube interna de Yandex. Una de las razones para la creación del monorepositorio fue la necesidad de reutilizar el código dentro de Yandex. Esto se vio obstaculizado en ese momento por la presencia de varios sistemas de construcción. Se requería un sistema unificado con soporte para compilaciones distribuidas eficientes para funcionar a escala de todo Yandex. También debe ser estable y utilizable.
Implementación de un sistema de construcción unificado. Nuestro sistema de compilación patentado ya make debutó en 2013, cuando era solo para código C++. Antes de crear, usamos CMake, pero su velocidad le impidió escalar a la escala de un monorepositorio. El propietario ya make funcionó mucho más rápido con Arcadia. No había otras opciones de código abierto que pudieran resolver nuestro problema: por ejemplo, Bazel se lanzó mucho más tarde, en 2015.
Escalado del sistema de control de versiones. Yandex utilizó anteriormente SVN como sistema de control de versiones. Aunque SVN tenía una gran capacidad, todavía era limitada y difícil de mantener. Además, éramos conscientes de que eventualmente nos encontraríamos con las limitaciones de las capacidades y conveniencia de SVN. Por ejemplo, se utilizaron heurísticas para implementar la capacidad de descargar solo la parte requerida del repositorio o el pago selectivo. Como resultado, en 2016 comenzamos a experimentar con otros sistemas de control de versiones además de SVN.
Mercurial fue la primera opción. Pero el principal problema que tuvimos fue la velocidad. Intentamos durante un año y medio poner Mercurial en producción, pero los resultados fueron decepcionantes. Por ejemplo, eventualmente tuvimos que reescribir partes de Mercurial para soportar FUSE, o hubiéramos tenido que llevar todo el repositorio a la computadora portátil de cada desarrollador.
Al final, resultó que era más barato escribir una solución interna desde cero y, en 2019, apareció Arc: un nuevo sistema de control de versiones para usuarios de Arcadia con una experiencia de usuario similar a Git. La base de Arc es FUSE (sistema de archivos en el espacio del usuario) en lugar del pago selectivo. Además, YDB actúa como una base de datos escalable, lo que simplifica enormemente el funcionamiento de Arc en comparación con Mercurial.
A menudo nos preguntan por qué no usamos git. Porque también tiene limitaciones de escala y funcionalidad: si solo importamos el tronco de Arcadia a git, el estado de git tardará unos minutos a esta escala. Al mismo tiempo, no existía una implementación estable de FUSE construida sobre git: VFS para Git ya no se está desarrollando y EdenFS finalmente se convirtió en Sapling, pero esto sucedió mucho más tarde.
Estado actual de la solución y planes para el futuro. Para comenzar el desarrollo, un usuario interno simplemente necesita crear una carpeta en nuestro monorepositorio, escribir código y decirle cómo construir su aplicación agregando el manifiesto de compilación. Como resultado, el usuario recibe solicitudes de extracción, configuración de CI y la capacidad de reutilizar cualquier código en la empresa.
En términos de escala, el tronco contiene actualmente 10 millones de archivos, el repositorio en su conjunto supera los 2 TiB y se realizan más de 30 mil confirmaciones cada semana.
Como resultado, en el ecosistema que creamos, debemos crear muchos componentes desde cero. Sin embargo, ahora está avanzando hacia el cumplimiento de los estándares globales. Arc, por ejemplo, admite trabajar con Git para un conjunto predefinido de proyectos.
Entonces, ¿por qué las grandes empresas tecnológicas tienen que inventar sus propias soluciones y por qué no pueden ser reemplazadas por otras que se adhieran a un estándar generalmente aceptado?
Innovación. Con frecuencia se exige a las grandes corporaciones que desarrollen soluciones a problemas que sólo se convertirán en algo común en el futuro. Así pueden surgir soluciones innovadoras con potencial para convertirse en estándares de mercado.
No siempre se da el caso de que un problema resuelto por una empresa se enfrente a alguien más que a la propia empresa. A veces, la experiencia de las grandes tecnologías con un problema específico ayuda a toda la industria a evitar ese problema al tomar un camino de desarrollo completamente diferente. No siempre es posible predecir el desarrollo del mercado y, como resultado, diferentes ejemplos de soluciones patentadas han tenido resultados muy diferentes.
ClickHouse es un ejemplo de un proyecto innovador verdaderamente exitoso que ha enriquecido enormemente el campo del procesamiento analítico en línea (OLAP). Sin embargo, este no es el caso para todos los proyectos. Porto, que comenzó como un proyecto de código abierto, no logró ganar terreno por diversas razones. Aunque algunas de sus características, como la capacidad de crear contenedores anidados, siguen siendo únicas.
Escala. Este punto es similar al anterior en algunos aspectos, porque no todas las empresas enfrentan el problema de la escalabilidad. Hubo un tiempo en el que 640 kbytes eran más que suficientes para todos, ¿no?
De hecho, el aumento exponencial de la carga del sistema fue una de las razones más importantes para el desarrollo de Arcadia y la nube interna. Por eso se desarrollaron Arc y Yandex Planner. Arc se creó en respuesta a la necesidad de un VCS fácil de usar que pueda permitir a los usuarios trabajar con un monorepositorio que contiene decenas de millones de archivos en un tronco sin dificultad. Yandex Planner se creó en respuesta a la necesidad de trabajar de forma eficaz con grupos de decenas de miles de nodos y millones de pods.
Las herramientas públicas siguen teniendo problemas de escala (después de todo, este es un escenario relativamente raro, e invertir en él con frecuencia simplemente no es rentable).
Inercia. Considere una herramienta interna que resuelva un problema dentro de una empresa. Una empresa que utilice activamente esta herramienta dedicaría recursos para adaptarla mejor a sus necesidades, transformándola eventualmente en una herramienta altamente especializada. Este proceso puede durar años.
Consideremos ahora la posibilidad de que, en algún momento, surja un estándar universalmente aceptado para resolver ese problema en particular. En este caso, la especialización puede seguir siendo un factor importante a la hora de decidirse por una solución interna. Considere la posibilidad de construir sistemas. Usamos ya make en Arcadia, aunque existe Bazel de Google. Son conceptualmente similares, pero cuando entras en detalles, muchos escenarios importantes se implementan de manera diferente, porque los patrones de carga para cada carga de trabajo pueden ser drásticamente diferentes. Como resultado, es casi seguro que los recursos ya gastados tendrán que reinvertirse para adaptar un nuevo estándar generalmente aceptado.
Migraciones. Si la sección anterior abordó la cuestión de adaptar el proyecto a los usuarios, abordemos ahora la cuestión de la migración de los propios usuarios. En mi opinión, la migración debería considerarse el siguiente problema tecnológico más importante después del nombramiento. Si asumimos que ya tenemos una herramienta interna en la empresa y queremos reemplazarla por una estandarizada, inevitablemente necesitaremos migraciones.
Conocemos muchos ejemplos de migraciones por nuestra experiencia desarrollando una nube interna. Las migraciones a gran escala toman tiempo, por lo que ambas herramientas deben ser compatibles simultáneamente durante períodos prolongados. Si este proceso involucra a una gran cantidad de usuarios, los problemas de gestión son inevitables. Ciertamente vale la pena intentar migrar sin la participación del usuario, pero no siempre es posible.
Continuidad del negocio. Para ser sincero, este punto ha adquirido recientemente suficiente importancia. Anteriormente, un número mucho menor de empresas lo tomaban en serio debido a preocupaciones sobre la dependencia de un proveedor. Confiar procesos críticos a un proveedor que puede poner fin a la colaboración en cualquier momento es arriesgado. JetBrains es un excelente ejemplo de esto, ya que ha restringido el uso de sus IDE a determinadas empresas. Otro ejemplo es Github Enterprise, que ha comenzado a suspender cuentas de usuarios con sede en Rusia.
Las soluciones internas suelen ser inmunes a este problema. Por un lado, todavía existen soluciones de código abierto. Por otro lado, no hay garantías de que el modelo de código abierto le acompañe en todo momento: por ejemplo, Corona, la mejora desarrollada internamente por Facebook para el software de programación Hadoop MapReduce, apareció en primer lugar debido a la imposibilidad de comprometerse. los parches necesarios para escalar Hadoop en sentido ascendente.
Al mismo tiempo, el aspecto legal del problema afecta al código abierto: por ejemplo, los commits en golang o k8s requieren la firma de un CLA. ¿Esto seguirá siendo un problema?
NIH. Sí, además de razones objetivas, es posible que las decisiones que se tomen no sean pragmáticas. Ése es el síndrome NIH en su máxima expresión.
Por ejemplo, en un intento de eliminar la influencia del lote en la computación, intentamos crear nuestro propio programador en el kernel de Linux. En la práctica, no salió nada bueno de ello; uno podría haberse conformado con las capacidades existentes del kernel de Linux. Sin embargo, cuanto mayores son los costes laborales, más esfuerzo se pone en elaborar y solucionar el problema, y menor es la probabilidad de padecer el síndrome NIH.
En resumen , como puedes ver, con frecuencia se requieren soluciones internas para las grandes empresas. La mayoría de ellos se fusionarán en el futuro con soluciones estándar globales unificadas aún por madurar, mientras que el resto pasará a la historia. En cualquier caso, decidir entre una solución propia y una ya preparada sigue siendo una cuestión difícil que no puede responderse sin antes entender el contexto y estimar el coste de dicho proyecto.