Infrastructuur is moeilijk: de pipeline

Infrastructuur is moeilijk! Het is belangrijk, noodzakelijk om dat te herhalen. Om er een mantra van te maken. Want in deze tijd van automatisering en aandachtsverschuiving naar development lijkt het inrichten van een paar containertjes iets wat je er even bijdoet. Klik klik op een schermpje, hook naar Git en klaar.

Dat inrichten van infrastructuur, containers en CI/CD pipelines vraagt om (volwassen) processen en een (volwassen) toolchain. En een volwassen organisatie ook trouwens. Voor een ontwikkelaar is een container misschien niet veel meer dan het resultaat van zijn Dockerfile, maar er gaat een wereld van afhankelijkheden achter schuil. Idealiter zijn die afhankelijkheden volledig geautomatiseerd, in de praktijk zijn organisaties vaak nog niet zo ver.

Ten dele wordt dit veroorzaakt door de toolchain. Die is simpelweg nog niet ver genoeg ontwikkeld, zoals bijvoorbeeld mooi geïllustreerd in het artikel van Yevgeniy Brikman van Gruntwork (https://blog.gruntwork.io/5-lessons-learned-from-writing-over-300-000-lines-of-infrastructure-code-36ba7fadeac1).

In een aantal artikelen ga ik verder in op innovatie in een innovatieve wereld, namelijk die van containers, microservices en pipelines. Een wereld waarin long term releases gemiddeld drie maanden oud worden en commodity niet meer bestaat. In dit artikel staat de CI/CD-pipeline centraal, met centraal daarin vijf aandachtspunten bij de inrichting daarvan.

De CI/CD-pipeline

Met een Continuous Integration/Continuous Delivery pipeline is het mogelijk om broncode in een aantal geautomatiseerde processen (zoals builden en integreren, code-analyse, functionele test en deployment) van code-repository naar productie te brengen. De introductie van een dergelijke pipeline is de toolset van de DevOps-er en vrijwel altijd randvoorwaardelijk voor een Agile, snel en efficiënt ontwikkelproces (Scrum of Kanban, of wat anders).

Of Jenkins de eerste CI/CD-tool was, is mij niet helemaal duidelijk – afhankelijk van hoe je de termen definieert is er vast iets te vinden dat van voor februari 2011 stamt, de maand waarin de eerste versie van Jenkins werd uitgebracht. Dat is inmiddels bijna acht jaar geleden en in de wereld van CI/CD is dat antieke geschiedenis. Toch is Jenkins er nog steeds en – getuige de nieuwe versie Jenkins-X – wordt er nog volop geïnnoveerd.

In de jaren tussen 2011 en zijn er veel verschillende pipelines geïmplementeerd. Met of zonder Jenkins. Ook door HCS Company (het bedrijf waar ik voor werk). Daarbij zijn veel ervaringen opgedaan, maar documentatie daarvan is er niet altijd. Hieronder vijf vraagstukken die ons bezighielden.

1.    Allesomvattend of niet?

Uit welke onderdelen bestaat een pipeline? In principe gaat het om de processen en tools van bron tot productie. Er bestaan verschillende modellen voor inrichting en volwassenheid van pipelines, zoals bijvoorbeeld die van Shippable (zie verwijzing in dit artikel https://globenewswire.com/news-release/2016/08/25/989275/0/en/Shippable-Launches-Industrialized-Continuous-Deployment-Platform.html). In dergelijke modellen valt op dat een pipeline altijd uit een aantal groepeerbare onderdelen bestaat. Uiteraard integration en deployment op het minst fijnmazige niveau, maar meer gedetailleerd is er sprake van bijvoorbeeld testen, opslag van artefacts, enzovoorts. Er is niet echt overeenstemming over die verschillende delen.

Dat roept de vraag op of een pipeline eigenlijk wel één geheel is. Misschien zorgt het gebruik van een orkestrator als Jenkins er wel voor dat een pipeline nu vaak wel als geheel wordt gezien. Een allesomvattende pipeline die alle facetten van het ontwikkel- en deployproces raakt is theoretisch en technisch vast een mooi construct, maar hoe praktisch is het? Een relatief eenvoudige pipeline bestaat al uit een behoorlijk aantal onderdelen (tools en processen) met elk hun eigen beheeruitdagingen. En met de huidige explosie van tools in deze ecosphere (zie ook vraagstuk 2) is de kans groot dat er alleen maar meer bijkomt.

Een pipeline is niet “af” als deze is ingericht, maar is net zo dynamisch als de componenten waar hij uit bestaat.

2.    Selecteer en beheer tools planmatig

Ooit bestond een softwarerelease uit een CD, een handleiding en een geldigheidstermijn of garantieperiode van jaren. Die tijd is voorbij: in de wereld van de hippe tools is een Long Term Release van enkele maanden meer regel dan uitzondering. Dat betekent voor wat minder hippe organisaties (en daar zijn er nog veel van) dat de toolkit die ze proberen te implementeren om bij te blijven, vaak (veel) sneller wordt geupdate dan ze hun eigen softwareproduct releasen! Als dat geen cultuurschok is…

Het aantal tools dat onderdeel is van de Cloud Native Landscape (https://landscape.cncf.io/) is begin december 2018 maar liefst 611. Dat is een indrukwekkende groei voor een overzicht dat nu ongeveer twee jaar bestaat. In deze tool-wereld is het mogelijk dat een product dat zes maanden geleden nog niet bestond, vandaag opeens hip is. Een mooi voorbeeld hiervan is het onderdeel “serverless”, dat eerst een vakje op de totaalplaat was maar nu een eigen afdeling heeft en eveneens gestaag groeit.

Meedoen in deze wereld vraagt dus om een totaal andere benadering van (beheer van) lifecycles, toolkennis en toolkeuze. Voor elk onderdeel van een pipeline is een afweging te maken over welk tool het beste is. Is het uitgangspunt de UNIX-filosofie (“do one thing and do it well”, dus een construct van verschillende tools die één ding doen) of het Zwitserse zakmes (één overkoepelend tool)?

Een belangrijke tool om niet te vergeten, trouwens: de opslag (en beheer!) van de infrastructure-as-codefragmenten. Dat is immers het nieuwe goud.

3.    Met de explosie van tools groeit de benodigde opslagcapaciteit

Denk goed na over de hoeveelheid artefacts, binaries, containers, containerimages, broncodefragmenten en configuratiebestanden die in en rond een pipeline bestaan – en vooral ook waar deze zijn opgeslagen. En hoe lang. Het duurste component binnen infrastructuur is immers opslag, terwijl de Cloud hierbij ook kosten voor dataverkeer rekent (hoeveel en of dit meer of minder dan bij lokale opslag is, is weer een hele andere discussie).

De Cloud is daarnaast een tweekoppig monster (Public en Private) met een hybride lijmlaag ertussen. Waar de data staat is misschien steeds minder relevant (met hybrid dataoplossingen als die van Nasuni en Panzura, bijvoorbeeld), maar dat ergens data staat, des te meer. Het nieuwe goud, weet u nog?

4.    Onderschat de complexiteit van parallel uitvoeren niet

Bij een efficiënt CI/CD proces is er altijd de afweging tussen snelheid en kwaliteit. Een orkestrator als Jenkins maakt het mogelijk om bepaalde taken binnen de pipeline parallel uit te voeren. Dit komt vooral verschillende testsoorten ten goede: zo is het mogelijk verschillende tests(soorten) in verschillende containers tegelijk uit te voeren

Maar welke testsoorten zijn onderdeel van de pipeline? Een pipeline laten wachten op een unittest is niet efficiënt. En veel testen tegelijk laten lopen leidt tot meer CPU-gebruik en potentieel meer datagebruik. En, niet onbelangrijk, de complexiteit die taken in parallel uitvoeren met zich meebrengt moet natuurlijk wel leiden tot een efficiëntie- of snelheidswinst.

Waak ervoor dat parallelle taken een pipeline oplevert met zoveel afslagen dat het geheel een kerstboom wordt. Mooi om naar te kijken, maar is het ook praktisch?

5.    Automatisering is niet hetzelfde als minder belangrijk maken

Alle taken in een pipeline, hoe minimaal in uitvoering en efficiënt weg-geautomatiseerd ook, zijn even belangrijk. Van elke stap moet dus bekend zijn waarom deze wordt uitgevoerd, wat de toegevoegde waarde is en als het een automatisering van een eerder handmatig proces betreft, waarom en hoe de automatisering is geïmplementeerd.

Dat betekent ook dat elke stap wordt beheerd – misschien wel door een niet-geautomatiseerd persoon. Voor mij ligt daarin de paradox van automate everything: wie beheert dan de automation?