Programujeme letenky

Vývojáři GOL IBE v C.E.E. Group Travelport
Programátorský web
Background image - Futurama office park

Začínáme dockerizovat

Tomáš Srb a Michal Bureš, 10. 3. 2022

Proč?

Od dávných časů probíhá vývoj naší aplikace na tzv. vývojářském serveru - každý vývojář tam má vlastní ssh účet, k dispozici jsou všechny potřebné překladače , http server s potřebnou verzí php atd.

Ač je to neuvěřitelné, čím dál méně našich vývojářů je ochotno vyvíjet kód v tak pokročilých nástrojích, jako je vim, mcedit nebo joe. (No, trochu je chápu - než jsem propadl kouzlu vimu, naprogramoval jsem si ve volném čase vlastní IDE s autokompletací, inteligentním vyhledáváním a tailováním logů.) Na nějakou dobu pomohlo nfs - nasdíleli jsme domovské adresáře na pracovní stanice a vývojáři mohli používat IDE dle vlastní volby.

Jenže... nfs:

Sshfs je sice bezpečnější, ale o to pomalejší a s user id také nezachází úplně korektně.

Samba... o sambě se NEBUDEME bavit.

Přechodnou dobu fungoval server GUI - bohatě dotovaný RAM i CPU, přes nfs připojený k serveru s c++ a httpd a lokálně nainstalovanými netbeansy, eclipse a vscode, přístupný přes rdesktop. Jenže nefunguje schránka (clipboard) mezi GUI a lokálním strojem. A na některých strojích nefunguje ani čeština. Někteří uživatelé si nainstalovali cygwin, spustili lokální xserver a do něj pouštěli aplikace z GUI serveru... fungovalo to, ale dost poomaaluu.

Takže vývojáři tiše začali s větší či menší podporou svého IDE vymýšlet různé synchronizační mechanismy, kterými dostávali zdroják ze serveru na svou pracovní stanici a po editaci zase zpět. Třeba pomocí rsync. Prozíravý čtenář jistě tuší, že to snadno vede k momentům typu "Kam se poděl ten kód? Ještě před chvílí tu byl!" a "Jakto, že tu ta změna není? Moment, pustím znova synchronizaci...".

Tak se objevila myšlenka "Když nemůže být IDE na serveru, což tak přesunout všechny potřebné překladače, http server atd. na pracovní stanici?".

Jenže... někteří vývojáři mají MacBooky s MacOS a někteří dokonce Windows... o různých verzích linuxů ani nemluvě. A kdo by si chtěl zaneřádit počítač http serverem s php atd.

Jak?

Virtualizace?

S virtualizací máme zkušenosti - naše servery běží ve vmware, když si potřebujeme něco zkusit, neváháme si lokálně v qemu nahodit malý virtuál na jedno použití... co kdybychom tedy udělali virtuální stroj odpovídající vývojářskému serveru, který by si mohl každý pustit na svém lokále? Servery konfigurujeme ansiblem - asi by bylo dobré použít stejné předpisy pro tvorbu virtuálu. Qemu je dobré, ale letmým průzkumem jsme zjistili, že většině vývojářů je bližší virtualbox, takže jsme použili ten. Nápad jistě dobrý, ale výsledky nebyly dobré - vznikl asi 10 GB bumbrlíček, vyžadující minimálně 16 GB RAM... a první vývojář, který chtěl pracovat kompletně vzdáleně měl notebook s menší pamětí. Byl připojen na server GUI a vývoj pokračoval.

Proběhlo několik pokusů s vagrantem - umožnilo umístit vývojářské prostředí vně virtuálu, což ušetřilo RAM i zjednodušilo práci, ale pořád to nebylo moc použitelné.

Kontainerizace?

Na dveře zaklepala relativně nová technologie kontainerů, konkrétně v implementaci zvané Docker. Zatím jen v linuxu, protože využívala pro linux specifické cgroups a namespaces. Zhruba v té době jsme přešli na gitlab a vznikl také web https://programatori.travelportgds.cz. Takže testy nového webu byly gitlabem automaticky spouštěny v dockeru v oficiálním image php. Ostatní projekty také využívaly spouštění testů gitlabem, ale za runnery sloužily virtuální servery napodobující vývojářský server, na kterém byly dosud spouštěny ručně (a dodnes je tam spouštět ručně lze).

Amazon Lambda

Výše popsaný proces se vlekl mnoho let, protože převod vývoje na lokální stroje nikdy nedostal skutečnou prioritu. Vždy jsme v tomhle ohledu řešili jen aktuální problémy a pokud možno nejsnazší cestou. Najednou vyvstal problém zásadní a termín řešení byl daný. Část naší c++ aplikace jsme vyčlenili do samostatné služby a pro lepší dostupnost ze strany zákazníků jsme ji obalili javascriptovou obálkou a nahráli do cloudu AWS jako tzv. lambdu.

(Ve stručnosti: když na vstupní bod AWS přijde požadavek, je naše aplikace spuštěna, požadavek vyřídí, odpověď je odeslána a aplikace je ukončena. Platíme jen za strojový čas spotřebovaný na vyřízení požadavku, neplatíme za nějaký trvale běžící virtuální stroj.)

Potíž nastal, když jsme aktualizovali operační systém našeho vývojářského serveru - najednou nebyla naše binárka kompatibilní se systémem spouštějícím lambdu. Moudřejší ustoupí - ustoupili jsme, vytvořili server se starou verzí systému a překládali a testovali onu část aplikace na něm. Nějakou dobu to fungovalo, ale Amazon oznámil, že prostředí, ve kterém běžela naše lambda s koncem roku přestane podporovat. Bylo jasné, že kompatibilita našeho starého systému a staré lambdy byla pouhá náhoda a těžko na ni můžeme spoléhat dál - AWS zaručuje verzi nodejs, verzi pythonu, ale zbytek systému je na jejich libovůli a těžko se do něj můžeme zkoušet trefovat.

Naštěstí lambda umožňuje i jiný způsob použití - zákazník může vytvořit dockerovský image se svou aplikací a se softwarem amazonu, zajišťujícím lambda-interface. Abychom se vyhnuli možným komplikacím s kompatibilitou, použili jsme za základ image amazonlinux:2, doporučovaný Amazonem. Najednou bylo třeba celý vývojový cyklus té části aplikace přesunout z ansiblem nainstalovaných virtuálních strojů do dockeru. Najednou máme image, který ji umí přeložit, jiný, který ji umí otestovat a další, který ji umí nahrát do cloudu a otestovat výsledek.

Zvolili jsme metodu co nejmenších image s pokud možno jednou, striktně definovanou funkcí - natolik nás vyděsily pokusy s použitím stávajících ansiblovských scriptů (jistě - pro kompilaci přece není zapotřebí vim, mc, http server... pro otestování zas není třeba překladač c++ a vývojářské balíky openssl či libxml).

Termín ukončení podpory staré verze lambdy v AWS jsme stihli a přechod byl prakticky bezvýpadkový.

Monorepo

Jednou z největších komplikací současné architektury mnoha samostatných produktů, které jsme postupně chtěli propojit, je testování a příprava prostředí pro vývojáře. Logicky se tedy nabízí spojit aplikace do jednoho repozitáře a zajistit tak vždy správné verze jednotlivých aplikací. Samo se pak nabízí spouštět automatizované testy při změně jakéhokoliv produktu či pouze vybraných. Monorepo s dockerem nám také umožňuje předpřipravit instalaci aplikací a dat v databázi tak aby vývojář byl schopen začít pracovat po spůštění jen nějkolika málo příkazů, včetně puštění všech automatizovaných testů proti své lokální instalaci. Situaci nám trochu komplikuje fakt, že nemálo aplikací provozujeme v cloudu (AWS). Řešíme to tak, že v rámci přípravy prostředí se připraví i tyto cloudové aplikace pro každého vývojáře zvlášť. Odstraňujeme tak bariéru úvodního nastavení pro každou aplikaci a zároveň máme popsané závislosti a propojení mezi jednotlivými aplikacemi. Každý vývojář tak může vidět projevy změn svého projektu na projektu cizím a zároveň tato změna vyvolá spuštění automatizovaných testů. Tím je docíleno včasného zachycení případné chyby.

Souběžně s převodem lambdy do dockeru probíhalo slučování repozitáře naší aplikace a nadstavby pro podporu korporátních společností (tím jsme nastoupili myšlenku monorepa - pro snazší řízení vzájemné kompatibility komponent naší aplikace verzovat vše společně v jednom gitovém repozitáři).

Každou z akcí prováděl jiný vývojářský tým víceméně nezávisle, takže i zvolený přístup byl různý. Monorepo od počátku mělo podporovat vývoj na lokální pracovní stanici a vyřešili jsme to kompletním přesunem vývoje aplikace do jednoho komplexního dockerového image. Z počátku se tým monorepa inspiroval pracemi na amazon lambdě - také zvolil za základ amazonlinux:2, ale brzy jej předstihl a použitelný výsledek měl mnohem dříve. Bylo to nutné, protože vývojáři podpory korporátů pracují vzdáleně a monorepo potřebovali rychle.

Aktuálně se přikláníme k názoru, že tvorba jednodušších kontainerů pro jednotlivé vývojářské akce spouštěné nad kódem umístěným na hostiteli bude výhodnější. Již nyní většinu akcí spouštíme pomocí shellové obálky, takže přechod na volání dockeru, místo lokálně instalovaných nástrojů bude pro vývojáře prakticky neviditelný. Pro některé akce již kontainery máme (primárně vznikly pro použití v automatických testech spouštěných gitlabem) a některé jsou již připraveny na použití při vývoji.

Konec?

Tady bych si dovolil článek přerušit, protože popis dospěl do současnosti a nakolik bude naše snažení použitelné ukáže až budoucnost.

Co jsem tím chtěl říct

tl;dr: Potřebujeme umožnit vývojářům provozovat kompletní aplikaci na jejich pracovních stanicích a rozhodli jsme se na to použít docker.