procesy-w-firmie-it-ci-cd

Wyjaśniamy procesy w IT – CI/CD

Tomek-Sapalski-Picture

TOMEK SAPALSKI

Zastanawialiście się kiedyś, jak wygląda proces tworzenia aplikacji i wdrażania ich w firmie?


Zaczniemy od prostego przykładu jednoosobowej działalności gospodarczej. Właściciel napisał swoją aplikację, umieścił na serwerze webowym i udostępnił do korzystania użytkownikom. Jako programista, taki właściciel zwykle pisze swój program na laptopie, następnie kopiuje wszystkie elementy na serwer. Jeśli po jakimś czasie chciałby uaktualnić swoją aplikację – wgrywa nowszą wersję i ma nadzieję, że wszystko będzie w porządku. W przypadku, kiedy coś nie działa – po prostu usuwa ją i powraca do starej. Jak sami widzicie, na początkowym etapie proces ten jest bardzo prosty i nie wymaga żadnych skomplikowanych działań.


Jednak, jeśli weźmiemy pod uwagę firmę, w której zatrudnionych jest kilkudziesięciu programistów – taka opcja już nie wchodzi w grę. Z pomocą przychodzą określone procesy, które mają za zadanie płynnie zsynchronizować wszystkie zmiany, jakie mogą pojawić się w aplikacji. W większych firmach, pomimo że poszczególni programiści również mogą sobie pracować na swoich laptopach, kod źródłowy przechowywany jest na specjalnej platformie kontroli wersji. Najczęściej jest to Git, GitHub, GitLab lub inne podobne narzędzie. Wszystkie posiadają jedną cechę wspólną – programista musi pobrać kod źródłowy i lokalnie nanieść zmiany, a następnie wprowadzić je ponownie na platformę. W międzyczasie programiści oczywiście muszą ze sobą zsynchronizować nanoszenie zmian, tak aby nie robić tego samego w tym samym czasie (można używać np. procesu GitFlow).


Ja jednak chciałbym przejść o krok dalej i omówić inną kwestię. Kontynuując na przykładzie dużej firmy – wyobraźmy sobie sytuację, że jeden z programistów wgrał najnowszą poprawkę do aplikacji. Wówczas budujemy serwer, który ma za zadanie sprawdzić, czy została wprowadzona nowa zmiana i następnie ten kod skompilować u siebie. Jeśli to się nie uda, do programisty zostaje wysłana informację o niedziałającym kodzie. Wtenczas zadaniem programisty jest oczywiście doprowadzenie do sytuacji, w której kod faktycznie się kompiluje.


Co to jest CI? 


Przechodzimy teraz do momentu, w którym zachodzi proces CI – ang. Continous Integration, czyli ciągła integracja. CI rozpoczyna się w momencie, kiedy serwer (np. Jenkins, TeamCity, GitLab, Bamboo) wychwytuje zmiany w kodzie na repozytorium i podejmuje próbę skompilowania kodu. Jeśli kompilacja jest pomyślna, aplikacja zostaje przekierowana do kolejnego etapu produkcji.


Następnie taki skompilowany kod możemy poddać testom jednostkowym, a jeśli jeszcze będzie nam mało, to możemy przekierować aplikację do sprawdzenia firmie zewnętrznej. Istnieją podmioty specjalizujące się w wyszukiwaniu błędów bibliotek. Jeżeli korzystamy z zewnętrznych bibliotek, możemy wysłać je razem z kodem do sprawdzenia, możemy też w tym celu skorzystać z dedykowanego programu testującego, który trzeba zainstalować lub serwisu w chmurze. Dzięki temu mamy szansę sprawdzić, czy nasza biblioteka nie zawiera elementów niebezpiecznych, a także czy nie ma w niej błędów (bugów).


Jeśli wszystko przebiegnie pomyślnie, nasz serwer CI po pomyślnej kompilacji aplikacji stawia tzw. artefakty (skompilowaną wersję aplikacji) i informuje, że wersja jest gotowa do wgrania. Te artefakty mogą być również obrazami dockerowymi. W tym momencie rozpoczynamy drugą część naszego procesu.


Co to jest CD?


CD to proces, który tłumaczony jest na dwa sposoby: Continuous Delivery lub Continuous Deployment.


Zanim nasza aplikacja, już skompilowana zostanie umieszczona na docelowym środowisku, może iść na początek na tzw. środowisko testowe, czyli do testerów. W tym momencie zaczynamy naszym serwerem CI/CD wykonywać drugi proces – CD. Podczas niego, artefakty umieszczane są na różnych środowiskach tak, aby nie trzeba było powtarzać procesu CI, tylko przejść bezpośrednio do wdrażania aplikacji. 


Zazwyczaj odbywa się to w ten sposób, że ten pierwszy proces (CI) to jest tzw. build naszej aplikacji, a ten drugi to jest release/deployment. Czyli najpierw aplikację budujemy, a później ją wdrażamy na serwer. Co w przypadku, kiedy nie mamy środowiska? Możemy użyć do tego chmury i skorzystać z opcji IaC – Infrastructure as Code. Narzędzia IaC to np. Cloud Formation albo Terraform – działają w ten sposób, że skrypt buduje całą infrastrukturę, serwery, bazy danych, otwiera porty itp. – robi wszystko, żeby środowisko było przygotowane na naszą aplikację. Najlepszym sposobem, żeby wdrożyć aplikację jest korzystanie z kontenerów – bierzemy obraz dockerowy i bezpośrednio wgrywamy go do środowiska.


Następnie możemy przejść do kolejnego etapu – testów. Jedną z metod są testy automatyczne. Możemy do tego użyć aplikacji typu Selenium, która działa w ten sposób, że udaje użytkownika i po prostu klika wszędzie, gdzie to jest możliwe sprawdzając, czy funkcje działają prawidłowo. Po przejściu testów automatycznych możemy dodatkowo skierować aplikację do testerów manualnych, którzy ręcznie zweryfikują, czy wszystko działa poprawnie.


Kolejnym krokiem, zanim aplikacja trafi do ostatecznego klienta jest staging, zwany również preproduction. Na tym etapie niejako udajemy produkcję i upewniamy się, czy na pewno nie został przeoczony żaden błąd – możemy to nazwać taką ostatnią próbą generalną przed oficjalnym udostępnieniem aplikacji użytkownikom. Czy ten proces jest potrzebny, skoro aplikacja została już przetestowana? Oczywiście i są ku temu dwa główne powody. Pierwszy z nich to stress testy. Podczas nich możemy zaatakować naszą aplikację licznymi web requestami i zobaczyć jak duży ruch jest w stanie udźwignąć. Pewne jest, że będzie miała swój limit. Dzięki temu możemy zobaczyć, na jakim jest poziomie. Drugi powód to testy bezpieczeństwa (security). Podczas nich próbujemy włamać się do aplikacji na różne sposoby i sprawdzamy, czy jest to możliwe. Jeśli to się nie uda – to możemy w końcu przejść do finalnego etapu, czyli produkcji.


Do tej pory nasz Continuous Delivery i nasz Continuous Deployment to był ten sam proces – wzięliśmy nasze artefakty i przetestowaliśmy na środowisku testowym i preprodukcyjnym. Teraz mogą nastąpić dwa różne scenariusze.


Pierwszy jest taki, że klient, czy właściciel mówi do działu IT – no to wrzucajcie na produkcję, jeśli uważacie, że wszystko jest w porządku. Może jednak równie dobrze powiedzieć – nie dzisiaj, bo np. marketing robi jakieś wydarzenie i bardzo dużo ludzi będzie wchodzić na tą naszą stronę, więc byłoby kiepsko, gdyby coś niefortunnego się wydarzyło i aplikacja by padła. Pomimo, że została wielokrotnie przetestowana i sprawdzona – i dział IT jest pewien, że wszystko jest w porządku – to klient na końcu decyduje, kiedy aplikacja może zostać wypuszczona na rynek. Taką sytuację nazywamy Continuous Delivery.


A co się dzieje w przypadku Continuous Deployment? Biznes nie mówi nic. Jeśli dział IT wszystko przetestował i twierdzi, że jest w porządku to aplikacja automatycznie zostaje wrzucona na produkcję.


Co to jest Blue-Green Deployment?


Jak się zabezpieczyć w przypadku, kiedy jednak mimo wszystko, po publikacji użytkownicy zgłoszą problemy i finalnie okaże się, że nie zauważyliśmy jakiejś usterki? Możemy zrobić dwie rzeczy. Pierwsza metoda to tak zwany Blue-Green Deployment. Polega na tym, że korzystamy z dwóch identycznych infrastruktur i w przypadku błędów szybko przełączamy się między nimi. Jedną możemy nazwać umownie „blue” a drugą „green”. Blue może być naszą infrastrukturą produkcyjną, a green tą, której używaliśmy do stagingu. Dzięki temu możemy szybko przekierować użytkowników, zyskując możliwość równoległego naprawiania błędów i aktualizowania aplikacji. Po pewnym czasie, kiedy wszystko zostanie naprawione, możemy oczywiście usunąć starą wersję.


Jest jeszcze druga opcja – na którą decydują się szczególnie duże korporacje – czyli testowanie na użytkownikach. Przebiega to w ten sposób, że aplikacja posiada load balancera, który w przypadku błędów ma możliwość przekierowania części ruchu na nowe serwery. Zwykle zaczyna od niewielkiej ilości np. 2 % i sprawdza, czy nikt nie zgłasza błędów. Następnie stopniowo zwiększa się procenty przekierowanych użytkowników, aż w końcu cały ruch przekierowany jest na nową infrastrukturę produkcyjną.


Podsumowanie CI/CD


Cały proces CICD polega właśnie na tym, żeby wgrywać nowe wersje naszej aplikacji na produkcję w sposób, który jak najbardziej zmniejsza ryzyko jakichkolwiek błędów. Nie ma co ukrywać, jest to operacja na żywym organizmie, tak więc nie możemy sobie pozwolić na to, żeby tak po prostu wszystko wyłączyć. 


Nawet jeżeli używamy Blue-Green Deployment i przełączamy się z jednej ze struktury na drugą – może okazać się, że to trwa jakiś czas zanim nowa infrastruktura faktycznie wszystko przejmie. Także nadal możemy się spotkać z sytuacją, że firma – np. bank wysyła maila, w którym informuje swoich klientów na temat przerwy technicznej w godzinach od północy do 3ciej nad ranem, podczas której usługi nie będą dostępne. To właśnie wtedy odbywa się wgrywanie nowej wersji, wyłączenie starych serwerów, włączenie nowych i oczywiście sprawdzenie, czy wszystko poprawnie działa.


Mam nadzieję, że mój artykuł przybliżył Wam procesy CI/CD, i że teraz rozumiecie, jak przebiegają oraz w jaki sposób się je wykorzystuje. Jeśli będziecie mieli jakieś dodatkowe pytania to oczywiście chętnie odpowiem.