Konfigurera Spark på GARN

Habr, hej! Igår på möte tillägnad Apache Spark, från killarna från Rambler&Co, det var ganska många frågor från deltagare relaterade till konfigurering av det här verktyget. Vi bestämde oss för att följa i hans fotspår och dela vår erfarenhet. Ämnet är inte lätt - så vi inbjuder dig att dela din upplevelse i kommentarerna, kanske vi också förstår och använder något fel.

En liten introduktion till hur vi använder Spark. Vi har ett tre månaders program "Big Data Specialist", och under den andra modulen arbetar våra deltagare med detta instrument. Vår uppgift som arrangörer är därför att förbereda klustret för användning i ett sådant fall.

Det speciella med vår användning är att antalet personer som samtidigt arbetar på Spark kan vara lika med hela gruppen. Till exempel på ett seminarium, när alla provar något samtidigt och upprepar efter vår lärare. Och det här är inte mycket - ibland upp till 40 personer. Det finns förmodligen inte många företag i världen som står inför ett sådant användningsfall.

Därefter kommer jag att berätta hur och varför vi valde vissa konfigurationsparametrar.

Låt oss börja från början. Spark har 3 alternativ att köra på ett kluster: fristående, med Mesos och med GARN. Vi bestämde oss för att välja det tredje alternativet eftersom det var vettigt för oss. Vi har redan ett hadoop-kluster. Våra deltagare är redan väl bekanta med dess arkitektur. Låt oss använda GARN.

spark.master=yarn

Mer intressant. Vart och ett av dessa tre distributionsalternativ har två distributionsalternativ: klient och kluster. Baserad dokumentation och olika länkar på Internet, kan vi dra slutsatsen att klienten är lämplig för interaktivt arbete - till exempel genom Jupyter anteckningsbok, och kluster är mer lämpad för produktionslösningar. I vårt fall var vi intresserade av interaktivt arbete, därför:

spark.deploy-mode=client

I allmänhet, från och med nu kommer Spark på något sätt att fungera på YARN, men detta räckte inte för oss. Eftersom vi har ett program om big data har deltagarna ibland inte räckt till med det som erhållits inom ramen för en jämn resursdelning. Och så hittade vi en intressant sak - dynamisk resursallokering. Kort sagt, poängen är denna: om du har en svår uppgift och klustret är ledigt (till exempel på morgonen), kan det här alternativet Spark ge dig ytterligare resurser. Där beräknas nödvändigheten enligt en listig formel. Vi går inte in på detaljer - det fungerar bra.

spark.dynamicAllocation.enabled=true

Vi ställde in den här parametern och vid start kraschade Spark och startade inte. Det stämmer, för jag var tvungen att läsa den dokumentation mer försiktigt. Det står att för att allt ska vara ok måste du även aktivera en extra parameter.

spark.shuffle.service.enabled=true

Varför behövs det? När vårt jobb inte längre kräver så mycket resurser bör Spark lämna tillbaka dem till den gemensamma poolen. Det mest tidskrävande steget i nästan alla MapReduce-uppgifter är Shuffle-steget. Denna parameter låter dig spara data som genereras i detta skede och släppa exekutorerna i enlighet därmed. Och exekutören är processen som beräknar allt på arbetaren. Den har ett visst antal processorkärnor och en viss mängd minne.

Denna parameter har lagts till. Allt verkade fungera. Det blev märkbart att deltagarna faktiskt fick mer resurser när de behövde dem. Men ett annat problem uppstod - vid något tillfälle vaknade andra deltagare och ville också använda Spark, men allt var upptaget där, och de var missnöjda. De kan förstås. Vi började titta på dokumentationen. Det visade sig att det finns en rad andra parametrar som kan användas för att påverka processen. Till exempel, om executorn är i standby-läge, efter vilken tid kan resurser tas från den?

spark.dynamicAllocation.executorIdleTimeout=120s

I vårt fall, om dina exekutorer inte gör något under två minuter, vänligen lämna tillbaka dem till den gemensamma poolen. Men denna parameter var inte alltid tillräcklig. Det var tydligt att personen inte gjort något på länge och resurser frigjordes inte. Det visade sig att det också finns en speciell parameter - efter vilken tid ska man välja exekutorer som innehåller cachad data. Som standard var denna parameter oändlig! Vi rättade till det.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Det vill säga, om dina exekutorer inte gör något på 5 minuter, ge dem till den gemensamma poolen. I det här läget har hastigheten för att släppa och utfärda resurser för ett stort antal användare blivit anständig. Mängden missnöje har minskat. Men vi bestämde oss för att gå längre och begränsa det maximala antalet exekutörer per ansökan - i huvudsak per programdeltagare.

spark.dynamicAllocation.maxExecutors=19

Nu finns det förstås missnöjda människor på andra sidan - "klustret är inaktivt, och jag har bara 19 exekutörer", men vad kan du göra? Vi behöver någon form av korrekt balans. Man kan inte göra alla glada.

Och ytterligare en liten historia relaterad till detaljerna i vårt fall. På något sätt var flera personer försenade till en praktisk lektion, och av någon anledning startade inte Spark för dem. Vi tittade på mängden gratisresurser – det verkar finnas där. Gnistan ska starta. Lyckligtvis hade dokumentationen redan lagts till underbarken någonstans vid den tiden, och vi kom ihåg att när Spark lanserades letar Spark efter en port att börja på. Om den första porten i området är upptagen, flyttas den till nästa i ordning. Om det är gratis, fångar det. Och det finns en parameter som anger det maximala antalet försök för detta. Standard är 16. Antalet är mindre än antalet personer i vår grupp i klassen. Följaktligen, efter 16 försök, gav Spark upp och sa att jag inte kunde starta. Vi har korrigerat denna inställning.

spark.port.maxRetries=50

Därefter ska jag berätta om några inställningar som inte är särskilt relaterade till detaljerna i vårt fall.

För att starta Spark snabbare rekommenderas det att arkivera jars-mappen som finns i SPARK_HOME-hemkatalogen och lägga den på HDFS. Då kommer han inte att slösa tid på att lasta dessa jarniks av arbetare.

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

Det rekommenderas också att använda kryo som en serialiserare för snabbare drift. Den är mer optimerad än standarden.

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

Och det finns också ett långvarigt problem med Spark att den ofta kraschar från minnet. Ofta händer detta i det ögonblick då arbetarna har räknat ut allt och skickar resultatet till föraren. Vi gjorde denna parameter större för oss själva. Som standard är det 1 GB, vi gjorde det till 3.

spark.driver.maxResultSize=3072

Och sist, som efterrätt. Hur man uppdaterar Spark till version 2.1 på HortonWorks-distribution - HDP 2.5.3.0. Den här versionen av HDP innehåller en förinstallerad version 2.0, men vi bestämde oss en gång för oss själva att Spark utvecklas ganska aktivt, och varje ny version fixar några buggar plus ger ytterligare funktioner, inklusive för python API, så vi bestämde oss för vad som måste göras är en uppdatering.

Laddade ner versionen från den officiella webbplatsen för Hadoop 2.7. Packade upp den och lade den i HDP-mappen. Vi installerade symbollänkarna efter behov. Vi lanserar den - den startar inte. Skriver ett väldigt konstigt fel.

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

Efter att ha googlat fick vi reda på att Spark bestämde sig för att inte vänta tills Hadoop föddes, och bestämde oss för att använda den nya versionen av jersey. De argumenterar själva med varandra om detta ämne i JIRA. Lösningen var att ladda ner tröja version 1.17.1. Placera detta i jars-mappen i SPARK_HOME, zippa det igen och ladda upp det till HDFS.

Vi kom runt det här felet, men ett nytt och ganska strömlinjeformat uppstod.

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

Samtidigt försöker vi köra version 2.0 – allt är ok. Försök gissa vad som händer. Vi tittade i loggarna för denna applikation och såg något i stil med detta:

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

I allmänhet löste sig inte hdp.version av någon anledning. Efter att ha googlat hittade vi en lösning. Du måste gå till GARN-inställningarna i Ambari och lägga till en parameter där till anpassad garnsida:

hdp.version=2.5.3.0-37

Denna magi hjälpte, och Spark tog fart. Vi testade flera av våra Jupyter bärbara datorer. Allt fungerar. Vi är redo för första Spark-lektionen på lördag (imorgon)!

UPD. Under lektionen kom ett annat problem upp. Vid något tillfälle slutade YARN att tillhandahålla containrar till Spark. I YARN var det nödvändigt att korrigera parametern, som som standard var 0.2:

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

Det vill säga att endast 20 % av resurserna deltog i resursfördelningen. Efter att ha ändrat parametrarna laddade vi om GARN. Problemet löstes och resten av deltagarna kunde också köra sparkkontext.

Källa: will.com

Lägg en kommentar