Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Nejdříve si trochu teorie. Co je to The Twelve-Factor App?

Jednoduše řečeno, je to dokument, který má za cíl usnadnit vývoj SaaS aplikací, protože informuje vývojáře a DevOps inženýry o problémech a praktikách, které se často objevovaly při vývoji moderních aplikací.

Dokument byl vytvořen vývojáři platformy Heroku.

Metodologie dvanácti faktorů (The Twelve-Factor App) může být použita pro aplikace napsané v jakémkoli programovacím jazyce a využívající jakékoli kombinace externích služeb (backing services) (databáze, message queue, cache atd.).

Krátce o faktorech, na kterých je tato metodologie založena:

  1. Základ kódu – Jeden základ kódu, sledovaný v systému správy verzí, – více nasazení
  2. Závislosti – Výslovně deklarujte a izolujte závislosti
  3. Konfigurace – Uchovávejte konfiguraci v runtime prostředí
  4. Externí služby (Backing Services) – Považujte externí služby (backing services) za připojitelné zdroje
  5. Sestavení, release, provádění – Přísně oddělujte fáze sestavení a provádění
  6. Procesy – Spusťte aplikaci jako jeden nebo více procesů, které neuchovávají vnitřní stav (stateless)
  7. Připojení portů (Port binding) – Exportujte služby přes připojení portů
  8. Paralelismus – Škálujte aplikaci pomocí procesů
  9. Zlikvidovatelnost (Disposability) – Maximalizujte spolehlivost pomocí rychlého spuštění a správného ukončení
  10. Parita vývoje/produkce aplikace – Udržujte prostředí vývoje, staging a produkce co nejpodobnější
  11. Logování (Logs) – Považujte log jako tok událostí
  12. Administrativní úkoly – Provádějte administrativní/management úkoly pomocí jednorázových procesů

Více informací o 12 faktorech najdete v následujících zdrojích:

Co je to Blue-Green deployment?

Blue-Green deployment – to je způsob dodání aplikace na production tím způsobem, že koncový klient nevidí žádné změny na své straně. Jinými slovy, nasazení aplikace s nulovým výpadkem.

Klasická schéma BG Deploy vypadá tak, jak je znázorněno na obrázku níže.

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

  • Na začátku jsou 2 fyzické servery s naprosto stejným kódem, aplikací, projektem, a je zde router (vyrovnávač zátěže).
  • Router původně směruje všechny dotazy na jeden ze serverů (modrá).
  • V okamžiku, kdy je třeba znovu provést vydání, celý projekt se aktualizuje na jiném serveru (alpha), který v tuto chvíli nezkouší žádné dotazy.
  • Po dokončení aktualizace kódu na modrém serveru, router dostane pokyn přepnout z zeleného na alpha server.
  • Nyní všichni klienti vidí výsledky kódu z modrého serveru.
  • Nějakou dobu, modrá server slouží jako záložní verze v případě neúspěšného nasazení na alpha server, a v případě neúspěchu a bugů, router přepne uživatelský tok zpět na modrá server se starou stabilní verzí, a nový kód se posílá na úpravu a testování.
  • A nakonec se stejně tak aktualizuje modrá server. A po jeho aktualizaci, router přepne tok dotazů zpět na modrá server.

Vypadá to všechno velmi dobře a na první pohled by s tím neměly být žádné problémy.
Ale protože žijeme v moderním světě, klasická schéma s fyzickým přepínáním pro nás nevyhovuje. Zatím si tuto informaci zapamatujte, vrátíme se k ní později.

Špatné a dobré rady

Poznámka: V níže uvedených příkladech jsou uvedeny nástroje/metodologie, které používám já, můžete použít jakékoli alternativy se podobnými funkcemi.

Většina příkladů se nějakým způsobem překrývá s webovým vývojem (to je překvapení), s PHP a Dockerem.

V následujících bodech je jednoduchý praktický popis použití faktorů na konkrétních příkladech, pokud chcete více teorie na toto téma, odkážte na odkazy výše na prvotní zdroj.

1. Kódová základna

Používejte FTP a FileZilla k nahrávání souborů na servery po jednom kuse, neukládejte kód nikde mimo produkční server.

V projektu by vždy měla být jednotná kódová základna, to znamená, že veškerý kód pochází z jednoho místa. Git repozitáře. Servery (produkční, staging, test1, test2 …) používají kód z větví jednoho společného repozitáře. Tím dosahujeme konzistence kódu.

2. Závislosti

Stahujte všechny knihovny do složek přímo do kořenového adresáře projektu. Aktualizace provádějte jednoduše přesunutím nového kódu do složky s aktuální verzí knihovny. Nainstalujte všechny potřebné utility přímo na hostitelském serveru, kde běží dalších 20 služeb.

Projekt by měl mít vždy jasně srozumitelný seznam závislostí (pod závislostmi také rozumím prostředí). Všechny závislosti by měly být jasně definovány a izolovány.
Jako příklad vezměme Composer a Docker.

Composer — správce balíčků, který umožňuje instalaci knihoven v PHP. Composer umožňuje přísně nebo nepřísně specifikovat verze a jasně je definovat. Na serveru může být 20 různých projektů a každý bude mít osobní seznam balíčků a knihoven, který nebude závislý na ostatních.

Docker — utilita, která umožňuje definovat a izolovat prostředí, ve kterém bude aplikace fungovat. Podobně jako s composerem, ale mnohem podrobněji, můžeme určit, s čím aplikace pracuje. Vybrat konkrétní verzi PHP, nainstalovat pouze potřebné balíčky pro projekt, aniž bychom přidávali něco navíc. A co je nejdůležitější, nepřekrývat se s balíčky a prostředím hostitelské mašiny a dalších projektů. To znamená, že všechny projekty na serveru běžící přes Docker mohou používat naprosto libovolnou sadu balíčků a úplně odlišné prostředí.

3. Konfigurace

Ukládejte konfigurace jako konstanty přímo v kódu. Oddělené konstanty pro testovací server, oddělené pro produkci. Provázujte práci aplikace v závislosti na prostředí přímo v obchodní logice projektu pomocí konstrukcí if else.

Konfigurace — to je jediné, čím by se měly lišit nasazení projektu (deployment). Ideálně by měly být konfigurace předávány prostřednictvím proměnných prostředí (env vars).

To znamená, že i když budete uchovávat několik konfiguračních souborů .config.prod, .config.local a při nasazování je přejmenovávat na .config (hlavní konfiguraci, ze které aplikace čte data), nebude to správný přístup, protože v takovém případě budou informace z konfigurací běžně přístupné všem vývojářům aplikace a data z produkčního serveru budou kompromitována. Všechny konfigurace by měly být uloženy přímo v systému nasazení (CI/CD) a generovány pro různá prostředí s různými hodnotami nezbytnými pro konkrétní prostředí právě v okamžiku nasazení.

4. Závislé služby (Backing Services)

Tvrdě se vázat na prostředí, používejte různá připojení pro stejné služby v konkrétních prostředích.

Tento bod se ve skutečnosti silně překrývá s bodem o konfiguracích, protože bez existence tohoto bodu nelze vytvořit normální konfigurační data a celkově možnost konfigurace zanikne.

Všechna připojení k externím službám, jako jsou frontové servery, databáze, caching služby, by měla být jednotná jak pro místní prostředí, tak pro externí/prod prostředí. Jinými slovy, mohu kdykoli změnit připojovací řetězec a nahradit dotazy na databázi č. 1 databází č. 2 bez změny kódu aplikace. Nebo abych to přehnal, jako příklad platí, že při škálování služby nebudete muset pro další caching server určovat připojení nějakým zvláštním způsobem.

5. Sestavení, vydání, provedení

Mějte na serveru pouze finální verzi kódu, bez šancí vrátit vydání zpět. Není potřeba plnit diskový prostor. Kdo si myslí, že může nasadit kód do produkce s chybou, je špatný programátor!

Všechny fáze nasazení by měly být mezi sebou oddělené.

Mějte možnost se vrátit zpět. Dělejte vydání s uložením rychle dostupných starých kopií aplikace (již sestavených a připravených k boji), abyste v případě chyb mohli obnovit starou verzi. To znamená, že je zde podmíněná složka releases a složka voltage, a po úspěšném nasazení a sestavení se složka voltage propojí symbolickým odkazem s novým vydáním, které se nachází uvnitř releases s podmíněným názvem čísla vydání.

A zde si připomeneme Blue-Green nasazení, které umožňuje nejen přepínání mezi kódem, ale také přepínání mezi všemi zdroji a dokonce prostředími s možností všechno vrátit zpět.

6. Procesy

Uložte stavová data aplikace přímo v samotné aplikaci. Používejte relace v paměti aplikace. Využívejte co nejvíce sdílených mezi externími službami. Omezte se na to, že aplikace může mít pouze jeden proces a nedovolte možnost horizontálního škálování.

Pokud jde o relace, uchovávejte data pouze v cache řízené externími službami (memcached, redis), tímto způsobem, i když budete mít spuštěno 20 procesů aplikace, může kterýkoli z nich, přistupující k cache, pokračovat v práci se zákazníkem ve stejném stavu, v jakém byl uživatel, když pracoval s aplikací v jiném procesu. Tento přístup zaručuje, že bez ohledu na počet kopií externích služeb, vše bude fungovat správně a bez problémů s přístupem k datům.

7. Zavázání portů (Port binding)

Jak pracovat s externími službami by měl znát pouze webový server. Ještě lépe je spouštět externí služby přímo uvnitř webového serveru. Například jako PHP modul v Apachi.
Všechny vaše služby by měly být navzájem přístupné prostřednictvím nějaké adresy a portu (localhost:5432, localhost:3000, nginx:80, php-fpm:9000), tedy z nginx mám přístup jak k php-fpm, tak k postgres, a z php-fpm k postgres a nginx, a vlastně z každé služby mám přístup k jiné službě. Tímto způsobem je životaschopnost jedné služby nezávislá na životaschopnosti jiné služby.

8. Paralelismus

Pracujte s jedním procesem, jinak by několik procesů nemuselo spolupracovat!

Nechte možnost škálování. Výborně pro to poslouží docker swarm.
Docker Swarm je nástroj pro vytváření a správu clusterů kontejnerů jak mezi různými stroji, tak i mezi množstvím kontejnerů na jednom stroji.

Pomocí swarmu mohu určit, kolik zdrojů budu přidělovat každému procesu a kolik procesů jedné a téže služby budu spouštět. Vnitřní vyrovnávač zátěže, přičemž přijímá data na určeném portu, je automaticky přesměrovává na procesy. Takže pokud zjistím, že zátěž serveru vzrostla, mohu přidat více procesů a tím snížit zátěž na určité procesy.

9. Odstranitelnost (Disposability)

Nepoužívejte fronty pro práci s procesy a daty. Ukončení jednoho procesu by mělo ovlivnit fungování celé aplikace. Pokud selže jedna služba, selže všechno.

Každý proces a služba mohou být kdykoliv vypnuty, a to by nemělo ovlivnit jiné služby (nejde samozřejmě o to, že služba nebude dostupná pro jinou službu, ale o to, že jiná služba se po této neukončí). Všechny procesy by měly končit jemně, tak, aby při jejich ukončení nedošlo k poškození dat a při dalším spuštění systém pracoval správně. To znamená, že i v případě havarijního ukončení by data neměla být ohrozena (vhodný mechanismus jsou transakce, dotazy do databáze pracují pouze ve skupinách, a pokud alespoň jeden dotaz ze skupiny neproběhne nebo proběhne s chybou, žádný jiný dotaz ze skupiny se nakonec skutečně neprovede).

10. Parita vývoje/provozu aplikace

Produkční, stagingová a lokální verze aplikace by měly být rozdílné. Na produkci máme framework Yii Lite a lokálně Yii, abychom měli na produkci rychlejší chod!

Ve skutečnosti by všechna nasazení a práce s kódem měly probíhat v téměř identickém prostředí (nejde o fyzický hardware). Také nasazení kódu na produkci by měl být schopen provést kdokoliv z vývojového týmu, a ne pouze speciálně vyškolený devops tým, který pouze díky zvláštní síle může nasadit aplikaci na produkci.

Toto nám také pomáhá Docker. Při dodržení všech předchozích bodů povede používání Dockeru proces nasazení prostředí jak na produkci, tak na lokálním stroji k zadání jedné nebo dvou příkazů.

11. Logování (Logs)

Logy píšeme do souborů a databáze! Soubory a databáze od logů nečistíme. Koupíme prostě pevný disk na 9000 Petabyte a hotovo.

Všechny logy by měly být považovány za proud událostí. Aplikace by se neměla zabývat zpracováním logů. Logy by měly být vypisovány buď do stdout, nebo zasílány pomocí protokolu, jako je UDP, aby aplikaci práce s logy nepůsobila žádné problémy. Na to je skvělý graylog. Graylog, přijímající všechny logy na UDP (u tohoto protokolu není potřeba čekat na potvrzení úspěšného přijetí paketu) nijak neovlivňuje aplikaci a pouze se zabývá strukturací a zpracováním logů. Logika aplikace se nemění pro práci s takovými přístupy.

12. Úkoly administrace

Pro aktualizaci dat, databáze atd. použijte samostatně vytvořený endpoint v API, jehož provedení dvakrát po sobě by mohlo způsobit, že se vám vše zdubluje. Ale vy přece nejste hloupí, nekliknete dvakrát, a migrace nám nejsou potřeba.

Všechny úkoly administrace by měly být prováděny ve stejném prostředí jako celý kód, na úrovni releasů. To znamená, že pokud potřebujeme změnit strukturu databáze, nebudeme to dělat ručně změnou názvů sloupců a přidáváním nových přes nějaké vizuální nástroje pro správu databáze. Na tyto věci vytváříme samostatné skripty — migrace, které se provádějí všude a ve všech prostředích se stejným a srozumitelným výsledkem. Pro všechny ostatní úkoly, jako je naplnění projektu daty, by měly být aplikovány podobné metodologie.

Příklad implementace na PHP, Laravel, Laradock, Docker-Compose

P.S. Všechny příklady byly vytvořeny na MacOS. Většina z nich je použitelná i pro Linux. Uživatelé Windows, omlouvám se, ale na Windows jsem dlouho nepracoval.

Představme si situaci, že na našem PC není nainstalována žádná verze PHP a vlastně nic jiného.
Instalujeme docker a docker-compose posledních verzí. (to lze najít na internetu)

docker -v && 
docker-compose -v

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

1. Instalujeme Laradock

git clone https://github.com/Laradock/laradock.git && 
ls

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Co se týče Laradocku, řeknu, že je to skvělá věc, která obsahuje spoustu kontejnerů a pomocných nástrojů. Ale používat Laradock bez úprav na produkci — nedoporučoval bych kvůli jeho nadbytečnosti. Lepší je vytvořit si vlastní kontejnery na základě příkladů v Laradocku, tak bude možnost optimalizace, protože nikomu není potřeba vše, co tam je, najednou.

2. Konfigurujeme Laradock pro práci naší aplikace.

cd laradock && 
cp env-example .env

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

2.1. Otevřete adresář habr (rodičovská složka, do které byl naklonován laradock) v jakémkoli editoru. (V mém případě PHPStorm)

V této fázi nastavíme pouze název projektu.

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

2.2. Spusťte obraz workspace. (Váš obraz se nějakou dobu bude sestavovat)
Workspace je speciálně připravený obraz pro práci s rámcem jménem vývojáře.

Přejděte dovnitř kontejneru pomocí

docker-compose up -d workspace && 
docker-compose exec workspace bash

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

2.3. Nainstalujte Laravel

composer create-project --prefer-dist laravel/laravel application

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

2.4. Po instalaci zkontrolujte, zda byla vytvořena složka s projektem, a ukončete compose.

ls
exit
docker-compose down

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

2.5. Vraťte se zpět do PHPStorm a nastavte správnou cestu k našemu laravel aplikaci v souboru .env.

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

3. Přidáme celý kód do Gitu.

K tomu vytvoříme na Githubu (nebo kdekoli jinde) repozitář. Otevřeme terminál ve složce habr a vykonáme následující kód.

echo "# habr-12factor" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:nzulfigarov/habr-12factor.git # zde bude odkaz na váš repozitář
git push -u origin master
git status

Zkontrolujte, jestli je všechno v pořádku.

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Pro pohodlí doporučuji použít nějaké vizuální rozhraní pro Git, v mém případě je to GitKraken. (tady je referenční odkaz)

4. Spusťte!

Před spuštěním se ujistěte, že na portech 80 a 443 nic neběží.

docker-compose up -d nginx php-fpm

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Takže náš projekt se skládá ze 3 samostatných služeb:

  • nginx — webový server
  • php-fpm — php pro příjem požadavků z webového serveru
  • workspace — php pro vývojáře

V tuto chvíli jsme dosáhli toho, že jsme vytvořili aplikaci odpovídající již 4 bodům z 12, konkrétně:

1. Základ kódu — všechen kód je v jedné repozitáři (malá poznámka: možná by bylo správné umístit docker dovnitř projektu laravel, ale to není zásadní).

2. Závislosti — Všechny naše závislosti jsou jasně uvedeny v application/composer.json a v každém Dockerfile každého kontejneru.

3. Externí služby (Backing Services) — Každá z služeb (php-fpm, nginx, workspace) žije svým vlastním životem a je připojena zvenčí, a při práci s jednou službou, druhá nebude ovlivněna.

4. Procesy — každá služba je jeden proces. Každá ze služeb neuchovává vnitřní stav.

5. Připojení portů (Port binding)

docker ps

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Jak vidíme, každá služba běží na svém vlastním portu a je dostupná pro všechny ostatní služby.

6. Paralelismus

Docker nám umožňuje spouštět několik procesů stejné služby s automatickou vyrovnávací zátěží mezi nimi.

Zastavíme kontejnery a spustíme je pomocí příznaku —scale

docker-compose down && 
docker-compose up -d --scale php-fpm=3 nginx php-fpm

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Jak vidíme, u php-fpm kontejneru se vytvořily kopie. V práci s tímto kontejnerem nemusíme nic měnit. I nadále se k němu obracíme přes port 9000 a Docker za nás reguluje zátěž mezi kontejnery.

7. Zlikvidovatelnost (Disposability) — každý kontejner lze zabít bez škody pro ostatní. Zastavení nebo restart kontejneru nijak neovlivní práci aplikace při následujících spuštěních. Každý kontejner lze také znovu spustit kdykoliv.

8. Parita vývoje/produkce aplikace — všechna naše prostředí jsou shodná. Při spuštění systému na serveru v produkci nebudete muset nic měnit ve vašich příkazech. Všechno bude přesně tak, jak je to založeno na Dockeru.

9. Logování (Logs) — všechny logy v těchto kontejnerech vycházejí na stream a jsou viditelné v konzoli Dockeru. (v tomto případě, ve skutečnosti, s jinými vlastním kontejnery, to může být jinak, pokud se o to nepostaráte)

 docker-compose logs -f

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Ale je tu háček v tom, že výchozí hodnoty v PHP a Nginxu také zapisují logy do souboru. Abychom splnili 12 faktorů, je nutné vypnout záznam logů do souboru v konfiguracích každého kontejneru zvlášť.

Docker také poskytuje možnost směrovat logy nejen do stdout, ale i do takových věcí, jako je graylog, o kterém jsem zmínil výše. A uvnitř graylogu můžeme manipulovat s logy jak chceme a naše aplikace si toho vůbec nevšimne.

10. Administrativní úkoly — všechny úkoly správy jsou vyřešeny pomocí Laravelu díky nástroji Artisan přesně tak, jak to chtěli tvůrci 12 faktorové aplikace.

Jako příklad ukážu, jak se provádějí některé příkazy.
Vstoupíme do kontejneru.

 
docker-compose exec workspace bash
php artisan list

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

Nyní můžeme využít jakýkoliv příkaz. (všimněte si, že jsme nenastavili databázi a cache, proto polovina příkazů nebude správně fungovat, protože jsou určeny k práci s cache a databází).

Vývoj aplikací a Blue-Green deployment na základě metodologie The Twelve-Factor App s příklady v PHP a Dockeru.

11. Konfigurace a 12. Sestavení, release, provádění

Tuto část jsem chtěl věnovat Blue-Green Deployment, ale ukázalo se, že je to příliš rozvinuté pro tento článek. O tom napíšu samostatný článek.

Ve zkratce, koncept je postaven na systémech CI/CD typu Jenkins a Gitlab CI. V obou lze nastavit proměnné prostředí spojené s konkrétním prostředím. Tím pádem se v takovém případě vykoná bod s Konfiguracemi.

A bod o Sestavení, release, provádění řeší vestavěné funkce v obou nástrojích s názvem Pipeline.

Pipeline umožňuje rozdělit proces nasazení na mnoho fází, vyčleňující fáze sestavení, uvolnění a provedení. V Pipeline také můžete vytvářet zálohy, a vlastně cokoliv jiného. Tento nástroj má neomezený potenciál.

Kód aplikace se nachází na Github.
Nezapomeňte inicializovat submodul při klonování tohoto repozitáře.

P.S.: Všechny tyto přístupy lze používat s jakýmikoli jinými nástroji a programovacími jazyky. Hlavní je, aby podstata zůstala stejná.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster