Pilotage des clusters EMR avec AWS CLI : du déploiement à l’automatisation

Amazon EMR (Elastic MapReduce) est un service géré facilitant l’exécution de frameworks Big Data tels que Spark, Hadoop, Hive ou Presto. L’AWS CLI offre une interface en ligne de commande complète pour orchestrer l’ensemble du cycle de vie des clusters, depuis leur création jusqu’à leur terminaison, en passantt par la configuration et la supervision.

Mise en place de l’environnement

Installez la CLI AWS et configurez vos identifiants :

pip install awscli
aws configure

Création rapide d’un cluster

Pour lancer un cluster minimal avec Spark et Hadoop :

aws emr create-cluster \
    --release-label emr-6.10.0 \
    --instance-type m5.large \
    --instance-count 3 \
    --use-default-roles \
    --applications Name=Spark Name=Hadoop

Gestion du cycle de vie des clusters

Création avancée

Définissez des groupes d’instances maître, cœur et tâches :

aws emr create-cluster \
    --name "Cluster-Analytique" \
    --release-label emr-6.10.0 \
    --applications Name=Hadoop Name=Spark Name=Hive \
    --instance-groups \
        InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m5.xlarge \
        InstanceGroupType=CORE,InstanceCount=2,InstanceType=m5.2xlarge \
        InstanceGroupType=TASK,InstanceCount=3,InstanceType=m5.2xlarge \
    --use-default-roles \
    --log-uri s3://mes-logs-emr/ \
    --auto-terminate

Utilisez les flottes d’instances pour tirer parti des instances Spot et réduire les coûts :

aws emr create-cluster \
    --release-label emr-6.10.0 \
    --instance-fleets \
        InstanceFleetType=MASTER,TargetOnDemandCapacity=1,InstanceTypeConfigs='[{InstanceType=m5.xlarge,WeightedCapacity=1}]' \
        InstanceFleetType=CORE,TargetSpotCapacity=8,InstanceTypeConfigs='[{InstanceType=m5.2xlarge,BidPrice=0.4,WeightedCapacity=4},{InstanceType=r5.2xlarge,BidPrice=0.5,WeightedCapacity=4}]' \
    --service-role EMR_DefaultRole \
    --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole,KeyName=ma-clef \
    --log-uri s3://mes-logs-emr/ \
    --enable-debugging

Personnalisation des applications

Créez un fichier mes-configurations.json :

[
    {
        "Classification": "spark-defaults",
        "Properties": {
            "spark.executor.memory": "4g",
            "spark.executor.cores": "2",
            "spark.driver.memory": "2g"
        }
    },
    {
        "Classification": "yarn-site",
        "Properties": {
            "yarn.nodemanager.resource.memory-mb": "16384",
            "yarn.scheduler.maximum-allocation-mb": "16384"
        }
    }
]

Appliquez cette configuration lors de la créasion :

aws emr create-cluster \
    --configurations file://mes-configurations.json \
    --release-label emr-6.10.0 \
    --instance-type m5.large \
    --instance-count 3 \
    --use-default-roles

Sécurité Kerberos

aws emr create-cluster \
    --security-configuration MaConfigSecurite \
    --kerberos-attributes Realm=EC2.INTERNAL,KdcAdminPassword=MonMotDePasse123 \
    --release-label emr-6.10.0 \
    --instance-type m5.large \
    --instance-count 3

Supervision des clusters

Lister les clusters actifs :

aws emr list-clusters --active

Obtenir des informations détaillées :

aws emr describe-cluster --cluster-id j-XXXXXXXXXX

Lister les instances d’un groupe particulier :

aws emr list-instances --cluster-id j-XXXXXXXXXX --instance-group-types CORE

Gestion des étapes

Ajouter des traitements Spark et Hive :

aws emr add-steps \
    --cluster-id j-XXXXXXXXXX \
    --steps \
        Type=Spark,Name="ETL-Spark",ActionOnFailure=CONTINUE,Args=[--class,com.exemple.Traitement,--master,yarn,--deploy-mode,cluster,s3://mon-bucket/jobs/traitement.jar,s3://donnees-entree/,s3://resultats/] \
        Type=Hive,Name="Analyse-Hive",ActionOnFailure=CONTINUE,Args=[-f,s3://mon-bucket/scripts/analyse.hql,-d,INPUT=s3://donnees-entree/,-d,OUTPUT=s3://resultats/]

Vérifier l’état d’une étape :

aws emr describe-step --cluster-id j-XXXXXXXXXX --step-id s-XXXXXXXXXX

Arrêt du cluster

aws emr terminate-clusters --cluster-ids j-XXXXXXXXXX

Fonctionnalités avancées

Mise à l’échelle automatique

aws emr create-cluster \
    --release-label emr-6.10.0 \
    --auto-scaling-role EMR_AutoScaling_DefaultRole \
    --instance-groups \
        InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m5.xlarge \
        'InstanceGroupType=CORE,InstanceCount=2,InstanceType=m5.2xlarge,AutoScalingPolicy={
            "Constraints":{"MinCapacity":2,"MaxCapacity":12},
            "Rules":[
                {
                    "Name":"ScaleOut",
                    "Description":"Ajout si mémoire YARN < 20%",
                    "Action":{"SimpleScalingPolicyConfiguration":{"AdjustmentType":"CHANGE_IN_CAPACITY","ScalingAdjustment":1,"CoolDown":300}},
                    "Trigger":{"CloudWatchAlarmDefinition":{
                        "ComparisonOperator":"LESS_THAN",
                        "EvaluationPeriods":1,
                        "MetricName":"YARNMemoryAvailablePercentage",
                        "Namespace":"AWS/ElasticMapReduce",
                        "Period":300,
                        "Threshold":20,
                        "Statistic":"AVERAGE",
                        "Unit":"PERCENT",
                        "Dimensions":[{"Key":"JobFlowId","Value":"${emr.clusterId}"}]
                    }}
                }
            ]
        }' \
    --use-default-roles

Actions de démarrage (Bootstrap)

aws emr create-cluster \
    --bootstrap-actions \
        Path=s3://elasticmapreduce/bootstrap-actions/configure-hadoop,Name="Config-Hadoop",Args=[-m,mapred.map.tasks=80,-m,mapred.reduce.tasks=40] \
        Path=s3://mon-bucket/scripts/installer-modules.sh,Name="Installer-Modules" \
    --release-label emr-6.10.0 \
    --instance-type m5.large \
    --instance-count 3 \
    --use-default-roles

Vue cohérente EMRFS

aws emr create-cluster \
    --emrfs Consistent=true,RetryCount=5,RetryPeriod=30 \
    --release-label emr-6.10.0 \
    --instance-type m5.large \
    --instance-count 3 \
    --use-default-roles

Bonnes pratiques et optimisation

Privilégiez les instances Spot pour les groupes de tâches et utilisez une famille d’instances variée pour éviter les interruptions de capacité :

aws emr create-cluster \
    --instance-fleets \
        InstanceFleetType=MASTER,TargetOnDemandCapacity=1,InstanceTypeConfigs='[{InstanceType=m5.xlarge}]' \
        InstanceFleetType=CORE,TargetSpotCapacity=10,InstanceTypeConfigs='[
            {InstanceType=m5.2xlarge,BidPrice=0.4,WeightedCapacity=4},
            {InstanceType=r5.2xlarge,BidPrice=0.5,WeightedCapacity=4},
            {InstanceType=c5.2xlarge,BidPrice=0.35,WeightedCapacity=4}
        ]' \
    --release-label emr-6.10.0 \
    --service-role EMR_DefaultRole \
    --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole

Mettez en place des alarmes CloudWatch pour suivre l’utilisation mémoire :

aws cloudwatch put-metric-alarm \
    --alarm-name "EMR-Memoire-Haute" \
    --alarm-description "Alerte si mémoire EMR > 85%" \
    --metric-name "MemoryUtilization" \
    --namespace "AWS/ElasticMapReduce" \
    --statistic "Average" \
    --period 300 \
    --threshold 85 \
    --comparison-operator "GreaterThanThreshold" \
    --evaluation-periods 2 \
    --alarm-actions "arn:aws:sns:us-east-1:123456789012:MonTopic" \
    --dimensions Name=JobFlowId,Value=j-XXXXXXXXXX

Diagnostic des incidents

Identifier la cause d’un échec de création :

aws emr describe-cluster --cluster-id j-XXXXXXXXXX --query 'Cluster.Status.StateChangeReason'

Consulter les logs d’une étape défaillante :

aws emr ssh --cluster-id j-XXXXXXXXXX --key-pair-file ma-clef.pem --command "tail -100 /var/log/hadoop-yarn/containers/application_*/container_*/stdout"

Récupérer les métriques d’allocation de conteneurs :

aws cloudwatch get-metric-statistics \
    --namespace AWS/ElasticMapReduce \
    --metric-name ContainerAllocated \
    --dimensions Name=JobFlowId,Value=j-XXXXXXXXXX \
    --start-time 2024-06-01T00:00:00Z \
    --end-time 2024-06-01T23:59:59Z \
    --period 300 \
    --statistics Average

Automatisation avec un script shell

#!/bin/bash
NOM_CLUSTER="Traitement-$(date +%Y%m%d-%H%M%S)"
VERSION_EMR="emr-6.10.0"
CHEMIN_LOGS="s3://mes-logs-emr/"

echo "Création du cluster $NOM_CLUSTER ..."
ID_CLUSTER=$(aws emr create-cluster \
    --name "$NOM_CLUSTER" \
    --release-label "$VERSION_EMR" \
    --applications Name=Hadoop Name=Spark Name=Hive \
    --instance-groups \
        InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m5.xlarge \
        InstanceGroupType=CORE,InstanceCount=2,InstanceType=m5.2xlarge \
        InstanceGroupType=TASK,InstanceCount=4,InstanceType=m5.2xlarge \
    --use-default-roles \
    --log-uri "$CHEMIN_LOGS" \
    --auto-terminate \
    --query 'ClusterId' \
    --output text)

echo "Attente de disponibilité du cluster $ID_CLUSTER ..."
aws emr wait cluster-running --cluster-id "$ID_CLUSTER"

echo "Ajout de l'étape de traitement ..."
aws emr add-steps \
    --cluster-id "$ID_CLUSTER" \
    --steps Type=Spark,Name="MonJob",ActionOnFailure=CONTINUE,Args=[--class,com.exemple.MonJob,--master,yarn,--deploy-mode,cluster,s3://mon-bucket/jobs/monjob.jar,s3://entree/,s3://sortie/]

echo "Traitement lancé, le cluster s'arrêtera automatiquement."

Étiquettes: aws-cli EMR big-data Spark Hadoop

Publié le 30 août à 15h25