neděle 30. července 2017

Google Cloud a Node.js


V minlém článku jsem představoval Next.js. Dneska bych se chtěl zaměřit na to, jak samotné Next.js provozovat v Google Cloudu. Kromě samotného Next.js / Node.js si ukážeme i možnost, jak horizontálně škálovat naší novou aplikaci.

Cloud vs In-House

V případě, že v roce 2017 zvolíte In-House vývoj, musíte k tomu mít sakra velký důvod. Existuje snad pouze jedna výhoda a tou je fakt, že máte data tam, kde je přesně chcete mít. Tedy v případě cloudu jste často limitováni v tom, kde vaše data leží.

Pokud si ovšem umíte obhájit to, že data máte v cloudu (např s podporou tokenizace), tak neexistuje žádný další důvod, používat vlastní servery. Použití vlastních serverů je stejné, jako běžet maraton s batohem plným kamení.

Ve chvíli, kdy mluvíme o cloudu jako je AWS, Azure či Google, tak mluvíme hlavně o ekosystému kolem. Jestli v cloudu využíváte pouze virtualizaci serverů a zbytek si řešíte sami, vězte, že to děláte špatně.

Stačí, když si zodpovíte na tyto otázky:
  1. Jak řešíte deploy aplikací?
  2. Jak řešíte logování?
  3. Jak řešíte monitoring?
  4. Jak řešíte databázi?
  5. Jak řešíte škálování (vertikální i horizontální)?
  6. Jak spravujete load balancing?
  7. Umíte jednoduše část svých requestů přesměrovávat na nové verze?
  8. Jak řešíte bezvýpadkové nasazení?
Pokud vaší odpovědí je všude cloud služba, gratuluji. Pokud ne, tak jaký je důvod, že si to řešíte sami? Není to náhodou neznalostí cloud služeb? Nebo je důvodem to, že používáte cloud od firmy, která poskytuje pouze virtualizaci? Buďte chytří. Tím, že zvolíte jedno z tria AWS, Azure či Google, si můžete dost svojí práci zjednodušit.

Google Cloud

V době, kdy jsem technologicky stavěl startup, tak jsme se shodli na tom, že vše bude v cloudu. Rovnou jsme tím zavrhli, že bychom v budoucnu řešili lokální nasazení, protože by to znamenalo extrémní nároky na infrastrukturu a vývoj.

V té době byla moje znalost cloud služeb dost omezená a žil jsem v tom, že si rozjedeme vlastní virtuální servery a tam si vše budeme spravovat sami.

Proto první volba padla na Compute Engine, což jsou samotné virtuální servery, kde si "naklikáte" vhodnou Linux distribuci a pomocí SSH konzole doinstalujete vše potřebné.

I když tímto způsobem můžete uspět, bude vás stát mnoho úsilí, abyste si vytvořili správnou infrastrukturu a byli schopni spravovat více tenantů, logování, monitoring, škálování, apod.

Díky tomu, že jsem velký odpůrce hesla: "Nesahej na to, co funguje". Tak jsem stále hledal způsob, jak to udělat jinak.

Tou variantou je App Engine....

App Engine

App Engine je platforma, která slouží k tomu, že vám sama bude spravovat vaší aplikaci. K tomuto účelu si sama umí vytvořit Docker kontejnery, které spouští a spravuje.

Abychom správně pochopili, jak App Engine funguje, je třeba si danou platformu rozdělit na několik částí.

App Engine - Services

Služby, dříve nazývány jako Moduly, jsou základní hlavní částí. Službu si můžete libovolně pojmenovat a současně s tím nastavit i routování na vlastní domény.

Aby to bylo lépe pochopitelné, tak si představte, že máte dvě aplikace. Backend a Frontend. Každá z nich bude nahrána do vlastní služby.

Kromě tohoto dělení, můžete zvolit i jiné. My jsme například služby využili tak, že každý tenant běží pod vlastní službou. Tedy Firma A je pod službou firma-a a Firma B je pod službou firma-b. Když k tomu použijete správné routování služeb, tak jednotlivé firmy budou vystupovat pod vlastní doménou třetího řádu. Tedy: firma-a.vasedomena.cz.

App Engine - Versions

Verze je podskupina služby. Představte si, že jste právě nahráli svou novou aplikaci. Vše funguje jak má a vy jste mezitím vytvořili novou verzi. Nová verze byla otestována a dostala nálepku "production ready".

Pokud využívate verze v App Engine, máte nyní několik možností:
  1. Po nasazení vypne původní verzi a nová verze se stane výchozí
  2. Po nasazení bude neaktivní a spustí se až na manuální zásah
  3. Po nasazení přesměruje třeba 10% requestů a zjistí se, zda na produkci nezpůsobuje problém
Toto je vlastnost, kterou na App Engine miluji. Máte velice jednoduše pod správou to, jak se budete chovat k novým verzím vaší aplikace.

App Engine - Instances

Instance jsou poslední částí skládanky. Nyní už víme, že naše aplikace beží pod službou X, má třeba dvě verze 1.1 a 1.2, kde se na verzi 1.2 přesměrovává 30% requestů.

Nyní přišel čas na vertikální a horizontální škálování. Při nasazení aplikace máte možnost si zvolit to, kolik instancí bude existovat. Min/Max. Máte například Node.js backend server, který má vysoký traffic a nároky na výkon. Nastavíte mu 3/20 instancí + lepší procesor + větší pamět. Tedy minimálně tři instance, maximálně 20. V případě frontentu to například bude 2/5 + slabší procesor + méně paměti. Asi každý si dovede představit tu úžasnou variabilitu.

Přesně tímto způsobem spravujeme Node.js. Pokud by se mě někdo zeptal na to, jak spravovat Node.js v produkci, toto je odpověď. Byla by hloupost, kdybychom se snažili ladit Node.js v produkci přes PM2, apod. Nikdy se nedostaneme do takového stavu. Zjednodušeně řečeno: "Lidé z Google vědí lépe, jak Node.js nastavit". Já jim pouze deklarativně řeknu, co od toho očekávám.

App Engine - Další možnosti

App Engine toho nabízí samozřejmě mnohem více. Ať už je to samotný monitoring (služeb, verzí či instancí), tak jsou zde takové věci jako je podpora logování do Stackdriver Logging, Cache, sdílené Sessions, apod.

Třešničkou na dortu mohou být různé kvóty na zdroje, vypínaní v čase, apod.

Node.js v Google Cloudu

Nyní se pojďme již konkrétně podívat na to, jak rozeběhnout Node.js v App Engine. Nejprve popíši celé flow a poté si ukážeme samotné kroky:
  1. Mám webovou aplikaci napsanou v Reactu přes Next.js. 
  2. Celý stack je následující: Typescript, React, Redux, Next.js. 
  3. Zdrojové soubory aplikace jsou uložené v GITu přes Bitbucket.
  4. V Google Cloudu je zrcadlení Bitbucketu do Source Repositories.
  5. Poté se v cloud konzoli provede checkout projektu a samotný deploy
  6. To je vše :)
Samotný deploy aplikace lze samozřejmě automatizovat. Ať už pomocí Bitbucket Pipelines či pomocí Jenkinse. Osobně čekám na to, až bude k dispozici API k AppEngine v google-cloud-node. Dokonce jsem před pár dny položil dotaz na vývojáře, kdy toto bude k dispozcici. Důvod proč bych rád toto API zde měl, je ten, že bych v budoucnu rád dělal deploy přes Cloud Lambda Functions, což vnímám jako optimální variantu.

V minulém článku jsem popisoval jak funguje Next.js s Typescriptem. Takže tento krok rovnou přeskočme. Podívejme se raději na to, jak provést samotný deploy.

Nejprve zmíním, že deploy můžete provést i z lokálního stroje. K tomuto účelu vám stačí nainstalovat si gcloud konzoli a v ní se autorizovat. Poté můžete ovládat cloud ze své konzole pomocí příkazu gcloud.

Aby byl deploy úspěšný, musíte ve svém projektu mít soubor app.yaml, který popisuje základní konfiguraci pro AppEngine. Pokud tento soubor nevytvoříte, tak AppEngine si vytvoří vlastní a aplikaci automaticky nahraje do služby s názvem default.

Ukázka, jak může takový jednoduchý app.yaml vypadat:
env: flex
runtime: nodejs
service: firma-a
Pokud vás zajímá, co vše se dá nastavit, doporučuji se podívat do manuálu.

Další věcí je konfigurace samotného package.json.

Zde je ukázka package.json pro Next.js s Typescriptem:
{
  "name": "@irminsul.cz/test_nextjs",
  "version": "1.0.0",
  "author": "Ales Dostal",
  "scripts": {
    "create-build-id": "node -e \"process.stdout.write(require('./package.json').version)\" > dist/.next/BUILD_ID;",
    "prebuild": "tsc && cp -R static dist/",
    "build": "next build dist",
    "predev": "tsc && cp -R static dist/",
    "dev": "concurrently \"tsc --watch\" \"next dist\"",
    "start": "npm run build && npm run create-build-id && next start dist -p 8080",
    "tslint": "tslint -c tslint.json -p tsconfig.json",
    "deploy": "gcloud app deploy --project apitree-test --version 1-0-0"
  },
  "dependencies": {
    "@types/node": "^8.0.8",
    "@types/react": "^15.0.35",
    "concurrently": "^3.5.0",
    "next": "^2.4.7",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "tslint": "^5.5.0",
    "tslint-react": "^3.0.0",
    "typescript": "^2.4.1"
  },
  "engines": {
    "node": ">=8.0.0"
  }
}
Je zde několik důležitých věcí, na které nesmíte nezapomenout.

V package.json se definuje verze node.js, na které naše instance poběží. V tomto případě můžete vidět, že jsme zvolili verzi Node.JS 8 nebo vyšší.

Dále je důležité mít ve scripts správně pojmenované commandy. Tím hlavním je "start". AppEngine se totiž bude snažit přesně tento command spustit. S tím souvisí i nutnost samotného portu. Pokud necháme výchozí nastavení, bude AppEngine čekat, že naše aplikace běží na portu 8080.

Pro to, aby v AppEngine správně běžel Next.js, je nutné zde provést jeden drobný hack. Tím hackem je nastavení BUILD_ID. Důvod proč, je ten, že pokud máte více instancí než jednu, tak by vaše aplikace mohla náhodně končit chybou. Více se dozvíte z následujícího issue.

V package.json můžete najít i samotný command pro deploy. Když se na něj podíváte blíže, tak si můžete všimnout, že definuje v jakém projektu bude nasazen a v jaké verzi. Projektem se zde míní hlavní projekt v Google Cloudu.

Nyní už nezbývá než spustit samotný deploy:
npm run deploy

Pokud jste vše nastavili správně, tak gcloud konzole provede následující:
  1. Stáhne si k sobě zdrojové soubory
  2. Vytvoří Docker kontejner s Node.js 8 a vyšší
  3. Nasadí do AppEngine
  4. Spustí na službě "firma-a"
  5. Pod verzí 1-0-0
  6. Spustí npm install
  7. Spustí npm start
  8. V tomto výchozím nastavení použije min 2 instance pro Node.JS

Závěr

Popsat, co všechno Google Cloud umí a to zejména App Engine by bylo příliš vyčerpávající. Tento popis berte jako jeden z návodů, jak rozeběhnout svojí aplikaci na platformě, která vás dostatečně odstíní od nutnosti ručně spravovat Node.js server ve vlastním virtuálním serveru.
Dále je nutné zmínit i to, že Google na svém Cloudu stále pracuje. Proto jsou některé jejich služby v Beta verzích, čímž znemožňují vše využít na 100%. Nicméně tím, že vývoj na této platformě jde rychle dopředu, tak bych se příliš neobával toho, že například tento způsob provozování Node.JS aplikací by byl nepoužitelný. Právě naopak.

A co vy? Už jste přešli na služby v cloudu?

Žádné komentáře:

Okomentovat

Když programátor založí a řídí firmu

Jako malý jsem chtěl být popelářem. Ani ne tak proto, že bych měl nějaký zvláštní vztah k odpadkům, ale hrozně se mi líbilo, jak...