Konfiguration von Spark auf YARN

Hallo Habr! Gestern beim Meetup ĂŒber Apache Spark, das von den Leuten von Rambler&Co organisiert wurde, gab es viele Fragen der Teilnehmer zur Konfiguration dieses Werkzeugs. Wir haben beschlossen, unser Wissen darĂŒber zu teilen. Das Thema ist nicht einfach — deshalb laden wir auch ein, Erfahrungen in den Kommentaren zu teilen; vielleicht verstehen wir auch etwas nicht richtig oder nutzen es falsch.

Eine kleine EinfĂŒhrung — wie wir Spark nutzen. Wir haben ein dreimonatiges Programm „Spezialist fĂŒr Big Data“, und im gesamten zweiten Modul arbeiten unsere Teilnehmer mit diesem Tool. Folglich liegt es in unserer Verantwortung als Organisatoren, einen Cluster fĂŒr diesen Anwendungsfall vorzubereiten.

Das Besondere an unserer Nutzung ist, dass die Anzahl der Personen, die gleichzeitig an Spark arbeiten, gleich der gesamten Gruppe sein kann. Zum Beispiel wÀhrend eines Seminars, wenn alle gleichzeitig etwas ausprobieren und dem Lehrer nachahmen. Das können manchmal 40 Personen sein. Wahrscheinlich gibt es nicht viele Unternehmen weltweit, die mit einem solchen Nutzungsszenario konfrontiert sind.

Im Folgenden werde ich erklÀren, wie und warum wir bestimmte Konfigurationsparameter ausgewÀhlt haben.

Lassen Sie uns von Grund auf neu beginnen. Spark bietet 3 Optionen zur AusfĂŒhrung im Cluster: standalone, mit Mesos und mit YARN. Wir haben uns fĂŒr die dritte Option entschieden, da sie fĂŒr uns logisch war. Wir haben bereits einen Hadoop-Cluster. Unsere Teilnehmer sind mit seiner Architektur gut vertraut. Lassen Sie uns YARN verwenden.

spark.master=yarn

Es wird jetzt interessanter. Jede dieser 3 Bereitstellungsoptionen hat 2 Bereitstellungsmodi: client und cluster. Aus Dokumentation. verschiedenen Quellen im Internet lĂ€sst sich schließen, dass der client fĂŒr interaktive Arbeiten geeignet ist — beispielsweise ĂŒber Jupyter Notebook, wĂ€hrend der cluster besser fĂŒr Produktionslösungen geeignet ist. In unserem Fall interessierte uns die interaktive Arbeit, daher:

spark.deploy-mode=client

Ab diesem Zeitpunkt wird Spark grundsĂ€tzlich irgendwie auf YARN funktionieren, aber das war uns nicht genug. Da unser Programm sich mit Big Data beschĂ€ftigt, fehlte es manchmal den Teilnehmern an den Ressourcen, die im Rahmen einer gleichmĂ€ĂŸigen Zuteilung zur VerfĂŒgung standen. Und hier entdeckten wir etwas Interessantes – die dynamische Ressourcenzuteilung. Kurz gesagt: Wenn Sie eine rechenintensive Aufgabe haben und der Cluster frei ist (zum Beispiel morgens), kann Spark Ihnen mit dieser Option zusĂ€tzliche Ressourcen bereitstellen. Der Bedarf wird durch eine ausgeklĂŒgelte Formel ermittelt. Wir werden nicht ins Detail gehen – sie funktioniert ziemlich gut.

spark.dynamicAllocation.enabled=true

Wir haben diesen Parameter gesetzt, und beim Start von Spark gab es einen Fehler, und es ließ sich nicht starten. Zurecht, denn wir hĂ€tten genauer lesen sollen. Dokumentation Dort steht, dass fĂŒr eine einwandfreie Funktion noch ein zusĂ€tzlicher Parameter aktiviert werden muss.

spark.shuffle.service.enabled=true

Wozu dient es? Wenn unser Job nicht mehr so viele Ressourcen benötigt, sollte Spark diese in den allgemeinen Pool zurĂŒckgeben. Die ressourcenintensivste Phase in fast jeder MapReduce-Aufgabe ist die Shuffle-Phase. Dieser Parameter ermöglicht es, die wĂ€hrend dieser Phase erzeugten Daten zu speichern und die Executors entsprechend freizugeben. Ein Executor ist der Prozess, der auf dem Worker alles berechnet. Er hat eine bestimmte Anzahl von Prozessorkernen und eine bestimmte Menge an Speicher.

Wir haben diesen Parameter hinzugefĂŒgt. Es scheint alles zu funktionieren. Es wurde deutlich, dass den Teilnehmern tatsĂ€chlich mehr Ressourcen zur VerfĂŒgung gestellt wurden, wenn sie benötigt wurden. Aber ein anderes Problem trat auf: Irgendwann wachten andere Teilnehmer auf und wollten ebenfalls Spark nutzen, aber alles war besetzt, und sie waren unzufrieden. Das ist verstĂ€ndlich. Wir begannen, die Dokumentation zu ĂŒberprĂŒfen. Dort stellte sich heraus, dass es noch einige Parameter gibt, mit denen der Prozess beeinflusst werden kann. Zum Beispiel, wenn der Executor im Wartemodus ist — nach welcher Zeit können die Ressourcen ihm entzogen werden?

spark.dynamicAllocation.executorIdleTimeout=120s

In unserem Fall gilt: Wenn Ihre Executors zwei Minuten lang keine AktivitĂ€ten zeigen, geben Sie sie bitte in den gemeinsamen Pool zurĂŒck. Aber selbst dieser Parameter reichte manchmal nicht aus. Man konnte sehen, dass eine Person schon lange nichts mehr tat, die Ressourcen jedoch nicht freigegeben wurden. Es stellte sich heraus, dass es noch einen speziellen Parameter gibt — nach welcher Zeit man Executors abnehmen kann, die zwischengespeicherte Daten enthalten. StandardmĂ€ĂŸig war dieser Parameter auf infinity eingestellt! Wir haben das angepasst.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Das bedeutet, wenn Ihre Executors in 5 Minuten keine AktivitĂ€ten zeigen, geben Sie sie in den gemeinsamen Pool zurĂŒck. In diesem Modus wurde die Geschwindigkeit der Ressourcenerteilung fĂŒr eine große Anzahl von Benutzern akzeptabel. Die Unzufriedenheit nahm ab. Aber wir beschlossen, weiterzugehen und die maximale Anzahl der Executors fĂŒr eine Anwendung zu begrenzen — im Grunde fĂŒr einen Teilnehmer des Programms.

spark.dynamicAllocation.maxExecutors=19

Jetzt gibt es natĂŒrlich auch Unzufriedene auf der anderen Seite — "Der Cluster steht still, und ich habe nur 19 Executors", aber was soll man machen — es braucht einen richtigen Ausgleich. Alle glĂŒcklich zu machen, wird nicht möglich sein.

Und noch eine kleine Geschichte zu den Besonderheiten unseres Falles. Bei einer praktischen Übung kamen einige Teilnehmer zu spĂ€t, und aus irgendeinem Grund ließ sich Spark nicht starten. Wir schauten uns die Anzahl der verfĂŒgbaren Ressourcen an – es schien, als wĂ€ren genĂŒgend vorhanden. Spark sollte starten. GlĂŒcklicherweise war die Dokumentation bis dahin schon irgendwo im Hinterkopf gespeichert, und wir erinnerten uns, dass Spark beim Start einen Port sucht, um sich zu verbinden. Wenn der erste Port im Bereich belegt ist, greift es auf den nĂ€chsten zugreifbaren Port zurĂŒck. Wenn dieser frei ist, wird er genutzt. Zudem gibt es einen Parameter, der die maximale Anzahl an Versuchen anzeigt. StandardmĂ€ĂŸig betrĂ€gt dieser 16. Das ist weniger als die Anzahl der Personen in unserer Gruppe wĂ€hrend der Übung. Folglich gab Spark nach 16 Versuchen auf und meldete, dass es sich nicht starten könne. Wir haben diesen Parameter angepasst.

spark.port.maxRetries=50

Anschließend erzĂ€hle ich von einigen Einstellungen, die nicht mehr stark mit unserem speziellen Fall verbunden sind.

FĂŒr einen schnelleren Start von Spark gibt es die Empfehlung, den Ordner 'jars', der im Heimatverzeichnis SPARK_HOME liegt, zu archivieren und auf HDFS zu legen. Dadurch wird die Zeit, die fĂŒr das Laden dieser JAR-Dateien auf den Workern benötigt wird, reduziert.

spark.yarn.archive=hdfs:///tmp/spark-archive.zip

FĂŒr schnellere Verarbeitung empfehlen wir, als Serializer Kryo zu verwenden. Dieser ist optimierter als der Standard-Serializer.

spark.serializer=org.apache.spark.serializer.KryoSerializer

Es gibt auch ein langjĂ€hriges Problem mit Spark, dass es oft wegen Speicherproblemen abstĂŒrzt. Dies geschieht hĂ€ufig, wenn die Worker alles berechnet haben und die Ergebnisse an den Driver senden. Wir haben diesen Parameter erhöht. StandardmĂ€ĂŸig betrĂ€gt er 1 GB, wir haben ihn auf 3 GB erhöht.

spark.driver.maxResultSize=3072

Zum Abschluss, wie man Spark auf Version 2.1 im HortonWorks-Distribution — HDP 2.5.3.0 — aktualisiert. Diese HDP-Version enthĂ€lt die vorinstallierte Version 2.0, aber wir haben uns einmal entschieden, dass Spark sich aktiv weiterentwickelt und jede neue Version Fehler behebt und zusĂ€tzliche Möglichkeiten bietet, auch fĂŒr die Python-API, weshalb wir beschlossen haben, ein Update durchzufĂŒhren.

Wir haben die Version von der offiziellen Website fĂŒr Hadoop 2.7 heruntergeladen. Entpackt und in den HDP-Ordner verschoben. Die Symlinks richtig gesetzt. Wir starten — es startet nicht. Es wird eine sehr unklare Fehlermeldung angezeigt.

java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig

Eine Google-Suche ergab, dass Spark beschlossen hat, nicht zu warten, bis Hadoop sich weiterentwickelt, und eine neue Version von Jersey verwenden will. Sie streiten sich darĂŒber sogar in JIRA. Die Lösung war – herunterzuladen Jersey Version 1.17.1. Dies in den jars-Ordner von SPARK_HOME zu verschieben, wieder zip zu erstellen und auf HDFS hochzuladen.

Wir konnten diesen Fehler umgehen, aber es trat ein neuer, ziemlich vager Fehler auf.

org.apache.spark.SparkException: Die Yarn-Anwendung ist bereits beendet! Sie wurde möglicherweise beendet oder konnte den Anwendungs-Master nicht starten.

Wir versuchen die Version 2.0 zu starten – alles in Ordnung. Versuch mal herauszufinden, woran es liegt. Wir haben die Logs dieser Anwendung durchgesehen und Folgendes gesehen:

/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jar

Kurz gesagt, aus irgendeinem Grund wurde hdp.version nicht aufgelöst. Nach einer Google-Suche fanden wir eine Lösung. Man muss in Ambari die YARN-Einstellungen aufrufen und dort einen Parameter in yarn-site hinzufĂŒgen:

hdp.version=2.5.3.0-37

Diese Magie half, und Spark lief. Wir haben einige unserer Jupyter-Notebooks getestet. Alles funktioniert. FĂŒr die erste Sitzung zu Spark am Samstag (schon morgen) sind wir bereit!

UDP. WĂ€hrend der Sitzung stellte sich ein weiteres Problem heraus. Irgendwann hörte YARN auf, Container fĂŒr Spark bereitzustellen. In YARN musste ein Parameter angepasst werden, der standardmĂ€ĂŸig auf 0.2 stand:

yarn.scheduler.capacity.maximum-am-resource-percent=0.8

Das bedeutet, dass nur 20 % der Ressourcen an der Verteilung beteiligt waren. Nachdem die Parameter geÀndert wurden, wurde YARN neu gestartet. Das Problem war behoben, und die anderen Teilnehmer konnten ebenfalls den Spark-Kontext starten.

Quelle: habr.com

Erwerben Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server đŸ”„ Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster