En la actualidad, muchas empresas tecnológicas enfrentan la necesidad de evolucionar sus entornos de computación para soportar cargas de trabajo cada vez más complejas y dinámicas. Uber, una plataforma que atiende a millones de usuarios diarios y genera vastos volúmenes de datos, demostró cómo es posible migrar cargas de trabajo interactivas a gran escala hacia Kubernetes sin causar interrupciones significativas en el servicio. Este tipo de migración es especialmente desafiante cuando se trata de ambientes interactivos que requieren mantenimiento del estado, persistencia de datos y personalización activa por parte de los usuarios. Para contextualizar, Uber desarrolló Data Science Workbench (DSW), una plataforma basada en notebooks interactivos como Jupyter y RStudio, pensada para científicos de datos, ingenieros de machine learning y especialistas en operaciones. DSW permite realizar análisis, visualización, entrenamiento de modelos y programación de flujos de trabajo a través de una interfaz web intuitiva.
Cada sesión de usuario corre en contenedores aislados con recursos variables según las necesidades, incluyendo memoria, CPU y GPU. Además, los usuarios pueden instalar paquetes específicos para sus trabajos, una característica fundamental que implica controlar dependencias y preservar entornos personalizados. Originalmente, la plataforma DSW funcionaba sobre Peloton, un gestor de contenedores basado en Apache Mesos que utilizaba clusters zonales dedicados para sesiones de usuario. Este enfoque presentaba limitaciones notables, como riesgos de caída total si un cluster fallaba, desequilibrios en la carga de trabajo y dificultades operativas para mantenimiento y escalabilidad. A pesar de sus fortalezas, Peloton no permitía una transición sencilla a entornos en la nube ni facilitaba la gestión homogénea del infrastructure.
La migración hacia Kubernetes respondió a la necesidad de superar estos obstáculos, alineándose con principios modernos de infraestructura que buscan evitar el bloqueo por proveedores, ofrecer automatización homogénea en el despliegue de recursos y simplificar el manejo centralizado de capacidad tanto en on-premise como en la nube. Un desafío crítico fue cómo modelar las sesiones interactivas de DSW dentro del ecosistema de Kubernetes. Las Jobs de Kubernetes están diseñadas para tareas batch no interactivas y de corta duración, mientras que las sesiones de DSW son interactivas y longevas. Uber encontró una solución elegante al adaptar las Jobs para funcionar con un solo pod activo por sesión, configurando un alto número de completaciones que permitiera mantener la sesión prolongada como una tarea que nunca finaliza realmente. Además, redefinieron las políticas de reinicio para garantizar la resiliencia sin caer en los puntos problemáticos de reinicios internos que pudieran afectar la estabilidad.
Uno de los avances más significativos fue la introducción de Federator, una capa de federación que abstrae múltiples clusters de Kubernetes distribuidos en diferentes zonas. Federator maneja balanceo de carga inteligente al asignar nuevas sesiones al cluster con mejor capacidad y estado de salud, minimizando tiempos de espera y mejorando la disponibilidad frente a fallos zonales. Esto representa una mejora considerable en comparación con la arquitectura anterior que dependía estrictamente de clusters dedicados. La gestión del sistema de archivos, y particularmente el montaje de NFS (Network File System), constituyó otro punto complejo. En Peloton, existían hosts dedicados para montar NFS, algo incompatible con la portabilidad y escalabilidad buscadas.
Kubernetes provee soporte nativo para NFS mediante drivers CSI o paquetes adicionales en el Kubelet, pero la implementación temprana en Uber aún no contaba con esta capacidad plenamente disponible. Por ello, se optó por un enfoque híbrido que permitió reemplazar los hosts dedicados por un montaje NFS central único para toda la flota de Kubernetes, manteniendo persistencia de archivos y sesiones sin interrupciones. La persistencia y recuperación de estados personalizados, como los paquetes de Python o R que los usuarios instalan dinámicamente, fue uno de los grandes retos para preservar la experiencia de usuario. Dado que cambiar de orquestador implica reiniciar contenedores, la pérdida de entornos personalizados era inevitable sin un mecanismo para guardar estos datos. Se exploraron tecnologías como Docker checkpoint y snapshots de volúmenes, pero estas resultaron inviables para las necesidades y rendimiento exigidos.
Como innovación, el equipo desarrolló una técnica para monitorizar las modificaciones en los directorios donde se instalan paquetes mediante el sistema de eventos inotify en Linux. Utilizando un mecanismo inteligente para controlar el ruido y evitar eventos repetidos (debouncing), pudieron registrar instalaciones y desinstalaciones en tiempo real, guardando esta información en un sistema de almacenamiento NFS compartido. Al reiniciar una sesión, el sistema automáticamente reinstalaba los paquetes faltantes, asegurando que el ambiente del usuario se reconstruyera rápidamente sin intervención manual. De esta manera, los usuarios experimentaron solo la pérdida del estado en memoria, mientras que sus notebooks y entornos permanecían intactos. Para mantener una experiencia unificada, también abordaron la limitación que implica la pérdida de funcionalidades del UI de Peloton al migrar a Kubernetes.
El equipo integró una replicación casi en tiempo real de datos desde etcd, la base de datos de Kubernetes, a Cassandra, la base previamente usada por Peloton. Esto permitió construir una interfaz de usuario llamada Compute UI, una versión renovada y compatible con Kubernetes que ofrece visibilidad detallada de pods, logs, estados de trabajos, y métricas de recursos en pools. Esta continuidad en la experiencia permite a usuarios y operadores gestionar las cargas de trabajo con herramientas familiares y potentes, maximizando la adopción sin curva de aprendizaje abrupta. Las mejoras también se reflejaron en el acceso a sistemas de archivos activos y logs. Implementaron un sistema denominado Browse Sandbox que permite a los usuarios explorar en tiempo real el sistema de archivos y acceder a logs de contenedores en ejecución o terminados.
Para las sesiones finalizadas, adoptaron estrategias de archivado que almacenan archivos y logs en TerraBlob, una solución de almacenamiento escalable, que garantiza accesibilidad histórica. Durante el proceso de desarrollo y despliegue hubo que afrontar problemas relacionados con el rendimiento de IOPS sobre NFS, derivados de la cantidad de pequeños archivos que forman los ambientes Python y R. Inicialmente, intentaron mantener todo el ambiente sobre NFS, pero las limitaciones técnicas los condujeron a optimizar la estrategia enfocándose en guardar solo la lista de paquetes instalados para acelerar el bootstrap y reducir la carga de IOPS. Finalmente, diseñaron una API robusta para el reinicio de sesiones que integra comunicación directa con el usuario, checkpointing en Peloton y la reanudación en Kubernetes. Este flujo garantizó una transición transparente para miles de sesiones y más de dos mil usuarios sin quejas ni reportes importantes de interrupciones.
La migración logró importantes beneficios en términos de eficiencia, ya que ahora los recursos de Kubernetes se comparten más dinámicamente entre equipos, facilitando la expansión ágil hacia entornos cloud y propiciando ahorros económicos sustanciales. Asimismo, se sentaron las bases para adoptar en un futuro cercano soporte nativo completo para NFS a través de drivers CSI o paquetes específicos en Kubelets, permitiendo una verdadera portabilidad de cargas de trabajo. En conclusión, el proyecto de migración a Kubernetes de Uber para sus cargas de trabajo interactivas a gran escala es un ejemplo de innovación, rigurosidad técnica y enfoque en la experiencia del usuario. La combinación de soluciones a nivel de arquitectura, manejo de estado, balanceo de recursos y herramientas de observabilidad permitió afrontar el desafío sin sacrificar productividad ni estabilidad. Este caso de éxito ofrece insights valiosos para otras organizaciones que enfrentan la necesidad de modernizar sus infraestructuras y optimizar la gestión de cargas interactivas en contenedores.
Migrar a orquestadores modernos como Kubernetes no tiene por qué ser un proceso disruptivo si se aplican estrategias inteligentes, desarrollo creativo y un fuerte compromiso con el usuario final. Las siguientes etapas en la evolución de la plataforma incluirán la adopción de soporte NFS completo y el perfeccionamiento continuo de la experiencia de gestión y desarrollo. Mientras tanto, la transición realizada garantiza a Uber una infraestructura más resiliente, escalable y alineada con estándares de la industria, capaz de soportar la creciente demanda y complejidad de sus operaciones de datos e inteligencia artificial.