1.3.2018Blogi

Apache Airflow – kaikki mitä meillä on, lähtee DAGeista

Olemme saaneet Solitalla Apache Airflowsta melko lyhyessä ajassa isoja hyötyjä ja ennen kaikkea tuotua kokoaan uudenlaisen automaation tason tekemiseen, jonka avulla olemme voineet siirtää enemmän fokusta dataputkien rakentelusta ja debuggauksesta asiakkaan liiketoimintaa hyödyttävään tekemiseen. Kollegani Mika summasi omassa Apache Airflow – mitä ja miksi datan kanssa työskentelevän tulee siitä tietää -blogikirjoituksessaan  hyvin Apache Airflown perusajatukset ja yleiset kokemukset sen käyttämisessä tuotannollisessa tietovarastointiratkaisussa. Tässä kirjoituksessa sukellan syvemmälle viime aikaisiin kokemuksiimme Airflown käytöstä ja kerron konkreettisesti sen tuomista hyödyistä sekä haasteista, joita olemme kohdanneet matkalla parempaan latausten hallintaan ja mukavampaan ylläpitoon.

Lähtötilanne ennen Airflown käyttöönottoa

Kun Airfowta alettiin tuoda projektissamme käyttöön, olimme ylläpidollisesti hieman haastavassa tilanteessa. Tietovarastoon ja analyyseihin liittyviä latauksia tehtiin useammalla eri ETL- tai data discovery -työkalulla ja latauksia pyöri päivittäin sekä Windows- että Linux-palvelimilla.

Latauksia oli orkestroitu ja ajastettu useammalla eri työkalulla, mm. SQL Server Agentilla, Crontabilla ja muutama rullasi vielä Windows Schedulerillakin. Näiden lisäksi iso osa latauksista ajettiin master-tyyppisten jobien avulla ja latauksien väliset riippuvuudet olivat upotettuina syvälle ETL-himmeleiden syövereihin.

Kaiken kaikkiaan lähtökohtamme voisi summata (kärjistetysti) seuraavasti:

  • Meillä ei ollut yhtenäistä näkymää kuinka viimeisimmät lataukset olivat onnistuneet
  • Latauksien suoritustietoja sijaitsi usean eri palvelimen tai sovelluksen lokeissa
  • Mahdollisuudet automatisointiin olivat minimaaliset tai olemattomat
  • Kaatuessaan lataukset antoivat pahimmillaan hyvin geneerisen virheen, josta ei voinut päätellä, mikä lataus sen oli lopulta aiheuttanut
  • Yksittäisen ajon uudelleen käynnistäminen oli hankalaa ja ei tarjonnut näkyvyyttä latauslogiikkaan
  • Latauksien riippuvuuksista ei ollut selkeää näkyvyyttä ja master jobien avulla oltiin luotu ylimääräisiä ja tarpeettomia riippuvuuksia
  • Kaiken kattavaa valvontaympäristöä varten oltaisiin jouduttu rakentamaan kokonaan oma ympäristönsä, joka hoitaisi tiedon keräämisen ja visualisoinnin

Yhtenä tiedostettuna haasteena Airflown käyttöönotolle oli, että olimme ottamassa sitä käyttöön EDW  (Enterprise Data Warehouse)-ympäristössä, jossa orkestrointi ja riippuvuudenhallintatarpeet ovat hieman erilaiset kuin useimmissa Airflowta koskevissa esimerkeissä. Esimerkeissä DAGit olivat yleensä pistemäisiä, tietyn osa-alueen ratkaisuja, mutta EDW-ratkaisussa latauksien väliset riippuvuudet monimutkaistuvat sitä mukaa kun uusia lähdejärjestelmiä tuodaan. Tämä tuo täysin omat haasteensa optimaalisten DAGien luomiseen.

Ensimmäiset askeleet Airflow-ympäristössä

Saatuamme Airflow-ympäristön pystyyn lähdimme alusta asti generoimaan DAGeja automaattisesti. DAGeja voi halutessaan luoda myös manuaalisesti käsin koodaamalla, joilloin tosin hyvin nopeasti huomaa, että samat elementit toistuvat latauksissa ja generointi metadatan avulla on ainoa järkevä tapa edetä.

Käyttämämme tietovaraston mallinnusmenetelmä yhdistettynä Solitan Agile Data Designeriin loi meille automaattisesti hyvän metadata-varaston, jonka avulla latausten luominen onnistui sujuvasti ja metadatan keräämiseen ei tarvinnut erikseen käyttää aikaa. DAGien automaattista luontia varten kirjoitimme Pythonilla hyvin simppelin DAG -”generaattorin”, joka generoi metadatan pohjalta parametrien mukaiset lataukset. Saatuamme generoinnin halutulle, aluksi hyvin minimaaliselle tasolle, lähdimme luomaan latauksia lähdejärjestelmistä tietovarastoon.

Koska Airflowta edeltävä ratkaisu nojasi hyvin paljon perinteiseen master-paketti pohjaiseen lähestymiseen, kokeilimme aluksi luoda DAGeihin ainostaan minimiriippuvuudet. Tällöin yhdessä DAGissa olisi 1 kpl stage-latauksia ja n kappaletta stage-tauluun liittyviä tietovarasto latauksia. Automaattisen generoinnin ansiosta pystyimme luomaan tarvittavat lataukset hyvin nopeaan tahtiin ja parissa päivässä meillä olikin useita kymmeniä DAGeja. Tällöin ongelmat alkoivat lähestyä eri suunnista.

 

Kuva 1 – Stage taulukohtainen DAG

Kuten sanottua, lähdejärjestelmästä tietovarastoon latauslogiikka noudatti aina samaa, yksinkertaista kaavaa, mutta kun tietovarastosta alettiin lataamaan dataa julkaisualueelle, mm. faktoihin ja dimensioihin, asiat alkoivat mennä hankalaksi. Olisimme voineet niputtaa koko latauslogiikan yhteen DAGiin silloin, kun kyse oli yhdestä faktasta, joka koostettaisiin yhdestä lähdejärjestelmästä. Kuitenkin, mikäli faktoja ja dimensiota tulisi lisää ja ne olisivat riippuvaisia useammasta lähteestä, olisimme lopulta mahdollisesti tilanteessa, jossa koko EDW ladattaisiin yhdellä DAGilla!

Tästä johtuen päätimme erottaa stage-tietovarasto DAGit ja julkaisu alueen DAGit kokonaan toisistaan. Erottelun etuna on myös se, että tietovarastoa ja julkaisualuetta voidaan ladata tarvittaessa eri sykleillä.

Ajattelimme ratkaisun olevan Airflow-sensori, jonka avulla on mahdollista ”kuunnella” toisessa DAGissa olevan taskin tilaa ja näin ollen käynnistää taski omassa DAGissa kun sensori ilmoittaa edellisen olevan valmis. Aloimme luomaan julkaisualueen lataukset sensorin avulla vain huomataksemme, että sensori ei toimi halutusti. Ongelma oli, että kun sensoreita alkoi olla tarpeeksi, ne veivät kaikki Airflow käytössä olevat resurssit. Näin ollen oltiin siis tilanteessa, jossa sensorit odottivat latauksia, jotka eivät voineet koskaan valmistua, koska sensorit veivät niiden tarvitsemat resurssit. Tämä yhdistettynä siihen, että olimme generoineet tässä vaiheessa jo lähemmäs sata pientä DAGia johti puolestaan siihen, että Airflow:n Scheduler alkoi piiputtamaan ja piti ottaa muuta askel taaksepäin .

Muutoksien kautta nykytilanteeseen

Vaikka yksi syy Airflow käyttämiselle oli, että pääsisimme useita latauksia yhteen niputtavista master-tyyppisistä latauksista eroon, päädyimme tekemään kompromissin, jossa koostamme kaikki samaan ajanhetkeen alkavat lähdejärjestelmä-tietovarasto-lataukset yhteen DAGiin. Airflowssa tämä ei onneksi ole niin iso ongelma kuin aikaisemmassa ratkaisussa, koska se tarjoaa loistavan näkyvyyden kaikkeen mitä DAGin sisällä tapahtuu ja esimerkiksi mahdollinen virhe latauksessa on hyvin helppoa bongata.

Kuva 2 – DAG, joka niputtaa yhteen useamman tietovarasto latauksen

Muutos vähensi oleellisesti DAGien määrää, joka on saanu Airflown yleisesti toimimaan huomattavasti paremmin. Olemme edelleen pitäneet julkaisualueen lataukset omissa DAGeissaan, mutta myös niiden kohdalla olemme yhdistäneet saman aihepiirin latauksia yhteen ja näin myös tiputtaneet DAGien määrää.

Emme ole vielä päässeet tilanteeseen, jossa saisimme käynnistettyä julkaisualueen latauksen välittömästi kun siihen riippuvat lataukset ovat valmistuneet, vaan olemme joutuneet ajastamaan ne erikseen. Yhtenä vaihtoehtona tähän on esimerkiksi luoda oma custom-operaattori, joka tarkastaa onko tarpeelliset lataukset valmistuneet ja voidaanko lataus suorittaa.

Olemme myös panostaneet lisää automaatioon ja ottaneet Jenkinsin käyttöön Airflown rinnalle. Voimme Jenkinsin avulla vielä helpottaa ja hallita DAGien generointia paremmin, julkaista niitä eri ympäristöjen välillä sekä versioida muutokset automaattisesti.

Kuva 3 – Yksinkertainen Jenkins deployment pipeline

Alkuasetelma versus loppuasetelma – kannattiko?

Jos mietitään alussa mainittua listaa, niin nyt olemme nyt seuraavassa tilanteessa:

  • Kaikki lataukset – työkalusta riippumatta – ajastetaan ja hallitaan samassa paikassa ja näkymä kokonaistilanteesta on helposti saatavilla
  • Latausten logit ovat samassa paikassa
  • Airflown ”configuration as a code”  lähestymisen avulla olemme automatisoituneet latauksien generoinnin hyvin pitkälle
  • Latauksen kaatuessa saamme suoraan ilmoituksen Slackiin selkeällä virheilmoituksella
  • Pystymme metadatan avulla generoimaan yksittäisiä latauksia tarpeen vaatiessa uudelleen
  • Näemme DAGeista suoraan latauksien riippuvuudet
  • Airflow tarjoaa valmiiksi erilaisia kuvaajia, joiden avulla on helppoa tarkastella ajojärjestystä ja kestoja. Airflown oman metakannan ja esim. Grafanan avulla voi helposti luoda vielä lisää visualisointeja kattavampaa monitorointia varten

Apachen käyttöönotto on ollut ehdottoman kannattavaa, sillä kasvaneen automaation myötä pystymme kohdistamaan tekemistämme nyt dataputkien rakentelusta ja debuggauksesta sellaisiin asioihin, joista asiakkaamme liiketoiminta hyötyy ihan oikeasti ja joka on meillekin mielekkäämpää.