

Tijdens de ontwikkeling van een groots idee liepen wij als BI-club tegen een probleem aan: het implementeren van een E(T)L-scriptje kost meer tijd dan het schrijven van het script zelf. Scheduling, logging, onderhoud, monitoring; het is vooral veel gedoe en voor een junior BI’er is het vaak te complex.
Je zou denken dat er wel een oplossing móét bestaan waarmee het bouwen van een API-koppeling zo simpel is als het schrijven van een scriptje & klaar. Na het proberen van verschillende oplossingen kwamen wij tot de conclusie dat we het toch echt zelf moesten bouwen.
In dit blog vertel ik hoe wij nu API-koppelingen kunnen bouwen met alleen een script en hoe het werkt. Ook neem ik je mee in de reis naar het eindresultaat. Daarbij ga ik wat dieper in op de keuzes die we onderweg gemaakt hebben en hoe het aan de achterkant gebouwd is.
//* Datahub is een werknaam in de zoektocht naar een betere naam.
1. Het probleem van veel klanten met veel verschillende systemen en verschillende architecturen
Voordat ik aftrap met de oplossing, ga ik eerst wat dieper in op het probleem.
Als relatief kleine organisatie beheren wij heel wat verschillende omgevingen. Soms op onze eigen infrastructuur, soms op die van de klant. We ontsluiten veel verschillende systemen en hebben te maken met variërende ‘skillsets’ bij de klant zelf.
Zo heb je dus al snel een samenraapsel van verschillende cloud en ‘on-premise’–systemen, losse scriptjes en mini-applicaties. Het documenteren van al deze oplossingen is al lastig, om nog maar te zwijgen over de complexiteit om als developer OPS (operations) te runnen over al die systemen, programmeertalen en runtimes heen. Dit had tot gevolg dat we single points of failures creëerden voor specifieke klanten bij specifieke developers en dat OPS voor onze junioren vrijwel onmogelijk was.
Als groeiende BI-club zijn wij gebaat bij de gulden middenweg tussen flexibiliteit in de te gebruiken systemen/tools en standaardisatie in the way of working zodat iedereen gemakkelijk op elk project inzetbaar is. Juist ook de minder ervaren developers. Vooral bij nieuwe BI Implementaties is het handig om versnelling aan te brengen met een tool zoals deze.
2. De oplossing: een scriptje schrijven en klaar is <naam>
Voor de uiteindelijke oplossing was ons uitgangspunt dat het bouwen van een API-koppeling niet moeilijker moest zijn dan het schrijven van een scriptje.
Andere eisen: zaken als monitoring, logging etc. moeten automatisch geregeld worden. Plus: een hoge kwaliteit van output, lage instapkosten, geen onderhoud, géén vendor lock-in, een hoge mate van customization en eenvoudig te monitoren.
Dit is hoe de Datahub werkt voor een BI-professional
Je loopt bijvoorbeeld tegen het probleem aan dat de klant een bronsysteem heeft dat niet direct via Azure Data Factory (ADF) kan worden benaderd. Het bronsysteem heeft wel een vrij eenvoudige REST-API waar je alle benodigde informatie kunt opvragen.
Een simpel python scriptje zou dan voldoende moeten zijn. Dus je maakt een kopie van ons standaard python project (of gewoon een leeg project) en je begint je script. Na wat development heb je een scriptje dat de REST-API uitleest en bestanden kan wegschrijven in een data lake (hier hebben we ook een standaard python package voor).
In het standaard project template zit automatisch een Dockerfile waarmee met één commando het script kan worden gebouwd tot een container image en kan worden geüpload naar onze private container registry. Vervolgens schiet je een request in op de Datahub-API om van de container image een job te maken. Hierin kan je wat configuratie meegeven zoals data lake credentials, API tokens etc. Deze worden natuurlijk encrypted opgeslagen en meegegeven tijdens de run van de container image.
Als laatste moet je ervoor zorgen dat het script runt op de juiste plek in de dataflow. Dus je logt in op ADF, je voegt een standaard “Datahub pipeline” toe aan een dataflow en je vult hier het ID van de zojuist aangemaakte job in. ADF zorgt dat het script wordt gestart. Houd bij of het script al klaar is en rapporteer als het script heeft gefaald. En klaar is Kees of <woke naam> of <een andere woke naam>.

Hoe de Datahub aan de achterkant werkt, vertellen we in hoofdstuk 6.
3. Het begon met een SaaS-platform
Het grootse idee dat ik aanhaal in de intro en waar de reis van onze tool begint, was een SaaS-platform met standaard connectoren. Een project waarmee we twee jaar geleden gestart zijn, maar waarin we nooit echt goed hebben doorgepakt. Simpelweg omdat we destijds met slechts 6 man én een BI-club aan het opbouwen waren, én dit project aan het ontwikkelen waren. Dat ging samen niet echt lekker, want de focus lag op onze BI-club.
Het gevolg was dat wij een halfwerkend platform hadden, geen oplossing voor het probleem van veel klanten met verschillende omgevingen én uiteindelijk veel scriptjes en andere oplossingen om ons eigen platform heen gebouwd hadden. Het ging nog net goed, maar het was vragen om problemen.
Na een jaar gebruik te hebben gemaakt van het platform (of eigenlijk juist niet), hadden we een hoop geleerd en hebben we de visie aangescherpt tot wat ze nu is.
We wilden ons grootste probleem tackelen door een product te bouwen voor intern gebruik. Met de gedachte dat als het dán goed werkt, wij het altijd nog kunnen productizen of onderdeel kunnen maken van het grotere SaaS-platform.
4. Nieuwe ronde, nieuwe kansen en vooral nieuwe uitgangspunten & requirements
Begin 2021 hebben we enkele sessies gehouden met ons volledige team voor de ontwikkeling van de nieuwe versie van de Datahub. Dit leverde een aantal uitgangspunten en technische requirements op: hieronder een korte toelichting.
Het implementeren van een connector moet niet moeilijker zijn dan simpele scriptjes schrijven.
Waar het uiteindelijk om draait is het proces van “Data in systeem X –> Data in Data Lake / DWH”. Dit willen wij zo eenvoudig mogelijk maken, zodat ook junioren eenvoudig scriptjes kunnen schrijven.
Het systeem is beheersbaar en je hebt volledige controle over de dataflow.
Het systeem moet erin voorzien dat dataflows kunnen worden gestart en gestopt vanuit ‘orchestratietools’ zodat het volledige management van dataflows buiten het systeem om kan worden uitgevoerd. Hierdoor heb je geen last van ‘timing issues’ of andere ondoorzichtige bugs door het managen van je dataflows in meerdere tools.
Lage instapkosten.
Het mag niet te duur zijn om in te stappen zodat het laagdrempelig inzetbaar is bij elk nieuw project.
Het moet schaalbaar zijn.
Als BI-club hebben we een groei-ambitie (vacatures vind je hier): dat betekent dat de oplossing met ons mee moet kunnen groeien. Niet tot een Google-omvang, maar wel de huidige honderden jobs/dag naar duizenden jobs/dag komend jaar.
Geen vendor lock-in!!
Wij vinden flexibiliteit een absolute must, zowel in de systemen die wij gebruiken als in de manier waarop wij onze diensten aanbieden. Dus geen vendor lock-ins.
De koppelingen moeten uit tal van verschillende systemen worden aangestuurd.
Zelf gebruiken wij Azure Data Factory om ETL-flows te beheren. Het systeem dat wij gaan gebruiken moet dus in deze flow passen. Maar niet voor alle klanten werken wij met ADF, dus ook via andere systemen moet het mogelijk zijn om die koppelingen aan te sturen.
Monitoring, betrouwbaarheid en kwaliteit moeten by-design goed zijn.
Het spreekt voor zich, maar monitoring is vaak een ondergeschoven kindje en krijgt pas aandacht na de eerste keer dat de koppeling haar werk niet goed heeft gedaan. Dit is vaak het gevolg van simpele scriptjes die snel worden geschreven en ergens worden uitgerold.
Het nieuwe systeem moet erin voorzien dat monitoring ‘automatisch’ wordt toegevoegd. En dat we slimme dingen zoals langlopende jobs en spontaan opgelopen laadtijden opmerken zonder dat je dit voor elk scriptje/koppelingetje opnieuw moet uitvinden.
We moeten kunnen beheersen of een sync parallel mag lopen of absoluut niet.
Voor sommige systemen is het niet handig om parallel de API te bevragen vanwege tijdsgebonden restricties of een token die elke minuut wijzigt etc. Hierover moet je dus controle kunnen uitoefenen.
Standaard koppelingen voor standaard systemen
We willen de weg van het bronsysteem tot data lake/datawarehouse zo kort mogelijk maken. Daarbij willen we dus ook voor standaard bronsystemen, standaard koppelingen ontwikkelen zodat we die voor meerdere klanten kunnen hergebruiken. Daarom moet het mogelijk zijn om configuratie, secrets en dergelijke vanuit het systeem door te geven aan de ‘scripts’.
5. Geen enkele beschikbare optie voldoet aan deze eisen
We hebben gezocht naar bestaande oplossingen die voldeden aan deze eisen, voordat wij zelf zijn gaan bouwen. Geen enkel bestaand product was namelijk een goede keuze voor de langere termijn.
Hieronder ga ik in op de drie beste opties die wij zagen en waarom ze niet voldoen aan de eisen.
Azure Functions
Om de requirements te vervullen zijn er tal van oplossingen mogelijk. Een hele goede kandidaat is Azure Functions. Het is namelijk schaalbaar, het biedt een HTTP API om syncs te starten en te stoppen. En er is een integratie binnen Azure Data Factory. Maar helaas is het niet allemaal ‘sunshine & rainbows’. Azure Functions is primair namelijk bedoeld om ‘kortlopende’ functies uit te voeren. Synchronisatiescripts zijn meestal niet kortlopend en daarmee dus niet de beste match voor een systeem als Azure Functions.
We hebben uitvoerig getest met Azure Functions en het platform was erg instabiel. Trigger runs konden om de kleinste redenen worden afgekapt. De development SDK’s waren niet optimaal. Durable functions kennen een complexe setup. En het creëert de lock-in op Azure en Microsoft.
Databricks
Daarnaast kun je denken aan een Databricks-omgeving voor iedere klant met standaard scripts. Er is wederom een integratie in de Azure Data Factory, maar niet per se in andere orchestratietooling. De clusters om spark jobs te draaien zijn niet goedkoop. En Apache Spark is in essentie ook bedoeld voor data-analyse werk en is daarmee geoptimaliseerd voor Dataframebewerkingen en -calculaties. Het opvragen van data via REST of SOAP is daarom niet ‘eenvoudig’ uit te drukken als een dataframe bewerking. Het matcht daarbij niet helemaal met de eisen aan het systeem.
All-in-one platformen
Dan heb je ook nog all-in-one platformen zoals FiveTran, Stitch, AirByte etc. Fantastische tools, maar ze komen van origine uit Amerika en hebben koppelingen met de grote wereldwijde partijen zoals Salesforce, Facebook, Hubspot. Maar niet met Exact Online, Twinfield, Nmbrs, Visma Severa. Dus als je deze platformen gaat gebruiken, heb je daarnaast altijd iets nodig om juist de onbekende systeemkoppelingen te maken.
Verder hebben deze systemen vaak een eigen scheduling-mechanisme en configuratiemogelijkheden in een webplatform. Dit maakt het lastiger (maar niet altijd onmogelijk) om volledige controle te hebben over je dataflow van voor tot achter.
6. Onze aanpak en keuzes tijdens het bouwen
De oplossing omgeving-agnostisch maken
Wij zijn gestart bij ons belangrijkste requirement: een oplossing die omgeving-agnostisch is en dus vanuit tal van verschillende systemen kan worden aangestuurd. Wat alle services – zoals Apache Airflow of een virtual machine van de klant – gemeen hebben, is dat zij HTTP spreken.
De webservice moet het centrale aanspreekpunt zijn voor al deze services en ervoor zorgen dat de scripts worden uitgevoerd, dat uitsluitend geauthenticeerde users een sync kunnen starten (no crypto miners please) en het verzorgen van de monitoring en logging. We hebben ervoor gekozen om deze functionaliteit beschikbaar te stellen via een REST-API.
Scripts runnen zonder servers in te richten
De volgende uitdaging die we willen tackelen, is het runnen van een script/applicatie waar we geen servers voor willen inrichten.
De koppelingen die wij schrijven zijn meestal heel eenvoudig: kopieer alle data of een subset van de data van een systeem naar een datawarehouse of een data lake. In de meeste gevallen kan dit worden geprogrammeerd met hele simpele scripts (de uitzonderingen daargelaten, ik kijk naar jou Twinfield!).
Maar ontwikkelen op of voor een ‘platform’ kan soms lastig zijn. Azure Functions is hier een voorbeeld van. Het is simpel om mee te beginnen, maar als je een durable function wilt maken, ben je ineens je halve dag kwijt aan het opzetten van Orchestrator functions, Activity functions en Client functions… Daar gaat je eenvoudige scriptje. Het moet mogelijk zijn om het scriptje zonder al te veel ‘gedoe’ gecontroleerd uit te voeren in een gecontroleerde omgeving.
Dé oplossing hiervoor zijn container images. Simpel en doeltreffend. En met goed ontwikkelde Base images en project templates ook enorm gemakkelijk te gebruiken voor minder ervaren developers.
Het geheel schaalbaar maken
Tot slot moet het allemaal schaalbaar zijn. Een webservice op een enkele server die container images runt op API-requests is slechts beperkt schaalbaar. Gelukkig zijn wij niet de enige partij met dit probleem en zijn er talloze manieren om dergelijke workloads schaalbaar te maken via Container Scheduling engines.
De drie grote platformen zijn Kubernetes, Nomad en Docker Swarm. Kubernetes is enorm populair en helaas ook enorm complex. Docker Swarm is heel simpel, maar wordt niet heel actief doorontwikkeld. Nomad is qua complexiteit de gulden middenweg tussen Docker Swarm en Kubernetes, maar is nog een relatief nieuwe speler in de markt.
Allemaal hebben ze voor- en nadelen en er wordt hard doorontwikkeld om deze platformen te verbeteren.
Welk platform over vijf jaar de winnaar zal zijn, durf ik niet te voorspellen. In onze usecase hebben we maar een kleine subset aan functionaliteiten van deze platformen nodig. Het is daarom mogelijk om een modulair systeem te bouwen dat in principe op alle drie de platformen kan draaien (momenteel is alleen Docker Swarm geïmplementeerd). Hierdoor kunnen we relatief eenvoudig overstappen wanneer er een nieuwe speler opstaat, Kubernetes makkelijker te beheren wordt of wanneer ze definitief stoppen met het doorontwikkelen van Docker Swarm. Zonder dat we dan alle implementaties bij alle klanten moeten aanpassen voor elk sync script dat we ooit hebben gebouwd.
Het begin van All Your BI Labs
Vanuit het Datahub-project is All Your BI Labs geboren. We vinden het niet alleen tof om eigen tools te ontwikkelen, we maken ons eigen werk graag zo eenvoudig mogelijk. Het past ook binnen onze visie om naarmate wij groeien, meer producten te gaan ontwikkelen naast al het projectenwerk.
Binnen ons Lab mag iedereen uit de organisatie projecten pitchen. Als het team er brood in ziet en de businesscase positief is, gaan wij ermee aan de slag.
Dat begon met enkele kleine projecten rondom de Datahub. De Datahub biedt ons namelijk enorm veel flexibiliteit. Dat is zowel een zegen als een vloek. Daarom begonnen wij met wat nieuwe utiliteiten zoals:
- een python package met een pipeline builder / executor voor het eenvoudig kunnen ontsluiten van HTTP API’s;
- een standaard python project template met alle benodigdheden om gebruik te kunnen maken van de Datahub Engine;
- een standaard Azure Data Factory-template voor het starten van een Job in de Datahub Engine;
- een “Way of Working”. Delta first, raw loads to data lake, processing in DWH.
Inmiddels ontwikkelen we verschillende grotere projecten die ook een grotere impact hebben op ons werk. Twee voorbeelden:
- We ontwikkelen een datawarehouse automation framework die 80% van het standaardwerk wegneemt (the plumbing) bij het inrichten van Data Vault. Zodat je zelf alleen nog bezig bent met het vertalen van de businesslogica in SQL-statements.
- We realiseren een platform waar iedereen in de organisatie op een veilige manier toegang heeft tot alle data. Zo hoeven ze niet te wachten op de developers.
Over dat laatste project wil ik komende zomer een nieuw artikel schrijven. We zitten op dit moment middenin de selectie van een aantal tools en het testen van de tools. Laat mij vooral weten wat je van dit soort artikelen vindt in de reacties! Of als je nog vragen hebt.