Ve společnosti True Engineering jsme nastavili proces kontinuální dodávky aktualizací na servery zákazníka a chceme se o tuto zkušenost podělit.
Nejprve jsme vyvinuli online systém pro zákazníka a nasadili jej ve vlastním Kubernetes klastru. Nyní naše vysoce zatížené řešení přešlo na platformu zákazníka, pro což jsme nastavili zcela automatizovaný proces kontinuálního nasazení. Díky tomu jsme urychlili time-to-market – dodávku změn do produkčního prostředí.
V tomto článku vám přiblížíme všechny etapy procesu kontinuálního nasazení (CD) neboli dodávky aktualizací na platformu zákazníka:
- jak tento proces začíná,
- synchronizace s Git repozitářem zákazníka,
- sestavení backendu a frontendu,
- automatické nasazení aplikace v testovacím prostředí,
- automatické nasazení na Prod.
Během procesu se podělíme o detaily nastavení.

1. Zahájení CD
Kontinuální nasazení začíná tím, že vývojář vloží změny do uvolňovací větve našeho Git repozitáře.
Naše aplikace funguje na základě mikroservisní architektury a všechny její komponenty jsou uloženy v jednom repozitáři. Díky tomu se sestavují a instalují všechny mikroservisy, i když došlo ke změně pouze u jednoho z nich.
Organizovali jsme práci prostřednictvím jednoho repozitáře z několika důvodů:
- Pohodlí vývoje – aplikace se aktivně vyvíjí, takže lze pracovat okamžitě se vším kódem.
- Jednotný CI/CD pipeline, který zaručuje, že aplikace jako jeden systém projde všemi testy a je dodána do prod prostředí zákazníka.
- Vylučujeme zmatek ve verzích – nemusíme uchovávat mapu verzí mikroservisů a popisovat pro každou mikroservisu její konfiguraci ve skriptech Helm.
2. Synchronizace s Git repozitářem zdrojového kódu zákazníka
Provedené změny se automaticky synchronizují s Git repozitářem zákazníka. Tam je nastavena sestava aplikace, která se spouští po aktualizaci větve, a nasazení do produkce. Oba procesy probíhají v jejich prostředí z Git repozitáře.
Nemůžeme pracovat s repozitářem klienta přímo, jelikož potřebujeme vlastní prostředí pro vývoj a testování. K těmto účelům používáme svůj Git repozitář - ten je synchronizován s jejich Git repozitářem. Jakmile vývojář nahraje změny do příslušné větve našeho repozitáře, GitLab okamžitě tyto změny odešle klientovi.

Poté je třeba provést sestavení. To se skládá z několika fází: sestavení backendu a frontendu, testování a dodání do produkce.
3. Sestavení backendu a frontendu
Sestavení backendu a frontendu je úkol, který probíhá paralelně v systému GitLab Runner. Konfigurace základního sestavení je uložena ve stejném repozitáři.
.
GitLab Runner stahuje kód z požadovaného repozitáře, pomocí příkazu pro sestavení Java aplikace jej sestaví a odešle do Docker registru. Zde máme backend a frontend, získáváme Docker obrazy, které ukládáme do repozitáře na straně klienta. Pro správu Docker obrazů používáme .
Synchronizujeme verze našich obrazů s verzí vydání, která bude uložena v Dockeru. Pro hladký provoz jsme provedli několik nastavení:
1. Mezi testovacím prostředím a produkčním se kontejnery nepřeskládávají. Provedli jsme parametrizaci, aby jeden a ten samý kontejner mohl fungovat bez přestavby se všemi nastaveními, proměnnými prostředí a službami jak v testovém prostředí, tak v produkci.
2. Pro aktualizaci aplikace přes Helm je nutné uvést její verzi. Naše sestavení backendu, frontendu a aktualizace aplikace jsou tři různé úkoly, proto je důležité používat všude stejnou verzi aplikace. Pro tento úkol používáme data z historie Git, jelikož máme konfiguraci K8S clusteru a aplikace v jednom Git repozitáři.
Verzi aplikace získáváme z výsledků provedení příkazu
git describe --tags --abbrev=7.
4. Automatické nasazení všech změn do testovacího prostředí (UAT)
Dalším krokem v tomto skriptu sestavení je automatická aktualizace clusteru K8S. K tomu dochází za předpokladu, že se celá aplikace sestavila a všechny artefakty byly publikovány v Docker Registry. Poté se spustí aktualizace testovacího prostředí.
Aktualizace clusteru se spouští pomocí . Pokud něco neproběhne podle plánu, Helm automaticky a samostatně vrátí všechny své změny zpět. Není třeba jeho práci kontrolovat.
Společně se sestavením dodáváme konfiguraci klastru K8S. Následujícím krokem je její aktualizace: configMaps, deployments, services, secrets a jakékoli další konfigurace K8S, které jsme změnili.
Poté Helm spouští aktualizaci aplikace v testovacím prostředí. Před tím, než bude aplikace nasazena na produkci. Je to uděláno proto, aby uživatelé mohli ručně zkontrolovat obchodní funkce, které jsme zveřejnili v testovacím prostředí.
5. Automatické nasazení všech změn na Prod
Pro nasazení aktualizace do produkčního prostředí stačí stisknout jedno tlačítko v GitLab — a kontejnery jsou okamžitě doručeny do produkčního prostředí.
Stejná aplikace může bez přepracování fungovat v různých prostředích — testovacím a produkčním. Používáme stejné artefakty, aniž bychom měnili něco v aplikaci, a parametry nastavujeme zvenčí.
Flexibilní parametrizace nastavení aplikace závisí na tom prostředí, ve kterém bude aplikace spuštěna. Všechny nastavení prostředí jsme přesunuli ven: vše je parametrizováno přes konfiguraci K8S a parametry Helm. Když Helm nasazuje sestavení v testovacím prostředí, používají se testovací parametry, zatímco v produkčním prostředí — parametrizace pro produkci.
Nejtěžší bylo parametrizovat všechny používané služby a proměnné, které závisí na prostředí, a převést je na proměnné prostředí a popis-konfiguraci parametrů prostředí pro Helm.
V parametrech aplikace se používají proměnné prostředí. Jejich hodnoty jsou zadány v kontejnerech pomocí K8S configmap, který se šablonuje pomocí Go šablon. Například, zadání proměnné prostředí pro název domény lze provést takto:
APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}
.Values.global.env – v této proměnné je uchováván název prostředí (prod, stage, UAT).
.Values.app.properties.app_external_domain – v této proměnné v souboru .Values.yaml zadáváme požadovanou doménu.
Při aktualizaci aplikace Helm vytváří soubory configmap.yaml z šablon a vyplňuje hodnotu APP_EXTERNAL_DOMAIN správnou hodnotou v závislosti na prostředí, ve kterém se aktualizace provádí. Tato proměnná je nastavena již v kontejneru. Přístup k ní má aplikace, což znamená, že v každém prostředí aplikace bude mít tato proměnná jinou hodnotu.
Relativně nedávno ve Spring Cloud byla přidána podpora K8S, včetně práce s configMaps: . Dokud projekt aktivně vyvíjíme a zásadně se mění, nemůžeme ho používat v produkci. Ale aktivně sledujeme jeho stav a používáme ho v DEV konfiguracích. Jakmile se stabilizuje, přepneme se z používání proměnných prostředí na něj.
Celkem
Takže, Continuous Deployment je nastaven a funguje. Všechny aktualizace probíhají jedním stisknutím tlačítka. Dodání změn do produkčního prostředí je automatické. A co je důležité, aktualizace nepozastavují činnost systému.

Plány do budoucna: automatizovaná migrace databáze
Uvažovali jsme o upgradu databáze a možnosti tyto změny vrátit zpět. Vždyť současně běží dvě různé verze aplikace: jedna stará a nová se spouští. Starou vypneme teprve, když se ujistíme, že nová verze funguje. Migrace databáze by měla umožnit práci s oběma verzemi aplikace.
Proto nemůžeme jen tak změnit název sloupce nebo jiné údaje. Můžeme však vytvořit nový sloupec, zkopírovat do něj data ze starého sloupce a napsat triggery, které při aktualizaci dat současně kopírují a aktualizují je v jiném sloupci. A po úspěšném nasazení nové verze aplikace, po uplynutí období post-launch support, budeme moci starý sloupec a již nepotřebný trigger odstranit.
Pokud nová verze aplikace nefunguje správně, můžeme se vrátit k předchozí verzi, včetně předchozí verze databáze. Jinými slovy, naše změny umožní současnou práci s několika verzemi aplikace.
Plánujeme automatizaci migrace databáze prostřednictvím K8S job, integrovanou do procesu CD. A určitě se o tento zážitek podělíme na Habru.
Zdroj: habr.com
