7 min de lecture

Comment optimiser votre cluster Spark avec des travaux Spark interactifs

Spark on Kubernetes

Dans cet article, vous apprendrez :

  • Comment réduire le temps d’exécution de votre travail Spark
  • Qu’est-ce qu’un job interactif chez Ilum
  • Comment exécuter une tâche d’étincelle interactive
  • Différences entre l’exécution d’une tâche Spark à l’aide de l’API Ilum et de l’API Spark

Types de tâches Ilum

Il existe trois types de tâches que vous pouvez exécuter dans Ilum : Emploi unique , Emploi interactif et Code interactif . Dans cet article, nous allons nous concentrer sur les Emploi interactif type. Cependant, il est important de connaître les différences entre les trois types d’emplois, alors faisons un rapide tour d’horizon de chacun d’eux.

Avec emplois uniques , vous pouvez soumettre des programmes de type code. Ils vous permettent de soumettre une application Spark au cluster, avec du code précompilé, sans interaction pendant l’exécution. Dans ce mode, vous devez envoyer un jar compilé à Ilum, qui est utilisé pour lancer une seule tâche. Vous pouvez soit l’envoyer directement, soit utiliser les informations d’identification AWS pour l’obtenir à partir d’un compartiment S3. Un exemple typique d’utilisation d’une seule tâche serait une sorte de tâche de préparation des données.

Ilum fournit également un interactif Mode de code , qui vous permet d’envoyer des commandes au moment de l’exécution. Cela est utile pour les tâches où vous devez interagir avec les données, telles que l’analyse exploratoire des données.

Emploi interactif

Les travaux interactifs ont des sessions de longue durée, qui vous permettent d’envoyer des données d’instance de travail à exécuter immédiatement. La caractéristique principale d’un tel mode est que vous n’avez pas à attendre que le contexte Spark soit initialisé. Si les utilisateurs pointaient vers le même ID de tâche, ils interagissaient avec le même contexte Spark. Ilum encapsule la logique de l’application Spark dans une tâche Spark de longue durée capable de gérer immédiatement les demandes de calcul, sans qu’il soit nécessaire d’attendre l’initialisation du contexte Spark.

Démarrage d’une tâche interactive

Voyons comment la session interactive d’Ilum peut être lancée. La première chose que nous devons faire est de mettre en place Ilum. Vous pouvez le faire facilement avec le minikube. Un tutoriel d’installation d’Ilum est disponible sous ce lien . Dans l’étape suivante, nous devons créer un fichier jar qui contient une implémentation de l’interface de travail d’Ilum. Pour utiliser l’API de travail Ilum, nous devons l’ajouter au projet avec certains gestionnaires de dépendances, tels que Maven ou Gradle. Dans cet exemple, nous allons utiliser du code Scala avec un Gradle pour calculer PI.

L’exemple complet est disponible sur notre Lien avec GitHub .

Si vous préférez ne pas le construire vous-même, vous pouvez trouver le fichier jar compilé ici .

La première étape consiste à créer un dossier pour notre projet et à y changer le répertoire.

$ mkdir exemple-de-job-interactif
$ cd exemple-de-job-interactif 

Si vous n’avez pas la dernière version de Gradle installée sur votre ordinateur, vous pouvez vérifier comment procéder ici . Exécutez ensuite la commande suivante dans un terminal à partir du répertoire du projet :

$ gradle init 

Choisissez une application Scala avec Groovy comme DSL. Le résultat doit ressembler à ceci :

Démarrage d’un démon Gradle (les versions suivantes seront plus rapides)

Sélectionnez le type de projet à générer :
  1 : de base
  2 : Candidature
  3 : Bibliothèque
  4 : Plug-in Gradle
Entrez la sélection (par défaut : de base) [1..4] 2

Sélectionnez la langue de mise en œuvre :
  1 : C++
  2 : Groovy
  3 : Java
  4 : Kotlin
  5 : Scala
  6 : Martinet
Entrez la sélection (par défaut : Java) [1..6] 5

Diviser les fonctionnalités en plusieurs sous-projets ?
  1 : Non - un seul projet d’application
  2 : Oui - Projets d’application et de bibliothèque
Entrez la sélection (par défaut : non - un seul projet d’application) [1..2] 1

Sélectionnez le script de construction DSL :
  1 : Groovy
  2 : Kotlin
Entrez la sélection (par défaut : Groovy) [1..2] 1

Générer une build à l’aide de nouvelles API et de nouveaux comportements (certaines fonctionnalités peuvent changer dans la prochaine version mineure) ? (par défaut : non) [oui, non] non                           
Nom du projet (par défaut : interactive-job-example) : 
Package source (par défaut : interactive.job.example) : 

> Tâche :init
Obtenez plus d’aide pour votre projet : https://docs.gradle.org/7.5.1/samples/sample_building_scala_applications_multi_project.html

CONSTRUIRE AVEC SUCCÈS en 30 secondes
2 tâches exploitables : 2 exécutées 

Maintenant, nous devons ajouter le dépôt Ilum et les dépendances nécessaires dans votre build.gradle lime. Dans ce tutoriel, nous allons utiliser Scala 2.12.

dépendances {
    implémentation 'org.scala-lang :scala-library :2.12.16'
    implémentation 'cloud.ilum :ilum-job-api :5.0.1'
    compileOnly 'org.apache.spark :spark-sql_2.12:3.1.2'
} 

Maintenant, nous pouvons créer une classe Scala qui étend le Job d’Ilum et qui calcule PI :

package interactive.job.example

import cloud.ilum.job.Job
import org.apache.spark.sql.SparkSession
importer scala.math.random

class InteractiveJobExample extends Job {

override def run(sparkSession : SparkSession, config : Map[String, Any]) : Option[String] = {

val tranches = config.getOrElse(« tranches », « 2 »).toString.toInt
    val n = math.min(100000L * tranches, Int.MaxValue).toInt
    val count = sparkSession.sparkContext.parallelize(1 jusqu’à n, tranches).map { i =>
      val x = aléatoire * 2 - 1
      val y = aléatoire * 2 - 1
      si (x * x + y * y <= 1) 1 sinon 0
    }.réduire(_ + _)
    Some(s"Pi est à peu près ${4.0 * count / (n - 1)} »)
  }
} 

Si Gradle a généré des classes principales ou de test, il vous suffit de les supprimer du projet et d’en créer une version.

$ gradle build 

Le fichier jar généré doit être dans ' ./exemple-de-travail-interactif/app/build/libs/app.jar ', nous pouvons ensuite revenir à Ilum. Une fois que tous les pods sont en cours d’exécution, veuillez créer une redirection de port pour ilum-ui :

kubectl port-forward svc/ilum-ui 9777:9777 

Ouvrez Ilum UI dans votre navigateur et créez un nouveau groupe :

ilum ui spark monitoring

Mettez le nom d’un groupe, choisissez ou créez un cluster, téléchargez votre fichier jar et appliquez les modifications :

ilum add group

Ilum créera un pod de pilote Spark et vous pourrez contrôler le nombre de pods Spark Executor en les mettant à l’échelle. Une fois que le conteneur Spark est prêt, exécutons les tâches :

ilum execute job

Maintenant, nous devons mettre le nom canonique de notre classe Scala

interactive.job.example.InteractiveJobExample 

et définissez le paramètre slices au format JSON :

{
  « config » : {
    « tranches » : « 10 »
  }
} 

Vous devriez voir le résultat juste après le début du travail

Vous pouvez modifier les paramètres et réexécuter une tâche et vos calculs seront effectués sur-le-champ.

Comparaison interactive et individuelle des offres d’emploi

Dans Ilum, vous pouvez également exécuter une seule tâche. La différence la plus importante par rapport au mode interactif est que vous n’avez pas besoin d’implémenter l’API Job. Nous pouvons utiliser le jar SparkPi à partir d’exemples Spark :

ilum add job

L’exécution d’une tâche comme celle-ci est également rapide, mais les tâches interactives le sont 20 fois plus rapide (4 s vs 200 ms) . Si vous souhaitez démarrer une tâche similaire avec d’autres paramètres, vous devrez préparer une nouvelle tâche et télécharger à nouveau le pot.

Comparaison entre Ilum et Apache Spark


J’ai configuré Apache Spark localement avec un Bitnami/Étincelle image docker. Si vous souhaitez également exécuter Spark sur votre machine, vous pouvez utiliser docker-compose :

$ curl -LO https://raw.githubusercontent.com/bitnami/containers/main/bitnami/spark/docker-compose.yml
$ docker-compose up 

Une fois que Spark est en cours d’exécution, vous devriez pouvoir accéder à localhost :8080 et voir l’interface utilisateur de l’administrateur. Nous devons obtenir l’URL Spark à partir du navigateur :

spark admin

Ensuite, nous devons ouvrir le conteneur Spark en mode interactif à l’aide de

$ docker exec -<containerid>it -- bash 
spark container

Et maintenant, à l’intérieur du conteneur, nous pouvons soumettre le job sparkPi. Dans ce cas, vous utiliserez SparkiPi à partir de l’exemple jar et, en paramètre maître, mettrez l’URL du navigateur :

$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi\
  --master spark://78c84485d233:7077 \
  /opt/bitnami/spark/examples/jars/spark-examples_2.12-3.3.0.jar\
  10 

Résumé

Comme vous pouvez le voir dans l’exemple ci-dessus, vous pouvez éviter la configuration et l’installation compliquées de votre client Spark en utilisant Ilum. Ilum prend le relais et met à votre disposition une interface simple et pratique. De plus, il vous permet de vous affranchir des limitations d’Apache Spark, dont l’initialisation peut prendre beaucoup de temps. Si vous devez effectuer de nombreuses exécutions de tâches avec une logique similaire mais des paramètres différents et que vous souhaitez que les calculs soient effectués immédiatement, vous devez absolument utiliser le mode de tâche interactive.

Ilum ferret

Similitudes avec Apache Livy

Ilum est un outil cloud natif pour la gestion des déploiements Apache Spark sur Kubernetes. Il est similaire à Apache Livy en termes de fonctionnalités : il peut contrôler une session Spark sur l’API REST et créer une interaction en temps réel avec un cluster Spark. Cependant, Ilum est conçu spécifiquement pour les environnements modernes et natifs du cloud.

Nous avons utilisé Apache Livy dans le passé, mais nous avons atteint le point où Livy n’était tout simplement pas adapté aux environnements modernes. Tite-Live est obsolète par rapport à Ilum. En 2018, nous avons commencé à migrer tous nos environnements vers Kubernetes, et nous avons dû trouver un moyen de déployer, surveiller et maintenir Apache Spark sur Kubernetes. C’était l’occasion idéale pour construire Ilum.