1 puntos por GN⁺ 5 시간 전 | Aún no hay comentarios. | Compartir por WhatsApp
  • La plataforma de datos de Slack operaba más de 700 operadores basados en SSH para pipelines de datos críticos como indexación diaria de búsqueda y trabajos analíticos, y todas las tareas requerían acceso SSH directo a clústeres AWS EMR de producción, lo que generaba una amplia superficie de ataque
  • Esta dependencia de SSH no solo implicaba riesgos de seguridad, sino que también se convirtió en un obstáculo clave para la modernización de infraestructura, incluyendo la transición a Spark on Kubernetes, EMR on EKS y la finalización de la iniciativa Whitecastle
  • Como solución, usaron YARN Distributed Shell para permitir la ejecución incluso de comandos arbitrarios de shell dentro de contenedores YARN, y unificaron todos los envíos de jobs mediante Quarry, la puerta de enlace REST propia de Slack
  • Migraron más de 700 jobs en 8 regiones de datos sin tiempo de inactividad (zero downtime) y completaron la eliminación del SSH al 100% en tres trimestres
  • Como resultado, lograron reducir la superficie de ataque, mejorar la confiabilidad de los trabajos y la visibilidad, además de sentar la base de infraestructura de próxima generación para Whitecastle y Spark on Kubernetes

Contexto: cómo se formó una plataforma de datos basada en SSH

  • La plataforma de datos de Slack, construida alrededor de 2017, adoptó SSH como la ruta más directa para que Airflow ejecutara jobs en clústeres EMR
    • Con SSHOperator, se conectaban al nodo maestro de EMR y luego ejecutaban comandos como spark-submit
  • Después, los equipos fueron creando por su cuenta operadores personalizados basados en SSH para distintos usos (no solo Spark, sino también MapReduce, AWS CLI y scripts Python personalizados)
  • Como resultado, se acumularon más de 700 jobs basados en SSH en producción

El costo real del enfoque con SSH

  • Riesgos potenciales de seguridad

    • El acceso SSH directo a clústeres de cómputo ampliaba la superficie de ataque
    • La distribución y rotación de llaves en todos los workers de orquestación aumentaba la carga operativa
    • Para una auditoría detallada era necesario correlacionar logs de múltiples sistemas
    • La gestión de permisos se complicaba por grupos de seguridad dedicados y configuraciones personalizadas
  • Problemas operativos

    • Los jobs no se distribuían, sino que se ejecutaban directamente en el nodo maestro de EMR, provocando contención de recursos
    • Cuando un Pod de Kubernetes se reiniciaba, la conexión SSH se cortaba y el job fallaba
    • Los jobs de larga duración seguían ejecutándose después de que se cerraba la conexión y se convertían en procesos zombie
    • Si la conexión se caía, no había forma de confirmar si el job había tenido éxito o fallado
  • Factores que bloqueaban la modernización

    • No podían avanzar a Spark on Kubernetes ni a EMR on EKS (primero debían eliminar la dependencia de SSH)
    • No podían mover el último clúster EMR de la cuenta principal a una cuenta hija, por lo que la iniciativa Whitecastle seguía incompleta
      • Whitecastle es la iniciativa de Slack para migrar la infraestructura de AWS a cuentas hijas y reforzar así la seguridad y el aislamiento de red
    • No era posible implementar monitoreo y visibilidad adecuados de los jobs
  • Caso representativo — equipo de Search Infrastructure

    • Operaban un pipeline que construía diariamente índices de búsqueda de Solr con datos de terabytes, pieza central de la funcionalidad de búsqueda de Slack
    • Al depender del envío de jobs por SSH, estaban expuestos a todos los problemas de confiabilidad mencionados arriba

Concepto básico del envío de jobs basado en REST

  • Limitaciones intrínsecas de SSH

    • Una conexión SSH es una conexión directa con estado; si se corta por un reinicio del Pod u otro evento, el comando puede seguir ejecutándose, fallar o dejar procesos huérfanos
    • No existe un medio confiable para reconectarse y verificar el estado
  • Alternativa REST

    • Motores de cómputo modernos como YARN, Trino y Snowflake admiten envío de jobs vía API HTTP
      • POST de solicitud de job → devuelve un ID de job
      • GET de estado del job → permite verificar si está ejecutándose, completado o fallido
      • DELETE del job → cancelación limpia
    • El ciclo de vida del job se administra del lado del servidor, así que aunque el cliente se reinicie, el job sigue ejecutándose y su estado puede consultarse
  • El papel y las limitaciones de YARN

    • Para cargas Hadoop (MapReduce, Spark, Hive), YARN actúa como administrador de recursos y también ofrece una API REST
    • Sin embargo, más de 300 jobs basados en CLI que ejecutaban comandos arbitrarios como aws s3 sync o hadoop distcp no contaban con una API REST lista para usarse
    • La clave para resolver esto fue YARN Distributed Shell

El punto de inflexión: YARN Distributed Shell

  • Spark ya contaba con la API REST de Livy, y Hive con HiveServer2, por lo que su migración era relativamente sencilla
  • En cambio, los jobs de MapReduce y más de 300 jobs basados en CLI eran un reto difícil porque no tenían una API REST inmediata
  • Requisitos

    • Una solución simple basada en REST que encajara de forma natural en la arquitectura
    • Aprovechar los mecanismos existentes de autenticación y autorización (sin necesidad de una capa de seguridad personalizada)
    • Usar un protocolo open source (la API estándar de YARN), no una solución propietaria
    • Evitar construir y operar una infraestructura personalizada para ejecución de jobs con la mínima complejidad posible
  • Alternativas evaluadas y descartadas

    • Construir un servicio wrapper personalizado para ejecución remota de comandos
    • Usar frameworks de ejecución remota como Ansible o Salt
    • Agregar desde cero un nuevo tipo de job a YARN
    • Todas resultaron inadecuadas por su complejidad excesiva, necesidad de seguridad personalizada o introducción de nuevas dependencias
  • Descubrimiento de YARN Distributed Shell

    • Con org.apache.hadoop.yarn.applications.distributedshell.ApplicationMaster era posible ejecutar scripts de shell arbitrarios dentro de contenedores YARN
    • Como ya viene incluido en YARN, usa la misma API REST y no requiere una capa de seguridad personalizada
  • Cómo funciona

    • 1. Subir el script de comandos a S3 (por ejemplo, aws s3 sync /tmp/data/ s3://bucket/output/)
    • 2. Enviarlo a YARN con la configuración de Distributed Shell
      • Se define application-type como MAPREDUCE e am-container-spec incluye variables de entorno como DISTRIBUTEDSHELLSCRIPTLOCATION, DISTRIBUTEDSHELLSCRIPTLEN y DISTRIBUTEDSHELLSCRIPTTIMESTAMP
    • 3. YARN asigna un contenedor, descarga el script y lo ejecuta
      • YARN administra límites de recursos como memoria y vCore, aislamiento de contenedores, reintentos y tolerancia a fallas, cancelación limpia y logging mediante la UI de YARN
  • Esta decisión permitió ejecutar en contenedores YARN no solo cargas Hadoop, sino también aws s3 sync, hadoop distcp y scripts Python personalizados

La solución: Quarry

  • Quarry es la puerta de enlace de envío de jobs basada en REST de Slack, creada para enviar trabajos a múltiples motores de cómputo como EMR/YARN, Trino y Snowflake
  • Ya había resuelto problemas de autenticación, confiabilidad y visibilidad, y encajaba exactamente con la eliminación de SSH
  • Capacidades de Quarry

    • Autenticación: uso de tokens entre servicios en lugar de llaves SSH
    • Envío de jobs: envío por API REST a YARN, Trino y Snowflake
    • Seguimiento de estado: monitoreo del estado de los jobs del lado del servidor
    • Gestión del ciclo de vida: cancelación y limpieza ordenadas basadas en API REST
    • Visibilidad: logs estructurados, métricas y tracing para todos los envíos de jobs
  • Cambio de arquitectura

    • Antes: Airflow → SSH Connection → EMR Master Node → Execute Command
    • Después: Airflow → Quarry REST API → YARN ResourceManager → EMR Container
    • El operador de Airflow hace solicitudes HTTP a Quarry en lugar de abrir conexiones SSH, y Quarry envía el job a YARN y luego consulta su estado
    • Aunque el Pod de Airflow se reinicie, el job continúa, porque Quarry mantiene la continuidad del proceso
  • Fortalezas de Quarry

    • Con soporte para YARN Distributed Shell, se convirtió en una puerta de enlace universal para envío de jobs
    • Jobs de Spark, consultas Hive y scripts de shell pasan por la misma API REST
    • Se eliminaron tanto las credenciales SSH como el acceso directo al clúster, y solo se usan llamadas REST con autenticación y seguimiento de jobs del lado del servidor

El recorrido de la migración

  • Había más de 700 jobs de producción en 8 regiones de datos independientes, con distintas configuraciones de red, requisitos de soberanía de datos y cargas críticas como indexación de búsqueda que debían mantenerse sin interrupciones, por lo que se necesitó un plan sistemático
  • Enfoque por etapas

    • Fase 1 – Prueba de concepto (PoC): validación del enfoque con Quarry usando jobs piloto, desarrollo del primer operador de Quarry y pruebas en entorno dev
    • Fase 2 – Revisión de seguridad: trabajo conjunto con el equipo de seguridad para definir el plan de eliminación de credenciales y validar que el enfoque REST cumpliera los requisitos
    • Fase 3 – Ejecución guiada por OKR: se definió como Key Result para dar visibilidad ejecutiva, y en esta etapa se alcanzó el hito del 80% de migración
    • Fase 4 – Migración masiva: varios equipos como Search Infrastructure, Data Engineering & Analytics y ML Services migraron en paralelo las cargas restantes en todas las regiones
    • Fase 5 – Limpieza final: se completaron los DAG pendientes, se retiraron todos los operadores SSH heredados y se alcanzó el 100%
  • Cifras de la migración

    • Más de 700 jobs migrados a través de 7 tipos de operadores
    • Despliegue en 8 regiones de datos independientes con rollout coordinado
    • 5 equipos cambiaron a los nuevos operadores
    • Sin interrupciones en servicios críticos para el negocio
    • Desde el piloto inicial hasta la eliminación total de SSH: 3 trimestres

Desafíos enfrentados durante la migración

  • Desafío 1 — Fallas de Virtual Memory Check

    • Durante la migración de un DAG de exportación de datos, un job que funcionaba con SSH falló por errores del chequeo de vmem
    • Causa: con SSH, el job se ejecutaba directamente en el nodo maestro y eludía la imposición de recursos de YARN; con Quarry, el job sí se enviaba correctamente a YARN, por lo que el contenedor era rechazado al exceder el límite de memoria virtual
    • Solución: desactivar el chequeo de vmem en todo el clúster siguiendo las mejores prácticas de AWS — "yarn.nodemanager.vmem-check-enabled": "false"
      • Esto coincide con la recomendación de AWS de que la contabilidad de memoria virtual en Linux no es confiable y que el límite de memoria física es suficiente
    • Lección: SSH había estado ocultando muchos problemas, así que al cambiar a un envío correcto a YARN hay que anticipar límites de recursos que antes no eran visibles y probar a fondo en dev
  • Desafío 2 — Aislamiento de red y problemas de conectividad con EKM

    • Al mover un job de infraestructura de búsqueda de dev desde un clúster dev a un clúster analítico de staging, aparecieron timeouts de conexión con EKM (Enterprise Key Management)
    • Error: Unable to execute HTTP request: Connect to sts.amazonaws.com:443 failed: connect timed out
    • Causa: el clúster original sí tenía enrutamiento de red hacia el endpoint de gestión de llaves, pero el clúster analítico de staging, ubicado en un segmento de red más estricto, no tenía conectividad equivalente, lo que dejó expuesta una dependencia de topología de red no declarada en la configuración del job
    • Solución: mover el trabajo de Search Infrastructure al clúster dev ETL, que sí tenía enrutamiento hacia el servicio dev; mantener en staging las cargas que requerían el catálogo Hive de producción; y escalar el clúster dev ETL para soportar la carga adicional
    • Lección: la topología de red importa muchísimo; antes de decidir en qué clúster ejecutar cada job, hay que entender el aislamiento de red y los límites entre cuentas
  • Desafío 3 — Complejidad multi-región

    • Por requisitos de soberanía de datos, operaban clústeres EMR en 8 regiones de datos independientes, así que eliminar SSH equivalía en la práctica a 8 migraciones en paralelo
    • Factores de complejidad

      • Gestión de configuración: cada región requería configuraciones de Quarry, endpoints de clúster y reglas de enrutamiento de red distintas
      • Carga de pruebas: cada cambio de código debía validarse en las 8 regiones
      • Despliegue secuencial: no podían desplegar todo al mismo tiempo, sino avanzar gradualmente por región
      • Problemas por región: diferencias en configuración de red, reglas de soberanía de datos y versiones de clúster
    • Cómo lo abordaron

      • Validación en una sola región piloto (principalmente en EE. UU.)
      • Documentación de requisitos de configuración por región
      • Construcción de un Quarry Operator con conciencia regional
      • Rollout gradual incorporando aprendizajes de cada región
      • Seguimiento separado del progreso de migración por región
    • Lección: la infraestructura multi-región no es simplemente N veces más difícil, sino N veces más compleja por los modos de falla propios de cada región, así que hay que asignar tiempo suficiente para coordinación entre regiones y depuración específica por región

Resultados

  • Se logró la eliminación del SSH al 100% y todos los jobs de producción pasaron a enviarse por REST a través de Quarry
  • Logros de seguridad

    • Se eliminó el acceso SSH a todos los clústeres EMR de producción en las 8 regiones de datos independientes, reduciendo drásticamente la superficie de ataque
    • La distribución de llaves SSH fue reemplazada por autenticación con tokens entre servicios, y los logs de la API REST proporcionaron una traza de auditoría adecuada
    • Todos los envíos de jobs quedaron con logs estructurados a través de Quarry
    • El último clúster EMR de la cuenta principal de AWS se movió a una cuenta hija, con lo que se completó la iniciativa Whitecastle
    • Al eliminar grupos de seguridad especiales y la compleja gestión de permisos, se simplificó el cumplimiento normativo
  • Mejoras operativas

    • Se eliminó la contención de recursos del nodo maestro, y todos los jobs no Hadoop ahora se ejecutan en contenedores YARN distribuidos con asignación adecuada de recursos
    • Aunque se reinicie un Pod cliente de Kubernetes, el job continúa, lo que mejoró drásticamente la confiabilidad, eliminó procesos zombie y permitió terminaciones limpias vía API REST
    • La API de Quarry ofrece estado, logs y métricas estructurados de los jobs, permite seguir todo su ciclo de vida, revisar logs de contenedores YARN y depurar con herramientas adecuadas
  • Base para el futuro

    • Al eliminar la dependencia de SSH, se habilitó la migración a Spark on Kubernetes
    • La arquitectura basada en REST se alinea con prácticas cloud-native
    • Frente a la complejidad de la configuración SSH, el Quarry Operator es más simple y fácil de mantener, lo que facilita el onboarding de equipos
    • Se desacopló Airflow de los detalles internos de la infraestructura EMR
    • Se estandarizó todo el envío de jobs en Quarry, facilitando cambios futuros
  • Dos años de operación en producción después de completar el proyecto validaron la solidez de la decisión arquitectónica, con mejoras en seguridad, estabilidad operativa y flexibilidad de infraestructura

Lecciones aprendidas

  • Qué funcionó bien

    • Migración gradual: rollout secuencial de Dev → GovDev/CommDev → Prod y migración por tipo de operador, acumulando aprendizaje en cada etapa
    • Fuerte colaboración entre equipos: cooperación entre Search, Analytics, Data Engineering, ML, Marketing y otras áreas, con revisiones de código rápidas y comunicación en canales compartidos
    • Seguimiento del progreso basado en analítica: se construyó un dashboard de avance para todas las regiones y se usaron consultas a la base de datos de Airflow para identificar trabajos restantes basados en SSH
  • Qué harían distinto si lo repitieran

    • Mapear la topología de red desde el principio: problemas de aislamiento como la conectividad con EKM se descubrieron tarde, por lo que habría sido mejor documentar los límites entre cuentas de Whitecastle y el enrutamiento de red antes de migrar clústeres
    • Probar antes los límites de recursos: el problema del chequeo de vmem apareció en una etapa tardía, por lo que habría sido mejor incluir desde el piloto pruebas de límites de recursos de YARN comparadas con SSH
    • Comunicar antes las restricciones sobre operadores: en la etapa final, algunos equipos no sabían que se había restringido el uso de nuevos SSHOperator, así que faltó una comunicación previa más amplia a todos los usuarios de Airflow
  • Buenas prácticas para migraciones a gran escala

    • Construir monitoreo antes de migrar: preparar desde temprano dashboards para saber siempre qué trabajos faltan, usando consultas a la base de datos de Airflow
    • Probar en múltiples entornos: validar en Dev, CommDev y GovDev para detectar problemas específicos de cada entorno antes de producción, especialmente haciendo pruebas entre límites de cuentas para descubrir antes problemas de aislamiento de red
    • Retirar operadores gradualmente: descontinuar CrunchExecOperator, S3SyncOperator y otros uno por uno, tratando cada etapa como un mini proyecto con sus propias pruebas y validación; es más lento, pero reduce mucho el riesgo

Aún no hay comentarios.

Aún no hay comentarios.