Jak działa Continuous Deployment

20 września 2021

Exanet working together blog

Continuous Deployment (CD)

Continuous Deployment (CD) jest ostatnim ogniwem realizującym cele metodologii DevOps, obejmującej m. in. jak najszybsze dostarczanie gotowego oprogramowania na serwery produkcyjne. Dzięki ciągłemu wdrażaniu (Continuous Deployment) jesteśmy w stanie usuwać błędy i dostarczać nowe funkcjonalności tak często, jak potrzebujemy, czyli na przykład kilka razy w tygodniu lub nawet kilka razy dziennie (co jest często wymogiem dla wielozespołowych i dużych organizacji).

Cele CD

Celem Continuous Deployment jest przyspieszenie wdrażania gotowego oprogramowania tak, aby nowe i poprawione funkcjonalności dotarły do klienta natychmiast po zakończeniu cyklu wytwarzania. Do osiągnięcia tego celu potrzebna jest automatyzacja powtarzalnych procesów, dzięki czemu ograniczone zostaje zapotrzebowanie na najbardziej krytyczny zasób, jakim jest czas wykwalifikowanej kadry inżynierskiej.

Przebieg procesu Continuous Deployment

Proces Continuous Deployment można podzielić na kilka etapów. Przy czym najważniejsze jest założenie, iż kolejny etap nie może się odbyć, jeśli poprzedni nie zakończył się pełnym sukcesem. Takie założenie pozwala zminimalizować ryzyko wdrożenia wadliwej aplikacji, jak również pozwala wykryć wady samego procesu na wczesnym etapie wdrażania.

Etap 0 – prace programistyczne

Na początku musi być nowa funkcjonalność lub poprawka błędu oprogramowania. Prace programistyczne prowadzone w jednej z metodologii zwinnych kończą się w momencie, gdy nowa funkcjonalność lub poprawka zostaje uznana za wykonaną.

Programiści tworząc kod zapisują swoją pracę w systemie wersjonowania kodu Git (najpopularniejszy obecnie, ale oczywiście są też inne), w gałęzi utworzonej specjalnie dla tej funkcjonalności. Po zakończeniu procesu wytwarzania kodu, wykonywany jest merge (złączenie) kodu związanego z nową funkcjonalnością z kodem oprogramowania w wersji deweloperskiej znajdującego się w gałęzi develop.

Sposób złączenia nie jest tutaj istotny, ważne aby dodany kod był wcześniej w jakiś sposób sprawdzony i zweryfikowany, np. z użyciem narzędzi Continuous Integration lub w procesie Code Review. W momencie gdy w gałęzi develop pojawia się nowy kod, rozpoczyna się faktyczny proces Continuous Deployment.

Exanet desk computer blog

Etap 1 – ciągłe wdrażanie wersji deweloperskiej

W pierwszym etapie system Continuous Deployment w sposób automatyczny wdroży wersję deweloperską aplikacji na specjalnie przygotowanym do tego celu serwerze deweloperskim. W tym miejscu ważne jest:

  •   aby wdrożenie odbywało się jak najszybciej, najlepiej natychmiast po złączeniu (merge) kodu nowej funkcjonalności z gałęzią develop,
  •   aby wdrożenie odbywało się automatycznie i nie wpływało na proces programowania,
  •   aby wdrożone oprogramowanie było dostępne dla deweloperów jak i dla testerów.

Zaznaczyliśmy wyżej, że wdrożenie na serwer deweloperski powinno odbywać się automatycznie. W tym celu potrzebne jest użycie systemu Continuous Deployment, który pozwala wykonywać automatyczne wdrożenia w odpowiedzi na zdarzenie, jakim jest pojawienie się nowego kodu w repozytorium kodu źródłowego. Najlepiej użyć do tego systemu Jenkins (lub innego systemu Continuous Integration).

Na tym etapie Jenkins w sposób ciągły monitoruje gałąź develop pod kątem nowych zmian, lub oczekuje wywołania odpowiedniego webhook przez system wersjonowania kodu źródłowego. W momencie wystąpienia powyższego zdarzenia, wywoływany jest proces Continuous Deployment na serwer deweloperski. W tym procesie przeprowadzone zostaną przez system Jenkins następujące kroki:

  •   Wybrany zostanie Jenkins Worker, czyli maszyna na której zostanie przeprowadzony cały proces tego etapu.
  •   Pobrany zostanie kod źródłowy gałęzi develop do katalogu roboczego maszyny Jenkins Worker.
  •   Pobrane zostaną wszystkie zależności i biblioteki potrzebne do zbudowania aplikacji.
  •   Przeprowadzony zostanie proces budowania aplikacji.
  •   Jenkins Worker połączy się z serwerem deweloperskim, np. za pomocą SSH lub FTP.
  •   Zbudowana aplikacja zostanie przekazana na serwer deweloperski.
  •   Jeśli trzeba zaktualizowana zostanie deweloperska baza danych tak, aby była zgodna z nową wersją oprogramowania i zawierała nowe dane testowe.
  •   Nastąpi przełączenie aplikacji na serwerze deweloperskim ze starej na nową, np. zmieniając konfigurację serwera HTTP lub podmieniając katalog publiczny.

Po zakończeniu procesu, zespół deweloperski i testerów posiada dostęp do jednolitego środowiska testowego.

code lines displayed on a macbook

Etap 2 – przygotowanie wydania nowej wersji oprogramowania

Po zakończeniu wytwarzania i testowania grup funkcjonalności i poprawek, które mają znaleźć się w najnowszej wersji oprogramowania, następuje merge (złączenie) gałęzi develop z gałęzią master (main). Złączenie to powinno zostać wykonane za pomocą Pull Request (Merge Request), aby można było wykonać solidne Code Review i przeprowadzić automatyczne Continuous Integration.

Gdy złączenie (merge) do gałęzi master (main) zostanie zaakceptowanie i zrealizowane, w systemie Git pojawi się nowa wersja naszej aplikacji gotowa do wdrożenia.

Etap 3 – wdrożenie na serwer staging

W tym etapie Jenkins w sposób ciągły monitoruje gałąź master (main) pod kątem nowych zmian lub oczekuje wywołania odpowiedniego webhook przez system wersjonowania kodu źródłowego. W momencie wystąpienia powyższego zdarzenia, wywoływany jest proces Continuous Deployment na serwer staging.

W tym procesie przeprowadzone zostaną przez system Jenkins te same kroki jak w etapie 1, przy czym serwer staging powinien jak najbardziej odwzorowywać środowisko produkcyjne do tego stopnia, że przed przeprowadzeniem wdrożenia, powinna znajdować się na nim ta sama wersja oprogramowania, która aktualnie pracuje w środowisku produkcyjnym.

W wielu przypadkach krokiem poprzedzającym Continuous Deployment na serwer staging jest zsynchronizowanie danych tego serwera z danymi produkcyjnymi, np. kopiowanie bazy danych. Z drugiej strony w wielu przypadkach, takie działanie jest niemożliwe, wtedy dane staging powinny w maksymalnym stopniu przypominać dane produkcyjne.

Po udanym procesie wdrożenia na serwer staging, zespoły testerów i project managerów mają dostęp do oprogramowania, które w maksymalny sposób odwzorowuje to, co za chwilę zostanie wdrożone na serwerach produkcyjnych i przekazane klientowi końcowemu. W tym momencie dostępna jest ostatnia szansa, aby wprowadzane zmiany przetestować i podjąć decyzję o ewentualnym wstrzymaniu wdrożenia.

Tylko i wyłącznie w przypadku poprawnego wdrożenia na serwerze staging i zaakceptowania wydania nowej wersji przez osobę decyzyjną, proces Continuous Deployment przechodzi do ostatniego etapu.

Etap 4 – wdrożenie produkcyjne

Ten etap jako jedyny powinien być wyzwalany ręcznie przez osobę, w której kompetencjach jest wdrożenie aplikacji na serwerze produkcyjnym. W tym etapie system Jenkins w sposób ciągły monitoruje wynik Continuous Deployment na serwer staging.

W przypadku wystąpienia nowego wdrożenia na serwerze staging, które zakończyło się powodzeniem, odblokowana zostaje możliwość uruchomienia Continuous Deployment na serwer produkcyjny.

System Jenkins oczekuje na podjęcie decyzji przez osobę do tego uprawnioną, czy wykonać wdrożenie, czy też anulować wdrożenie. Decyzja zostaje potwierdzona za pomocą wyboru odpowiedniego przycisku w panelu kontrolnym. Wtedy dopiero system Jenkins przechodzi do realizacji Continuous Deployment na serwer produkcyjny.

W tym etapie system Jenkins ponownie wykonuje kroki:

  •   Wybrany zostanie Jenkins Worker, czyli maszyna na której zostanie przeprowadzony cały proces tego etapu.
  •   Pobrany zostanie kod źródłowy gałęzi develop do katalogu roboczego maszyny Jenkins Worker.
  •   Pobrane zostaną wszystkie zależności i biblioteki potrzebne do zbudowania aplikacji.
  •   Przeprowadzony zostanie proces budowania aplikacji.
  •   Jenkins Worker połączy się z serwerem deweloperskim, np. za pomocą SSH lub FTP.
  •   Zbudowana aplikacja zostanie przekazana na serwer deweloperski.
  •   Jeśli trzeba, zaktualizowana zostanie deweloperska baza danych tak, aby była zgodna z nową wersją oprogramowania.
  •   Nastąpi przełączenie aplikacji na serwerze deweloperskim ze starej na nową, np. zmieniając konfigurację serwera HTTP lub podmieniając katalog publiczny.
  •   Dokonana zostanie weryfikacja poprawności wdrożenia, np. poprzez wywołanie zdefiniowanych adresów URL i sprawdzenie odpowiedzi, lub wykonanie nieinwazyjnych testów, np. za pomocą narzędzia Selenium.

Po udanym wykonaniu wdrożenia na serwer produkcyjny proces się kończy. Jeśli proces w którymś kroku nie powiódł się, należy przeprowadzić rollback, czyli przywrócenie oprogramowania do poprzedniego stanu. Ważne jest, aby mieć gotowy scenariusz na okoliczność pojawienia się konieczności szybkiego wykonania rollback. Rollback opisany jest w następnym etapie.

Microsoft laptop on a desk

Etap 5 – jeśli coś pójdzie niewłaściwie

W IT zdarzają się sytuacje, że coś wychodzi nie do końca po myśli wykonawcy. Jest to w pewnym stopniu wpisane w specyfikę branży i nie koniecznie wynika z braku kompetencji czy niestaranności inżynierów. Należy być zatem przygotowanym, szczególnie jeśli do czynienia mamy z procesami wysoce skomplikowanymi, a do tego korzystającymi z automatyzacji, tak jak w przypadku Continuous Deployment. Dostępne są możliwości, by przygotować się na ewentualne problemy.

Jeśli coś pójdzie nie tak w trakcie opisanych wyżej czterech etapów procesu, w 99% przypadków jesteśmy w stanie wykryć problem przed wdrożeniem produkcyjnym, dzięki zastosowaniu dwóch poprzedzających wdrożeń na serwery deweloperski i staging. Jeśli mimo to Continuous Deployment na serwer produkcyjny zakończy się niepowodzeniem, należy mieć opracowany scenariusz rollback, czyli jak najszybszego przywrócenia poprzedniej wersji oprogramowania. Scenariusz ten może być realizowany automatycznie w momencie wykrycia błędu wdrożenia przez system Jenkins lub może zostać wykonany ręcznie przez inżyniera.

W obu przypadkach scenariusz powinien obejmować następujące elementy:

  •   Wykonanie kopii zapasowej przed wykonaniem wdrożenia.
  •   Podjęcie decyzji dotyczącej przywracanych elementów, na podstawie informacji z systemu Jenkins, co zostało wykonane i na którym etapie doszło do niepowodzenia.
  •   Kolejne przywracanie poszczególnych elementów do stanu sprzed wdrożenia, najczęściej w odwrotnej kolejności niż wdrożenie.
  •   Weryfikacja poprawności wdrożenia, np. poprzez wywołanie zdefiniowanych adresów URL i sprawdzenie odpowiedzi lub wykonanie nieinwazyjnych testów, np. za pomocą narzędzia Selenium, tak jak przy udanym wdrożeniu.

Złożoność procesu Continuous Deployment

Jak pewnie można zauważyć, proces Continuous Deployment posiada pewien stopień złożoności. Wymaga m.in. zapewnienia puli zasobów serwerowych, tym większej im większe oprogramowanie. Często wymagać też będzie wprowadzenia zmiany w sposobie pracy programistów i testerów, która obejmować będzie wyraźne odseparowanie kodu w trakcie wytwarzania (Work In Progress) od kodu zrealizowanego (gotowego do testowania), od kodu produkcyjnego oznaczonego konkretną wersją (“nietykalnego”).

Kolejną ważną sprawą jest opracowanie sposobu wdrażania oprogramowania, który będzie możliwy do automatyzacji za pomocą takich systemów Continuous Deployment jak Jenkins, czyli maksymalnie powtarzalny oraz wolny od elementów wymagających podejmowania złożonych decyzji.

Na koniec należy opracować solidny scenariusz Rollback na wypadek niepowodzenia wdrożenia produkcyjnego.

Celem jest implementacja procesu, który umożliwia szybie (ciągłe) wdrażanie nowych wersji aplikacji z minimalnym udziałem kadry inżynierskiej. W idealnych warunkach praca zespołu ogranicza się do:

  •   Przeglądów kodu.
  •   Testów manualnych.
  •   Akceptacji Pull Request (Merge Request).
  •   Ostatecznej akceptacji wdrożenia produkcyjnego.

Należy tutaj zwrócić uwagę, że powyższe czynności, w mniejszym lub większym stopniu, powinny być wykonywane w każdym procesie wytwarzania oprogramowania, nawet jeśli nie korzystamy jeszcze z Continuous Deployment, jako część procesu zapewnienia jakości.

Exanet begin cooperation blog