data engineering

Comment nous avons construit un moteur ELT piloté par configuration pour orchestrer l'ingestion de 39 datasets sur le Cloud AWS

N
Nassim El Ghazaz
|14 avril 2026|10 min read
Comment nous avons construit un moteur ELT piloté par configuration pour orchestrer l'ingestion de 39 datasets sur le Cloud AWS

Lorsque nous avons commencé à construire des lacs de données (data lakes) pour des entreprises gérant des paysages informatiques complexes, nous sommes rapidement tombés sur un problème auquel chaque équipe de données est tôt ou tard confrontée : l'étalement des pipelines.

Le client avait des dizaines de tables ERP à ingérer. Données de ventes, données de référence, dossiers de qualité, exportations financières, rapports sur la santé et la sécurité environnementales. Chacune avait sa propre logique d'extraction, son propre calendrier d'exécution, ses propres particularités. L'approche classique aurait été d'écrire un pipeline dédié pour chacune. Copier le modèle, ajuster la configuration, déployer. Répéter quarante fois.

Nous n'avons pas emprunté cette voie.

Au lieu de cela, nous avons construit un moteur unique qui lit un fichier de configuration YAML et génère dynamiquement l'ensemble du flux de travail d'ingestion. Aujourd'hui, ce moteur gère 39 sources de données à travers 8 domaines d'activité, orchestré par AWS Step Functions, alimenté par cinq fonctions Lambda de base, et maintenu par une équipe qui touche rarement au code d'ingestion désormais. Lorsqu'un nouveau jeu de données doit arriver, quelqu'un ajoute quelques lignes à un fichier YAML et déploie. C'est tout.

Cet article explique comment nous l'avons conçu, pourquoi l'ELT piloté par la configuration change la donne pour les plateformes de données d'entreprise, et les modèles AWS spécifiques qui le rendent possible.

Le problème avec le data pipeline par source

La plupart des équipes de données commencent par une approche raisonnable. Vous devez ingérer un tableau de votre ERP? Écrivez une Lambda, configurez une machine à états Step Function, câblez le catalogue Glue, déployez. Cela prend une journée, peut-être deux. Terminé.

Maintenant, multipliez cela par quarante. Soudainement, vous avez quarante fonctions Lambda légèrement différentes, quarante piles CloudFormation, quarante choses à surveiller, corriger et déboguer lorsque quelque chose se casse à 3 heures du matin. Ils font tous essentiellement la même chose avec des variations mineures dans le schéma, la planification et la logique de transformation. Mais comme chacun a sa propre base de code, une correction de bug signifie la mise à jour de quarante dépôts.

Nous avons observé ce schéma dans des entreprises de toutes tailles, des équipes de taille moyenne en pleine croissance aux grandes organisations. L'équipe d'ingénierie de données devient un goulot d'étranglement, non pas parce que le travail est difficile, mais parce que le travail est répétitif et chaque nouvelle source signifie un autre pipeline sur mesure.

La question que nous nous sommes posée était simple : qu'est-ce qui change réellement entre ces pipelines ? La réponse s'est avérée être étonnamment peu.

Configuration en tant que source unique de vérité

L'idée principale était que la plupart des variations entre les pipelines peuvent être exprimées en tant que données, et non en code. Ce qui change d'un tableau ERP à un autre est le nom de l'objet, le format de fichier, la nécessité d'une extraction delta, quels champs sélectionner, et si le jeu de données est suffisamment grand pour nécessiter un traitement par lots.

Nous avons donc centralisé tout cela dans un seul fichier de configuration YAML. Voici une version simplifiée de ce à quoi ressemble une famille de jeux de données:

YAML
1qualityManagement:
2  description: "Quality management objects"
3  objects:
4    - name: QALS
5      format: tsv
6      deltaField: "ENSTEHDAT:2020:CURRENTYEAR"
7      deltaStrategy: "1"
8      batchProcessing: true
9      fieldsList: "PRUEFLOS;WERK;ART;STAT"
10
11    - name: QAVE
12      format: tsv
13
14    - name: QASR
15      format: tsv
16      fieldsList: "PRUEFLOS;VESSION;VESSION_EXT"

Notez comment chaque objet hérite de valeurs par défaut sensées. Si vous avez juste besoin d'une extraction complète simple au format TSV, l'entrée de configuration est de deux lignes. Si vous avez besoin d'extraction delta avec sélection de champs et traitement par lots, vous ajoutez ces propriétés. Le moteur gère le reste.

Nous avons regroupé les ensembles de données en neuf familles logiques : données de base, ventes, finances, qualité, RH, autorisations, et ainsi de suite. Chaque famille a son propre calendrier et son propre ensemble d'objets. Ajouter une nouvelle table à une famille existante revient littéralement à ajouter un bloc YAML et à déployer.

L'Architecture: Un Moteur, Deux Chemins

Le moteur fonctionne sur AWS Step Functions avec un modèle d'orchestration à deux niveaux.

Au niveau supérieur, une Machine d'État principale se déclenche selon un calendrier via EventBridge. Chaque famille de jeux de données a son propre déclencheur CRON. La plupart des familles s'exécutent une fois par jour. Les familles à haute vélocité comme les données de ventes s'exécutent deux fois par jour. La Machine d'État principale appelle une Lambda de Mapping de Configuration de Tâche, qui lit la configuration YAML et renvoie une liste de payloads utiles, une par objet dans cette famille.

Les Step Functions parcourent ensuite cette liste en utilisant un état Map, traitant jusqu'à dix objets en parallèle. Chaque objet déclenche une Machine d'État ELT qui gère l'extraction, le chargement et la transformation proprement dits.

La machine d'état ELT a deux chemins d'exécution selon la façon dont les données arrivent.

Pour l'extraction basée sur le tirage, le moteur appelle le système ERP directement via des connecteurs RFC, récupère les données, agrège des fichiers en plusieurs parties en un seul fichier d'atterrissage sur S3, puis exécute une requête INSERT Athena pour déplacer les données de la zone d'atterrissage (landing) vers la zone brute (raw).

Pour l'ingestion basée sur le push (dépôts de fichiers à partir du transfert de fichiers géré), le moteur détecte le nouveau fichier via un événement S3, valide le schéma par rapport aux en-têtes de colonne attendus, applique les transformations personnalisées via Athena SQL et archive le fichier traité.

Les deux chemins aboutissent au même endroit : une table propre et typé dans le catalogue Glue, situé dans l'une des huit bases de données brutes spécifiques au domaine, prête pour les consommateurs en aval.

Cinq fonctions Lambda qui font tout

L'ensemble du moteur fonctionne sur cinq fonctions Lambda principales. Chacune a une responsabilité unique.

Le Job Config Mapper est le cerveau. Il reçoit un nom de famille de datasets, charge la configuration YAML, et produit une liste de payloads utiles d'exécution. Chaque payload contient tout ce dont les étapes suivantes ont besoin : le nom de l'objet, le bucket S3 cible, les paramètres d'extraction delta, les indicateurs de traitement par lots. Les variables d'environnement injectent le contexte d'exécution comme les noms de bases de données et les chemins de bucket, donc le même code fonctionne sur dev, staging et production sans modification.

Le Batch Processor gère de grands datasets avec beaucoup de données historiques. Lorsqu'un objet a le traitement par lots activé, cette fonction divise l'extraction en segments annuels. Une table avec des données de 2020 à 2026 devient six extractions séparées, chacune couvrant une année. Cela maintient une faible pression sur la mémoire, isole les échecs (si le lot de 2023 échoue, les autres sont toujours terminés) et vous offre une granularité de surveillance année par année. Les lots s'exécutent séquentiellement pour éviter de surcharger le système source.

Le Files Aggregator gère les exportations en plusieurs parties. Les systèmes ERP d'entreprise divisent souvent les grandes extractions en plusieurs fichiers. Cette fonction les consolide en un seul fichier en utilisant les téléchargements multiparties S3. Les petits fichiers (moins de 10 Mo) sont agrégés en mémoire ; les gros fichiers sont directement diffusés comme parties de téléchargement. À la fin, il génère la requête SQL Athena qui déplacera les données du landing vers le raw.

Le gestionnaire Prepare and Analyze traite les ingestions de dépôt de fichiers en deux phases. La phase de préparation extrait les métadonnées de l'événement S3, associe le fichier à son domaine et sa table cibles, et configure les chemins de copie et d'archivage. La phase d'analyse lit les premiers kilobytes du fichier, valide le délimiteur avec le sniffer CSV et vérifie les en-têtes de colonne par rapport aux schémas attendus. Si quelque chose semble incorrect, le pipeline s'arrête avant que des données incorrectes n'entrent dans la zone brute.

Le Gestionnaire d'erreurs est le filet de sécurité. Chaque échec dans la machine d'état est acheminé ici. Il normalise les informations d'erreur et les envoie au système centralisé d'orchestration des tâches, où l'équipe des opérations peut les voir aux côtés des échecs de tous les autres "ingesters".

Pourquoi choisir Athena pour les transformations

Une question que nous posons souvent est pourquoi nous utilisons Athena pour la transformation de landing-to-raw au lieu de le faire dans Lambda ou Glue.

La réponse est pratique. La transformation à ce stade est relativement simple : prendre les données de la table d'atterrissage, ajouter un horodatage d'intégration, appliquer un certain type de casting our parsing de date pour des tables spécifiques, et insérer dans la table brute. Athena gère cela avec une seule instruction SQL, et elle s'adapte automatiquement. Pas de cluster à gérer, pas de surcharge Spark pour ce qui est essentiellement un SELECT... INSERT INTO.

Pour les tables standard, le SQL est généré dynamiquement :

SQL
1INSERT INTO master_data_raw.erp_material
2SELECT [columns],
3    CAST(CURRENT_TIMESTAMP AS TIMESTAMP) AS integrationdate
4FROM landing_database.erp_material_landing

Pour les tableaux qui nécessitent des transformations personnalisées (analyse de format de date, logique conditionnelle, renommage de champs), nous avons des fonctions SQL dédiées qui produisent la requête appropriée. L'essentiel est que même ces requêtes personnalisées sont invoquées via la même étape de la machine d'état. Le pipeline ne se soucie pas si le SQL est trivial ou complexe. Il exécute la requête, vérifie les erreurs, et passe à la suivante.

Voici à quoi ressemble réellement l'intégration d'un nouvel ensemble de données

C'est là que la conception se révèle payante. Lorsqu'une équipe d'entreprise vient vers nous et dit qu'elle a besoin d'une nouvelle table ERP dans le lac de données, voici ce qui se passe.

Tout d'abord, nous ajoutons l'objet à la configuration YAML sous la famille appropriée. S'il s'agit d'une extraction complète simple, cela représente deux lignes. S'il nécessite un chargement delta ou un traitement par lots, quelques lignes supplémentaires.

Deuxièmement, nous créons les tables du Glue Catalog pour les zones de landing et raw. Il s'agit d'une définition de schéma unique.

Troisièmement, nous déployons. La construction SAM récupère la nouvelle configuration, et la prochaine exécution programmée inclut automatiquement le nouvel objet.

Aucune nouvelle fonction Lambda. Aucunes nouvelles machines d'état. Aucuns nouveaux stacks CloudFormation. Le moteur sait déjà comment gérer cela car la logique est générique et les spécificités résident dans la configuration.

En pratique, l'intégration d'un nouveau jeu de données standard prend environ trente minutes. La majeure partie de ce temps est consacrée à la définition de la table Glue, et non au code du pipeline.

Leçons apprises en cours de route

Les limites de concurrence sont plus importantes que vous ne le pensez. Nous plafonnons l'exécution parallèle à dix objets par famille. Au début, nous avons tout fait sans restriction et avons parfois submergé la couche RFC du système ERP. La limite de débit est un choix délibéré: assez rapide pour être terminée dans la fenêtre de planification, assez douce pour éviter d'impacter les charges de travail transactionnelles.

Le traitement par lots séquentiel est une caractéristique, pas une limitation. Lors du traitement de grands ensembles de données historiques, l'exécution de lots en parallèle semble attrayante mais crée des pics de mémoire imprévisibles et peut déclencher un bridage. Le traitement séquentiel avec des partitions annuelles vous offre une consommation prévisible des ressources et une isolation des erreurs plus nette.

La validation du schéma détecte les problèmes tôt. Le renifleur CSV et la validation des en-têtes de colonnes dans la phase d'analyse nous ont sauvés plus d'une fois de la corruption silencieuse des données. Un fichier avec le mauvais délimiteur ou une colonne manquante est rejeté avant d'atteindre la zone brute, au lieu de produire des résultats déroutants en aval.

Le backoff exponentiel n'est pas optionnel. Chaque étape de la machine d'état possède une logique de réessai avec un backoff exponentiel (commençant à 15 secondes, jusqu'à 5 réessais). Les défaillances transitoires dues au throttling d'Athena, à la cohérence finale de S3 ou aux démarrages à froid de Lambda se résolvent d'elles-mêmes sans intervention humaine dans la grande majorité des cas.

Séparer le landing du raw, toujours. La zone de landing est éphémère. Les fichiers arrivent, sont validés, transformés dans la zone brute, puis archivés ou supprimés. Cette séparation signifie que vous pouvez toujours rejouer à partir de la source si quelque chose ne va pas, et la zone brute reste propre et typée.

La Big Picture

Ce moteur est un élément d'une plateforme de données plus vaste qui dessert plus de trente applications clientes dans seize domaines d'activité. L'approche basée sur la configuration au niveau de l'ingestion donne le ton pour toute l'architecture: convention plutôt que configuration, moteurs génériques plutôt que pipelines sur mesure, et simplicité opérationnelle comme objectif de conception de premier ordre.

Pour les organisations traitant des exigences strictes de gouvernance des données, ce modèle présente un autre avantage. Comme chaque pipeline suit le même chemin à travers le même moteur, l'audit et la conformité deviennent simples. Vous pouvez retracer n'importe quel enregistrement de la zone brute jusqu'à son fichier source, son horodatage d'ingestion et la configuration exacte qui a régi son traitement.

Si vous construisez une plateforme de données et vous vous retrouvez à copier des modèles de pipeline pour chaque nouvelle source, prenez du recul. Identifiez ce qui varie réellement. Placez cette variance dans la configuration. Construisez un moteur qui gère le reste. Votre futur vous-même (et votre équipe opérationnelle) vous en remerciera.


Chez VERAPLOT, nous construisons des plateformes de données pour les entreprises qui ont besoin d'aller vite sans rien casser. Que vous soyez une équipe en pleine croissance avec dix sources de données ou une grande organisation avec des centaines, notre objectif est de nous concentrer sur les architectures AWS natives utilisant Python, Step Functions, Glue, Athena et l'écosystème serverless plus large. Si la prolifération des pipelines vous ralentit, nous aimerions en parler.

Contactez-nous sur veraplot.com

data engineeringAWSELTconfiguration-drivendata ingestion

Comments

0/3000