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.
À la fin du TD, vous devez être capables de :
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.
Avant de créer quoi que ce soit :
eu-west-3.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.
Dans la configuration logicielle :
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éé.
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.
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 :
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 :
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.
É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).
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 :
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. 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.
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.
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.
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 :
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 ».
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 ?
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.
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.
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 :
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.
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.
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.
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.
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 :
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.
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.
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
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.
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.
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 :
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.
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.
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.
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.
É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).
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à.
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).
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/`).
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.
É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.
É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.
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()`.
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.
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.
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 :
Ouvrez les options de dimensionnement et repérez :
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 ?
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.
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.
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.
Avant de terminer le cluster, conservez dans votre compte rendu :
Depuis le terminal :
aws s3 ls s3://NOM_DU_BUCKET/td2/ --recursive
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.
Après la terminaison :
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.
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.
| 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.
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 |
|---|---|---|---|---|---|
Remettez un compte rendu court contenant :
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.