A Spark konfigurálása a YARN-on

Habr, szia! Tegnap tovább Az Apache Sparknak szentelt találkozó, a Rambler&Co srácaitól elég sok kérdés érkezett a résztvevőktől az eszköz konfigurálásával kapcsolatban. Úgy döntöttünk, hogy az ő nyomdokaiba lépünk, és megosztjuk tapasztalatainkat. A téma nem könnyű - ezért arra kérjük, ossza meg tapasztalatait a megjegyzésekben, talán mi is értünk és rosszul használunk valamit.

Egy kis bevezető a Spark használatába. Három hónapos programunk van „Big Data specialista”, és a második modulban résztvevőink ezen a hangszeren dolgoznak. Ennek megfelelően a mi feladatunk, mint szervezők a klaszter felkészítése az ilyen eseten belüli használatra.

Felhasználásunk sajátossága, hogy a Sparkon egyidejűleg dolgozók száma megegyezik a teljes csoporttal. Például egy szemináriumon, amikor mindenki egyszerre próbál ki valamit, és a tanárunk után ismétli. És ez nem sok - néha akár 40 ember is. Valószínűleg nem sok olyan cég van a világon, amely ilyen használati esettel szembesül.

Ezután elmondom, hogyan és miért választottunk ki bizonyos konfigurációs paramétereket.

Kezdjük a legelejéről. A Sparknak 3 lehetősége van a fürtön való futtatásra: önállóan, Mesos használatával és YARN használatával. Úgy döntöttünk, hogy a harmadik lehetőséget választjuk, mert ez volt számunkra értelmes. Már van egy hadoop klaszterünk. Résztvevőink már jól ismerik építészetét. Használjunk FONALOT.

spark.master=yarn

Tovább érdekesebb. A 3 központi telepítési lehetőség mindegyikéhez 2 telepítési lehetőség tartozik: ügyfél és fürt. Alapján dokumentáció és az interneten található különféle hivatkozások alapján megállapíthatjuk, hogy a kliens alkalmas interaktív munkára - például a jupyter notebookon keresztül, a fürt pedig inkább a termelési megoldásokra. Esetünkben az interaktív munka volt érdekelt, ezért:

spark.deploy-mode=client

Általánosságban elmondható, hogy mostantól a Spark valahogyan működik a YARN-on, de ez nekünk nem volt elég. Mivel van programunk a big data-ról, előfordult, hogy a résztvevőknek nem volt elegük az egyenletes forrásszeletelés keretein belül szerzettekből. És akkor találtunk egy érdekes dolgot - a dinamikus erőforrás-elosztást. Röviden, a lényeg a következő: ha nehéz feladatod van, és a fürt szabad (például reggel), akkor ezzel a lehetőséggel a Spark további erőforrásokat adhat. Ott egy ravasz képlet szerint számítják ki a szükségszerűséget. Nem megyünk bele a részletekbe – jól működik.

spark.dynamicAllocation.enabled=true

Beállítottuk ezt a paramétert, és indításkor a Spark összeomlott, és nem indult el. Így van, mert el kellett olvasnom dokumentáció óvatosabban. Azt írja ki, hogy ahhoz, hogy minden rendben legyen, egy további paramétert is engedélyezni kell.

spark.shuffle.service.enabled=true

Miért van rá szükség? Amikor a munkánk már nem igényel annyi erőforrást, a Sparknak vissza kell adnia őket a közös készletbe. Szinte minden MapReduce-feladat legidőigényesebb szakasza a Shuffle szakasz. Ez a paraméter lehetővé teszi az ebben a szakaszban generált adatok mentését és a végrehajtók felszabadítását. A végrehajtó pedig az a folyamat, amely mindent kiszámol a dolgozón. Bizonyos számú processzormaggal és bizonyos mennyiségű memóriával rendelkezik.

Ez a paraméter hozzáadásra került. Minden működni látszott. Észrevehetővé vált, hogy a résztvevők több erőforrást kaptak, amikor szükségük volt rájuk. De egy másik probléma is felmerült - egy ponton más résztvevők felébredtek, és szintén használni akarták a Sparkot, de ott minden elfoglalt volt, és boldogtalanok voltak. Meg lehet őket érteni. Elkezdtük nézegetni a dokumentációt. Kiderült, hogy számos egyéb paraméterrel is befolyásolható a folyamat. Például, ha a végrehajtó készenléti állapotban van, mennyi idő után lehet erőforrást elvenni tőle?

spark.dynamicAllocation.executorIdleTimeout=120s

Esetünkben, ha a végrehajtói két percig nem csinálnak semmit, akkor kérjük visszaküldeni őket a közös medencébe. De ez a paraméter nem mindig volt elég. Egyértelmű volt, hogy az illető hosszú ideje nem csinált semmit, és az erőforrások sem szabadultak fel. Kiderült, hogy van egy speciális paraméter is - mennyi idő után kell kiválasztani a gyorsítótárazott adatokat tartalmazó végrehajtókat. Alapértelmezés szerint ez a paraméter a végtelen volt! Kijavítottuk.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Azaz, ha a végrehajtói 5 percig nem csinálnak semmit, adják át őket a közös medencébe. Ebben a módban az erőforrások felszabadításának és kiadásának sebessége nagyszámú felhasználó számára megfelelővé vált. Az elégedetlenség mértéke csökkent. De úgy döntöttünk, hogy tovább megyünk, és korlátozzuk az alkalmazásonkénti végrehajtók maximális számát – lényegében program résztvevőnként.

spark.dynamicAllocation.maxExecutors=19

Most persze vannak elégedetlenek a másik oldalon – „a klaszter tétlen, és csak 19 végrehajtóm van”, de mit tehetsz? Valamiféle helyes egyensúlyra van szükségünk. Nem lehet mindenkit boldoggá tenni.

És még egy kis történet, ami az esetünk sajátosságaihoz kapcsolódik. Valahogy többen elkéstek egy gyakorlati óráról, és valamiért nem indult el helyettük a Spark. Megnéztük a szabad források mennyiségét – úgy tűnik, hogy van. A Sparknak indulnia kell. Szerencsére addigra a dokumentáció már felkerült valahova az alkéregbe, és emlékeztünk rá, hogy induláskor a Spark keres egy portot, amin elindulhat. Ha a tartomány első portja foglalt, akkor sorrendben a következőre lép. Ha ingyenes, akkor rögzíti. És van egy paraméter, amely jelzi a kísérletek maximális számát. Az alapértelmezett 16. A szám kevesebb, mint ahány ember van csoportunkban az osztályban. Ennek megfelelően 16 próbálkozás után Spark feladta és közölte, hogy nem tudok elindulni. Ezt a beállítást javítottuk.

spark.port.maxRetries=50

Ezután néhány olyan beállításról fogok beszélni, amelyek nem nagyon kapcsolódnak esetünk sajátosságaihoz.

A Spark gyorsabb elindításához javasoljuk, hogy archiválja a SPARK_HOME kezdőkönyvtárában található jars mappát, és tegye HDFS-re. Akkor nem vesztegeti az idejét azzal, hogy a munkások berakják ezeket a jarnikokat.

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

A gyorsabb működés érdekében szintén ajánlott a kryo használata sorosítóként. Optimalizáltabb, mint az alapértelmezett.

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

És van egy régóta fennálló probléma a Sparkkal, hogy gyakran összeomlik a memóriából. Ez gyakran abban a pillanatban történik, amikor a dolgozók mindent kiszámoltak, és elküldik az eredményt a sofőrnek. Ezt a paramétert magunknak növeltük. Alapértelmezés szerint 1 GB, mi 3-at csináltunk belőle.

spark.driver.maxResultSize=3072

És végül desszertként. A Spark frissítése a 2.1-es verzióra a HortonWorks disztribúción – HDP 2.5.3.0. A HDP ezen verziója tartalmaz egy előre telepített 2.0-s verziót, de egyszer úgy döntöttünk, hogy a Spark meglehetősen aktívan fejlődik, és minden új verzió kijavít néhány hibát, valamint további funkciókat is biztosít, beleértve a python API-t is, ezért úgy döntöttünk, hogy mit kell meg kell tenni egy frissítést.

Letöltötte a verziót a Hadoop 2.7 hivatalos webhelyéről. Csomagolja ki és helyezze be a HDP mappába. Szükség szerint telepítettük a szimbolikus linkeket. Elindítjuk – nem indul el. Nagyon furcsa hibát ír.

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

A guglizás után rájöttünk, hogy a Spark úgy döntött, nem várja meg Hadoop születését, és a mez új verziója mellett döntött. Ők maguk vitatkoznak egymással erről a témáról a JIRA-ban. A megoldás a letöltés volt mez verzió 1.17.1. Helyezze ezt a SPARK_HOME jars mappájába, csomagolja be újra, és töltse fel a HDFS-be.

Megkerültük ezt a hibát, de egy új és meglehetősen egyszerűsített hiba lépett fel.

org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master

Ugyanakkor megpróbáljuk a 2.0-s verziót futtatni - minden rendben van. Próbáld kitalálni, mi történik. Megnéztük az alkalmazás naplóit, és valami ilyesmit láttunk:

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

Általában valamiért a hdp.version nem oldódott meg. A guglizás után megtaláltuk a megoldást. Meg kell lépnie az Ambari YARN beállításaival, és hozzá kell adnia egy paramétert az egyéni fonal webhelyhez:

hdp.version=2.5.3.0-37

Ez a varázslat segített, és Spark elindult. Több Jupyter laptopunkat teszteltük. Minden működik. Készülünk az első Spark leckére szombaton (holnap)!

UPD. A tanórán újabb probléma derült ki. Valamikor a YARN leállította a konténerek biztosítását a Spark számára. A YARN-ben módosítani kellett a paramétert, amely alapértelmezés szerint 0.2 volt:

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

Azaz a források mindössze 20%-a vett részt az erőforrások elosztásában. A paraméterek megváltoztatása után újratöltöttük a YARN-t. A probléma megoldódott, és a többi résztvevő is képes volt szikrakontextus futtatására.

Forrás: will.com

Hozzászólás