Obrovskou výhodou cloudových služeb je možnost si podle potřeby kdykoliv „pronajmout“ procesor, operační paměť a diskový prostor. Aby toto bylo možné, musí mít provozovatel z čeho brát – musí si trvale držet výkonnostní rezervu. Tato rezerva ale pochopitelně nic nevydělává, naopak její pořízení a provoz stojí nemálo prostředků. Amazon se svými Spot Instancemi snaží alespoň něco těch peněz dostat zpět.
Spot Instances tedy žijí v přebytečné kapacitě datacenter, na stejném hardwaru jako běžné instance. Rozdíl nastává, až když je tato přebytečná kapacita potřeba – v tu chvíli systém váš virtuál bez milosti a varování zabije. Spoty jsou tedy vhodné na úlohy, které umožňují streamovat výsledky nebo jdou rozdělit na menší tasky.
Jako maximální velikost jednoho tasku je rozumné zvolit jednu hodinu běhu – pokud vám totiž Amazon instanci zruší, poslední hodinu neplatíte. V nabídce jsou však instance všech velikostí dostupných v on-demand režimu, v současné době tedy až po virtuál s 32 jádry, 244 GB RAM a 640 GB SSD storage. Nerozdělitelná úloha, která na takovém stroji zabere víc než hodinu, by už za změnu architektury stála.
Podobně nestabilní jako instance jsou i jejich ceny, Amazon je totiž určuje podle aktuální poptávky po svých zdrojích. Z vaší strany to funguje tak, že si zvolíte maximální hodinovou sazbu, za jakou chcete počítat. Když se amazoní cena dostane přes váš strop, bude vaše instance zrušena.
Samozřejmě, vhodnou volbou maximální hodinovky lze zvýšit „trvanlivost“ instance. Proto je v grafech vývoje ceny vidět, že se příležitostně Spot Price dostane nad úroveň ceny persistentní on-demand instance – někdy i násobně.
Běžně se však sazby pohybují kolem 10–20 % ceny on-demand instance. Hodina běhu zmíněné 32 jádrové obludy stojí na Linuxu $0.2561 proti $2.8 (tedy 9 % plné ceny), rozumnější jednojádro Medium s 3.75GB RAM, běžně za $0.07 vyjde na $0.0081, tedy 12 % on-demand ceny a přibližně 120 Kč za měsíční běh.
vCPU a ECU
Všechny velikosti instancí jsou hodnoceny dvěma parametry: vCPU (virtuální CPU) a ECU (Elastic Compute Unit). ECU je jednotka výkonu, zatímco vCPU je počet jader, které má mašina k dispozici. Prakticky je tedy Medium instance třikrát výkonnější než Small, přestože mají shodně jedno fyzické jádro. Od Large instance výš jsou pak stroje vícejádrové – aplikace tedy musí podporovat běh ve více vláknech
Z naší praxe: životy instancí i ceny jsou vcelku stabilní. Během loňského června a července nám asi 7 dní s přestávkami běželo paralelně 50–100 small a medium instancí. Celkem jsme napočítali více než pět tisíc instance-hodin (cca 7 instance-měsíců). Obvykle jsme měli cenu nastavenou jen těsně nad minimem a přesto nám pár strojů z clusteru (nikdy ne všechny) vypnuli jednou nebo dvakrát. Konečný účet byl tehdy $108, Amazon mezitím asi o třetinu zlevnil.
Je nutné poznamenat, že sleva se počítá pouze na instance-hodiny. Nejsou do ní tedy zahrnuty zejména přenosy dat, storage (GB-měsíce) a I/O operace. Všechny tři jedou dle standardního ceníku Amazon Web Services a v našem setupu tvořily dohromady cca 20 % ceny.
Jak na to
Princip, kdy instance může kdykoliv vzniknout a zaniknout klade specifické nároky na architekturu řešení, stavíte vlastně malý výpočetní grid. Každá instance si zažádá o úlohu nějakému master serveru, spočítá ji a pak ji uploadne na storage. Nám taskmastera i storage dělala jedna small on-demand instance s Redisem.
Můžete si samozřejmě spočítaná data posílat mimo Amazon na váš server a ušetřit za běh on-demand instance, počítejte ale s vyšší cenou za data transfer mimo AWS. Pokud by měla být faktor i síťová latence, tak je dobré vědět, že nám nejbližší irské datacentrum má ceny znatelně vyšší než americké protějšky.
Kromě softwarové architektury je potřeba připravit i samotný operační systém, aby po nastartování sám spustil procesující program. K tomu Amazon nabízí tvorbu vlastních AMI, Amazon Machine Image. Jednoduše si vytvoříte novou instanci s distribucí dle chutě, nainstalujete všechny potřebné programy a do crontabu přidáte patřičnou @reboot direktivu. Následně v administraci přes Create Image naklonujete disk této instance do AMI. Při vytváření Spot Requestu pak stačí vybrat tento AMI jako zdroj pro nové instance.
Další krok Spot Requestu vám nabídne si zažádat rovnou o několik instancí se stejným setupem paralelně. Nemusíte tedy žádost ani stokrát proklikávat, ani psát bashové skripty s API voláním. Praktická je i možnost nastavit Request jako perzistentní: pokud vám Amazon instance zařízne, tak po opadnutí ceny zpět pod vaši hranici vytvoří stejný počet nových instancí (zdůrazňují nových, staré instance budou vždy nenávratně ztraceny).
Po potvrzení se Spot Request pár minut zpracovává a vyhodnocuje, zda se s vaší cenou může spustit. Pokud ano, tak první task requesty očekávejte během asi pěti minut od zadání, ani stovka nových instancí není dodávána „na objednávku“.
Až budete mít spočítáno, můžete instance zrušit ručně v administraci, voláním přes API nebo je jednoduše vypnout přes shutdown – ve všech případech dojde k terminaci instance. Pozor v případě persistentních requestů: Amazon nerozlišuje, zda instance zanikla zásahem systému nebo vaší rukou a vytvoří jejího náhradníka. Spot Requesty se opět dají zrušit hromadně v administraci nebo přes veřejné API.
Na co novináři potřebovali sto virtuálů?
Závěrem pár slov konkrétně k našemu problému a jeho řešení. Loni jsme z oddělení datové žurnalistiky dostali za úkol spočítat dojezdové časy pražské MHD před a po změně jízdního řádu. Cílem bylo zjistit, kdo si polepšil a kdo naopak. A vzhledem k více než 3000 zastávek, které PID obsluhuje, to nebyl výpočetně triviální úkol.
Výstupem našeho snažení měla být aplikace, kde by si uživatel kliknul do mapy a zvýraznilo se mu území, které může z této polohy za nastavitelný počet minut dosáhnout. Takové zadání je za možnostmi většiny GIS software, ty totiž obvykle umí síťovou analýzu spočítat pro jeden, předem daný výchozí bod. My však uživatelům chtěli nabídnout možnost zobrazit si takovou analýzu právě pro jejich byt, dům či práci.
Jako datový zdroj jsme zvolili hash table spojující pár odjezdové a příjezdové stanice s dobou jízdy mezi nimi. Je to dostatečně jednoduchý formát, se kterým se po exportu do JSONu dá snadno pracovat v JavaScriptové vizualizaci a který zároveň nepřináší velký overhead ani nároky na server (stran datové náročnosti) a klienta (stran výpočetní náročnosti).
Spojení nám počítal GraphServer, který hledá nejkratší cestu v hodnoceném grafu. Jako zdrojová data posloužily GTFS soubory, po dlouhých bojích vydupané z DPP a pro přestupy pak OpenStreetMap data. Kvůli snížení výpočetní náročnosti jsme nevyžadovali podmínku stejné doby odjezdu, takže z trasy A-B-C jsme spočítali nejen A-C, ale i všechny mezilehlé A-B a B-C.
Zdrojové párování každé zastávky s každou jsme spočítali z GTFS a uložili do Redisového Sorted Set (kvůli optimalizaci seřazeného podle vzdálenosti mezi zastávkami). Každé spočítané spojení znamenalo zápis do výsledkového Hashe a smazání záznamu ze zdrojového Sorted Set.
Zdrojový task se tedy mazal až po jeho úspěšném provedení a neexistovala mezilehlá informace „task se právě provádí“. Tuto race condition jsme vyřešili jednoduše tak, že se přes ZRANGE selektoval náhodný 1. – 1000. záznam. Řešení primitivní, ale výkonné – small instance zvládala s cca 50% vytížením CPU odbavovat řádově tisíce requestů za vteřinu.
Takto jsme k našim účelům přiohnuli různý dostupný, většinou opensource software. Vše by se pravděpodobně dalo naprogramovat na míru tak, aby to spočítal jeden kancelářský PC za pár hodin. Ale náklady by určitě byly podstatně vyšší, než dva tisíce korun za sedm CPU-měsíců amazoních instancí.