Nasze wdrożenie Continuous Deployment na platformie klienta

W True Engineering opracowaliśmy proces ciągłego dostarczania aktualizacji na serwery klientów i chcemy podzielić się tym doświadczeniem.

Na początek opracowaliśmy dla klienta system online i wdrożyliśmy go we własnym klastrze Kubernetes. Teraz nasze rozwiązanie o dużym obciążeniu zostało przeniesione na platformę klienta, dla której przygotowaliśmy w pełni automatyczny proces Continuous Deployment. Dzięki temu przyspieszyliśmy time-to-market – dostarczenie zmian do środowiska produktowego.

W tym artykule omówimy wszystkie etapy procesu Continuous Deployment (CD) czyli dostarczania aktualizacji na platformę klienta:

  1. Jak zaczyna się ten proces?
  2. synchronizacja z repozytorium Git klienta,
  3. montaż backendu i frontendu,
  4. automatyczne wdrażanie aplikacji w środowisku testowym,
  5. automatyczne wdrożenie do Prod.

Po drodze udostępnimy szczegóły konfiguracji.

Nasze wdrożenie Continuous Deployment na platformie klienta

1. Uruchom płytę CD

Ciągłe wdrażanie rozpoczyna się od przekazania przez programistę zmian do gałęzi wydania naszego repozytorium Git.

Nasza aplikacja działa w oparciu o architekturę mikroserwisową, a wszystkie jej komponenty przechowywane są w jednym repozytorium. Dzięki temu wszystkie mikroserwisy są zbierane i instalowane, nawet jeśli któryś z nich uległ zmianie.

Zorganizowaliśmy pracę poprzez jedno repozytorium z kilku powodów:

  • Łatwość programowania – aplikacja aktywnie się rozwija, dzięki czemu możesz pracować z całym kodem na raz.
  • Pojedynczy potok CI/CD gwarantujący, że aplikacja jako pojedynczy system przejdzie wszystkie testy i zostanie dostarczona do środowiska produkcyjnego klienta.
  • Eliminujemy zamieszanie w wersjach - nie musimy przechowywać mapy wersji mikroserwisów i opisywać jej konfiguracji dla każdego mikroserwisu w skryptach Helma.

2. Synchronizacja z repozytorium Git kodu źródłowego Klienta

Wprowadzone zmiany są automatycznie synchronizowane z repozytorium Git klienta. Tam konfigurowany jest zespół aplikacji, który jest uruchamiany po aktualizacji gałęzi i wdrożeniu do kontynuacji. Obydwa procesy pochodzą w swoim środowisku z repozytorium Git.

Nie możemy współpracować bezpośrednio z repozytorium klienta, ponieważ potrzebujemy własnych środowisk do programowania i testowania. Do tych celów używamy naszego repozytorium Git - jest ono zsynchronizowane z ich repozytorium Git. Gdy tylko programista opublikuje zmiany w odpowiedniej gałęzi naszego repozytorium, GitLab natychmiast przekazuje te zmiany klientowi.

Nasze wdrożenie Continuous Deployment na platformie klienta

Następnie musisz wykonać montaż. Składa się z kilku etapów: montażu backendu i frontendu, testów i dostarczenia na produkcję.

3. Montaż backendu i frontendu

Budowa backendu i frontendu to dwa równoległe zadania, które realizowane są w systemie GitLab Runner. Jego oryginalna konfiguracja zestawu znajduje się w tym samym repozytorium.

Tutorial dotyczący pisania skryptu YAML do budowania w GitLabie.

GitLab Runner pobiera kod z wymaganego repozytorium, składa go za pomocą polecenia budowania aplikacji Java i wysyła do rejestru Dockera. Tutaj składamy backend i frontend, pozyskujemy obrazy Dockera, które umieszczamy w repozytorium po stronie klienta. Do zarządzania obrazami Dockera używamy Wtyczka Gradle.

Synchronizujemy wersje naszych obrazów z wersją, która zostanie opublikowana w Dockerze. Aby zapewnić płynne działanie, wprowadziliśmy kilka regulacji:

1. Kontenery nie są przebudowywane pomiędzy środowiskiem testowym a środowiskiem produkcyjnym. Dokonaliśmy parametryzacji tak, aby ten sam kontener mógł współpracować ze wszystkimi ustawieniami, zmiennymi środowiskowymi i usługami zarówno w środowisku testowym, jak i produkcyjnym, bez przebudowy.

2. Aby zaktualizować aplikację poprzez Helm, musisz określić jej wersję. Budujemy backend, frontend i aktualizujemy aplikację – to trzy różne zadania, dlatego ważne jest, aby wszędzie używać tej samej wersji aplikacji. Do tego zadania wykorzystujemy dane z historii Git, ponieważ konfiguracja i aplikacje naszego klastra K8S znajdują się w tym samym repozytorium Git.

Wersję aplikacji pobieramy z wyników wykonania polecenia
git describe --tags --abbrev=7.

4. Automatyczne wdrażanie wszystkich zmian na środowisko testowe (UAT)

Następnym krokiem w tym skrypcie kompilacji jest automatyczna aktualizacja klastra K8S. Dzieje się tak pod warunkiem, że cała aplikacja została zbudowana, a wszystkie artefakty zostały opublikowane w rejestrze Docker. Następnie rozpoczyna się aktualizacja środowiska testowego.

Rozpocznie się aktualizacja klastra Aktualizacja hełmu. Jeśli w rezultacie coś pójdzie nie tak, jak planowano, Helm automatycznie i niezależnie cofnie wszystkie wprowadzone zmiany. Jego praca nie wymaga kontroli.

Konfigurację klastra K8S dostarczamy wraz z montażem. Dlatego kolejnym krokiem jest aktualizacja: configMaps, wdrożeń, usług, sekretów i wszelkich innych konfiguracji K8S, które zmieniliśmy.

Następnie Helm uruchamia aktualizację RollOut samej aplikacji w środowisku testowym. Przed wdrożeniem aplikacji w środowisku produkcyjnym. Dzieje się tak, aby użytkownicy mogli ręcznie przetestować funkcje biznesowe, które umieszczamy w środowisku testowym.

5. Automatyczne wdrażanie wszystkich zmian w Prod

Aby wdrożyć aktualizację na środowisko produkcyjne, wystarczy kliknąć jeden przycisk w GitLabie – a kontenery zostaną natychmiast dostarczone do środowiska produkcyjnego.

Ta sama aplikacja może pracować w różnych środowiskach – testowym i produkcyjnym – bez przebudowy. Korzystamy z tych samych artefaktów, nie zmieniając niczego w aplikacji, a parametry ustawiamy zewnętrznie.

Elastyczna parametryzacja ustawień aplikacji uzależniona jest od środowiska, w którym aplikacja będzie wykonywana. Przenieśliśmy wszystkie ustawienia środowiska na zewnątrz: wszystko jest sparametryzowane poprzez konfigurację K8S i parametry Helma. Gdy Helm wdraża zestaw w środowisku testowym, ustawienia testowe są do niego stosowane, a ustawienia produktu są stosowane do środowiska produkcyjnego.

Najtrudniejszą rzeczą było sparametryzowanie wszystkich używanych usług i zmiennych zależnych od środowiska oraz przełożenie ich na zmienne środowiskowe i opis-konfiguracje parametrów środowiskowych dla Helma.

Ustawienia aplikacji korzystają ze zmiennych środowiskowych. Ich wartości ustawiane są w kontenerach za pomocą mapy konfiguracyjnej K8S, która jest szablonowana przy użyciu szablonów Go. Na przykład ustawienie zmiennej środowiskowej na nazwę domeny można wykonać w następujący sposób:

APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}

.Wartości.global.env – w tej zmiennej przechowywana jest nazwa środowiska (prod, stage, UAT).
.Values.app.properties.app_external_domain – w tej zmiennej ustawiamy żądaną domenę w pliku .Values.yaml

Podczas aktualizacji aplikacji Helm tworzy plik configmap.yaml z szablonów i wypełnia wartość APP_EXTERNAL_DOMAIN żądaną wartością w zależności od środowiska, w którym rozpoczyna się aktualizacja aplikacji. Ta zmienna jest już ustawiona w kontenerze. Dostęp do niej można uzyskać z aplikacji, więc każde środowisko aplikacji będzie miało inną wartość tej zmiennej.

Stosunkowo niedawno w Spring Cloud pojawiła się obsługa K8S, obejmująca współpracę z configMaps: Kubernetes w wiosennej chmurze. Chociaż projekt aktywnie się rozwija i radykalnie się zmienia, nie możemy go wykorzystać w produkcji. Ale aktywnie monitorujemy jego stan i wykorzystujemy go w konfiguracjach DEV. Gdy tylko się ustabilizuje, przestaniemy używać do niego zmiennych środowiskowych.

Razem

Zatem ciągłe wdrażanie jest skonfigurowane i działa. Wszystkie aktualizacje odbywają się po jednym naciśnięciu klawisza. Dostarczanie zmian do środowiska produktu odbywa się automatycznie. I co ważne, aktualizacje nie zatrzymują systemu.

Nasze wdrożenie Continuous Deployment na platformie klienta

Plany na przyszłość: automatyczna migracja bazy danych

Pomyśleliśmy o aktualizacji bazy danych i możliwości wycofania tych zmian. Przecież jednocześnie działają dwie różne wersje aplikacji: stara działa, a nowa już działa. A starą wyłączymy dopiero wtedy, gdy będziemy pewni, że nowa wersja działa. Migracja bazy danych powinna umożliwić pracę z obiema wersjami aplikacji.

Dlatego nie możemy po prostu zmienić nazwy kolumny ani innych danych. Możemy jednak stworzyć nową kolumnę, skopiować do niej dane ze starej kolumny i napisać wyzwalacze, które przy aktualizacji danych jednocześnie skopiują i zaktualizują je w innej kolumnie. A po pomyślnym wdrożeniu nowej wersji aplikacji, po okresie wsparcia po uruchomieniu, będziemy mogli usunąć starą kolumnę i niepotrzebny wyzwalacz.

Jeżeli nowa wersja aplikacji nie działa poprawnie, możemy przywrócić poprzednią wersję, w tym poprzednią wersję bazy danych. Krótko mówiąc, nasze zmiany pozwolą Ci pracować jednocześnie z kilkoma wersjami aplikacji.

Planujemy zautomatyzować migrację bazy danych poprzez zadanie K8S, integrując je z procesem CD. I na pewno podzielimy się tym doświadczeniem na Habré.

Źródło: www.habr.com

Dodaj komentarz