Konfiguriranje Spark na YARN

Habr, zdravo! Jučer na sastanak posvećen Apache Sparku, od momaka iz Rambler&Co, bilo je dosta pitanja učesnika vezanih za konfigurisanje ovog alata. Odlučili smo krenuti njegovim stopama i podijeliti svoje iskustvo. Tema nije laka - stoga vas pozivamo da podijelite svoje iskustvo u komentarima, možda i mi nešto pogrešno razumijemo i koristimo.

Mali uvod u to kako koristimo Spark. Imamo tromesečni program “Specijalist za velike podatke”, a tokom drugog modula naši polaznici rade na ovom instrumentu. Shodno tome, naš zadatak, kao organizatora, je da pripremimo klaster za korištenje u takvom slučaju.

Posebnost naše upotrebe je da broj ljudi koji istovremeno rade na Sparku može biti jednak cijeloj grupi. Na primjer, na seminaru, kada svi pokušavaju nešto u isto vrijeme i ponavljaju za našim učiteljem. A to nije puno - ponekad i do 40 ljudi. Vjerovatno nema mnogo kompanija u svijetu koje se suočavaju s takvim slučajem upotrebe.

Zatim ću vam reći kako i zašto smo odabrali određene konfiguracijske parametre.

Počnimo od samog početka. Spark ima 3 opcije za pokretanje na klasteru: samostalno, koristeći Mesos i koristeći YARN. Odlučili smo se za treću opciju jer nam je to bilo logično. Već imamo hadoop klaster. Naši učesnici su već dobro upoznati sa njegovom arhitekturom. Koristimo YARN.

spark.master=yarn

Dalje zanimljivije. Svaka od ove 3 opcije postavljanja ima 2 opcije raspoređivanja: klijent i klaster. Na osnovu dokumentaciju i raznim linkovima na Internetu, možemo zaključiti da je klijent pogodan za interaktivni rad - na primjer preko jupyter notebook-a, a klaster pogodniji za produkcijska rješenja. U našem slučaju nas je zanimao interaktivni rad, dakle:

spark.deploy-mode=client

Generalno, od sada će Spark nekako raditi na YARN-u, ali to nam nije bilo dovoljno. Budući da je naš program o velikim podacima, ponekad učesnicima nije bilo dovoljno onoga što je dobijeno u okviru ravnomjernog cijepanja resursa. A onda smo pronašli zanimljivu stvar - dinamičku alokaciju resursa. Ukratko, poenta je sljedeća: ako imate težak zadatak i klaster je slobodan (na primjer, ujutro), onda vam korištenje ove opcije Spark može dati dodatne resurse. Potreba se tamo izračunava po lukavoj formuli. Nećemo ulaziti u detalje - radi dobro.

spark.dynamicAllocation.enabled=true

Postavili smo ovaj parametar i nakon pokretanja Spark se srušio i nije se pokrenuo. Tako je, jer sam morao da je pročitam dokumentaciju pažljivije. U njemu se navodi da da bi sve bilo u redu potrebno je i da omogućite dodatni parametar.

spark.shuffle.service.enabled=true

Zašto je to potrebno? Kada naš posao više ne zahtijeva toliko resursa, Spark bi ih trebao vratiti u zajednički bazen. Faza koja oduzima najviše vremena u gotovo svakom MapReduce zadatku je faza Shuffle. Ovaj parametar vam omogućava da sačuvate podatke koji su generisani u ovoj fazi i u skladu s tim otpustite izvršioce. A izvršilac je proces koji sve obračunava na radnika. Ima određeni broj procesorskih jezgara i određenu količinu memorije.

Ovaj parametar je dodat. Činilo se da sve funkcionira. Postalo je primjetno da su učesnicima zapravo dato više resursa kada su im bili potrebni. No, pojavio se još jedan problem - u nekom trenutku su se probudili i drugi učesnici koji su također htjeli koristiti Spark, ali tamo je sve bilo zauzeto i bili su nezadovoljni. Mogu se razumjeti. Počeli smo da gledamo dokumentaciju. Pokazalo se da postoji niz drugih parametara koji se mogu koristiti za utjecaj na proces. Na primjer, ako je izvršitelj u stanju pripravnosti, nakon kojeg vremena mu se mogu uzeti resursi?

spark.dynamicAllocation.executorIdleTimeout=120s

U našem slučaju, ako vaši izvršitelji ne rade ništa dva minuta, molimo vas da ih vratite u zajednički bazen. Ali ovaj parametar nije uvijek bio dovoljan. Bilo je jasno da osoba već duže vrijeme ništa ne radi, a sredstva se ne oslobađaju. Ispostavilo se da postoji i poseban parametar - nakon kojeg vremena odabrati izvršitelje koji sadrže keširane podatke. Podrazumevano, ovaj parametar je bio beskonačnost! Ispravili smo to.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Odnosno, ako vaši izvršitelji ne rade ništa 5 minuta, dajte ih u zajednički bazen. U ovom načinu rada, brzina puštanja i izdavanja resursa za veliki broj korisnika postala je pristojna. Količina nezadovoljstva je smanjena. Ali odlučili smo da idemo dalje i ograničimo maksimalan broj izvršilaca po aplikaciji – u suštini po učesniku programa.

spark.dynamicAllocation.maxExecutors=19

Sad su, naravno, nezadovoljni sa druge strane - "klaster miruje, a ja imam samo 19 izvršilaca", ali šta možete, treba nam neka ispravna ravnoteža. Ne možeš sve usrećiti.

I još jedna mala priča vezana za specifičnosti našeg slučaja. Nekako je nekoliko ljudi zakasnilo na praktičnu nastavu, a Varnica iz nekog razloga nije krenula umjesto njih. Pogledali smo količinu besplatnih resursa - čini se da postoji. Iskra bi trebalo da počne. Srećom, do tada je dokumentacija već bila dodana negdje u podkorteks, a mi smo se sjetili da kada se pokrene, Spark traži port na kojem će početi. Ako je prvi port u opsegu zauzet, prelazi na sljedeći po redu. Ako je slobodan, hvata. I postoji parametar koji pokazuje maksimalan broj pokušaja za to. Podrazumevano je 16. Broj je manji od broja ljudi u našoj grupi u razredu. Shodno tome, nakon 16 pokušaja, Spark je odustao i rekao da ne mogu da počnem. Ispravili smo ovaj parametar.

spark.port.maxRetries=50

Zatim ću vam reći o nekim postavkama koje nisu baš povezane sa specifičnostima našeg slučaja.

Da biste brže pokrenuli Spark, preporučuje se da arhivirate mapu jars koja se nalazi u matičnom direktoriju SPARK_HOME i stavite je na HDFS. Onda neće gubiti vrijeme na utovar ovih jarnika od strane radnika.

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

Također je preporučljivo koristiti kryo kao serijalizator za brži rad. Optimiziraniji je od zadanog.

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

Postoji i dugogodišnji problem sa Spark-om da se često ruši iz memorije. Često se to dešava u trenutku kada radnici sve izračunaju i pošalju rezultat vozaču. Ovaj parametar smo povećali za sebe. Podrazumevano je 1GB, mi smo napravili 3.

spark.driver.maxResultSize=3072

I na kraju, kao desert. Kako ažurirati Spark na verziju 2.1 na HortonWorks distribuciji - HDP 2.5.3.0. Ova verzija HDP-a sadrži unaprijed instaliranu verziju 2.0, ali smo jednom za sebe odlučili da se Spark prilično aktivno razvija, a svaka nova verzija ispravlja neke greške plus pruža dodatne mogućnosti, uključujući i za python API, pa smo odlučili šta treba biti urađeno je ažuriranje.

Preuzeta verzija sa službene web stranice za Hadoop 2.7. Raspakujte ga i stavite u HDP folder. Po potrebi smo instalirali simbolične veze. Pokrećemo ga - ne počinje. Piše veoma čudnu grešku.

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

Nakon guglanja saznali smo da je Spark odlučio ne čekati da se rodi Hadoop, te je odlučio koristiti novu verziju dresa. I sami se raspravljaju o ovoj temi u JIRA-i. Rješenje je bilo preuzimanje verzija dresa 1.17.1. Stavite ovo u mapu tegli u SPARK_HOME, ponovo zipirajte i otpremite na HDFS.

Zaobišli smo ovu grešku, ali se pojavila nova i prilično pojednostavljena.

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

U isto vrijeme pokušavamo pokrenuti verziju 2.0 - sve je u redu. Pokušajte da pogodite šta se dešava. Pogledali smo u zapisnike ove aplikacije i vidjeli nešto ovako:

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

Općenito, iz nekog razloga hdp.version nije riješen. Nakon guglanja pronašli smo rješenje. Morate otići na postavke YARN-a u Ambariju i tamo dodati parametar na prilagođeno mjesto pređe:

hdp.version=2.5.3.0-37

Ova magija je pomogla i Varnica je poletela. Testirali smo nekoliko naših jupyter laptopova. Sve radi. Spremni smo za prvi Spark čas u subotu (sutra)!

DUP. Tokom lekcije pojavio se još jedan problem. U nekom trenutku, YARN je prestao da obezbeđuje kontejnere za Spark. U YARN-u je bilo potrebno ispraviti parametar, koji je po defaultu bio 0.2:

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

Odnosno, samo 20% resursa je učestvovalo u raspodeli resursa. Nakon promjene parametara, ponovo smo učitali YARN. Problem je riješen, a ostali učesnici su također mogli pokrenuti Spark kontekst.

izvor: www.habr.com

Dodajte komentar