De SSH à REST : moderniser les pipelines de données EMR de Slack avec une approche centrée sur la sécurité
(slack.engineering)- La plateforme de données de Slack exploitait plus de 700 Operators basés sur SSH pour faire tourner des pipelines critiques, comme l’indexation quotidienne de recherche et les tâches analytiques, chaque job exigeant un accès SSH direct aux clusters AWS EMR de production, ce qui créait une vaste surface d’attaque
- Cette dépendance à SSH constituait non seulement un risque de sécurité, mais aussi un obstacle majeur à la modernisation de l’infrastructure, notamment pour Spark on Kubernetes, la transition vers EMR on EKS et l’achèvement de l’initiative Whitecastle
- La solution a consisté à utiliser YARN Distributed Shell pour permettre l’exécution de commandes shell arbitraires dans des conteneurs YARN, et à unifier toutes les soumissions de jobs via Quarry, la passerelle REST interne de Slack
- Plus de 700 jobs ont été migrés sans interruption (zero downtime) dans 8 régions de données, avec une suppression de SSH portée à 100 % en trois trimestres
- Résultat : réduction de la surface d’attaque, amélioration de la fiabilité des traitements et meilleure visibilité, tout en posant les bases de la future infrastructure, comme Whitecastle finalisé et Spark on Kubernetes
Contexte : la formation d’une plateforme de données basée sur SSH
- La plateforme de données de Slack, mise en place vers 2017, avait adopté l’approche SSH comme chemin le plus direct pour qu’Airflow exécute des jobs sur des clusters EMR
SSHOperatorse connectait au nœud maître EMR puis exécutait des commandes commespark-submit
- Par la suite, les équipes ont développé leurs propres Operators personnalisés basés sur SSH pour répondre à divers usages (pas seulement Spark, mais aussi MapReduce, AWS CLI et des scripts Python personnalisés)
- Au final, plus de 700 jobs basés sur SSH se sont accumulés en production
Le coût réel de l’approche SSH
-
Risques de sécurité potentiels
- L’accès SSH direct aux clusters de calcul élargissait la surface d’attaque
- La distribution et la rotation des clés sur l’ensemble des workers d’orchestration augmentaient la charge opérationnelle
- Une corrélation de logs entre plusieurs systèmes était nécessaire pour des audits détaillés
- La gestion des autorisations se complexifiait avec des groupes de sécurité dédiés et des configurations personnalisées
-
Problèmes opérationnels
- Les jobs n’étaient pas distribués et s’exécutaient directement sur le nœud maître EMR, provoquant des contentions de ressources
- Lors du redémarrage d’un Pod Kubernetes, la connexion SSH était rompue, entraînant l’échec du job
- Les jobs longue durée continuaient parfois après la fermeture de la connexion, se transformant en processus zombies
- En cas de déconnexion, il devenait impossible de savoir si un job avait réussi ou échoué
-
Frein à la modernisation
- Impossible d’avancer vers Spark on Kubernetes et EMR on EKS (la suppression de la dépendance à SSH était un préalable)
- Le dernier cluster EMR du compte principal n’avait pas pu être déplacé vers un compte enfant, empêchant l’achèvement de l’initiative Whitecastle
- Whitecastle est l’initiative de Slack visant à migrer l’infrastructure AWS vers des comptes enfants afin de renforcer la sécurité et l’isolation réseau
- Il était impossible de mettre en place une surveillance et une visibilité adaptées sur les jobs
-
Cas emblématique — l’équipe Search Infrastructure
- Un pipeline qui construit chaque jour des index de recherche Solr à partir de téraoctets de données, au cœur de la fonctionnalité de recherche de Slack
- Comme il reposait sur des soumissions de jobs via SSH, il subissait tous les problèmes de fiabilité évoqués ci-dessus
Le principe de base de la soumission de jobs via REST
-
Les limites intrinsèques de SSH
- Une connexion SSH est une connexion directe avec état : si elle est interrompue, par exemple lors du redémarrage d’un Pod, la commande peut continuer à s’exécuter, échouer ou laisser un processus orphelin
- Il n’existe pas de moyen fiable de se reconnecter pour vérifier l’état du job
-
L’alternative REST
- Les moteurs de calcul modernes comme YARN, Trino et Snowflake prennent en charge la soumission de jobs via API HTTP
- requête POST pour soumettre un job → retour d’un ID de job
- requête GET pour consulter l’état du job → exécution / terminé / échec
- requête DELETE pour supprimer un job → annulation propre
- Le cycle de vie du job est géré côté serveur : même si le client redémarre, le job continue de s’exécuter et son état reste consultable
- Les moteurs de calcul modernes comme YARN, Trino et Snowflake prennent en charge la soumission de jobs via API HTTP
-
Le rôle et les limites de YARN
- Pour les workloads Hadoop (MapReduce, Spark, Hive), YARN sert de gestionnaire de ressources et fournit aussi une API REST
- En revanche, plus de 300 jobs basés sur CLI exécutant des commandes arbitraires comme
aws s3 syncouhadoop distcpn’avaient pas d’API REST directement exploitable - La clé pour résoudre ce problème a été YARN Distributed Shell
La percée : YARN Distributed Shell
- Pour Spark, l’API REST de Livy, et pour Hive, HiveServer2, rendaient la migration relativement simple
- En revanche, les jobs MapReduce et plus de 300 jobs basés sur CLI étaient un véritable casse-tête, faute d’API REST prête à l’emploi
-
Exigences
- Une solution REST simple s’intégrant naturellement à l’architecture
- La réutilisation des mécanismes d’authentification et d’autorisation existants (sans couche de sécurité personnalisée)
- L’usage d’un protocole open source plutôt que d’une solution propriétaire (API YARN standard)
- Un minimum de complexité afin d’éviter de construire et maintenir une infrastructure maison d’exécution de jobs
-
Options étudiées puis abandonnées
- Construire un service wrapper personnalisé pour l’exécution de commandes à distance
- Utiliser des frameworks d’exécution distante comme Ansible ou Salt
- Ajouter de zéro un nouveau type de job à YARN
- Toutes ces pistes ont été jugées inadaptées à cause d’une complexité excessive, de la nécessité d’implémenter une sécurité sur mesure ou de nouvelles dépendances
-
La découverte de YARN Distributed Shell
org.apache.hadoop.yarn.applications.distributedshell.ApplicationMasterpermet d’exécuter des scripts shell arbitraires dans des conteneurs YARN- Cette fonctionnalité est déjà incluse dans YARN et utilise la même API REST, sans nécessiter de couche de sécurité personnalisée
-
Fonctionnement
- 1. Téléverser le script de commande vers S3 (par exemple
aws s3 sync /tmp/data/ s3://bucket/output/) - 2. Le soumettre à YARN avec la configuration Distributed Shell
- définir
application-typesurMAPREDUCEet inclure dansam-container-specdes variables d’environnement commeDISTRIBUTEDSHELLSCRIPTLOCATION,DISTRIBUTEDSHELLSCRIPTLEN,DISTRIBUTEDSHELLSCRIPTTIMESTAMP
- définir
- 3. YARN alloue un conteneur, télécharge le script puis l’exécute
- YARN gère les limites de ressources comme la mémoire et les vCore, l’isolation du conteneur, les retries et la tolérance aux pannes, l’annulation propre, ainsi que les logs via l’interface YARN
- 1. Téléverser le script de commande vers S3 (par exemple
- Ce choix a permis d’exécuter non seulement des workloads Hadoop, mais aussi
aws s3 sync,hadoop distcpet des scripts Python personnalisés dans des conteneurs YARN
La solution : Quarry
- Quarry est la passerelle de soumission de jobs via REST de Slack, conçue pour envoyer des jobs vers plusieurs moteurs de calcul comme EMR/YARN, Trino et Snowflake
- Elle résolvait déjà les problèmes d’authentification, de fiabilité et de visibilité, et répondait donc parfaitement à l’abandon de SSH
-
Les fonctions de Quarry
- Authentification : utilisation de jetons de service à service au lieu de clés SSH
- Soumission des jobs : envoi à YARN, Trino et Snowflake via API REST
- Suivi d’état : surveillance côté serveur du statut des jobs
- Gestion du cycle de vie : annulation propre et nettoyage via API REST
- Visibilité : logs structurés, métriques et traçage pour toutes les soumissions de jobs
-
Changement d’architecture
- Avant :
Airflow → SSH Connection → EMR Master Node → Execute Command - Après :
Airflow → Quarry REST API → YARN ResourceManager → EMR Container - Les Operators Airflow n’ouvrent plus de connexion SSH : ils envoient une requête HTTP à Quarry, qui soumet le job à YARN puis interroge régulièrement son état
- Même si le Pod Airflow redémarre, le job continue d’exister, Quarry conservant la continuité du suivi
- Avant :
-
Les points forts de Quarry
- Grâce au support de YARN Distributed Shell, Quarry est devenue une passerelle générique de soumission de jobs
- Les jobs Spark, les requêtes Hive et les scripts shell passent tous par la même API REST
- Plus besoin d’identifiants SSH ni d’accès direct au cluster : seuls des appels REST avec authentification et suivi serveur des jobs sont utilisés
Le parcours de migration
- Avec plus de 700 jobs de production répartis sur 8 régions de données indépendantes, des configurations réseau différentes, des exigences de souveraineté des données et des workloads critiques comme l’indexation de recherche qui ne pouvaient subir aucune interruption, une planification méthodique était indispensable
-
Une approche par étapes
- Phase 1 – preuve de concept (PoC) : valider l’approche basée sur Quarry avec des jobs pilotes, puis développer le premier Quarry Operator et le tester en environnement de dev
- Phase 2 – revue sécurité : collaborer avec l’équipe sécurité pour planifier la suppression des identifiants et vérifier que l’approche REST répondait aux exigences de sécurité
- Phase 3 – exécution pilotée par les OKR : en faire un Key Result pour gagner en visibilité auprès de la direction, avec à cette étape le franchissement du jalon des 80 % de migration
- Phase 4 – migration à grande échelle : plusieurs équipes, dont Search Infrastructure, Data Engineering & Analytics et ML Services, migrent en parallèle les workloads restants dans toutes les régions
- Phase 5 – nettoyage final : finaliser les DAG oubliés, retirer tous les Operators SSH legacy et atteindre 100 %
-
Les chiffres de la migration
- Plus de 700 jobs migrés sur 7 types d’Operators
- Déploiement coordonné dans 8 régions de données indépendantes
- 5 équipes passées aux nouveaux Operators
- Aucune interruption sur les services critiques pour l’activité
- Trois trimestres entre le pilote initial et la suppression complète de SSH
Les défis rencontrés pendant la migration
-
Défi 1 — échecs du Virtual Memory Check
- Lors de la migration de DAG d’export de données, des jobs qui fonctionnaient via SSH ont commencé à échouer à cause des vérifications vmem
- Cause : avec SSH, les jobs s’exécutaient directement sur le nœud maître et contournaient les contraintes de ressources YARN ; avec Quarry, ils étaient correctement soumis à YARN, qui rejetait les conteneurs dépassant les limites de mémoire virtuelle
- Solution : désactiver la vérification vmem sur tous les clusters conformément aux bonnes pratiques AWS —
"yarn.nodemanager.vmem-check-enabled": "false"- Cela suivait la recommandation d’AWS selon laquelle la comptabilité de la mémoire virtuelle Linux n’est pas fiable et que la limite de mémoire physique suffit
- Leçon : SSH masquait de nombreux problèmes ; en passant à une soumission YARN correcte, il faut s’attendre à voir apparaître des problèmes de limites de ressources auparavant invisibles et tester suffisamment en environnement de dev
-
Défi 2 — séparation réseau et problèmes de connectivité EKM
- Lors du déplacement de jobs de l’infrastructure de recherche en dev d’un cluster dev vers un cluster analytique de staging, des timeouts de connexion à EKM (Enterprise Key Management) sont apparus
- Erreur :
Unable to execute HTTP request: Connect to sts.amazonaws.com:443 failed: connect timed out - Cause : le cluster d’origine disposait d’un routage réseau vers le endpoint de gestion des clés, mais le cluster analytique de staging, situé dans un segment réseau plus strict, ne disposait pas d’une connectivité équivalente, révélant une dépendance à la topologie réseau qui n’était pas explicitée dans la configuration du job
- Solution : déplacer les traitements de l’infrastructure de recherche vers un cluster ETL dev disposant d’un routage vers les services dev ; conserver en staging les tâches nécessitant le catalogue Hive de production ; et augmenter la capacité du cluster ETL dev pour absorber la charge supplémentaire
- Leçon : la topologie réseau est cruciale ; il faut comprendre la séparation réseau et les frontières de compte avant de décider sur quel cluster exécuter quel job
-
Défi 3 — la complexité multi-région
- Les exigences de souveraineté des données imposaient l’exploitation de clusters EMR dans 8 régions de données indépendantes ; l’abandon de SSH revenait donc en pratique à mener 8 migrations en parallèle
-
Facteurs de complexité
- Gestion de configuration : chaque région nécessitait sa propre configuration Quarry, ses endpoints de cluster et ses règles de routage réseau
- Charge de test : chaque modification de code devait être validée dans les 8 régions
- Déploiement séquentiel : impossible de déployer partout en même temps, il fallait un rollout progressif région par région
- Problèmes spécifiques à chaque région : différences de configuration réseau, de règles de souveraineté des données et de versions de cluster
-
Réponse apportée
- Validation dans une région pilote unique (principalement basée aux États-Unis)
- Documentation des exigences de configuration propres à chaque région
- Construction d’un Quarry Operator capable de prendre en compte la région
- Rollout progressif avec intégration des enseignements région par région
- Suivi séparé de l’avancement de la migration pour chaque région
- Leçon : une infrastructure multi-région n’est pas seulement N fois plus difficile ; elle l’est aussi à cause des modes de défaillance propres à chaque région, ce qui impose de prévoir suffisamment de temps pour la coordination inter-région et le debug local
Résultats
- Suppression de SSH portée à 100 %, tous les jobs de production étant désormais soumis via REST par l’intermédiaire de Quarry
-
Résultats côté sécurité
- Suppression de l’accès SSH à l’ensemble des clusters EMR de production dans les 8 régions de données indépendantes, avec une réduction majeure de la surface d’attaque
- Remplacement de la distribution de clés SSH par une authentification par jetons de service à service, avec des logs API REST assurant une vraie traçabilité d’audit
- Toutes les soumissions de jobs disposent désormais de logs structurés via Quarry
- Migration du dernier cluster EMR du compte AWS principal vers un compte enfant, ce qui a permis d’achever l’initiative Whitecastle
- Simplification de la conformité grâce à la suppression des groupes de sécurité spécialisés et des mécanismes complexes de gestion des autorisations
-
Améliorations opérationnelles
- Suppression des contentions de ressources sur le nœud maître ; tous les jobs non Hadoop s’exécutent désormais dans des conteneurs YARN distribués avec une allocation correcte des ressources
- Les jobs survivent aux redémarrages des Pods Kubernetes côté client, ce qui a fortement amélioré leur fiabilité ; les processus zombies ont disparu et l’arrêt propre est possible via l’API REST
- L’API Quarry fournit des états, logs et métriques structurés sur les jobs, permettant de suivre l’ensemble de leur cycle de vie, de consulter les logs des conteneurs YARN et de déboguer avec les bons outils
-
Bases pour l’avenir
- La suppression de la dépendance à SSH rend désormais possible la migration vers Spark on Kubernetes
- L’architecture REST est alignée avec les pratiques cloud native
- Le Quarry Operator, plus simple et plus facile à maintenir que des configurations SSH complexes, facilite l’onboarding des équipes
- Airflow a été découplé des détails d’infrastructure EMR
- Toutes les soumissions de jobs sont standardisées via Quarry, ce qui simplifie les évolutions futures
- Deux ans d’exploitation en production après l’achèvement ont confirmé la solidité de ces choix d’architecture, avec des améliorations sur les plans de la sécurité, de la stabilité opérationnelle et de la flexibilité de l’infrastructure
Enseignements tirés
-
Ce qui a bien fonctionné
- Migration progressive : rollout séquencé Dev → GovDev/CommDev → Prod et migration par type d’Operator, permettant d’apprendre à chaque étape
- Forte collaboration inter-équipes : coopération entre Search, Analytics, Data Engineering, ML, Marketing et d’autres domaines, avec des revues de code rapides et une communication fluide sur des canaux partagés
- Suivi piloté par l’analytique : création d’un tableau de bord de suivi de migration dans toutes les régions et identification des tâches SSH restantes via des requêtes sur la base de données Airflow
-
Ce qu’ils feraient différemment
- Cartographier plus tôt la topologie réseau : les problèmes de séparation réseau, comme la connectivité EKM, ont été découverts tard ; il aurait fallu documenter les frontières de compte Whitecastle et le routage réseau avant la migration des clusters
- Tester plus tôt les limites de ressources : le problème vmem est apparu tardivement ; il aurait fallu intégrer dès la phase pilote des tests des limites de ressources YARN par rapport à SSH
- Mieux communiquer en amont sur les restrictions liées aux Operators : quand l’usage de nouveaux
SSHOperatora été restreint dans la phase finale, certaines équipes ne l’avaient pas remarqué ; il aurait fallu renforcer la communication préalable auprès de tous les utilisateurs d’Airflow
-
Bonnes pratiques pour les migrations à grande échelle
- Mettre en place la supervision avant la migration : construire tôt un tableau de bord permettant de savoir à tout moment quelles tâches restaient à migrer, en s’appuyant sur des requêtes Airflow DB
- Tester dans plusieurs environnements : utiliser Dev, CommDev et GovDev pour identifier les problèmes propres à chaque environnement avant la production, en particulier les tests entre frontières de compte pour détecter en amont les problèmes de séparation réseau
- Retirer les Operators progressivement : supprimer un par un des Operators comme CrunchExecOperator ou S3SyncOperator, en traitant chaque étape comme un mini-projet avec ses propres tests et validations ; plus lent, mais nettement moins risqué
Aucun commentaire pour le moment.