Vagrant

Znáte to. Děláte na pěti projektech, jeden potřebuje MongoDB, druhý PostgreSQL, třetí MySQL a Redis, čtvrtý je ještě na PHP s Apachem. Pátý je čistý Python. Po půl roce děláte na třech projektech, z nichž dva jsou nové, první chce ElasticSearch a druhý vás nutí zkoušet si na localhostu něco s Nginxem. Samozřejmě ty staré projekty sem tam nějak udržujete, takže je nemůžete jen tak smazat z disku a závislosti vyhodit.

Na blogu běžně sprostý nebývám, ale berme to jako terminus technicus - po půl roce máte prostě svůj počítač zasraný vývojářskými věcmi. Pokud navíc máte nějakou odrůdu Ubuntu, služby se vám spouští samy - tzn. že vám jede MongoDB, PostgreSQL, MySQL, Redis, Apache, ElasticSearch a Nginx i během toho, co se jenom díváte na film.

No a to jsem ani nezmínil, že kvůli některým věcem musíte docela zasahovat do OS - např. pro PostgreSQL je běžné mít v systému uživatele pro každou roli v databázi, MongoDB zase po čase a určité zátěži vyžaduje změnu pár konfiguráků pro navýšení několika linuxových limitů. Špína je zažraná.

Řešení

Když mě tohle celé štvalo, postěžoval jsem si na Twitter a tam mě poslali k šípku Vagrantu. Vagrant je takový obal nad VirtualBoxem či jiným správcem virtuálních mašin, který vám na pár příkazů do minuty vyrobí neekologickou, tedy velice spotřební virtuálku na vývoj. Hodně lidí to má na zkoušní atomových výbuchů, ale hodí se to právě i na izolaci závislostí potřebných k vývoji.

Další detaily o Vagrantu si zjistěte v jeho dokumentaci nebo si pusťte tohle video z Tkalců (sraz webařů z Valašského Meziříčí), na kterém jsem začal i já:

Dojmy

Chtěl jsem něco, co mi spustí všechny závislosti když začnu pracovat na projektu a shodí je, když přestanu. Pak jsem chtěl něco, co izoluje všechny možné databáze a servery (prostě striktně cokoliv za hranicemi běžného Pythoního virtualenvu) od mého ubohého uživatelského OS. To druhé jsem dostal, to první ne.

Lokální služby

V podstatě mám ty virtuálky hlavně na databáze, jen na jedné mám nějaké to PHP, Apache, apod. Fajn je, že pokud člověk striktně dodrží čistotu a ve vlastním OS opravdu žádné takové služby nemá, vše lze jednoduše udělat tak, aby to po spuštění vypadalo jako místní služba:

config.vm.network "forwarded_port", guest: 5432, host: 5432  # PostgreSQL
config.vm.network "forwarded_port", guest: 6379, host: 6379  # Redis
config.vm.network "forwarded_port", guest: 9200, host: 9200  # ElasticSearch

Má to ale i své háčky - např. PostgreSQL takto logicky nepojede přes socket a spolu s dalšími se musí dodatečně nastavit, aby obsluhovala i dotazy z "venku". Pro virtuálku je totiž náš OS a z něj přicházející spojení vlastně jako jakýkoliv jiný klient někde z internetu. Zase si člověk díky tomu lépe odzkouší a uvědomí reálnou produkční architekturu, kde většinou není kód a databáze na jednom stroji.

Velkým problémem, který jsem zatím nedořešil, je magická autodetekce produkčního a vývojového prostředí v Nette. To si samozřejmě na virtuálce myslí, že je na produkci a ani po různém woodoo s maňásky ve tvaru Davida Grudla se mi nepovedlo ho plně přesvědčit o něčem jiném (trochu jo, ale z debugbaru zmizela polovina panelů - eh, WTF?). Je to sice legacy projekt, je tam starší Nette, kdo ví jak je to dnes, ale stejně. Porod, práce navíc, otrava, nechuť, smutek, atakdále...

Automatizace workflow

Kód, Python, atd. mám normálně u sebe - to mi nevadí, protože co se týče izolace, vystačím si s nástrojem virtualenvwrapper a jeho konceptem pro projekty. Když chci ale "spustit" takový projekt, někdy pro to musím udělat celou kopu věcí:

  • tunelovat přes SSH vývojový server
  • spustit správné databázové aj. servery / spustit Vagrant
  • spustit Sublime Text s příslušným projektem
  • spustit development server s PYTHONDONTWRITEBYTECODE=1 a pod příslušným virtualenvem
  • spustit aspoň jeden nějaký terminál v rootu projektu, samozřejmě opět s PYTHONDONTWRITEBYTECODE=1 a pod příslušným virtualenvem
  • zapnout si v Togglu, že pracuju na příslušném projektu

Jak vidíte, s tímto vším mi Vagrant vůbec nepomůže a přitom je fakt otrava tohle všechno pořád dokola dělat.

To ani nemluvím o vypínání. Můžu mít na virtuálce databázové servery a na vagrant up je spustím, ale musím se zase stejně starat o to, abych je potom i vypnul přes vagrant suspend. Na což zapomínám, takže mi pak v paměti běží nejen databáze, ale i VirtualBox. Naštěstí tedy většinou aspoň jen z jednoho projektu, ale ani to není pravidlem, často mám takto zbytečně rozjeté i dvě virtuálky. V tomto ohledu to tedy moc velký posun od service redis-server start a service redis-server stop není.

Pro práci na Synopsi.TV jsem si napsal bash skript (bez toho Togglu) a namapoval si ho na ikonku, ale není to teda nic moc. O nějakém vypínání se mi navíc může jen zdát - jedině že bych si udělal druhou ikonku, která to všechno shodí a pro jistotu bych si to vrazil i někam do /usr/lib/pm-utils/, aby se to provedlo vždy automaticky také před usnutím počítače.

Zkoušel jsem ten svůj skript hodit někam do "po spuštění" ke konkrétnímu virtualenvu (vitualenvwrapper má nějaké hooky, podobně jako v gitu), ale toto řešení shořelo na tom, že životnost virtualenvu není rovna mé práci na projektu - během práce můžu mít otevřených i pět terminálů a v každém mít aktivovaný ten virtualenv. Navíc ani ten se nedeaktivuje (hook se nezavolá) automaticky při zavření terminálu, musel bych ručně napsat deactivate, abych vše zavřel - a jsme tam, kde jsme byli.

DevOps & Provisioning

Co jsem v poslední době opravdu neměl moc rád a snažil jsem se tomu co nejpečlivěji vyhýbat, bylo DevOps, tedy správa serverů.

Rok jsem měl koupené vlastní VPS u Wedosu a platil ho, ale stejně jsem vždy věnoval maximum úsilí tomu, aby vše co jsem vyrobil jelo i na free instanci na Heroku, kde byl potom deployment absolutně bez práce.

Štítil jsem se jakékoliv instalace a nastavování. Dokonce mi ten server převzal do správy kamarád a řekl mi, že dokud tam budou neziskové projekty, že se o to postará, ale já jsem se ani tak neodhodlal tam za ten rok nahrát jediný bajt svého kódu.

No a s Vagrantem to na mě skočilo ze zálohy jako krvelačná šelma. Aby na instanci něco jelo, musí se to tam nainstalovat a případně ještě nastavit - takže zase DevOps, zase provisioning. Navíc mi přišlo, že jsou v těch virtuálkách nějaké nestandardní haluze, např. jsem se dost pral se špatným locale apod. Spousta drbání navíc, které mě vůbec nebaví. Na druhou stranu, má to jednu výhodu a jedno řešení do budoucna:

  • Zapisuju si do souboru každý příkaz, kterým jsem na mašině něco nainstaloval nebo nastavil. Nebo tam přidám aspoň komentář, pokud byla procedura moc interaktivní a nevím, jak bych ji udělal automatizovaně. Dělám si iluze, že tohle mi jednou pomůže stejnou virtuálku nastavit v mžiku znova a stejně tak se dá ten kód verzovat, použít jako moje knowledge base pro skripty k jiným virtuálkám, atd.
  • Bude-li mě ve své jednoduchosti otravovat předchozí bod, můžu se naučit nějaký nástroj na provisioning (byť mě děsí, že se co půl roku objeví nový, módnější) a propojit ho s Vagrantem. Slibuji si od toho, že tam jen napíšu nějaké "nastav mi locale na toto a udělej PostgreSQL uživatele na toto" a on to udělá magicky za mě, bez zkoumání samotných shellových příkazů.

Takže doufám, že mě ten automatizovaný provisioning jednou nezklame a bude to opravdu "DevOps pro blbečky a lenivce", jak si to představuju já.

Zhodnocení

Co mi Vagrant přinesl:

  • izolace vývojářského bordelu
  • lepší představa o produkční klient-server architektuře
  • naučil jsem se něco nového a nejspíš mě to donutí proniknout do toho provisioningu, bez něhož to stejně do budoucna asi moc nepůjde (fůůůj, blééé)
  • naučil jsem se zapisovat si příkazy, kterými něco instaluji/nastavuji na serverech
  • můžu mít virtuálku dost věrně kopírující produkční prostředí, bez ohledu na svůj vlastní OS (mnohem lépe se z Windows nebo Macu vyvíjí pro Linuxový server apod.)
  • mám stále k dispozici závislosti i ke starším projektům a přitom mi nezavazí v systému, navíc i pokud bych virtuálku smazal a k projektu se vrátil po roce, můžu ji snadno obnovit pomocí seznamu příkazů

Co je na prd:

  • neřeší mi to problém se vstupem do a výstupem z práce na konkrétním projektu
  • je to práce navíc (ale stejně bych to všechno musel nějak nainstalovat u sebe)
  • aplikace si myslí, že jsou na serveru a musí se dodatečně nastavovat, aby odpovídaly i "ven"
  • konfigurák je v Ruby, které je pro mě někdy trochu jako hieroglyfy
  • nelze se moc vyhnout DevOps, je nutností výhodou se naučit nějaký provisioning

Kdybyste měli nápad na nějaký nástroj, který by řešil to zapnutí/vypnutí projektu, rád si nechám poradit. Úplně ideálně kdyby to byla nějaká skrytá feature věcí, které už dávno používám. Nebo kdyby to aspoň bylo "pro blbečky" úplně stejně jako Vagrant a člověk to nemusel dlouze studovat a hrát si s tím - přeci jen jsem placen za programování a nastavování OS k vývoji je pouze otravná, doprovodná činnost (ne, moje hobby to fakt není, hobby je v mých očích florbal nebo tancování). Díky za všechny tipy.