Table des matières

TD2 - De Docker à AWS EMR : Hadoop managé dans le cloud

Big Data et traitement massif - séance 2

Important - environnement AWS

Ce TD utilise la console AWS et quelques commandes exécutées depuis un terminal. Il s’agit d’une découverte manuelle d’Amazon EMR. N’utilisez ni Terraform ni CloudFormation dans ce TD : l’automatisation de cette infrastructure fera l’objet du TD3.

AWS est un environnement payant. Pensez à activer une alerte sur AWS Budget si vous dépassez une limite de 1$.

Prérequis avant la séance (TD2 - AWS EMR)

À faire avant le jour du TD : un délai d’activation peut être nécessaire.

  1. Se connecter à la console AWS avec son compte personnel (Free Tier).
  2. Aller dans le service EMR (Elastic MapReduce), via la barre de recherche en haut de la console.
  3. Si le message « Complete your account setup » apparaît (accès limité en « Free Plan »), cliquer sur le bouton « Upgrade plan ». Aucune information supplémentaire ne devrait être demandée si les informations de paiement sont déjà enregistrées : la mise à niveau est instantanée et gratuite, sans plan de support payant à choisir.
  4. Vérifier que la page d’accueil du service EMR s’affiche, sans message de blocage.
  5. Cette étape n’affecte pas le solde de crédit Free Tier (100–150 $ selon les comptes) et ne génère pas de facturation. Il s’agit uniquement d’une vérification de compte requise par AWS pour débloquer l’accès à certains services.

Objectifs

À la fin du TD, vous devez être capables de :

Fil rouge : les ventes d’un site e-commerce

Dans la séance précédente, vous avez généré un fichier `ventes.csv`, puis vous avez travaillé dans un mini-cluster Hadoop lancé avec Docker Compose. Le chemin logique utilisé était notamment :

/data/ecommerce/ventes.csv
/data/ecommerce/input/
/data/ecommerce/output/

Vous reprenez le même générateur Python et le même format de fichier. Le résultat métier demandé reste le même : calculer le chiffre d’affaires total par catégorie avec MapReduce Streaming.

Dans la séance précédente, les conteneurs simulaient les machines d’un cluster sur votre poste. Dans ce TD, les machines sont des instances EC2 provisionnées par Amazon EMR dans un VPC AWS.

Question de départ

Votre fichier actuel fait peut-être quelques mégaoctets. Et si `ventes.csv` pesait 500 Go ? Sur combien de machines faudrait-il le stocker et le traiter ? Que faudrait-il configurer vous-même, et que pourrait prendre en charge un service managé ?

Écrivez vos premières hypothèses avant de commencer. Vous les vérifierez dans les missions suivantes.

Préparation - vérifier les éléments disponibles

Avant de créer quoi que ce soit :

  1. récupérez le script de génération de `ventes.csv` de la séance précédente ;
  2. récupérez `mapper.py` et `reducer.py` de la séance précédente ;
  3. vérifiez que vous avez accès à la console AWS ;
  4. sélectionnez la région AWS eu-west-3.

Mission 1 - Créer un cluster EMR avec la console AWS

Objectif

Vous devez fournir une infrastructure Hadoop capable d’exécuter le traitement des ventes. Vous ne démarrez plus quatre conteneurs à la main : vous devez décrire le cluster à un service cloud et comprendre les choix proposés.

1.1 Ouvrir EMR et préparer la création

  1. Connectez-vous à la console AWS avec votre compte perso.
  2. Vérifiez la région affichée en haut à droite.
  3. Ouvrez Amazon EMR puis la page de gestion des clusters.
  4. Choisissez la création d’un cluster, et non un cluster « instantané » ou une fonction d’analyse préconfigurée si plusieurs parcours sont proposés

1.2 Choisir les logiciels

Dans la configuration logicielle :

  1. sélectionner la version EMR emr-7.14.0 ;
  2. choisir l'offre d'applications Spark Interactive, qui installe automatiquement Hadoop, YARN, HDFS et MapReduce (inclus dans le socle Hadoop, non affichés séparément dans la liste des applications) ;
  3. vérifier que Hive, Spark, Livy et JupyterEnterpriseGateway sont bien cochés (sélection par défaut de cette offre) ;
  4. ne cocher aucune application supplémentaire (Pig, Oozie, HBase, Presto, Trino, Zeppelin, Flink, TensorFlow, etc.) : elles ne sont pas nécessaires pour ce TD et alourdissent inutilement le démarrage du cluster ;
  5. noter la version exacte affichée dans la console.

Les noms de menus et la version exacte peuvent évoluer dans la console. Ce qui compte ici est de relever la release EMR, la version Hadoop et les applications réellement installées, plutôt que de recopier aveuglément une capture d'écran.

Relevez dans la console la région, la release EMR, l’offre d’applications et les versions Hadoop/YARN. Vérifiez surtout que Hadoop, HDFS, YARN, MapReduce, Hive et Spark sont effectivement installés ; indiquez en une phrase pourquoi les applications supplémentaires ne sont pas nécessaires ici.

Remarque : YARN, HDFS et MapReduce ne sont pas des cases à cocher séparées dans la console EMR - ils font partie intégrante du socle Hadoop installé dès que “Hadoop” est sélectionné (ce qui est automatique avec l'offre Spark Interactive). Il n'y a donc pas de choix à faire les concernant, seulement à vérifier leur présence et leur version dans les détails du cluster une fois créé.

1.3 Comprendre les nœuds

Dans la section matériel, la console AWS propose un choix entre groupes d'instances uniformes (par défaut) et flottes d'instances flexibles. Gardez le mode par défaut pour ce TD.

La console affiche alors trois rôles :

Remplacez le type d'instance par défaut par une instance généraliste standard, plus universellement compatible :

Configuration recommandée pour ce TD :
  Primaire         : m5.xlarge
  Unité principale : m5.xlarge
  Tâche - 1        : m5.xlarge

Groupe EMR Nombre choisi Type d'instance Rôle attendu
Primaire 1 m5.xlarge services de coordination, NameNode, ResourceManager
Unité principale 3 m5.xlarge stockage HDFS et exécution YARN
Tâche - 1 1 m5.xlarge exécution YARN sans stockage HDFS durable du cluster

La famille m5 est une famille d'instances généralistes (x86_64, Intel), le choix le plus répandu et documenté pour EMR/Hadoop. Elle offre un bon équilibre CPU/mémoire, suffisant pour ce TD.

À noter : avec les 3 instances d'unité principale, la réplication HDFS par défaut (facteur 3) devrait être respectée.

1.4 Comprendre les rôles des nœuds

Dans une architecture Hadoop, le nœud qui coordonne les métadonnées et les ressources n’est pas un nœud de stockage de données utilisateur. Les nœuds qui portent les DataNodes stockent les blocs HDFS et exécutent généralement des tâches YARN ; les nœuds task ajoutent surtout de la capacité de calcul et ne doivent pas être assimilés à une copie des données.

Complétez mentalement le rapprochement avec le mini-cluster Docker étudié précédemment, puis répondez :

  1. Quels services associez-vous aux rôles Primary (Primaire), Core (Unité principale) et Task (Tâche) ?
  2. Que se passe-t-il si l’on ajoute 10 nœuds task mais aucun nœud core ?
  3. Le cluster choisi démontre-t-il une tolérance de panne réelle ? Justifiez en tenant compte du nombre de nœuds core et du facteur de réplication.

1.5 Réseau

Sur un compte AWS standard, un VPC par défaut existe déjà dans chaque région, avec un subnet public dans chaque zone de disponibilité. EMR le sélectionne automatiquement : il n'y a rien à créer ni configurer manuellement pour ce TD.

Dans la section réseau de l'assistant de création :

1. vérifiez que le VPC proposé est bien le VPC par défaut (``vpc-xxxxxxxx (default)``) ;
2. un subnet est présélectionné : laissez la valeur proposée ;
3. les security groups sont créés automatiquement par EMR (un pour le master, un pour les core/task) si vous ne modifiez rien.

Notez les valeurs proposées automatiquement :

Notez dans le compte rendu le VPC, le subnet, les deux security groups et la présence d’une adresse publique pour le master.

Le security group du master créé par défaut n'autorise pas le SSH entrant. Il faudra l'ouvrir manuellement après la création du cluster (voir section suivante) pour pouvoir vous connecter.

Répondez :

  1. Pourquoi un cluster peut-il avoir besoin d'une communication interne même si vous ne vous connectez qu'au master ?
  2. Pourquoi les nœuds core et task ne doivent-ils généralement pas être ouverts directement à Internet ?

1.6 Paire de clés EC2 (accès SSH)

Pour pouvoir se connecter en SSH au nœud primaire du cluster (console, exécution manuelle de commandes Hadoop, consultation de fichiers de logs), une paire de clés EC2 est nécessaire.

  1. Si vous possédez déjà une paire de clés EC2 dans la région utilisée, vous pouvez la réutiliser.
  2. Sinon, créez-en une nouvelle avant de lancer le cluster :

Étapes (en dehors de la création du cluster EMR) :
  EC2 > Réseau et sécurité > Paires de clés > Créer une paire de clés
  Nom : td-hadoop-votrenom
  Type de clé : RSA
  Format de fichier privé :
     - .pem si vous vous connectez depuis Linux/Mac ou WSL
     - .ppk si vous utilisez PuTTY sous Windows

Le fichier de clé privée est téléchargé une seule fois. Conservez-le précieusement (par exemple dans votre dossier utilisateur, avec des droits restreints) : il ne pourra pas être retéléchargé depuis la console AWS.

Sous Linux/Mac, pensez à restreindre les droits du fichier avant de l'utiliser :

chmod 400 td-hadoop-votrenom.pem

Dans la configuration du cluster EMR, section Sécurité, sélectionnez cette paire de clés dans le menu déroulant Paire de clés EC2 (SSH).

1.7 Rôles IAM

EMR nécessite deux rôles IAM pour fonctionner :

Dans la section Rôle IAM, AWS propose deux options pour chacun de ces deux rôles :

Cas attendu : votre compte est un compte AWS standard (personnel, free tier ou passé en basic)

Sur ce type de compte, vous disposez normalement des droits IAM complets. Choisissez Créer une fonction du service pour les deux champs. AWS génère automatiquement les rôles nécessaires, généralement nommés :

  1. ``EMR_DefaultRole`` ou ``AmazonEMR-ServiceRole-xxxx`` (rôle de service) ;
  2. ``EMR_EC2_DefaultRole`` ou ``AmazonEMR-InstanceProfile-xxxx`` (profil d'instance EC2).

Ces rôles seront ensuite proposés automatiquement lors des prochaines créations de cluster. C'est le cas normal et attendu pour ce TD.

Cas exceptionnel : erreur de création (droits IAM restreints ou rôle déjà partiellement créé)

Il peut arriver, même sur un compte standard, qu'un des deux rôles existe déjà (par exemple suite à un essai antérieur) sans que le second n'existe. Ce n'est pas incohérent : ce sont deux ressources IAM indépendantes.

Si vous tentez Créer une fonction du service pour le champ Fonction du service EC2 et obtenez une erreur du type :

Échec de la création du rôle EMR_EC2_DefaultRole. Vous n'obtenez peut-être pas l'autorisation nécessaire pour effectuer cette action.

Marche à suivre dans ce cas :

  1. Retournez sur Choisir une fonction du service existant pour le champ Fonction du service EC2 ;
  2. vérifiez si un rôle apparaît dans la liste déroulante, par exemple ``EMR_EC2_DefaultRole`` (déjà créé lors d'un essai précédent) ;
  3. sélectionnez-le s'il apparaît.

1.8 Associer la clé SSH et créer le cluster

1. Sélectionnez la paire de clés EC2 fournie ou créée pour le TD. 2. Vérifiez une dernière fois la région, le nombre d’instances, le type d’instance, le rôle IAM et le réseau. 3. Créez le cluster. 4. Observez les états successifs : démarrage, configuration, attente, en cours d’exécution. 5. Tant que le cluster n’est pas à l’état Waiting ou équivalent, ne lancez pas le job.

Le bouton de création lance des ressources facturées. Relevez l’heure de création et le nom du cluster. Le nettoyage de la Mission 7 est obligatoire, même si le job échoue.

Mission 2 - Explorer le cluster depuis le master

2.1 Récupérer l’adresse du master

Dans la page du cluster, ouvrez les détails et relevez le DNS ou l’adresse publique du nœud primaire. Depuis votre poste :

ssh -i ma-cle-emr.pem hadoop@DNS_PUBLIC_DU_MASTER

Le nom d’utilisateur dépend de l’image. Pour une AMI EMR standard, `hadoop` est couramment utilisé ; ne remplacez pas ce nom au hasard si la consigne de votre compte indique autre chose.

À la première connexion, vérifiez l’empreinte proposée. Si vous obtenez `Permission denied (publickey)`, contrôlez le chemin de la clé, `chmod 400`, le nom d’utilisateur et la règle SSH du security group.

2.2 Identifier la machine

hostname
whoami
cat /etc/os-release | head
free -h
df -h

Relevez le nom d’hôte et la mémoire visible. Comparez la machine avec votre ordinateur et avec le conteneur master de la séance précédente.

2.3 Observer HDFS

Exécutez :

hdfs dfs -ls /
hdfs dfs -df -h
hdfs dfsadmin -report

Selon la version, la sortie peut contenir des lignes supplémentaires. Relevez au minimum : nombre de DataNodes vivants, capacité totale, capacité utilisée et espace restant.

Indicateur observé Valeur relevée Interprétation
DataNodes vivants / morts
Capacité et espace utilisé HDFS
Nœuds YARN disponibles
Processus repérés avec `jps`

Le stockage HDFS répartit les blocs sur les DataNodes, tandis que YARN attribue des ressources aux applications via les NodeManagers. Cette distinction permet d’interpréter les sorties de `hdfs dfsadmin -report` et `yarn node -list` sans supposer que tous les nœuds ont le même rôle.

Questions :

  1. Le nombre de DataNodes est-il égal au nombre total de machines ? Pourquoi ?
  2. La réplication HDFS apporte-t-elle une persistance après la destruction du cluster ? Justifiez.
  3. En quoi `yarn node -list` complète-t-elle `hdfs dfsadmin -report` ?

Dans un cluster EMR, la répartition exacte des démons dépend de la release, des options et du type de nœud. Utilisez les commandes et la console comme source d’observation : ne concluez pas à partir du seul nom « master », « core » ou « task ».


Mission 3 - Accéder aux interfaces web avec un tunnel SSH

Objectif

Dans la séance précédente, vous ouvriez des ports Docker exposés sur `localhost`. Dans AWS, les interfaces du master ne doivent pas être publiques par défaut. Comment observer l’interface NameNode et l’interface YARN sans ouvrir leurs ports à Internet ?

3.1 Vérifier l’accès direct

Depuis votre poste, essayez éventuellement d’ouvrir l’URL de l’interface indiquée dans la console EMR ou dans la documentation de la release. Si l’accès direct échoue, c’est une information utile : le service existe dans le réseau du cluster, mais n’est pas exposé à votre navigateur.

N’ajoutez pas une règle `0.0.0.0/0` simplement pour faire fonctionner l’interface.

3.2 Mettre en place un tunnel local

Gardez une première session SSH ouverte. Dans un second terminal, créez des redirections locales vers les ports web du master. Les numéros de ports peuvent varier selon la release ; utilisez ceux affichés dans la console.

ssh -i ma-cle-emr.pem \
  -N \
  -L 9870:localhost:9870 \
  -L 8088:localhost:8088 \
  hadoop@DNS_PUBLIC_DU_MASTER

Ouvrez ensuite dans votre navigateur :

http://localhost:9870
http://localhost:8088

Le port `9870` est fréquemment associé à l’interface web du NameNode et `8088` à celle du ResourceManager, mais vérifiez la page de votre cluster. Si un service utilise un autre port, remplacez la redirection.

Pour explorer plusieurs interfaces sans ajouter chaque port, vous pouvez utiliser un proxy SOCKS dynamique si la consigne le permet :

ssh -i ma-cle-emr.pem -N -D 8157 hadoop@DNS_PUBLIC_DU_MASTER

Configurez ensuite le navigateur ou une extension pour utiliser un proxy SOCKS5 sur `localhost:8157`. Cette méthode n’est pas équivalente à une publication de ports : le navigateur envoie ses requêtes à travers la session SSH.

3.3 Observer et comparer

Dans l’interface NameNode, relevez l’état des DataNodes, la capacité et les blocs. Dans l’interface YARN, relevez les nœuds, les ressources et les applications.

Relevez directement dans les deux interfaces le nombre de DataNodes live, la capacité HDFS utilisée, les nœuds YARN actifs, les ressources disponibles et les applications en cours.

Questions :

  1. Pourquoi le navigateur peut-il afficher `localhost` alors que le NameNode est dans AWS ?
  2. Quelle différence de sécurité entre un port Docker publié localement et un tunnel SSH ?

Mission 4 - Stocker les données dans HDFS et dans S3

Objectif

Vous devez placer `ventes.csv` dans le cluster pour une première observation, mais aussi le conserver indépendamment du cluster. Déposez-le dans HDFS et dans Amazon S3, puis comparez les deux stockages.

4.1 Préparer un espace S3

Les noms de buckets S3 doivent respecter les contraintes suivantes :

Créez votre bucket avec la commande suivante :

aws s3 mb s3://NOM_DU_BUCKET --region eu-west-3

Remplacez NOM_DU_BUCKET par le nom choisi. La région eu-west-3 (Paris) est celle utilisée pour ce TD ; assurez-vous que votre cluster EMR est bien créé dans la même région.

aws s3api put-object --bucket NOM_DU_BUCKET --key td2/
aws s3api put-object --bucket NOM_DU_BUCKET --key td2/input/
aws s3api put-object --bucket NOM_DU_BUCKET --key td2/output/

Vérifiez enfin votre identité AWS et l'accès au préfixe du bucket :

aws sts get-caller-identity
aws s3 ls s3://NOM_DU_BUCKET/td2/

La première commande permet d'identifier le compte et l'utilisateur ou le rôle IAM utilisés. La seconde vérifie que les droits permettent bien d'accéder à l'espace S3 du binôme. Ne copiez pas de clé personnelle sur le master. Si la commande aws n'est pas configurée comme attendu, vérifiez le rôle IAM associé au profil d'instance.

4.2 Copier les données dans S3

Vous pouvez déposer le fichier depuis votre poste avec la console S3 ou avec l’AWS CLI. Exemple depuis le poste, avec authentification configurée :

aws s3 cp ventes.csv \
  s3://NOM_DU_BUCKET/td2/input/ventes.csv
aws s3 ls s3://NOM_DU_BUCKET/td2/input/

Si vous avez d’abord copié le fichier sur le master, exécutez plutôt la commande depuis le master. Notez la taille affichée et, si possible, l’horodatage.

4.3 Copier également le fichier dans HDFS

Depuis le master :

hdfs dfs -mkdir -p /data/ecommerce/input
hdfs dfs -put -f ventes.csv /data/ecommerce/input/ventes.csv
hdfs dfs -ls -h /data/ecommerce/input
hdfs dfs -du -h /data/ecommerce/input/ventes.csv

Contrôlez le contenu sans afficher tout le fichier :

hdfs dfs -cat /data/ecommerce/input/ventes.csv | head
aws s3 cp s3://NOM_DU_BUCKET/td2/input/ventes.csv - | head

Comparez les deux sorties : en-tête, séparateur, ordre des colonnes et premières lignes doivent être compatibles avec la séance précédente.

4.4 Comparer HDFS, S3 et EMRFS

Dans les traitements EMR, un chemin s3://... peut être utilisé comme source ou destination par Hadoop grâce à la couche d'intégration S3 d'EMR, souvent appelée EMRFS. Vous allez l'utiliser sans la traiter comme un disque local.

Critère HDFS du cluster EMR S3
Dépendance au cluster actif
Répartition / persistance
Usage dans ce TD

Répondez :

  1. Après la suppression du cluster, que deviennent le fichier HDFS et l’objet S3 ?
  2. Pourquoi S3 convient-il à la conservation des entrées et sorties, sans être un disque local du master ?

S3 n’est pas un espace temporaire gratuit. Les objets restent présents et peuvent continuer à entraîner des coûts selon la classe, les requêtes et les transferts.


Mission 5 - Relancer MapReduce Streaming depuis S3

Contexte

Dans la séance précédente, le job lisait un fichier local ou HDFS du cluster Docker. Cette fois, le fichier d’entrée est dans S3 et le résultat doit également être écrit dans S3. Le calcul métier ne change pas.

5.1 Vérifier le contrat du job

Réutilisez `mapper.py` et `reducer.py` de la séance précédente.

#!/usr/bin/env python3
import sys

for line in sys.stdin:
    line = line.strip()

    if line.startswith("date"):  # on saute l'en-tête
        continue

    champs = line.split(",")
    date_vente, commande_id, client_id, categorie, ville, montant = champs

    # clé = catégorie, valeur = montant
    print(f"{categorie}\t{montant}")

#!/usr/bin/env python3
import sys
 
totaux = {}
 
for line in sys.stdin:
    categorie, montant = line.strip().split("\t")
    montant = float(montant)
    totaux[categorie] = totaux.get(categorie, 0) + montant
 
for categorie, total in sorted(totaux.items()):
    print(f"{categorie}\t{total:.2f}")

Testez localement avec un petit extrait avant de soumettre le job :

head -n 20 ventes.csv | python3 mapper.py | sort -k1,1 | python3 reducer.py

Puis copiez les scripts sur le master. Depuis votre poste :

scp -i ma-cle-emr.pem mapper.py reducer.py \
  hadoop@DNS_PUBLIC_DU_MASTER:/home/hadoop/

Sur le master :

chmod +x mapper.py reducer.py
head -n 3 ventes.csv
printf 'date,commande_id,client_id,categorie,ville,montant\n2026-01-01,C001,CL001,Livres,Paris,12.50\n' | ./mapper.py

5.2 Vérifier les chemins S3

Avant le lancement, choisissez un répertoire de sortie qui n’existe pas encore :

INPUT=s3://NOM_DU_BUCKET/td2/input/ventes.csv
OUTPUT=s3://NOM_DU_BUCKET/td2/output/ca-par-categorie

aws s3 ls "$INPUT"
aws s3 ls "$OUTPUT" || true

Hadoop refuse généralement d’écrire dans un répertoire de sortie déjà présent.

5.3 Lancer le job

Depuis `/home/hadoop` sur le master :

hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar \
  -files mapper.py,reducer.py \
  -input "$INPUT" \
  -output "$OUTPUT" \
  -mapper "python3 mapper.py" \
  -reducer "python3 reducer.py"

Le chemin du jar peut varier selon la release. Si le chemin ci-dessus n’existe pas, recherchez le jar déjà installé :

find /usr/lib /usr/share -name 'hadoop-streaming*.jar' 2>/dev/null | head

Relancez la commande avec le chemin réellement trouvé. Observez les phases de soumission, map, shuffle/sort et reduce.

5.4 Observer l’application YARN

Pendant ou après l’exécution :

yarn application -list -appStates ALL
hdfs dfs -ls -h "$OUTPUT"
aws s3 ls "$OUTPUT/"

Le job peut produire un ou plusieurs fichiers `part-*` ainsi qu’un marqueur `_SUCCESS`. Affichez le résultat :

aws s3 cp "$OUTPUT/part-*" -

Si le motif `part-*` n’est pas accepté par votre version d’AWS CLI, listez les objets puis copiez le nom exact retourné.

Étape Observation
Application YARN
Tâches map/reduce et temps total
Fichiers de sortie et résultat vérifié
Erreurs ou lignes rejetées

Questions :

  1. Le job lit-il les données depuis le disque local du master ? Comment le vérifier ?
  2. Que se passe-t-il si vous relancez le job avec le même `OUTPUT` ?
  3. Si le master est remplacé après le job, où chercher le résultat ?

Mission 5 bis - Enchaîner deux jobs MapReduce pour calculer un top-N

Objectif

Vous allez produire, pour chaque catégorie de produit, les N meilleurs clients selon leur chiffre d’affaires (par exemple, le top 3). Le traitement repose sur deux jobs MapReduce chaînés : la sortie du job 1 devient l’entrée du job 2, via HDFS ou S3.

Le schéma de `ventes.csv` utilisé dans ce TD est : `date_vente,commande_id,client_id,categorie,ville,montant`. La colonne `client_id` est donc bien disponible ; l’exercice retient l’option (a) : adapter le job 1 pour conserver le client dans sa clé d’agrégation. Les scripts du job réel de la Mission 5 restent inchangés ; pour cette mission, utilisez des copies ou des scripts distincts pour l’agrégation par catégorie et par client.

5 bis.1 Job 1 : préparer le chiffre d’affaires par catégorie et par client

Voici, tels quels, le mapper et le reducer du job réel présenté en Mission 5. Ils montrent précisément pourquoi sa sortie ne contient pas `client_id`.

#!/usr/bin/env python3
import sys

for line in sys.stdin:
    line = line.strip()

    if line.startswith("date"):  # on saute l'en-tête
        continue

    champs = line.split(",")
    date_vente, commande_id, client_id, categorie, ville, montant = champs

    # clé = catégorie, valeur = montant
    print(f"{categorie}\t{montant}")

#!/usr/bin/env python3
import sys
 
totaux = {}
 
for line in sys.stdin:
    categorie, montant = line.strip().split("\t")
    montant = float(montant)
    totaux[categorie] = totaux.get(categorie, 0) + montant
 
for categorie, total in sorted(totaux.items()):
    print(f"{categorie}\t{total:.2f}")

Le mapper réel émet donc `categorie<TAB>montant`, et le reducer réel produit `categorie<TAB>total` (avec deux décimales). Le format réel du job 1 est par conséquent :

categorie<TAB>total

Pour cette mission, adaptez le job 1 (par exemple en utilisant une copie de `mapper.py` et de `reducer.py`) afin d’émettre et d’agréger une clé composée de `categorie` et `client_id`. Le contrat intermédiaire attendu après cette adaptation est :

Champ 1 Champ 2 Champ 3
`categorie` `client_id` `total_ca`

categorie<TAB>client_id<TAB>total_ca

Le mapper adapté doit extraire `client_id` de la troisième colonne et transmettre catégorie, client et montant ; le reducer adapté doit regrouper par couple `(categorie, client_id)` et additionner les montants. Ne remplacez pas le mapper/reducer du job réel de la Mission 5 : l’objectif est de produire ici le contrat intermédiaire à trois champs nécessaire au job 2.

5 bis.2 Job 2 : concevoir le calcul du top-N

Le job 2 est à concevoir par les étudiants. Aucun `mapper.py` ni `reducer.py` complet n’est fourni pour ce job.

Contrat d’entrée : une ligne produite par le job 1 adapté, au format `categorie<TAB>client_id<TAB>total_ca`.

Contrat de sortie : pour chaque catégorie, les N meilleurs clients, triés par chiffre d’affaires décroissant. Vous pouvez utiliser une ligne par client, par exemple :

categorie<TAB>client_id<TAB>total_ca

Les lignes d’une même catégorie doivent apparaître dans l’ordre décroissant de `total_ca`. En cas d’égalité, définissez et documentez un second critère déterministe, par exemple `client_id` croissant.

5 bis.3 Rappel sur le chaînage MapReduce

Le job 1 adapté écrit ses résultats dans un répertoire de sortie HDFS ou S3. Le job 2 lit ce répertoire comme entrée : il ne doit démarrer qu’une fois le job 1 terminé et son résultat vérifié. Pour que chaque reducer du job 2 reçoive toutes les lignes d’une catégorie, le mapper du job 2 doit utiliser `categorie` comme clé : le partitionnement envoie alors une catégorie donnée vers un seul reducer. Le reducer ne voit que les valeurs associées à sa clé ; il doit donc effectuer le tri localement pour classer les clients de cette catégorie par chiffre d’affaires.

5 bis.4 - TODO

Écrivez mapper_topn.py et reducer_topn.py respectant les contrats d'entrée/sortie ci-dessus. Testez-les en local avec un petit échantillon avant de les déployer sur EMR (cat exemple.txt | python3 mapper_topn.py | sort | python3 reducer_topn.py).

5 bis.5 Exemple de soumission de deux steps EMR

Adaptez les chemins S3, le nom du cluster, le jar Streaming et les noms des scripts à votre travail. Le second step lit la sortie du premier ; remplacez `mapper_topn.py` et `reducer_topn.py` par les scripts que vous aurez conçus. Le premier step doit utiliser les scripts adaptés du job 1 (par exemple `mapper_client.py` et `reducer_client.py`), et non les scripts originaux qui agrègent seulement par catégorie.

CLUSTER_ID=j-XXXXXXXXXXXXX
JOB1_OUTPUT=s3://NOM_DU_BUCKET/td2/output/ca-par-categorie-client
JOB2_OUTPUT=s3://NOM_DU_BUCKET/td2/output/top-3-clients-par-categorie

aws emr add-steps --cluster-id "$CLUSTER_ID" --steps \
  Type=STREAMING,Name=agregation-categorie-client,ActionOnFailure=TERMINATE_CLUSTER,Args=[-files,mapper_client.py\,reducer_client.py,-input,s3://NOM_DU_BUCKET/td2/input/ventes.csv,-output,"$JOB1_OUTPUT",-mapper,python3\ mapper_client.py,-reducer,python3\ reducer_client.py] \
  Type=STREAMING,Name=top-3-clients,ActionOnFailure=TERMINATE_CLUSTER,Args=[-files,mapper_topn.py\,reducer_topn.py,-input,"$JOB1_OUTPUT",-output,"$JOB2_OUTPUT",-mapper,python3\ mapper_topn.py,-reducer,python3\ reducer_topn.py]

Le paramètre N doit être transmis selon la convention choisie dans vos scripts (par exemple dans la configuration du second step). Vérifiez que `JOB1_OUTPUT` existe avant le lancement du job 2 et que les deux répertoires de sortie n’existent pas déjà.

Mission 6 — Alternative Hive

Contexte

Jusqu'ici, les agrégations ont été réalisées avec Hadoop Streaming / MapReduce. Hive propose une alternative SQL : on décrit le résultat attendu avec une requête, et Hive traduit cette requête en traitements distribués. On va reprendre les calculs de chiffre d'affaires (CA) déjà réalisés : CA par catégorie (Mission 5) puis CA par catégorie et client (Mission 5 bis, job 1).

Prérequis et connexion

Le cluster EMR doit avoir l'application Hive installée (case « Hive » cochée lors de la création du cluster). Depuis votre poste, connectez-vous au nœud maître :

ssh -i clé.pem hadoop@<DNS-master>

Sur le master, lancez ensuite le shell Hive :

hive

Les chemins ci-dessous sont des exemples. Remplacez `s3:<votre-bucket>/ventes/` par le chemin S3 réel utilisé aux missions précédentes (par exemple `s3:NOM_DU_BUCKET/td2/input/`).

6.1 — Déclarer la source CSV

Dans le shell Hive, créez une table externe qui pointe vers le CSV des ventes sur S3. Utilisez `ROW FORMAT DELIMITED` avec une virgule comme séparateur et adaptez les colonnes/types à votre fichier réel. Si le CSV possède une ligne d'en-tête, prévoyez sa gestion avec `tblproperties ('skip.header.line.count'='1')`.

-- À compléter avec le chemin S3 réel et, si besoin, les colonnes du CSV du TD
CREATE EXTERNAL TABLE ventes_hive (
  date_vente STRING,
  client_id   STRING,
  categorie   STRING,
  produit     STRING,
  quantite    INT,
  montant     DOUBLE
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION 's3://<votre-bucket>/ventes/'
TBLPROPERTIES ('skip.header.line.count'='1');

Vérifiez la déclaration et quelques lignes avec `DESCRIBE ventes_hive;` et une requête de lecture limitée. Attention : une table externe ne déplace pas les données et sa suppression ne supprime pas les objets S3.

6.2 — CA par catégorie (Mission 5)

Écrivez et exécutez une requête Hive `GROUP BY` qui retrouve le résultat de la Mission 5 : une ligne par `categorie` et la somme des montants sous le nom `total_ca`. Triez éventuellement le résultat par CA décroissant pour faciliter la comparaison avec MapReduce.

6.3 — CA par catégorie et client (Mission 5 bis, job 1)

Écrivez et exécutez une requête `GROUP BY categorie, client_id` qui respecte le contrat de la Mission 5 bis, job 1 : produire `categorie`, `client_id` et `total_ca`. Comparez quelques lignes avec la sortie du job MapReduce.

6.4 — Option : top-N en une requête

Option plus difficile. Calculez d'abord les totaux par couple catégorie/client dans une sous-requête, puis appliquez une fonction de fenêtrage `RANK()` ou `ROW_NUMBER()` avec `PARTITION BY categorie ORDER BY total_ca DESC`. Le fenêtrage doit donc porter sur le résultat agrégé, et non directement sur les lignes CSV.

Obtenez le top-N des clients pour chaque catégorie en filtrant le rang (`rang ⇐ N`). Testez le comportement en cas d'égalité entre deux clients et indiquez si vous avez choisi `RANK()` ou `ROW_NUMBER()`.

6.5 — Synthèse

Comparez Hive et MapReduce brut sur les points suivants : temps de développement, lisibilité, performances, souplesse et facilité de maintenance. Dans quels cas conserveriez-vous un job MapReduce brut plutôt qu'une requête Hive ? Justifiez votre réponse à partir des missions réalisées.

Mission 7 - Observer le dimensionnement et le coût

Le job fonctionne. Mais un cluster de trois machines est-il toujours un bon choix ? Vous devez relier la configuration technique à la facture et au volume de données.

7.1 Relever les ressources

Dans la console EMR et dans la page EC2, observez les types d’instances, leur nombre et leur état. Complétez :

Groupe Type Nombre vCPU / mémoire indiqués Coût horaire affiché ou estimé
Master
Core
Task

Le coût réel dépend notamment de la région, du type d’instance, du modèle de facturation, des options EMR, du stockage et d’éventuels transferts.

Pour une estimation simplifiée :

coût horaire approximatif
  = coût EMR des nœuds
  + coût EC2 des instances
  + stockage / requêtes / transferts éventuels

coût de la séance
  ≈ coût horaire × durée pendant laquelle les ressources restent actives

Questions :

  1. Un cluster arrêté est-il nécessairement un cluster qui ne coûte plus rien ?
  2. Quelles ressources continuent éventuellement à exister après la terminaison d’EMR ?
  3. Pourquoi un gros cluster peut-il coûter plus cher tout en terminant le job plus vite ?
  4. Pour un job ponctuel, quel compromis feriez-vous entre durée et coût ?

7.2 Survoler l’auto-scaling

Ouvrez les options de dimensionnement et repérez :

  1. la différence entre nombre minimal et maximal de nœuds ;
  2. les groupes auxquels une règle peut s’appliquer ;
  3. les métriques ou conditions utilisées ;
  4. l’effet possible sur la capacité de calcul ;
  5. l’effet possible sur HDFS si des nœuds portant des données sont retirés.

Discutez en quelques lignes : quel groupe ajouter pour absorber un pic de calcul, pourquoi les nœuds task sont adaptés, pourquoi la réduction des core est risquée et quelles métriques surveiller ?

7.3 Relier panne, ressources et persistance

La réplication protège des blocs contre certaines pannes de nœuds, tandis que YARN peut relancer ou perdre une tâche selon l’étape atteinte. Cette distinction, observée précédemment sur un mini-cluster, doit être réinterprétée ici avec des nœuds EMR et une sortie persistée dans S3.

  1. Que pourrait faire YARN si un NodeManager devient indisponible, et que pourrait-il arriver à une tâche en cours ?
  2. Pourquoi la tolérance de panne ne signifie-t-elle pas « aucune interruption visible » ?
  3. Quel rôle joue S3 si le cluster entier disparaît ?

Ne terminez, n’arrêtez et ne redémarrez pas une instance depuis EC2 pendant le TD sans consigne explicite. Ces actions peuvent mettre le cluster dans un état incohérent et compliquer le nettoyage.


Mission 8 - Nettoyer et vérifier les ressources

Le travail est terminé. Un cluster EMR laissé en fonctionnement continue de mobiliser des ressources. Vous devez le supprimer, puis vérifier ce qui reste volontairement dans S3.

8.1 Vérifier le résultat avant destruction

Avant de terminer le cluster, conservez dans votre compte rendu :

  1. le nom et l’identifiant du cluster ;
  2. la release EMR ;
  3. les types et nombres de nœuds ;
  4. la commande du job ;
  5. le chemin S3 de l’entrée ;
  6. le chemin S3 du résultat ;
  7. une copie textuelle du résultat ou sa capture ;
  8. les réponses aux tableaux et questions.

Depuis le terminal :

aws s3 ls s3://NOM_DU_BUCKET/td2/ --recursive

8.2 Terminer le cluster

Dans la console EMR :

1. sélectionnez uniquement votre cluster ; 2. choisissez Terminate / Terminer ; 3. confirmez après avoir vérifié le nom ; 4. attendez l’état terminé ; 5. observez les instances EC2 associées et vérifiez qu’elles sont également libérées selon le comportement du service.

La terminaison est destructive pour le cluster et son HDFS local. Elle ne supprime pas automatiquement les objets S3 que vous avez déposés. Vérifiez donc les deux faits séparément.

8.3 Vérifier ce qui reste

Après la terminaison :

  1. essayez de retrouver le cluster dans l’historique EMR ;
  2. vérifiez que les instances du cluster ne sont plus en cours d’exécution ;
  3. vérifiez que le préfixe S3 contient encore l’entrée et le résultat ;
  4. supprimez les objets uniquement selon la consigne de restitution.

aws s3 ls s3://NOM_DU_BUCKET/td2/binomeXX/ --recursive
aws s3 rm s3://NOM_DU_BUCKET/td2/binomeXX/ --recursive

Complétez :

Vérifiez séparément l’état du cluster et des instances, la disparition de HDFS `/data/ecommerce`, la conservation temporaire des objets S3 et le sort de la clé SSH. Notez l’action restante pour chaque ressource.


Synthèse - Docker Compose (séance précédente) versus EMR (TD2)

Complétez d’abord la colonne « observation » sans chercher une définition générale.

Rédigez une synthèse courte, fondée sur vos observations, en traitant : provisioning et mise à l’échelle ; tolérance de panne et persistance ; accès aux interfaces ; sécurité et coût.

Questions de synthèse

  1. Quel travail d’administration est pris en charge par EMR, et quel travail reste sous votre responsabilité ?
  2. Pour un fichier de 500 Go, quelles contraintes disparaissent et lesquelles apparaissent ?
  3. Où placeriez-vous les données d’entrée et les sorties d’un pipeline reproductible ?
  4. Quelle vérification évite le mieux une erreur de sécurité ou de facturation ?

Commandes utiles

Besoin Commande
Connexion SSH au master `ssh -i ma-cle.pem hadoop@DNS_PUBLIC_DU_MASTER`
Copier un fichier vers le master `scp -i ma-cle.pem fichier hadoop@DNS_PUBLIC_DU_MASTER:/home/hadoop/`
Vérifier l’identité AWS du nœud `aws sts get-caller-identity`
Lister un préfixe S3 `aws s3 ls s3:BUCKET/PREFIX/ –recursive` | | Copier vers S3 | `aws s3 cp fichier.csv s3:BUCKET/PREFIX/`
Copier depuis S3 `aws s3 cp s3:BUCKET/PREFIX/fichier.csv .` | | Supprimer un préfixe S3 | `aws s3 rm s3:BUCKET/PREFIX/ –recursive`
Lister HDFS `hdfs dfs -ls -h CHEMIN`
Créer un répertoire HDFS `hdfs dfs -mkdir -p CHEMIN`
Envoyer vers HDFS `hdfs dfs -put -f fichier CHEMIN/`
Afficher le début d’un fichier HDFS `hdfs dfs -cat CHEMIN/fichier head`
Taille HDFS `hdfs dfs -du -h CHEMIN`
État des DataNodes `hdfs dfsadmin -report`
Nœuds YARN `yarn node -list`
Applications YARN `yarn application -list -appStates ALL`
Processus Hadoop locaux `jps`
Tunnel NameNode / YARN `ssh -i ma-cle.pem -N -L 9870:localhost:9870 -L 8088:localhost:8088 hadoop@DNS_PUBLIC_DU_MASTER`
Proxy SOCKS `ssh -i ma-cle.pem -N -D 8157 hadoop@DNS_PUBLIC_DU_MASTER`
Trouver le jar Streaming `find /usr/lib /usr/share -name 'hadoop-streaming*.jar' 2>/dev/null head`
Lancer MapReduce Streaming `hadoop jar CHEMIN_STREAMING.jar -files mapper.py,reducer.py -input s3:BUCKET/input/ -output s3:BUCKET/output/ -mapper “python3 mapper.py” -reducer “python3 reducer.py”`

Remplacez toujours `BUCKET`, `PREFIX`, `DNS_PUBLIC_DU_MASTER`, `ma-cle.pem`, `XX` et les chemins de sortie par vos valeurs réelles. Une commande qui contient encore un placeholder ne doit pas être exécutée telle quelle.

Ouverture - TD3 et l’infrastructure as code

Dans ce TD, vous avez créé et supprimé un cluster manuellement. Dans le TD3, vous étudierez l’automatisation de cette infrastructure.

Répondez à la question suivante :

Que faudrait-il automatiser dans ce que vous venez de faire à la main ?

Dressez une liste ordonnée d’au moins huit éléments. Pensez aux paramètres du cluster, à la sécurité, au réseau, aux rôles IAM, aux chemins S3, au lancement du job, à la collecte des résultats, au dimensionnement et au nettoyage.

Puis classez chaque élément selon sa nature :

Élément à automatiser Paramétrage Provisionnement Exécution Vérification / nettoyage Risque en cas d’erreur

Livrable

Remettez un compte rendu court contenant :

  1. les valeurs complétées dans les tableaux ;
  2. une preuve de connexion SSH et de l’exploration HDFS/YARN ;
  3. une preuve du tunnel et des deux interfaces web observées ;
  4. les chemins S3 d’entrée et de sortie ;
  5. le résultat du chiffre d’affaires par catégorie ;
  6. la comparaison mini-cluster Docker / EMR ;
  7. l’état du nettoyage et la liste des éléments à automatiser pour le TD3.

Dernière vérification avant de quitter AWS : votre cluster est terminé, vos instances de test ne tournent plus, et les objets S3 sont supprimés.