Airflow : quels pièges éviter lors d’un déploiement à grande échelle

Mohamed Amine Bergaoui
neoxia
Published in
10 min readMar 5, 2020

Au sein de l’équipe Data de Neoxia, nous accompagnons nos clients depuis plusieurs années dans la mise en place au sein de leurs systèmes informatiques de Data Platforms, leur permettant de collecter des données de différentes sources, les stocker, les traiter et réaliser des analyses poussées dessus. Ces Data Platforms sont souvent déployées sur des environnements cloud publics (notre expérience couvre Google Cloud Platform, Amazon Web Services et Microsoft Azure), qui offrent des solutions de stockage à bas coût et faciles à prendre en main (entre autres, Google Cloud Storage, AWS S3, Azure Datalake Storage), ainsi que des solutions de collecte et de traitement de données scalables et variées. Dans ces Data Platforms, la question de l’orchestration de ces flux de collecte et de traitement a longtemps été une épine dans notre pied, jusqu’à l’avènement d’Apache Airflow.

Airflow en quelques mots

L’idée derrière Apache Airflow est assez simple : définir dans un fichier Python des objets correspondant aux jobs à exécuter, ou en termes plus “airflowiens”, des DAGs (Directed Acyclic Graphs). Ces DAGs correspondent ainsi à un graphe de dépendance entre les différentes tâches du job à exécuter, dans un ordre particulier. Ces tâches peuvent être, par exemple, l’exécution de scripts Bash ou Python en local, la copie des données depuis/vers différentes sources (API, bases de données, serveurs FTP, etc.) ou bien l’exécution de traitements plus complexes sur des systèmes distribués (BigQuery, DataFlow, EMR, Athena, etc.). Ces tâches sont exécutées via des “workers” au sein d’Airflow, et sont ordonnancées par un “scheduler”.

Airflow comprend également un “webserver”, qui offre une interface graphique assez riche permettant de visualiser l’historique d’exécution d’un DAG, consulter les logs d’une tâche particulière, relancer l’exécution de cette tâche en cas de besoin, éditer des variables utilisées dans les DAGs ou bien éditer les informations de connexion aux systèmes tiers (par exemple, le nom du serveur, le login et le mot de passe pour une base de données).

Airflow, la solution parfaite pour tout le monde ?

Au cours des derniers mois, l’utilisation d’Apache Airflow s’est largement démocratisée, et nous avons eu l’occasion d’échanger avec plusieurs Data Engineers et Data Architects ayant mis Airflow au centre de l’architecture de leur Data Platform, avec un succès quelquefois mitigé. Les équipes qui ont tiré au mieux profit d’Airflow partagent toutefois quelques points communs : il s’agit le plus souvent d’équipes de taille assez réduite, avec des membres partageant des priorités et des mandats assez similaires. Dans les autres cas, la collaboration entre des équipes plus hétérogènes sur une même plateforme, et avec une seule instance Airflow, donne parfois lieu à plusieurs problématiques de sécurité, de gouvernance, de performance, etc. Ces problématiques peuvent néanmoins être adressées via la mise en oeuvre de règles de gouvernance assez strictes.

Gérer des environnements Airflow multiples

Développer des flux pour la collection et le traitement de données nécessite souvent deux environnements au minimum : un environnement pour la production, ainsi qu’un environnement pour les tests, branché sur des données de test. On retrouve néanmoins chez certains développeurs une tentation de déroger à cette obligation de déployer les DAGs sur deux environnements distincts, notamment pour la récupération de données depuis des sources externes, pour lesquelles il n’y a pas de données de test (par exemple, pour la récupération de données météo depuis une source externe). Cette tentation est, entre autres, justifiée par une volonté de minimiser les coûts de stockage (à quoi bon stocker deux fois des données identiques ?), et les coûts liés à la collecte de données (par exemple, pour la récupération de données depuis une API payante). Les développeurs ne doivent néanmoins pas céder à cette tentation, car il est en effet primordial d’avoir des environnements totalement isolés pour réaliser différents tests sur les données.

Pour limiter le coût lié à la récupération des données, il est possible de mettre pause les DAGs de l’environnement de test depuis l’interface graphique d’Airflow. Néanmoins, l’utilisation de cette fonctionnalité pourrait ne pas être suffisante si on veut à tout prix éviter qu’un DAG s’exécute sur deux environnements distincts en même temps. En effet, à date, Airflow ne demande aucune confirmation lors de l’activation ou la désactivation d’un DAG (via une pop up comme cela est pourtant d’usage afin d’éviter les fausses manipulations). Pour cette raison, il est préférable d’utiliser une variable Airflow pour la gestion de l’expression crontab liée à la planification des jobs. Cette approche permet facilement d’avoir des fréquences différentes pour l’exécution des DAGs sur les environnements de production et de test (sur un environnement de test, il n’y a pas besoin d’avoir des données aussi fraîches que sur un environnement de production) et permet également aux administrateurs Airflow de changer facilement la fréquence d’exécution, sans avoir à redéployer les DAGs.

Mettre en pause un DAG de collection ne doit pas nous empêcher d’alimenter en données les environnements de test. Cette alimentation peut se faire via le lancement ponctuel des DAGs sur les environnements de test Airflow (via les fonctionnalités de triggers externes), ou bien en mettant en place un mécanisme de copie des données anonymisées depuis l’environnement de production.

Gérer des cycles de développement à plusieurs vitesses

Nous retrouvons souvent chez les administrateurs d’Airflow une volonté de centraliser le code source de l’ensemble des DAGs dans un dépôt Git unique, sur lequel est configuré un script de déploiement continu adéquat. L’un des principaux avantages d’Airflow est le déploiement extrêmement simple de nouveaux DAGs, dans le sens où il suffit de copier le code source, tel quel, vers un répertoire qui peut être lu par Airflow. Cette approche a pour avantage de faciliter l’intégration de nouveaux développeurs. Ainsi, un nouveau Data Engineer arrivant sur le projet a accès rapidement à plusieurs exemples de DAGs fonctionnels, développés aux normes dictées par les administrateurs d’Airflow. De même, il sera très simple pour lui de déployer de nouveaux DAGs. En effet, il suffira de lui donner les droits en écriture sur le dépôt Git, où il pourra ajouter les fichiers Python contenant la définition du DAG.

Pour la gestion des environnements, il est possible de mettre en place un premier pipeline de déploiement continu vers l’environnement de test à partir d’une branche “test” sur le dépôt Git, et un autre pipeline pour le déploiement en environnement de production à partir de la branche master. Se pose alors la question des développements concurrents sur la même instance (par exemple, si deux développeurs travaillent sur deux DAGs différents en même temps). On peut dans ce cas s’inspirer des pratiques et des outils mis en oeuvre sur des sujets de développement plus classiques (Gitflow par exemple), en mettant en place des branches pour les nouvelles fonctionnalités (dans notre cas, les nouveaux DAGs)..

Exemple d’un workflow GIT pour le déploiement de DAGs Airflow

Cette approche nécessite néanmoins un certain niveau de maîtrise de Git. Dans le cas contraire, cela représente un risque important pour l’ensemble des DAGs, et il ne faut pas hésiter à multiplier le nombre de dépôts Git (on peut même imaginer avoir un dépôt différent pour chaque DAG). Des outils comme Gitlab ou Bitbucket permettent de regrouper les dépôts Git sous un même projet, ce qui permet de préserver une forme de “centralisation” des DAGs Airflow.

Assurer un suivi des règles de gouvernance

Une autre difficulté liée à l’utilisation d’Airflow par plusieurs profils différents en même temps est de faire respecter des règles de gouvernance pour les DAGs, communes à tous les Data Engineers. En effet, il est important de s’assurer que chacun des DAGs a un nom explicite, qu’ils aient un owner bien spécifié (est-ce qu’il s’agit de l’équipe en charge du DAG, ou bien de la personne qui l’a développé ?), que des adresses mails soient renseignées pour envoyer des alertes en cas d’échec d’un DAG, etc. D’autant plus que les exemples de DAGs fournis avec Airflow ne respectent pas la plupart de ces règles !

Exemple de DAG présent dans le dépôt Git officiel Airflow, qui ne définit pas d’owner

Des vérifications régulières et automatiques peuvent être mises en place afin de garantir que les règles de gouvernance sont bien appliquées. En effet, au moment où Airflow charge les fichiers Python contenant les DAGs, il alimente sa base de données avec une table “dags” et une table “tasks” contenant les métadonnées des DAGs. Ces tables peuvent être utilisées afin de vérifier automatiquement que les règles sont bien respectées ; en créant par exemple un DAG “monitoring_gouvernance” qui réalise cette analyse et envoie des alertes relatives aux DAGs ne respectant pas les règles de gouvernance. Cette option reste néanmoins une solution palliative et n’empêche pas les développeurs de déployer des DAGs ne respectant les règles. La meilleure solution reste donc une revue de code rigoureuse avant tout déploiement d’un DAG ; par exemple, en changeant les permissions sur la branche master pour empêcher tout déploiement sans revue de code préalable.

Assurer la sécurité des accès

Airflow est conçu pour permettre aux développeurs d’accéder à différentes sources de données en lecture/écriture. Les informations d’accès à ces sources (notamment les logins et mots de passe) sont toutes stockées dans la base de données d’Airflow, ce qui la rend particulièrement sensible. Airflow met en place des mécanismes pour protéger les données, notamment le chiffrement des informations dans la base, via la librairie Fernet. Airflow permet également de cacher les variables dont le nom contient par exemple le mot “password”, mais cette fonctionnalité peut être assez problématique, dans le sens où elle donne un faux sentiment de sécurité : Airflow permet depuis son interface d’exporter en clair toutes les variables, même celles qui sont cachées.

Une autre option de sécurisation d’Airflow est l’activation de RBAC : par défaut, toutes les variables, tous les DAGs, et toutes les métriques, sont visibles par l’ensemble des utilisateurs de l’instance. Avec l’activation de RBAC, il est possible de définir des profils d’utilisateurs avec des accès restreints. Ainsi, il est possible de donner la permission à un utilisateur de voir le contenu d’une seule variable parmi toutes celles définies.

Bien que cette fonctionnalité permette de mieux assurer la sécurité, sa mise en place reste assez contraignante. En effet, les développeurs ont souvent besoin d’avoir accès aux contenus des variables et d’en créer des nouvelles. De plus, certaines failles de sécurité persistent ; un développeur peut par exemple ajouter un DAG dans lequel il imprime le contenu d’une variable, qu’il pourra consulter dans les logs d’exécution.

Si la sécurité est un enjeu primordial et qu’il y a une volonté claire de mettre en place des accès différents suivant l’équipe qui intervient sur Airflow, une solution radicale s’impose : créer autant d’instances que d’équipes différentes. Cette approche n’implique pas forcément une charge aussi importante qu’on pourrait le penser pour les déploiements. En effet, plusieurs solutions existent pour déployer en quelques clics de nouvelles instances Airflow sur GCP, AWS ou Azure. Sur AWS par exemple, nous retrouvons en ligne des stacks CloudFormation pour le déploiement de clusters Airflow totalement industrialisés. Sur GCP, la problématique est encore plus simple : il suffit de créer une nouvelle instance de Google Cloud Composer, qui n’est rien d’autre qu’une version d’Airflow packagée par Google.

Lutter contre les DAGs trop “gourmands”

Enfin, l’un des problèmes rencontrées lorsqu’on laisse une instance Airflow en “libre service” pour plusieurs équipes, c’est que certaines équipes finissent par s’accaparer toutes les ressources (RAM et CPU) des workers. Ceci est d’autant plus vrai quand les équipes utilisent massivement les PythonOperator, qui permettent d’exécuter du code Python directement dans les tâches. Ceci a pour incidence de faire planter l’exécution de certains DAGs. Une première solution consiste à diminuer la “task concurrency” et la “DAG concurrency”, évitant ainsi d’avoir plusieurs tâches qui tournent en parallèle et se battant pour des ressources. Une seconde solution consiste à utiliser des files d’exécution différentes (permettant ainsi d’isoler les DAGs trop gourmands). Mais il s’agit dans les deux cas de solutions palliatives, et ne permettant pas de résoudre dans la durée ces problématiques de performance. Les autres options consistent à mettre en place des stratégies d’autoscaling, afin de redimensionner les workers de manière automatisée, ou bien à adopter une approche plus serverless des DAGs. Par exemple, si on souhaite lancer une analyse simple sur des fichiers plats présents dans un datalake construit sur GCS (ou S3), il vaudra mieux privilégier le lancement de requêtes via Airflow sur des tables externes BigQuery (ou AWS Athena) branchées aux buckets, plutôt que de charger les fichiers depuis le code Python dans un PythonOperator.

Conclusion

Malgré quelques difficultés rencontrées dans sa mise en oeuvre à grande échelle, Airflow reste selon nous la solution open source de référence pour l’orchestration de flux, pour sa flexibilité, ses nombreux opérateurs, et sa communauté d’utilisateurs de plus en plus active ; y compris à travers le meetup Airflow Paris. Toutefois, les problématiques de mise à l’échelle évoquées dans cet article mettent en évidence le rôle important d’un métier au sein de l’écosystème Data assez méconnu : celui d’ingénieur DataOps. Mettant en application les principes DevOps et Agile, le DataOps intervient à chacune des étapes du cycle de vie de la donnée pour assurer un meilleur suivi de la qualité des données et de la bonne santé des flux de collecte et de traitement. Nous reviendrons vers vous prochainement dans un article sur le rôle du DataOps dans les différents projets Data menés par neoxia !

--

--