0
votes

Dépendance en python manquante lors de la soumission de la tâche de Pyspark à EMR avec le flux d'air

Nous utilisons un script d'amorçage pour installer des bibliothèques python sur les nœuds du cluster EMR pour nos travaux Spark. Le script ressemble à ceci:

return self.loads(obj)
 File "/mnt1/yarn/usercache/root/appcache/application_1565624418111_0001/container_1565624418111_0001_01_000033/pyspark.zip/pyspark/serializers.py", line 577, in loads
   return pickle.loads(obj, encoding=encoding)
ModuleNotFoundError: No module named 'sklearn'

    at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.handlePythonException(PythonRunner.scala:452)
    at org.apache.spark.sql.execution.python.ArrowPythonRunner$$anon$1.read(ArrowPythonRunner.scala:172)
    at org.apache.spark.sql.execution.python.ArrowPythonRunner$$anon$1.read(ArrowPythonRunner.scala:122)
    at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.hasNext(PythonRunner.scala:406)
    at org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:37)

Une fois le cluster en place, nous utilisons le SparkSubmitHook d'Airflow pour soumettre des travaux à EMR. Nous utilisons cette configuration pour lier pyspark à python3 . Le problème est que, de temps en temps, lorsque le travail commence à s'exécuter, nous obtenons une erreur ModuleNotFoundError: Aucun module nommé 'sklearn' . Un tel stacktrace est comme celui-ci ci-dessous:

sudo python3 -m pip install pandas==0.22.0 scikit-learn==0.21.0

Ce problème est de nature sporadique, donc sur 10 soumissions de travail, il peut se produire 2-3 fois. Nous utilisons EMR 5.23.0. J'ai également essayé de passer à la version 5.26.0, mais le même problème persiste.

Si je vais aux nœuds du cluster, et que je vérifie ce package «manquant», je peux voir qu'il est déjà installé. Donc, ce n'est clairement pas le problème avec le script bootstrap. Cela me laisse assez confus, car je n'ai aucune idée de ce qui se passe ici. Je suppose que cela se lie à une version différente de Python lorsque le travail est déclenché à partir d'Airflow, mais ce n'est qu'une photo dans le noir. Toute aide est appréciée.


0 commentaires

4 Réponses :


1
votes

cas similaire peut pour référence. Je ne sais pas si cela fonctionne pour EMR Dans le cas de hadoop, l'environnement et le package python doivent être installés sous l'utilisateur hadoop ou spark.

si vous installez le package python dans root ou dans un autre environnement utilisateur, un cas similaire peut se produire.

Alors, essayez d'installer votre package avec le même nom d'utilisateur que hadoop ou spark.

Mise à jour =============================================== =

J'avais l'habitude d'installer le banc de travail cloudear qui a un environnement de cloud étincelant similaire. Dans ce cas, la dépendance distribuée est également nécessaire.

Voici le lien hypertexte https://www.cloudera.com/ documentation / data-science-workbench / latest / topics / cdsw_pyspark.html # distributing_dependencies

Les clés sont:

    1. installer le package de dépendances dans tous les nœuds cloud.
    1. configurer l'environnement virtuel conda
    1. configurer l'environnement de chemin pyspark ou pyspark3.
    1. déployer la configuration yarn & spark sur la passerelle (l'hôte sparksubmit ou l'hôte airflow).

Bonne chance.

Si vous trouvez la réponse utile, merci de voter.


3 commentaires

hmm, je pense qu'il est installé sous l'utilisateur hadoop. Sinon, cela n'aurait pas fonctionné lorsque nous avons exécuté nos travaux directement à partir du nœud maître EMR, au lieu de la vm airflow. En outre, cela fonctionne 8 fois sur 10. Donc, il y a là une incohérence.


c'était le contraire pour moi @Yong Wang ... installer uniquement des packages car sudo fonctionnait ... différentes versions possibles d'ec2 sont le problème ... voir le message ici stackoverflow.com/questions/57315030/…


en fait 1 est pris en charge par le script bootstrap. 2 apporte une complexité supplémentaire, avec peu d'avantages, la direction est plus impliquée, nous n'avons donc pas suivi cette voie. 3 est fait en utilisant les paramètres de configuration dans EMR. Seulement 4 est un peu inconnu, il faut donc explorer ce domaine.



1
votes

Une façon de résoudre votre problème pourrait être de changer la façon dont vous envoyez votre travail au cluster:

  • Package le code de l'étape à exécuter (avec ses dépendances) sur un bucket a s3 (en utilisant pipenv et pipfiles par exemple). Le package ressemblerait à ceci:
step_to_run = [
                {
                    'Name': 'your_step_name',
                    'ActionOnFailure': 'CONTINUE',
                    'HadoopJarStep': {
                        'Jar': 'command-runner.jar',
                        'Args': ["spark-submit", "--master", "yarn", "--deploy-mode", "client", "--py-files", "s3://<script_to_execute_package>.zip", "/tmp/driver.py", "<script_to_execute_main>.py", "", "--arg_to_pass_1", "arg1", "--arg_to_pass_2", "arg2", ...]
                    }
                }
]

some_task = EmrAddStepsOperator(
                task_id='some_task',
                job_flow_id='the_previously_created_job_flow_id',
                aws_conn_id=aws_conn_id,
                steps=extract_check_args_spark_step,
                dag=dag
            )

            some_task_check = EmrStepSensor(
                task_id='task_check_extract_check',
                job_flow_id='the_previously_created_job_flow_id',
                step_id="{{ task_instance.xcom_pull('some_task', key='return_value')[0] }}",
                aws_conn_id=aws_conn_id,
                poke_interval=10,
                dag=dag
            )
  • Au lieu d'utiliser SparkSubmitHook, utilisez un EmrAddStepsOperator (+ Sensor + CreateJobFlowOperator). Exécutez l'étape avec votre code Python empaqueté. Ce serait quelque chose comme ceci:
<script_to_execute_package>.zip
|- <script_to_execute_main>.py
|-other step files.py
|- ...
|-scikit-learn
    |-scikit-learn files
    | ...
|-pandas
    |- pandas files
    |- ...
|-other packages
    |-other packages files
    |- ...



1 commentaires

Merci, je vais jeter un coup d'œil à cela.



0
votes

Après beaucoup d'essais et d'erreurs, l'extrait suivant a bien fonctionné en tant que script d'amorçage. La partie commentée a également été précédemment incluse dans notre scipt, et cela a causé des problèmes. Après avoir supprimé cette partie, tout semble fonctionner correctement.

sudo python3 -m pip install --upgrade pip==19.1.1 >> /tmp/out.log

wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/s/spatialindex-1.8.5-1.el7.x86_64.rpm >> /tmp/out.log
sudo yum -y localinstall spatialindex-1.8.5-1.el7.x86_64.rpm >> /tmp/out.log

sudo python3 -m pip install python-dateutil==2.8.0 pandas==0.22.0 pyarrow==0.13.0 scikit-learn==0.21.0 geopy==1.19.0 Shapely==1.6.4.post2 geohash2==1.1 boto3==1.9.183 rtree==0.8.3 geopandas==0.5.0 >> /tmp/out.log

# python3 -m pip install --user python-dateutil==2.8.0 pandas==0.22.0 pyarrow==0.13.0 geopy==1.19.0 Shapely==1.6.4.post2 geohash2==1.1 boto3==1.9.183
# python3 -m pip install --user scikit-learn==0.21.0

Une note ici, lorsqu'un travail est soumis via Airflow, il s'exécute en tant qu'utilisateur root. C'est donc probablement pour cette raison que l'installation de --user ne fonctionne pas. Parce que ce scipt est exécuté en tant qu'utilisateur hadoop sur chaque nœud EMR.


0 commentaires

0
votes

Une autre solution, si vous utilisez LaunchClusterOperator dans votre fichier DAG, consiste à utiliser le Propriété "cluster_overrides". Ensuite, vous pouvez simplement copier la configuration depuis ceci Page Amazon. Le résultat ressemblerait donc à ceci (mentionner deux fois "Configurations" est fait intentionnellement):

   LaunchClusterOperator(dag=yourdag, param2="something", cluster_overrides={
       "Configurations": [
         {
           "Classification": "spark-env",
           "Configurations": [
             {
              "Classification": "export",
              "Properties": {"PYSPARK_PYTHON": "/usr/bin/python3"} 
             }
            ]
         }
       ]
      }
     )


1 commentaires

Si vous regardez la question, j'ai mentionné cette configuration. Cela n'a en fait pas aidé à résoudre le problème, car le problème était dans le script d'amorçage.