Transkrypcja
Wprowadzenie i zaproszenie
Cześć, Michał.
Cześć, Wojtek.
Witamy w kolejnym odcinku. Jak zwykle na początku od razu powiemy zaproszenie, czyli zapraszamy do śledzenia naszego kanału i komentowania, lajkowania, subskrybowania. I również komentowania tematów, które chcielibyście może posłuchać – technicznych zarówno, ale też i biznesowych, bo postaramy się z Michałem tutaj opowiedzieć o różnych spektrach naszej pracy. Także zachęcamy. A dzisiaj? O czym dzisiaj Michał będzie?
Dzisiaj… o tych płytach CD.
Płytach CD?
To chyba nie było takiego tematu.
Nie, no będzie o płytach CD oraz o płytach CI, a dokładnie CI/CD, taki nowy standard, czyli Continuous Integration i Continuous Delivery.
Ale płyty CD się pojawią i jeszcze dyskietki się pojawią.
Będą miały występ gościnny.
Będą miały. To znaczy, nie mamy przy sobie żadnej, ale wspomnimy. Nie mamy nawet czytników, żebym taką odtworzyć.
Czekaj, czekaj. Ja mam. Jeszcze mam…
…osobny, w sensie na USB, ja też mam.
Aha, nie, osobny, nie, mam w kompie.
To masz starego kompa.
Mam starego kompa. Wcale się tego nie wstydzę. Ma takie dwa, nie, jeden ma, przepraszam. Jeden, ale dwa napędy jeszcze.
Może jeszcze masz nagrywarkę?
Nagrywarkę mam. Nawet dwie. Nie, czekaj, mam jedną. Dobra, nie pamiętam jaką mam konfigurację. Na pewno jedno to jest nagrywarka DVD, a drugie to może być nagrywarka CD. O, tak jakoś może być.
Ale wracając do tematu.
Wracając.
Po co to – te płyty CD były? Po co w ogóle cały ten proces?
Dawne praktyki dostarczania oprogramowania
Jak było w umowie napisane, że komponenty oprogramowania, które tworzymy, mamy dostarczać zamawiającemu razem z protokołem odbioru na nośniku CD lub DVD, to trzeba było mieć. I w życiu tego nie zrobiłem nigdy. Nie nagrałem.
Może jeszcze, widzisz, komuś płyty CD z kodem dostarczyłeś. Ja akurat nie musiałem tego dostarczać, moich artefaktów. Ale tak, na pewno miałem okazję robić ręcznie część z tych rzeczy. Natomiast…
To zaczynamy, jak to drzewiej bywało.
Czyli z procesem dostarczania tego, co robimy na co dzień.
To co robimy na co dzień, nie robimy.
Co my właściwie robimy na co dzień?
Mówimy tu o oprogramowaniu. Uściślijmy może, że chodzi nam o oprogramowanie, dostarczanie pewnych rzeczy. I właściwie tworzymy te nasze aplikacje, nasze systemy po to, żeby ktoś mógł z nich skorzystać i po to, żeby ktoś je używał. A żeby ktoś mógł je używać, to wiadomo, musimy przejść cały proces od zbudowania, poprzez jakieś przetestowanie – czy to manualne, czy automatyczne – na wdrożeniu na dane środowisko skończywszy. Cały ten proces drzewiej, jak to wspomniałeś, jak on wyglądał?
Tak, był sobie serwer gdzieś tam. Gdzieś tam sobie był taki serwer, na niego się wbijało. No i trzeba było mieć artefakt. Teraz pytanie, i tam ręcznie i tam go ręcznie… I na przykład artefakt zsyłało się mailem. Bywały takie przypadki. No wiadomo, na tej płycie mógł sobie artefakt powędrować, tak? I wtedy z płyty go musiał taki admin wrzucić tam. Admin, DevOps… jeszcze wtedy DevOpsów nie było. To wtedy był taki administrator, czego tam był administrator?
Serwera.
Serwera systemów, sieci, cokolwiek. Tak, on brał taki artefakt i najczęściej to wiedział chyba, co z nim zrobić, a czasem nie wiedział, więc musiał się dopytać i potrafił nawet zadzwonić gdzieś tam i pytać o szczegóły, co tam, jak tam.
A jak już miał taki artefakt, skądś go tam pobrał… Wiadomo, że w bardziej ogarniętych miejscówkach to tam z jakiegoś, no właśnie też serwera, w sensie jakiegoś takiego składowiska, dzisiaj byśmy to jakimś storage’em nazwali, jakimś share’em, udziałem sieciowym, czy czymś tam. Zresztą to już się w tamtych czasach też udziałem sieciowym potrafiło nazywać, więc na przykład tam można było wrzucić takiego zbudowanego jara. No i sobie go brano, konfigurowano i co robiono? Wdrażano.
Czyli kopiowano do folderu webapp na serwerze, albo ufając oczywiście, że ten skopiowany z tego udziału to jest ten, co trzeba, właściwy, nie mając żadnej pewności, żadnego nawet odcisku, hasza, nic. Po prostu brano, ufano, że to jest dobry artefakt.
No bo co, czemu miałby być niedobry?
No właśnie, przecież nikt chyba nie czyha tutaj na nasze artefakty.
Musiałby wiedzieć, gdzie czyhać.
Tak, ja muszę przyznać, że z pierwszej ręki, czy ten proces dany mi było obserwować, bo w swojej pierwszej pracy, poza takimi obowiązkami wytwarzania kodu jako junior, byłem właśnie takim pipeline’em budującym. I właśnie w dużej mierze był to ręczny proces i do tego stopnia ręczny, że na moją skrzynkę mailową spływały komponenty z różnych zespołów, które ja z tej skrzynki wrzucałem do katalogu budującego, w którym odpalałem wielusetlinijkowy skrypt antowy, który sobie coś tam budował, brał te wszystkie artefakty, tworzył z tego wielkiego eara.
Ja ten skrypt chyba później przerabiałem kiedyś.
Bardzo możliwe, tak, tak. Żeby nadało się do użycia. Później, po wielu latach, ten projekt gdzieś tam do nas wrócił. Natomiast ten proces wymagał też… No był już ten skrypt budujący, więc przynajmniej nie musiałem ręcznie wszystkiego kopiować, ale musiałem te moduły z tego maila pokopiować, których było kilkanaście. Musiałem oczywiście też poustawiać pewne zmienne, czy to nazwy aplikacji, jakieś tam nazwy serwera, cokolwiek, bo tego oczywiście nikt nie pomyślał, żeby to zautomatyzować. Na co tak samo?
Więc takich ręcznych… Wiedziałeś jak?
No tak, ja wiedziałem. Chyba że zapominałem i czasami tego nie robiłem. Przecież po co spisywać sobie te trzy ręczne kroki? Przecież zawsze je zapamiętam. Jak się okazało – nie zawsze, więc czasami po odróżnieniu okazało się, że aplikacja nie łączy się, ponieważ był zły adres, ponieważ powody…
Wyzwania ręcznego procesu budowania i wdrażania
Ale jak już bezpiecznie zbudowałem sobie ten artefakt, tego EARa… Czasami trzeba było podmienić kodową klasę w pliku jar, bo na przykład coś nie działało, więc sobie lokalnie budowałem dany projekt i tylko jedną klasę podmieniałem w tym jarze.
A tego rozpakowywałeś w locie, tak?
Tak, albo po prostu go tam wrzucałem, więc wiadomo, takie standardowe praktyki budujące. Jar to jest zip, więc co za problem go rozpakować? Nie rozpakowujemy, wrzucamy klasę, zamykamy i do widzenia.
Jak już zbudowałem tego wspaniałego EARa, wrzucałem go na FTPa i najczęściej – bo ten FTP to jeszcze nie było miejsca do wzrżenia – najczęściej dawałem znać zespołowi z Łodzi, bo to akurat byli chłopaki z Łodzi, z miasta Łódź. No i też najczęściej nie wysyłało się maila, bo to wiadomo, kto tam maila sprawdza regularnie, więc chwytałem za słuchawkę i dzwoniłem i mówiłem: „Halo, proszę deploya”.
No i tak wyglądał deploy tak naprawdę i oni tam już to wrzucali na…
Na właściwy serwer. No i cały proces tak wyglądał. Więc był wybitnie manualny, błędogenny, no i tak naprawdę dość, no taki…
No ale teraz to masz skilla, bo teraz potrafisz. Musiałeś to wszystko zrobić ręcznie, więc teraz to ustawienie jakiejś pipeline’y gdzieś tam, to dla ciebie jest taka…
No tak, wtedy wiadomo. Czyli można by zaryzykować, że każdy junior powinien taki proces przejść.
Mógłby przejść, żeby wiedział i docenił to, co teraz ma, oczywiście. Żeby wiedział, czego nie robić.
Ale właśnie, tak, jak ktoś to przeszedł, to zupełnie inaczej, można powiedzieć, patrzy na obecne narzędzia i ogólnie sposób dostarczania, no bo też czasami łatwo stracić tak naprawdę, że tak powiem, perspektywę i wziąć za pewnik, co się właściwie dzieje w momencie, kiedy my ten nasz kod pushujemy i ile rzeczy tak naprawdę musi się wykonać, żeby on trafił w ogóle gdziekolwiek.
Pomijając już taką samą systemy kontroli wersji, które też jeszcze – może nie tak niedawno, ale kilkanaście, dziesiąt, powiedzmy, dwadzieścia lat temu – to już były bardzo popularne. Ale to były czasy nie tak dawno, kiedy wcale to nie było oczywiste. I ten kod też gdzieś tam się kopiowało jako zwykłe foldery i gdzieś tam ręcznie, gdzieś tam się merge’owało ten kod.
Tak, tak. Takie opowieści też krążyły.
Tak, może nam to już nie było dane, aż tak.
No mi nie było, bo ja już zacząłem od Subversion.
Tak, tak. No ja również. Znaczy, było tam później taki regres do tego, jak on się CVS nazywał, tak?
CVS, tak, tak. To po prostu po Subversion to był straszny dramat, ale jak już się okazało, że Git jest na tym świecie…
To jest Git.
To już było Git. No właśnie, ale trzeba było przejść tę drogę zanim twórcy albo branża, można powiedzieć, doceniła fakt, że te procesy, które są powtarzalne, dla człowieka są takie dość nudne i przez to, że są nudne, właśnie łatwo popełnić błąd. Łatwo zapomnieć nam po prostu cokolwiek.
Dokładnie, dokładnie.
Ryzyko polegania na „magikach” i silosach wiedzy
Pomijając, że najczęściej w takich procesach ręcznych w firmach bardzo często zajmowała się z tym ograniczona grupa osób, często właściwie jedna. I nieraz w firmie jest taki magik, który…
Wszystko wie.
Wszystko wie. Ta osoba wie, jak budować aplikacje, zna wszystkie sztuczki, wie, co trzeba ustawić. Tylko najgorzej, jak gdzieś się zniknie.
No właśnie. I to już nawet nie problem to, że zniknie to raz, bo może odejść, może wpaść pod autobus, może cokolwiek się z nią stać, ale najczęściej równie dobrze może jej laptop zniknąć i cała wiedza albo większość tej wiedzy razem z tym laptopem, więc to też nie jest takie…
Wtedy to były takie duże klocki.
No wtedy może tak, ale taki klocek też potrafi się spalić, dysk potrafi się zepsuć, więc jest to duże ryzyko, jakby nie patrzeć. I to jest zaskakujące, jak często duże organizacje polegały na tym, na fakcie, że dostarczanie jakiejś tam ciągłej ich oprogramowania było naprawdę bazowane na bardzo wątłym założeniu, że dana osoba albo dany komputer będzie działać i to wszystko będzie się spinać.
Dostarczanie to było, ale czy ciągłe? To tutaj można by domniemywać, że nie ciągłe.
W ówczesnym rozumieniu to pewnie, no to zawsze jest troszkę dyskretne, ale w ówczesnym rozumieniu to pewnie, pewnie powiedzmy było to w miarę ciągłe, ale oczywiście nie w takim szerszym rozumieniu.
No to ta ciągłość jest taka, co trzy miesiące raz, czy raz, a później jakieś tam patche. Jest przerwa i można od nowa ten cały sposób wymyślić.
No właśnie, chyba dlatego właśnie przyspieszenie tego procesu dostarczania oprogramowania i jakby realizowania kolejnych wersji pociągnęło za sobą też potrzebę właśnie dopracowania tych narzędzi i w ogóle całego procesu, który za tym stoi. No bo masz rację, no jeśli to robimy raz na trzy miesiące, raz na pół roku, no to faktycznie może zbudowanie tego ręcznie i skopiowanie tego do folderu, no nie jest aż tak straszne kontra zbudowanie…
Pełnych narzędzi, które przekładają, że mamy te narzędzia.
Też nie powiedziałbym, że nie jest tak straszne, bo raz na pół roku musisz znowu przypominać, co tam się robi. Ewentualnie sięgnąć do scenariusza tego, no ale jak już masz spisany scenariusz, to czemu on nie jest w formie skryptu? To byłaby to już odpowiedź gotowa na pytanie: skryptować czy nie skryptować. Przepraszam.
Pewnie dlatego, że były takie momenty nieciągłości w tym skrypcie, bo nie wszystkie rzeczy dało się jednak tym skryptem załatwić.
Ale to można mieć ileś ciągłych skryptów w nieciągłym procesie, nadzorowanym z góry przez tego magika, na przykład.
Magik musiałby odpalić po prostu kilka skryptów, zamiast jeden jakiś gruby.
Automatyzacja a narzędzia kontroli wersji
Tylko że wtedy to się zaczyna coraz bardziej niewiele różnić od takiego ręcznego podejścia, bo jeśli mamy odpalić skrypty, które robią tylko kopiowanie, to równie dobrze możemy to skopiować ręcznie. Ale masz rację, rzeczywiście to skryptowanie było gdzieś tam na bakier, ale brak narzędzi, brak też takich ułatwień, które mamy teraz, chociażby nawet w samym procesie integracji, budowania i odpalania testów.
Wsparcia platformy, bo jak na przykład trzeba było to robić na Windowsach drzewiej 20 lat temu, takich starych Windowsach, to powodzenia ze skryptowaniem. Dopiero takie skryptowanie z prawdziwego zdarzenia to jest od czasu, kiedy już mamy Linux blisko, a jeszcze tam gdzieś po drodze się na Windowsach pojawił ten PowerShell.
Ale skrypty w BAT-cie też były bardzo fajne, więc…
No były. Wiesz, tak koślawo pisało.
No tak, no były dość takie nieprzyjemne, takie toporne. Były troszkę toporne, to prawda. No nie było tam wszystkich takich udogodnień jak w POSIX-ie, już były od lat 70. czy tam kiedy? Czy od 80.?
No właśnie, ale wracamy teraz do czasów nam współczesnych bardziej. I tego tutaj całego dobrodziejstwa, toolingu i narzędzi, które mamy.
I tak naprawdę Continuous Integration to już chyba dla wszystkich jest rzecz taka oczywista. Dzielimy się tym kodem, integrujemy go regularnie. Historie nasze robimy w branchach, mamy jakiś tam główny branch, który wdrażamy. To już jest coś, co chyba nie trzeba w większości ludzi tłumaczyć.
I tak naprawdę… to są takie pewne oczywiste rzeczy, nawet jeśli nie wychodzimy, można powiedzieć, krok dalej, czyli to jest tylko te nasze integration, a już samo jakby dostarczanie robimy ręcznie, to to już jest przynajmniej dobry krok do tego, żeby zautomatyzować tą pierwszą część tego procesu ogólnego dostarczania.
No bo jakby nie patrzeć, no w przeszłości też to różnie bywało. Różne na to modele. Czytam ostatnio Uncle Boba, Roberta C. Martina i jego „Clean Architecture”.
A tam on przytacza takie drzewiej. I on tam ma wiele takich opowieści z mchu i paproci, jak to było te 40 lat temu.
To miał lepiej niż my mieliśmy, bo my tu tylko tak niecałe 20.
Tak, tak, tak. I właśnie Wuja Bob przytacza taki pattern takiego cotygodniowego merge’owania projektów na zasadzie, że od poniedziałku do czwartku zespoły pracują nad swoimi feature’ami i w piątek robimy wielkie merge’owanie.
Tylko bez jeszcze kontroli wersji, tak?
Nie, to już w sumie nawet może z kontrolą wersji było. Przytacza to nie to jako ciekawostkę, nie to jako wzorzec, który warto zastosować. Tak troszkę, troszkę tak nie do końca miałem wrażenie, po której, że tak powiem, stronie stoi odnośnie stosowania tego podejścia.
No bo naocznie oczywistym jest, że może go na wspominki wziął.
Że może go na wspominki wziął. No bo jednak trudno, żeby, żeby, żeby mieć takie podejście, że merge’ujemy tylko w jeden dzień w tygodniu, jakiś tam wyznaczony, a wcześniej kisimy ten nasz kod.
Chociaż bywaliśmy w projekcie, w którym się merge’owało w jakiś jeden dzień w miesiącu.
Tak, no właśnie to jest. Samo merge’owanie to jest jedna rzecz. Pytanie właśnie, na ile nasz kod jest gotowy, ale to bardziej też chodzi o nawet takie podgonienie z funkcjonalnościami z tego głównego brancha do naszego chociażby. Czyli mamy nasz kod, możemy go tam sobie nawet ten tydzień czy dwa gdzieś tam przykisić, bo nie jesteśmy jeszcze gotowi go wydać, ale przynajmniej wiemy, że on jest up to date z główną gałęzią tego kodu.
Zalety Git i nowoczesnych narzędzi CI/CD
Ale teraz spaniały jesteś, bo na Gicie siedzisz. A jak siedziało się na takim Subversion i to jeszcze w jakichś dziwactwach takich, że bałeś się w ogóle cokolwiek zaciągnąć, bo się projekt rozsypywał i trzeba było wchodzić w XML-a, który tam opisywał workspace i coś tam poprawiać.
Oczywiście, że tak. No to wtedy wiadomo, że w piątek to najlepiej w co drugi jeszcze.
Tylko jakby nie patrzeć, to jest tylko odwlekanie tego, co nieuniknione. Czy takie merge’owanie regularne każdego ranka przed naszym tutaj zaczęciem pracy, mimo że to będzie troszkę każdego ranka bolało, czy jest jednak lepsze od takiego wielkiego merge’owania w piątek, kiedy wiadomo, że już tego kodu się nazbierało? No i oczywistą sprawą jest, że lepiej robić to jak najczęściej.
No i całe narzędzia Code Integration i obecne GitLaby, GitHuby i tutaj nasze narzędzia wybitnie nam w tym pomagają. I tutaj nawet nie zastanawiamy się czasami nad tym procesem, tylko robimy go niejako automatycznie. Bierzemy sobie nową wersję, merge’ujemy sobie nasze branche i lecimy dalej. Dużo łatwiej jest to zrobić na Gicie, który to wspiera od samego początku. Znaczy, który w ogóle chyba powstawał, bo wydaje mi się, że Linusowi to przyświecało, że właśnie ówczesne systemy kontroli wersji – przynajmniej te takie będące w zasięgu społeczeństwa, nie mówię o jakichś takich może bardziej zaawansowanych, nie wiem czy wtedy były w ogóle, bo z Gita obok Gita jest jeszcze kilka innych, których akurat nie miałem przyjemności nigdy przetestować, mniej lub bardziej płatnych, które mają podobną filozofię do Gita – ale w czasach, kiedy Git powstawał, to chyba nie było tak różowo i tam wtedy szczytem techniki mogło być takie Subversion. Znaczy na pewno było najbardziej popularne chyba z tego, co co pamiętam, bo właśnie nasz projekt pierwszy, do którego zostałem zaproszony i który koncertowo zepsułem na dzień dobry, ale naprawiliśmy to, właśnie był na Subversion. Tam się trzeba było nauczyć tego Subversion, bo tam na studiach tego nie uczą nas.
To komu nie wiadomo, to są ważniejsze rzeczy, takie jak napisanie klas tam wielokrotnie podzieliczonych i zrobienie z tego całego zwierzyńca albo z ich shape. No ale w każdym razie, ten taki Git, to on ładnie ułatwia. Dużo prościej się zaciąga takiego developa do siebie, czy tam jakiegoś innego głównego, i ewentualnie jakieś małe konflikty rozwiązuje, gdzie on i tak zapewnia merge’owanie większości. No wiele rzeczy możemy wręcz z poziomu samego Gita gdzieś tam z badźować na naszym magic queście, jak wiemy, że jesteśmy ileś tam commitów do tyłu, to bardzo często udeśniam to wręcz z poziomu, że tak powiem tutaj przeglądarki i platformy to zrobić, więc rzeczywiście to na pewno jest niesamowita pomoc.
Na przykład w IDE i pewnie w innych narzędziach. Tutaj nie polecam wsparcia w Visual Studio, bo tam to trzeba naprawdę chyba było książkę przeczytać, co przyświecało autorom tego interfejsu użytkownika, bo jakaś to w ogóle do niczego nie było podobne.
Tutaj o narzędziach, to rzeczywiście warto to wspomnieć, że to nie jest tylko i wyłącznie sam Git, ale czyli te narzędzia też wkoło niego, czyli właśnie takie główne IDE chociażby.
To grubsze rzeczy, to tak mogą trochę włosy zjeżyć na głowie, jak tam to coś tam ponaprawiać, kiedy się coś grubo rypnie.
Jeśli mocno się skonfliktujemy i sobie ponadpisujemy, to zawsze może być problem. Ale taka IDE, właśnie, często przychodzi z pomocą, nie? I po prostu zrobi te wszystkie dziwne rzeczy.
I później będą sobie w logu podejrzeć, co ona to właściwie na tym Gicie porobiła. To połowy ja koment w ogóle nie znam.
Ale właśnie, to jest też zaleta, że nie musisz ich tam znać, bo są wykonywane za ciebie. Czy ciebie jako programistę interesuje dokładna litania, komend, która tam będzie wykonana? Ciebie interesuje rezultat, czyli chcesz po prostu mieć najświeższą wersję tego kodu zmergowaną z najświeższą wersją w głównej gałęzi i tyle.
A czy po drodze to będzie merge, czy to będzie rebase, czy to będzie jakiś jeszcze inny sposób? Dopóki nie nadpiszemy komuś jakiś zmian, no to i da się to zrobić automatycznie. Niech rzeczywiście tą pracę odwalają za nas narzędzia.
No dokładnie. No i później mamy to już wrzucone i wracamy do naszego tego potoku. No bo wrzucić do repka to jest super, ale dobrze jakby tam coś tam się z tym dalej działo.
Proces Continuous Delivery
No właśnie i tutaj jest dalsza część całego procesu, czyli tak zwane Continuous Delivery, czy jeszcze chcesz krok wcześniej?
Krok wcześniej, to tak pomiędzy tym Delivery. W sensie pomiędzy wrzuceniem a dostaniem zielonego światła na to nasze Delivery. To jeszcze mamy takie kroki jak na przykład zbudowanie tego i to nawet wielokrotne. I tutaj może przynajmniej na początku nie dla wszystkich jest oczywistością, że aplikacja może się wielokrotnie zbudować.
Bo na przykład pierwszy build jest nieoptymalizowany produkcyjnie, dlatego żeby można było po prostu zbudować go sobie pod testy. Natomiast już build produkcyjny leci sobie po przetestowaniu funkcjonalności, ale już może być oflagowany tak, żeby tam jakieś optymalizacje poszły. Co na przykład uniemożliwiłoby potencjalnie wykonanie niektórych testów być może.
Dlatego się te dwa koncepty rozdzielone.
Tak jak już mamy wszystkie testy odpalane, łącznie z jakimiś integracyjnymi. No to już wtedy wrzucamy wszystko do jednego worka. I to jest ten etap, kiedy ty do tego katalogu sobie to wrzucałeś, odpalałeś ten wielki skrypt antowy. No to ten CI, taki CI Wojtas odpala tam sobie ten skrypt swój, już wtedy nie antowy, tylko, no najczęściej teraz jest to opisane w składni jakiejś deklaratywnej danego środowiska, na którym budujemy, nie? Jeżeli to będzie GitLab, GitHub ma swoje jakieś tam Azure, AWS i co tam tylko mamy.
Tak, właśnie to jest też trochę może niedoceniana zaleta takiej – to nie jest do końca Infrastructure as Code, ale powiedzmy, że pipeline’y nasze budujące mogą być częścią infrastruktury. Ale faktycznie dzięki temu osiągamy tą powtarzalność, bo mamy ten nasz proces budowania w postaci deklaratywnych komend, instrukcji. I to nie tylko proces budowania aplikacji jako takiej, czyli że budujemy Gradle, npm, czy cokolwiek techniczne budowania, ale budowania faktycznie łącznie z testami, łącznie z wypchaniem tego artefaktu gdzieś dalej, czyli tak zwane lany, całe. Tak, dokładnie, te pasy, tak, po których to się wszystko porusza.
Tak i kombinację zwaną pipeline’u. Pipeline’u to nazwę lubię najbardziej. Piękne spostrzeganie. I tak naprawdę mając to w postaci kodu, po pierwsze, możemy w ogóle śledzić zmiany w takim skrypcie, więc możemy sobie jasno zobaczyć co się działo, może coś trzeba poprawić. No i mamy też pełną powtarzalność. Nie polegamy na czynniku ludzkim, który musi zapamiętać listę kroków.
Jeszcze gdzieś tam troszkę pewnie różną per środowisko, troszkę różną per jakiś tam właśnie mówisz, deweloperski build albo produkcyjny. Wszystko mamy to gdzieś zakodowane, można powiedzieć, no i dzięki temu nie zginie. Dopóki nasz GitHub czy jakiś inny tool, który tym zarządza, stoi, no to będziemy mieli do tego dostęp. Więc tutaj nie ma jakby tego ryzyka, że jedna osoba wie wszystko i jedna osoba znika z organizacji i wtedy jest wielki alarm.
Zdecydowanie.
Zalety automatyzacji i skalowania procesów
I jeszcze mamy kolejne tutaj, że tak powiem, korzyści płynące z tego, bo nie dość, że mamy to wszystko oskryptowane, właśnie wyryte w kamieniu, także będzie powtarzalne. To każde takie odpalenie może być też osobno sparametryzowane. Mając taką skryptologię, możemy sobie właśnie zwielokrotnić ilość tych naszych różnych stage’y na potrzeby tego czy tamtego, różnych tam wymagań, na potrzeby różnych testów. Możemy sobie ten sam, powiedzmy, artefakt zbudować z kilku różnych branchy, żeby sobie tam coś porównać, nie?
I często tak się robi, że się właśnie dodaje jakiś, buduje się artefakt z tego. To znaczy najczęściej te pipeline’y są tak już skrojone, że potrafi nam zbudować z developa, czyli z takiego main brancha, znaczy z głównego brancha, ze źródła prawdy. O, tak najlepiej powiedzieć, nie? Potrafi nam zbudować artefakt wykonywalny i jednocześnie ma tam warunki, z których branchy jeszcze może coś takiego zrobić, nie? Więc zbuduje w analogiczny sposób z dowolnego brancha, ja sobie zakładam brancha feature’owego i mam za chwilę artefakt z mojego brancha feature’owego, który mogę sobie po prostu pobrać, odpalić czy coś tam i mogę go sobie przetestować w takich czy innych warunkach, albo wręcz mogę sobie zrobić dedykowane branche na dedykowane środowiska i…
I te środowiska budować, więc możliwości są praktycznie nieograniczone, ale wiadomo, że ograniczają nas tutaj te minuty budowania, czyli pieniądz.
Ale co jeszcze jest ważne, to to, że z każdego takiego stage’a, z każdej w ogóle operacji, mamy tam loga dość, najczęściej już tak wysmażonego, że wszystko widać w nim. Po prostu najistotniejsze informacje pojawiają nam się.
W plikach dziennika.
No i to jest też kolejna rzeczywiście zaleta, no bo wtedy dowodniczących zespołu może to sprawdzić. Tak naprawdę niekoniecznie musi to sprawdzać, można powiedzieć, rola DevOpsa sensu stricte. To może być zwykły deweloper, który sobie zobaczy.
A i bardzo często jest. I bardzo często jest, no bo taki DevOps on niekoniecznie może wiedzieć, albo ma wiedzieć czemu ten czy inny artefakt się nie zbudował, bo to może być bardzo specyficzne dla danej aplikacji.
Mogą być nawet jakieś błędy z tych etapów budowania, jeżeli na przykład budujemy coś Gradle.
Co się nie pykło. No to właśnie najbardziej tutaj będzie chyba programista, ten który potrzebował tego feature’a, zainteresowany czemu to się nie zbudowało tam, skoro jemu się zbudowało lokalnie, dokładnie. Nie sprawdził nic po niej, wypchnął na czerwono. Ale jakże, jakże to jest inna sytuacja od czasów kiedy jakieś zupełnie zewnętrzne, oddzielne zespoły budowały artefakty. Nie, no to to już było ze zwierzęcenie i degrengolada strasznie.
No tak, i często wysyłały jakieś logi do zespołów deweloperskich: „I patrzcie, nie buduje się nam, pomóżcie”. I wtedy był cały ping-pong mailowy, no to wyślijcie logistego, pokażcie logistego. I ta cała, no tak naprawdę te dwa jakby etapy, no i te dwa, można powiedzieć, zespoły, powinny bliżej pracować, dzięki temu jednak szybciej dojdą do sedna problemu, jeśli taki nastąpi.
Ja też zawsze, jak miałem okazję do, po współczuwania im, to im współczuwałem. Takim właśnie zespołom wdrożeniowym, a kilka razy miałem, bo oni to naprawdę mieli przewalone. Bo jak na przykład była organizacja odpowiednio duża, jakieś korpo i tam było kilka zespołów do budowania wszystkiego, a zespołów deweloperskich było na przykład 20.
Albo 60, jak tak akurat w pewnej takiej fajnej firmie, dla której robiliśmy tutaj cacka. No to ich tam było 60 i to rozsianych po świecie na przykład. No i teraz wyobraźmy sobie, że nawet 5 jest takich zespołów DevOpsowych, które budują coś tam i wdrażają. To skąd one biedne mają wiedzieć, co to się w ogóle wyrabia? Jakie dependencje przyszły? Jakie poginęły z tego kodu? Jakich się spodziewać błędów? Jakie integracje w ogóle z czymkolwiek zewnętrznym?
To wiąże się już z takim narzutem typu, my zrobiliśmy naszą zmianę w tym kodzie, tą naszą zmianę przyrostową. I jeszcze oprócz tej zmiany, przetestowania oczywiście lokalnej, jak najbardziej, musimy wypluć tonę dokumentacji, która pokaże jak to wdrożyć w ogóle.
Tak, mimo że sami tak naprawdę moglibyśmy spokojnie to zbudować i pewnie wdrożyć, no bo sami też jako zespół, jako twórcy wiemy…
Tylko nam nie chcieli dawać haseł do produkcji.
No tak, no bo na to powinny być troszkę sprytniejszym sposobem niż hasła plaintextem. Ale faktycznie to jest takie przeciwdziałanie powstaniu takich silosów wiedzy, czyli każdy ma po prostu swój kawałek wiedzy. Nie interesuje go zupełnie co się dzieje w następnym etapie czy w poprzednim, no bo to nie jest jego działka.
No i to jednak znacznie spowalnia cały proces dostarczania już finalnego rozwiązania, więc nie ma co się dziwić, że w obecnych czasach następuje coraz większe podejście do tego, że zespoły deweloperskie powinny tak naprawdę na całym obszarze od…
Tworzenia, trochę nie ma wyjścia, bo teraz wyobraźmy sobie, że mamy takich mikroserwisów 25. No i ten jeden zespół nieszczęsny DevOpsowy ma ogarniać 25 mikroserwisów razy ileś tam zespołów, na przykład. Trochę ciężko, nie?
To jest bardzo niepraktyczne, to się nie przeskalowało. Jeszcze jak były te monolity, że siedzieliśmy i my tu jeden z 20 zespołów zmerge’owaliśmy raz na tam miesiąc.
Tak.
Nasze dyrdymały do jednego wielkiego czegoś i później brał to ten jeden główny majster i budował to, nie? I to się budowało całą noc, a później się testowało trzy noce.
Nawet była taka rola takiego buildmastera, który na tydzień…
Jechał na miejsce i był odpowiedzialny za budowanie. Rzeczywiście.
Taki master cieśla, nie?
No tak, no tak. No to się na pewno we współczesnych organizacjach naprawdę nie wyskaluje. No bo jeśli taki Uber ma kilka tysięcy mikroserwisów, no to ile musiałbym mieć DevOpsów, żeby to wszystko obsłużyć na taki poziomie?
Ile w ogóle na komunikacji, nie?
No właśnie. A to wszystko są powtarzalne czynności, które jak widać doskonale się automatyzują, więc odpowiedź na pytanie, czy skryptować, czy nie skryptować, jest: skryptować.
I już.
I po prostu kiedy? Jak najwcześniej. Czyli na przykład zakładamy sobie, powiedzmy, nie wiem, nasz zespół dostaje wymagania nowego projektu. Zbieramy się razem z Product Ownerem, rozkminiamy tam z biznesem, ze wszystkimi, z UX-em, ktokolwiek by tam chciał być zainteresowany, tym jest mile widziany. Rozkminiamy założenia, co się będzie, gdzie działo i już możemy sobie zacząć przygotowywać środowiska. Przygotowujemy sobie środowisko lokalne, środowisko deweloperskie, takie do wrzucenia kodu po prostu na pierwszego builda, na pierwsze testy, jeżeli trzeba środowisko testowe i środowisko produkcyjne.
I taki schemat daje się zastosować już od pierwszych minut w ogóle projektu. Idealnie jakby się to udało zrobić takim jednym przyciśnięciem magicznego przycisku: „Stwórz mi środowisko”.
Czasami to już praktycznie w ten sposób zmierza. Pamiętam właśnie, że u tego samego klienta, o którym tu wspomniałeś, w momencie przejścia na AWS i stawiania właśnie małych mikroserwisów, no to tak naprawdę pipeline’y budujące na TeamCity – bo tam używaliśmy TeamCity akurat – one de facto z odpowiedniej templatki powstawały praktycznie automatycznie, żeby nie powiedzieć całkowicie automatycznie.
No bo jednak, jeśli proces tak naprawdę stawiania infrastruktury – no bo to od tego trzeba wyjść, jeśli mówimy tutaj o mikroserwisach i o takim dostarczaniu automatycznym – jest automatyczny, no to wtedy proces budowania musi nam za tym nadążyć.
Więc jedno tak naprawdę…
Nie ma już wyjścia wtedy.
Trzeba zawołać z poziomu skryptu, trzeba zawołać te zasoby, które nam tam mają powstać.
No i dlatego trzeba to skryptować.
No i tutaj wchodzi właśnie ta druga część, bo już zbudowaliśmy sobie nasz artefakt, przetestowaliśmy go na przykład testami jednostkowymi, integracyjnymi.
Jeszcze nie, bo wspomnieliśmy o jednym, ale to wyjdzie zaraz z drugiej części.
Wyjdzie w praniu.
Mamy ten nasz release na środowisko, czy to testowe, czy jakieś tam akceptacyjne, czy wręcz nawet na produkcyjne, ale to tutaj częściej skok manualny. No i tak naprawdę już ta część, czyli właśnie realizowanie tego naszego artefaktu i wdrażanie go jest właśnie już częścią Continuous Delivery.
Z tym, że samo Delivery nie ogranicza się tylko i wyłącznie do deploymentu, bo wdrożyć aplikacje to każdy umie, ale powiedzmy, prawie każdy. Tylko pytanie, co się dzieje po wdrożeniu?
To przecież może być tak, że trzeba używać.
No tak, to już zostawiamy to na odpowiedzialność użytkowników, którzy będą tego używać. Tylko że na przykład po takim wdrożeniu, jeśli mamy wiedzieć, że ta aplikacja wciąż działa, to może trzeba by było troszkę monitorować.
Mieć monitory te aplikacje.
Ale właśnie to można sięgnąć jeszcze do kroków wcześniejszego. Może można by też monitorować ten proces budowania, budowania, testowania wszystkich tych etapów, które nam od momentu pushowania naszych zmian do tego brancha, z którego budujemy, do momentu wyplucia artefaktu, i to jeszcze takiego, który działa, po prostu. Już wiemy, że jakiegoś tam emituje. Cały ten proces można monitorować i z tego może sobie robić wykresy jakieś.
Najczęściej już same narzędzia jakby nam to dają i pokazują na przykład częstotliwości zielonych buildów i tego typu rzeczy, więc to najczęściej już mamy. W jakiś sposób możemy sobie to jeszcze dodatkowo pokryć jakimiś statystykami, natomiast już jakby sam proces wdrożenia i samo dostarczanie oprogramowania nieodłącznie musi się wiązać z monitorowaniem tego bieżącego stanu, czyli wdrożonej aplikacji, no bo chcielibyśmy potencjalnie móc na przykład może wycofać świeżo wdrożoną wersję, bo jednak poszło coś nie tak, może widzimy wzrost błędów 500, może widzimy spadek aktywnych sesji, cokolwiek. Może warto by było tutaj takie zatoczyć, można powiedzieć, koło domykające i cofnąć się do przysłowiowego tyłu, no bo rzeczywiście, jeśli chcemy mieć ten proces continuous i tak już idziemy w eliminację tego czynnika ludzkiego, no to nie chcemy, żeby teraz siedział jakiś tam biedny deweloper, czy inny DevOps i patrzył w tą naszą Kibanę, czy coś tam w piątek w nocy.
Jeszcze jakby siedział jakiś inny, to spoko, ale jak my…
No właśnie, a to też jest praca niewdzięczna i mało ciekawa, więc pewnie chcielibyśmy, żeby ten kawałek na przykład…
Albo mando.
Albo mando. Jakoś zmęczę.
Jakoś zmęcz.
To później asoka tylko i już poleci.
Już chyba asoki nie zdzierzę.
Ale zobaczymy.
Ale zobaczymy. To może jak już tą Kibanę obejrzę do końca i wszystko będzie działać, oczywiście.
Na Kibanie tak, to już miał cały sezon do oglądania.
Ale właśnie, ten krok wracając do Continuous Delivery. Właśnie nie chcielibyśmy mieć jakby żadnego elementu tutaj albo jak najmniej tych elementów pozostawionych człowiekowi. No i faktycznie warto by było to też połączyć z jakimś automatycznym przywróceniem poprzedniej wersji.
Albo chociażby jakimś automatycznym alarmingiem, tak żebyśmy chociaż dostali tę informację.
Tak. Najczęściej to są automatyczne jakieś wersje. Alarmowanie, bo automatyczne przywracanie to też musiałoby być zrobione bardzo ostrożnie, żebyśmy wiedzieli kiedy przywracać, kiedy nie.
No tutaj łatwo się trochę zapędzić.
Tak, że to coś nam nie pykło, a to nie, to przywracamy, sorry, dzięki. No i tak w kółko, nie?
Monitorowanie i wizualizacja procesów
Chociaż na to są inne sposoby też, ale to przejdziemy w odpowiednim czasie.
Ale tak, no.
Czyli zaraz.
Czyli zaraz. Ale monitoring, chociażby w takie aktywne powiadamianie, że faktycznie…
Przede wszystkim tak, mieć wgląd, kompletny wgląd w to, co się tam dzieje, informację zwrotną z tego, nie? I to z całego tego systemu wdrażania, tej ciągłej integracji i ciągłego wdrażania.
I to bardzo fajnie się na przykład obrazuje na takich wielkich ekranach, które sobie lubią w firmach, zwłaszcza takich większych software’owych, wisieć na ścianach. I my też miewaliśmy takie wiszące cacka, gdzie na przykład wszystkie pipeline’y są w postaci takich kwadracików odpowiednio się kolorujących, nie? Jak widzimy, że tam miga kwadracik, znaczy, że w tym momencie coś tam się buduje.
Jest to po prostu wzięte z nażywca, wręcz ten…
Taki dashboard złożony z takich wykresów właśnie z Kibany czy z czegoś podobnego, które to na bieżąco pokazują stan tych komponentów, które tam coś budują.
I to się fajnie ogląda, to można godzinami siedzieć, tak podziwiać, jak one to tam działają.
Boże, już jest z tymi właśnie wykresami, które pokazują te 500 później.
Później trzeba trochę coś w końcu z nimi zrobić. Jak już pierwszy stres przejdzie, to trzeba zacząć myśleć o co tam się zepsuło. Na szczęście wyjątki pomagają w skumaniu, co tam się zepsuło.
No ale nie ma co ukrywać, że jednak, mając tego typu narzędzia i gdzieś tam śledząc to, bardzo fajnie, jeśli to my, jako zespół, wykryjemy awarie, zanim zrobi to na przykład nasz Product Owner, czy ktoś…
Właśnie po to te telewizory są świecące nam w oczy.
To szybkie reagowanie właśnie też jest…
To szybkie reagowanie właśnie to nam kilka razy wręcz pochwałę przyniosło ze strony takiego biznesu, bo jak my byliśmy w stanie poinformować ich wcześniej, zanim oni jeszcze w ogóle przeczuwali, że coś jest nie halo, że my już wiemy, co nie działa, no to oni myśleli sobie: „Ooo, żeż ty…”.
To oni tam to nieźli są w te klocki.
A my po prostu patrzyliśmy tak: „O, kur…”.
„…ka wodna, znowu nam tam się zepsuło, nie?”.
No z raz czy dwa tak może się zdarzyło.
No z raz czy dwa. Natomiast, no tak, no to jest… To jest często może przez…
Często, powiedzmy, często gdzieś tam przez zespoły traktowane troszkę bardziej po macoszemu, no bo wiadomo, ja swój feature zakodowałem i mam ręce czyste i biorę następny task z boarda, przesuwam na in progress, a to co się dzieje później to mnie zupełnie nie interesuje. Natomiast to co robimy, to też warto spojrzeć czasami jako taki szerszy proces, że tak naprawdę takie definition of done, czyli to kiedy nasz task jest faktycznie zrobiony, no nie kończy się z momentem commita i nawet czy nawet approva tego commita w merge queście, tylko de facto po szczęśliwym wdrożeniu tego taska na produkcję, bo to jest naprawdę koniec pracy, a nawet jeszcze nie i nawet wtedy, kiedy on działa tam, a nawet jeszcze sprawdzenie…
Tak, czyli może jakieś metryki, może sprawdzenie czy on w ogóle nie wysypał czegoś, bo jeśli nasz task teoretycznie działa, ale wysypuje 5 innych rzeczy, no to tak naprawdę nie działa.
No nie działa.
Więc tutaj na przykład, tak jak wspomniałeś, może nie zachcieć wdrożyć, bo w tym akurat kawałku, który my przetestowaliśmy sami i jesteśmy zadowoleni, nawet który się automatycznie przetestował, na przykład na CI-u. Wszystko było zielono, ale jak się zintegrowało z całą resztą, bo my akurat wypuszczaliśmy jeden mikroserwis, a tam 5 innych z naszego czyta i zapomnieliśmy o wersjonowaniu API, więc poszła jakaś zmiana taka niszcząca, no to 5 innych już leży w tym momencie.
No i wtedy możemy ten rollback mieć taki wielki czerwony przycisk do wycofywania zmiany. Wtedy on się może przydać.
Ale za szybko, oczywiście, nie może być, żeby niechcąco go nie wcisnąć, tylko niech to nie będzie szybka do tłuczenia, bo byśmy ciągle to szkło musieli wymieniać. Ten lepiej jest taki podnoszony, wciskasz i zamykasz, bez kluczyka, bo to jeszcze kluczyk zgubisz i…
Jak, kluczyk i dwie osoby w tym samym momencie muszą przekręcić.
No właśnie, jak to drzewiej w filmach.
Korzyści dla biznesu i zespołu
Ale jakby nie patrzeć, są tu właśnie techniczne zalety i coś, co ułatwia nam pracę i pomaga tak naprawdę w doprowadzeniu danego feature’a do takiego szczęśliwego zakończenia i tak naprawdę pozwala nam stale monitorować naszą pracę i wiedzieć, że faktycznie, dobra, to zadanie, ten task, ta rzecz jest zrobiona, wydaje się działać, a przynajmniej nie wysypuje aplikacji, więc tu jesteśmy, że tak powiem, zadowoleni i też cały ten proces dzięki temu można powiedzieć zatoczył koło.
Natomiast od takiej strony może już biznesowej, albo jakby nie patrzeć, szeroko rozumiany biznes, no tak naprawdę…
Biznes interesuje to, że zmiany faktycznie zostaną wytworzone, zostaną wdrożone. Teoretycznie nie ma to znaczenia, czy zrobi to właśnie nasz pan DevOps ręcznie.
Ale praktycznie ma.
W praktyce może ma, ale tak naprawdę ta różnica jest, że tak powiem, trudna zauważalna, bo wiadomo, że te detale umykają jednak osobom nietechnicznym i tak naprawdę, czy to zrobi człowiek, czy zrobi jakiś automat, tu śmiem się leciutko nie zgodzić, żeby te zmiany dotarły do etapu tutaj końcowego.
Z tym się zgadzam, ale chciałbym się leciutko nie zgodzić, oczywiście z tym, że dla nich to nie ma znaczenia. Bo ma.
Masz szybkość tej zmiany.
No właśnie.
I w ogóle ogólna jej poprawność. Jeśli mówimy o jednostkowym takim wdrożeniu, można powiedzieć, to teoretycznie…
Jednostkowym wdrożeniem to tak, to po prostu nie było na produkcji, nagle jest: „O, dobra, możemy klikać”, spoko. Ale jeżeli mówimy o dostarczaniu, a tutaj tematem odcinka jest dostarczanie ciągłe, to fajnie jakby się dostarczało ciągle w sposób pewny.
Zawsze tak samo. Z tym samym poziomem bezpieczeństwa, z tym samym poziomem powiadamiania o wszystkim, co tam się dzieje, w przewidywalny sposób naturalnie i co? I jakoś tak w miarę regularnie, szybko, bezproblemowo.
No właśnie, chyba ten tutaj czynnik tej szybkości tak naprawdę determinuje, no właśnie, tą automatyzację procesu.
Chyba tą eliminację czynnika ludzkiego, który właśnie tą błędogenność tutaj pokazuje.
Tak. O, skrypt się jednak myli rzadziej.
Myli się rzadziej.
Z tym, że ta szybkość, no bo też możemy wtedy powiedzieć: „Ok, biznes powie, no dobra, to się wdraża szybko, ale co ja będę z tego mieć?”.
No i w tym… No jak? No więcej hajsu, gościu.
No właśnie, sam fakt, że to będzie szybciej, to niekoniecznie może oznaczać więcej tych pieniędzy.
Wydanych na te kolejne pipeline’y.
No tak, bo to wiadomo, zje dużo minut. Ale tutaj bardziej możemy to ubrać w jakieś słowa, na przykład jeśli chcemy przekonać w jakiejś organizacji kogoś, żeby zastosować tego typu proces.
To mówcie, że w podcaście mówili, że trzeba.
W podcaście to jest raz, ale jeśli chcemy to jeszcze rozwinąć, to możemy powiedzieć na przykład: „Drogi Biznesie. To będzie szybciej, ale szybciej będzie na zasadzie: będziecie mogli szybciej wdrażać swoje nowe zmiany, albo będziecie mogli szybciej iterować nad swoimi pomysłami. Na przykład drogi biznesie, jeśli macie pomysł w poniedziałek, że zrobimy to, to i to. No to wiadomo, my to zrobimy, zaimplementujemy. Ale to się nie wdroży po tygodniu, bo tak na przykład kiedyś tyle zajmowało czasu na wdrożenie. Bo zanim tam zespół DevOpsowy usiądzie…”. Tylko jeśli zrobimy to, to, to i to z naszego procesu dostarczania, to jak tylko skończymy tą historię, ona będzie wdrożona powiedzmy w 15 minut. Bo tyle potrwa na przykład cały proces CI/CD. I to jest już wydatny argument dla, można powiedzieć, biznesu. Bo wtedy rzeczywiście nawet taka częstotliwość wymyślania nowych rzeczy, nowych feature’ów może być w czasie rzeczywistym. No bo wiemy, że te pomysły realnie mogą być szybko wdrożone, a nie tak jak to często bywało, że: „No dobrze, kiedy to zrobicie?”. „No, zrobimy feature’a za 3 dni, a będzie wdrożony za 3 tygodnie. Bo wtedy dopiero jest wyznaczone, bo jest okno”. No i wtedy wiadomo, że tak naprawdę wszelkie entuzje do nowych pomysłów dość mocno siada. No bo nie przekłada się to na efekt taki bardzo wydatny. A jednak dla biznesu jest ważne, żeby te zmiany wdrażać dość szybko.
No bo tak naprawdę biznes bardzo często nie wie, w którą stronę pójść. Bo to nie jest tak, że wszyscy, że tak mówią, właściciele produktów bardzo, bardzo…
Są narzędzia.
Są narzędzia, tak. Więc sobie jeszcze do tego przejdziemy. Ale generalnie właśnie iteracja bardzo szybka. Potrzeba szybkich iteracji, potrzeba eksperymentów po prostu. Czyli na przykład wprowadzamy feature. Nie pykło, wycofujemy, wprowadzamy następny. Jest lepiej, git, no to idziemy w tą stronę.
No, czyli szybkość wdrażania, ta częstotliwość wyższa wdrażania tych zmian, pewność, że te zmiany są wdrożone bezpiecznie, zgodnie z procedurami.
Bo na przykład każdorazowo obowiązkowy audyt bezpieczeństwa przechodzi, dajmy na to. Jeżeli system jest tak krytycznie, w sensie ma takie wymagania krytyczne, że musi to być zrobione, to za każdym razem to się zrobi z automatu tak samo.
Przepraszam, inny przykład: automatyczne testy wydajnościowe. Jeżeli wiemy, że dany kawałek musi działać wydajnie, no to zapuszczamy tam jakąś srogą maszynerię, która go spróbuje stłamsić. Jak się obroni, przechodzi testy, wypuszczamy go, wiemy, że jest dobrze. Jak nie, sprawdzamy, jaka jest regresja, ile jest procent pogorszenia. Mówiliśmy o tym w którymś tam z początkowych odcinków, jak takie testy można robić, to można na wielu poziomach robić, nie? I można to robić automatycznie.
Można, a już korzystając… No na chmurze to jeszcze jest trochę problematyczne z tą wydajnością, bo musi mieć powtarzalne środowisko.
No tak.
Musimy mieć te gwarancje zachowane, że dostajemy faktycznie takie klocki, ale powiedzmy…
Problem zmierzenia, tak, bo tak. Da się to przynajmniej teraz jakoś ogarnąć w sensowny sposób. No i takie wszelkiej maści weryfikacji, jak jesteśmy w stanie dołożyć do tego naszego pipeline’a, dokładamy sobie i wypuszczamy i wiemy, że wypuszczamy software bezpieczny.
Testowanie i 12 Factor App
To, że w ogóle każdy build wymaga zielonych testów, żeby przejść krok dalej, żeby na przykład z poziomu testów przejść do zbudowania artefaktu, który dalej posłuży do już właściwego wdrożenia. To już wiemy, że tak długo jak te testy nie są oczywiście oszukane, a no tutaj to już jest nasza odpowiedzialność deweloperska, żeby one jednak były adekwatne do tego, co faktycznie testują, no to możemy mieć pewność, że wypuszczamy faktycznie przetestowane oprogramowanie. I tak naprawdę współcześnie komponenty oprogramowania, które są wypuszczane do wdrażania, no w większości przetestowane automatycznie. Testerzy manualni, to już jest taka wisienka na torcie, najczęściej po prostu biorą sobie do testów jakiś tam już manualnych właśnie, całe środowiska i sobie po nich klikają.
I też oczywiście mają sformalizowane scenariusze, bo muszą mieć do tego, żeby za każdym razem tą powtarzalność zachować, ale ograniczamy ich pracę do tego, żeby…
Żeby faktycznie postawili tą kropkę nad „i”, już tą końcową.
No właśnie, czyli jednym słowem możemy sobie w tym naszym procesie ciągłego dostarczania zawrzeć jednocześnie wszelkie techniczne kryteria, które potrzebujemy, żeby nasz, powiedzmy, build artefakt został zweryfikowany, czyli tak jak mówisz, test, jakiś security check i sprawdzanie analizę statyczną, tego typu rzeczy, to można przejść automatycznie. Część z nich może być pewnymi wymogami, można powiedzieć, niefunkcjonalnymi. Takim bardziej regulacyjnym sprawdzeniem, chociażby ten security check, to często jest też jakiś tam bardziej regulacyjny wymóg, że nie mamy kodu podatnego na jakieś exploity czy tego typu rzeczy.
Tak, tutaj przykładem jest Veracode lub podobne, który sprawdza, czy zależności do naszego kodu są w wymaganych wersjach. Te wersje są tam waitlistowane. Jeżeli któraś wersja się nie zgadza, to wracamy.
No i w ten sposób tak naprawdę efekt naszych prac ląduje na tej produkcji, co jest celem i zespołu, i biznesu, więc jakby tutaj spełnione są, że tak powiem, chęci obu tych stron i tak naprawdę ten proces, no, wydatnie, wydatnie wspomaga właśnie, właśnie, właśnie.
I ląduje tam nie dość, że w skończonym czasie, to jeszcze dość szybko.
Tak, szybko, powtarzalnie i bezbłędnie.
Natomiast, no są też pewne, przejdziemy tu już do takich pomocnych hintów, sami gdzieś tam stosowaliśmy w takim procesie. No bo tak naprawdę, to się też wiąże z pewnym kosztem. I tu już nawet pominiemy pewnie koszty jakby utrzymania tych wszystkich pipeline’ów i tego typu rzeczy, no bo to wiadomo, zawsze będzie jakiś koszt niezerowy.
Czasami. Wciąż jakieś zależności mogą nam się pozmieniać, może nam się zmienić sposób budowania, więc no wszystkie te kroki, im więcej wiadomo tych kroków będzie w tym procesie i integracji, i delivery, no to będzie, trzeba się troszkę tym zająć. Natomiast no musimy też czasami dostosować też nasze systemy, żeby one faktycznie były gotowe na taką ciągłą, na takie ciągłe dostarczanie i nawet nie mówimy jeszcze o o tym prawdziwym ciągłym, tak?
O prawdziwym ciągłym deploymencie, bo jest jeszcze taka odmiana continuous, może nie tyle odmiana, ale Continuous Delivery i Continuous Deployment, czyli tak naprawdę albo Continuous Live Delivery.
Też albo Continuous Live Delivery, tak, to określenia są podobne, więc może, może, może… Może na początek troszkę, troszkę powiem o tym Continuous Deployment, bo pamiętam, że w tym właśnie projekcie, o którym wspomnieliśmy, nawet rozważaliśmy kiedyś Continuous Deployment. Nawet nie wiem czy nie wprowadziliśmy go gdzieś tam w jakimś małym zakresie.
Może na chwilkę nawet.
Nawet był wprowadzony.
W czasie kiedy to było tak strasznie modne na konferencjach, to tam tak wychwalano i najwięksi magicy, nawet chyba pokroju Wujka Boba, też chyba o tym wspominali.
Chociaż Wujek Bob to tak umiarkowanie.
On chyba bardziej umiarkowany. Ale chyba jego koledzy młodsi troszkę.
On bardziej to robił merge’r w piątek.
Mający więcej życia w sobie, to oni jednak próbowali. Natomiast…
No to proszę, na czym to polega?
No tak naprawdę to jest… idziemy jeszcze krok dalej. Czyli nie tyle dostarczamy ciągle, bo samo dostarczanie to polega na budowaniu i na faktycznie zamieszczaniu tego kodu w artefaktory i w jakimś repozytorium gdzieś. Natomiast bardzo często samo wdrożenie na produkcję to już pociąga ze sobą jakiś manualny krok, ewentualnie jakiś cykliczny trigger, czyli powiedzmy wdrażamy co jakiś tam interwał czasu.
Natomiast Continuous Deployment de facto oznacza to, że każdy nasz commit po przejściu oczywiście przez proces CI/CD ląduje na produkcji. Każdy, oczywiście, do głównego, do mastera, do developa. No i to jest, na pierwszym oka, to może wydawać się dość…
Crazy.
Dość takie szalone. No bo jak? Jak każdy mój commit? Przecież ja nie jestem pewien, czy ja to dobrze zrobiłem. Jakieś krzaki wykomituję i co?
No właśnie.
Przecież ja to dopiero wrzuciłem. Ja tego jeszcze nie przetestowałem. To nie może wejść na produkcję.
Jeszcze nikt nie przetestował.
Jeszcze nikt nie przetestował, więc jest to dość szalone. Ja mam na myśli spore zaufanie dla zespołu, dla swoich procesów.
Pewnie dla siatki i testów.
Dla całego procesu właśnie CI/CD. No bo tak naprawdę on będzie nam gwarantował, że faktycznie ten kod będzie jakoś tam sprawdzony. Natomiast to są firmy, które chwalą się takimi sytuacjami, że robią kilkadziesiąt deploymentów dziennie na przykład. No bo tyle mają commitów do mastera. No i każdy commit leci na produkcję.
I jakoś żyją.
I systemy działają, wersjonowanie analogowe. Jakieś mają różne sprytne techniki bądź tak kumaty zespół, że jakoś to im działa. Natomiast trzeba sobie jasno powiedzieć, że to pewnie nie do końca będzie podejście, które będzie pasowało dla każdej organizacji i to nie do końca może być, to może po prostu nie wszystkim pasować i rzeczywiście to może być taki święty graal, coś do czego dążymy, ale pytanie, czy nam rzeczywiście daje to jakąś biznesową przewagę?
W sporej części przypadków. Pewnie to taka miła ciekawostka.
Pewnie tak. Ale może się przydać…
Narzędzia wspierające wdrożenia – Feature Switch i Testy A/B
Prawie do pochwalenia się, że my jesteśmy…
My to jesteśmy tacy super, że my to wdrażamy ciągle, ale być może gdyby tak rozważyć środowisko właśnie podlegające ciągłym testom, to to byłaby genialna metoda, żeby te testy robić i je obserwować.
Ale to jeszcze warto dopowiedzieć, że to nie jest tak, że chaotycznie pchamy wszystko jak leci, bo wprawdzie przeszło nam to testy, bo inaczej by pipeline nie zgodził się na wypuszczenie tego artefaktu, czyli niby z grubsza się zgadza, ale dalej mogą być krzaki, że w sensie funkcjonalnie jest coś nie halo. I tu na szczęście z pomocą przychodzą przynajmniej dwa rodzaje narzędzi, jak nie trzy, lub cztery z tej listy, którą tu mamy strasznie tajnej. Ale taki podstawowy dwa to jest Feature Switch i test A/B. To są dwa takie cacka, z którymi bardzo przyjemnie się pracuje.
Jak już się dołoży do projektu.
No to później wdrażanie takiej zmiany ciągłej jest już naprawdę dosłownie przyjemne. Bo jak działa Feature Switch? Jak sama nazwa wskazuje, włącza lub wyłącza taki feature. Czyli mamy sobie naszą funkcjonalność, którą jesteśmy w stanie zawrzeć gdzieś tam w jakimś zbiorze. I dostęp do tego zbioru regulujemy właśnie tą wajchą tego switcha. Jak jest włączony, to feature działa.
Czyli na przykład dostajemy na front-endzie ten kawałek UI-a i na back-endzie te endpointy. Natomiast kiedy feature jest wyłączony…
To z UI-a nam to gaśnie i tych endpointów z back-endu nie możemy zawołać. Ot i wielka filozofia cała na temat switchowania. Natomiast od strony kuchni jest to zrobić już troszkę ciężej, bo tam jest potrzebny kawałek sprytnej infrastruktury, który daje się ładnie zarządzać.
Najlepiej jak takie feature switche są włączane niezależnie od w ogóle samego pipeline’a, bo w kilku wersjach to spotkałem. Taka wersja najprostsza to jest to, że robi się prostego boolean’a w kodzie i można go sobie przełączyć w commitcie. No więc pushujemy jakąś zmianę z włączonym featurem. Wchodzi na produkcję, testujemy. Widzimy, że coś jest nie halo. Pushujemy szybko wyłączenie feature’a, tylko i wyłączenie. Taki malutki commitcik i siup, gaśnie nam to.
Tylko zajmuje to tyle, ile zajmuje cały pipeline wdrożenia. Od początku do końca. Jak nam się odpukać, coś zmerge’owało po drodze, bo koledzy tam właśnie dopisali jakieś krzaki i się wykrzaczył pipeline, no to niestety jesteśmy troszkę jakby w tym, tam nie powiem gdzie, bo to się nie przełączyło, więc lepsze są feature switche, które się zarządzają z zewnątrz jakąś konfiguracją.
Tudzież na przykład taka konfiguracja dostarczana z zewnątrz. To o tym będzie mowa pewnie za chwilę.
No ale takim feature switchem możemy sobie właśnie Continuous Delivery ograć całkiem zgrabnie, bo Product Owner, który ma genialny pomysł, może ten pomysł dostać i może dostać nawet tego feature switcha do ręki. Niech go sobie sam włączy i wyłączy, i tak właśnie bywało w naszym projekcie. Tym właśnie takim fajnym o feature switchowanym i żeby daleko nie szukać, w ostatnim swoim też tak zrobiłem.
Znaczy akurat ja miałem tego, a nie, to sorry, to Product Owner miał też dostęp do tego feature switcha, więc wszystko odbyło się zgodnie z przepisami.
I ludzie od biznesu to właśnie doceniają, że dostają swój kawałek funkcjonalności, który na produkcji są w stanie przetestować. To już jest najlepszy sposób testowania, bo każde środowisko testowe jest jednak nieprodukcyjnym środowiskiem. Choćby było w 99% zgodne, to jednak na produkcji jak zadziałało, to jest git, a na produkcji mogę sobie to włączyć, wyłączyć i mogę sobie sprawdzić czy to działa.
A drugie narzędzie to testy A/B.
Tak, tak.
No i tutaj jeszcze tylko dodam może o feature switchach. Tu też oczywiście mamy niezerowy koszt użycia feature switcha, no bo jednak jednocześnie wtedy mamy w kodzie, można powiedzieć, dwie wersje naszej logiki, dwie wersje naszego frontu, naszego UI-a. Natomiast ja też na feature switcha zawsze patrzyłem jako coś, co troszkę pomaga mi oddzielić pewne funkcjonalności.
Tak pozornie, tak niepozornie tylko.
Architektonicznie albo wręcz designersko tak, w sensie odostosów z poziomu projektowania oprogramowania. Sprawia, że trzeba się troszkę bardziej zastanowić nad danym featurem, no bo tak jak robimy czasami jakieś zmiany, no to…
Ten tak naprawdę zakres zmian, ten taki blast radius to sam jest tak duży, że dotykamy wszystkich możliwych klas, no przecież musimy to zrobić, no bo robimy funkcjonalność. Natomiast, mając tam uwadze to, że musimy to gdzieś ukryć za feature switchem.
To czasami sprawia, że dwa razy się zastanowimy.
Tak, więc to pomaga tak troszkę w takiej lepszej modularyzacji.
I tu właśnie na przykład wzorzec strategii przychodzi z pomocą albo jakieś ogólnie wzory projektowe, które do zarządzania kodem albo zarządzania feature’ami są używane. Jakieś tam dekoratory, jakieś proxy, jakieś cudawianki inne takie.
Tak, to dobre okazje, żeby tego użyć.
Dokładnie, to jest wręcz wymarzona okazja, bo możemy sobie zachcieć na przykład wypuścić nasz feature w dwóch wersjach i na poziomie Springa zrobić sobie dwie implementacje tego samego interfejsu dla danego jakiegoś tam bina i feature switchem tylko powiedzieć, która jest aktywna w danym momencie. Więc tutaj jest wykorzystywany wzorzec strategii i proxy za jednym zamachem.
Brzmi wspaniale, a później możemy oczywiście stary kodzik usunąć, czyszcząc nasze feature switche, co też jest bardzo przyjemną robotą.
Tak i przynajmniej wtedy to też ograniczamy ilość wątpliwości, co można usunąć, a czego nie. Jak mamy system rozbudowany na tyle, że jest tam kodu w milionach linii, to pewne usuwania rzeczy robi się tak dość ostrożnie.
Albo przynajmniej z duszą na ramieniu się je robi. Natomiast jak mamy tutaj powiedziane, że ten fragment jest pod kontrolą feature switcha i teraz feature switch ma być ciągle włączony, to ten wariant dla wyłączonego usuwamy bezproblemowo.
Canary Deployment i 12 Factor App
No i pewną wariacją też na temat feature switcha jest sposób deploymentu nazwie Canary Deployment. Czyli to jest sytuacja, kiedy dostarczamy nową wersję aplikacji tylko w pewnej grupie użytkowników. No i ci użytkownicy wtedy sobie mogą poklikać, potestować, my możemy zebrać metryki, sprawdzić jak zachowuje się ta wersja i wtedy zadecydować o tym, czy faktycznie wdrażamy już dla całej, można powiedzieć, populacji naszych użytkowników.
Natomiast warto sobie też spojrzeć na, jeśli chcemy rzeczywiście mieć aplikację, która będzie łatwiejsza właśnie w takim ciągłym dostarczaniu, warto sobie spojrzeć na coś, co nazywa się 12 Factor App.
To jest zbiór.
Część z nich odnosi się do designu aplikacji jako takich, natomiast jest kilka cech tego podejścia, które wybitnie właśnie pomagają w tworzeniu takich łatwo konfigurowalnych aplikacji, które rzeczywiście będziemy mogli później zautomatyzować w naszych procesach wdrożeniowych.
Głównie w tym podejściu takim 12-faktorowym, tam głównie też położony jest nacisk na wersjonowanie naszego kodu, na częste deploymenty, na external config, czyli podejście.
Tak naprawdę, które mówi nam, że budowane artefakty powinny być de facto te same, niezależnie od naszego środowiska.
No tu jakby możemy pominąć kwestie właśnie jakieś tam optymalizacyjne czy tego typu rzeczy, bo możemy mieć środowisko stricte deweloperskie, które rzeczywiście będzie troszkę inne, a na przykład jakiś tam staging, QA czy jakkolwiek to tam zwać.
Tylko nie wszędzie, ale zaraz dopowiem, gdzie są ograniczenia.
Ale generalnie jakby zakładamy raczej, że budowany artefakt powinien być zawsze taki sam, czyli nie powinien w środku zawierać…
Jak rozmawiają prawnicy: „co do zasady”.
Co do zasady. Co do litery, co do zasady.
Czyli nie zaszywamy w naszej aplikacji, w sensie w naszym artefakcie, żadnych haseł, żadnych ścieżek dostępu specyficznych do środowiska, żadnych domen, parametrów, które mają cokolwiek wspólnego ze środowiskiem.
Już się pojawiło to słowo, więc wszystko musi być sparametryzowane.
Wszystko musi być sparametryzowane.
I wszystkie parametry wyciągnięte.
Dokładnie. I wtedy możemy tak naprawdę ten sam artefakt, na przykład obraz dockerowy, który sobie zbudujemy, możemy wdrażać sobie na różne środowiska. Wiedząc, że to jest dokładnie ten sam artefakt, więc zachowanie powinno być przynajmniej co do kodu, powinno być takie samo. Możemy sobie też taki artefakt nawet ściągnąć lokalnie i spróbować lokalnie go przetestować.
I nawet więcej, bo robimy to, bo po prostu na dzień dobry robimy sobie Docker Compose’a, który stawia nam całe takie środowisko. I wszystkie te przecież dockerki tam są dokładnie tak sparametryzowane, bo my dostarczamy wszystkich parametrów do nich, jakie one wymagają.
Bo to jest też podstawa tak naprawdę…
Jeśli mówimy o takim procesie dostarczania, no to jeśli będziemy tych kroków mieli dużo i w każdym z kroków będziemy budować nasze aplikacje, no to ciężko nam będzie zejść do jakiegoś rozsądnego czasu dostarczenia. Natomiast jeśli tylko zbudujemy to raz, a później będziemy tylko wdrażać na odpowiednie środowiska ten sam obraz, raz zbudowany, i tylko podłączać sobie czy to plik propertiesów Springa, czy jakiś plik ENV z aplikacji reaktowej, czy cokolwiek innego.
Czy serwer konfiguracji.
No to wybitnie na pewno skrócimy ten proces jakby całościowego dostarczenia na dane środowisko. I też ilość błędów zminimalizujemy, bo de facto mamy jedną wersję kodu. Nie mamy wersji kodu na określone środowiska.
Czasem się tego nie da zrobić z takich względów, że mamy jedną bazę kodu i iluś klientów końcowych. I dla każdego klienta końcowego jeszcze domerge’owujemy jakieś jego tweaky.
No to już jest tak.
To już jest taki specjalizowane troszkę, ale właśnie w tym projekcie, w którym byłem, tak było. I jeszcze była jedna rzecz w tym projekcie, ostatnim moim. Mianowicie…
Tam było tak, że akurat to ze specyfiki chyba C++ troszkę wynikało, że artefakty pobudowane z flagami optymalizacyjnymi nie nadają się do debugowania. Natomiast dobrze jest mieć taki artefakt, na którym są zapuszczone testy, jeszcze z informacjami debuggera tam zawartymi, po to, żeby można było sobie tą binarkę ściągnąć, na przykład CI-a, jeśli ona jeszcze istnieje, a tak bywało i tak właśnie się debuguje takie cacka.
No i zobaczyć, czemu akurat tam się crashuje, na przykład w tym miejscu akurat, czemu akurat w tym teście leci ten błąd, że wszystko umiera. Bierzemy taki artefakt i patrzymy, ładujemy symbole debuggera i widzimy, że: „O, sorry, ale tu nam się coś tam usunęło z kolekcji, a nie powinno”.
No tak, tak, no wtedy na pewno unikniemy tego syndromu: „U mnie działa”.
Tak było, że u mnie działało, a tam przestało działać. Chciałem to zaciągnąć i zobaczyć, czemu tam nie działa.
Jeśli chcemy mieć powtarzalny ten proces, to musimy minimalizować ten efekt: „u mnie działa”. Czyli środowiska powinny być jak najbardziej zwilżone w konfiguracji, w zestawie użytych technologii, w stacku. Jeśli mamy na produkcji jakąś bazę danych, to postarajmy się mieć lokalnie czy na innych środowiskach tą samą bazę danych. A nie, że tu używamy takiej, tu używamy takiej, tutaj używamy H2. Wtedy możemy zapomnieć o takim sensownym odtwarzaniu błędów.
Bo jeśli środowiska i otoczenie naszej aplikacji się różni, to wtedy ciężko coś będzie wyśledzić.
Ale tu mamy podstawowe zasady wtedy połamane.
Przyszłość ciągłego dostarczania
No tak, tak, ale to są na pewno jakieś tam techniki, które powinny nam pomóc w takim wdrażaniu, no i my stosując sporą część z nich, gdzieś tam przez wiele lat udawało nam się robić Continuous Delivery, aplikacji, która miała kilka milionów użytkowników, która miała do czynienia też z płacącymi użytkownikami, no i która była codziennie od dziewiątej rano była wdrażana na produkcję automatycznie. Także tak naprawdę, no…
Czy gdzieś tam baliśmy się każdego poranka?
No, przed grubszymi zmianami czasami pauzowało się pipeline, ale to była raczej wyjątkowa sytuacja.
No już jak tam się tak wybitnie czerwieniło, to się zresztą pauzowało. Natomiast co do zasady rzeczywiście szliśmy na produkcję z aplikacją o 9 rano, no i polegaliśmy na naszym procesie i wierzyliśmy, że wyłapiemy te błędy również monitorując tą aplikację.
Generalnie, chyba możemy powiedzieć, że to się nam powodziło.
Udawało całemu zespołowi zresztą.
No tak, tak, ale to właśnie to się udawało, bo były te narzędzia dodatkowe tak tam podłączone i tam właśnie jeszcze do tych testów A/B nawiążę, bo to jest coś podobnego troszkę z natury do Canary Deployment, bo tutaj część użytkowników też dostaje tylko część dostaje jakąś nową funkcjonalność. W teście A/B to mamy po prostu mechanizm, który selektywnie włącza dla pewnych, przepraszam, dla pewnych użytkowników ten nowy feature, a dla reszty stary i możemy sobie określić procentowo, że powiedzmy dla dziesięciu procent puszczamy ten nowy feature, nie? I wtedy sprawdzamy, jak ten feature nam tam performuje.
Tylko że to, że go włączymy, to jest tylko początek, bo jeszcze musimy jego monitorowanie też mieć pod spodem, więc to już jest trochę grubsza maszyneria. Ale jak mamy skonfigurowany sposób włączenia takiego testu, przy czym A/B to jest taka nazwa umowna, że mamy dwie wersje, wersje A i wersje B. Może być A/B/C i nawet więcej, jak kto woli. Oczywiście wszystko musi mieć ręce i nogi, więc to musi być też odpowiednio zaprojektowane, czyli nawet biznesowo musi być przewidziane, że te wszystkie warianty mają sens i że się gdzieś tam ich wspólny mianownik i tak…
To są głównie biznesowe decyzje.
Tak, tak. No i właśnie jak mamy możliwość selektywnego wypuszczenia w świat tych naszych różnych wariantów, plus możliwość podglądania ich wyników, to wtedy możemy sobie sprawdzić, jak taki test przebiegał, który wariant był najfajniejszy, który się np. najmniej sypał użytkownikom końcowym. I po skończeniu takiego testu wyłączamy wszystkie warianty te nadmiarowe, zostawiamy główny feature, czyli tak jakbyśmy wszystkie feature switche dla tych wariantów wyłączyli i mamy główną funkcjonalność. Powiedzmy, czyli tą starą, która działa. Tutaj test A/B albo feature switch działają bardzo podobnie dla jednego takiego aspektu, mianowicie jak włączamy coś, to to przy takim naprawdę Continuous Live Delivery coś na gorąco wchodzi i od razu nam się zaczyna sypać, bo po prostu jest jakiś tam critical error w tym. Od razu to możemy wyłączyć.
I to jest podstawowa zaleta i bez tego właściwie nie ma tego Continuous Delivery prawdziwego, Continuous Deploymentu.
Ciężko sobie wyobrazić, rzeczywiście.
Bo nawet to revertowanie, które by trwało, powiedzmy, niech build trwa nam 5 minut. Ale my właśnie wypuściliśmy, w chwili tej równej 0 wypuszczamy ten nasz zrąbany kawałek i on nam za każdym razem rzuca 500, w feature, który ma 2 miliony np. wejść, nie? No to przez 5 minut po prostu jesteśmy wyłączeni w tym obszarze, nie?
To jeszcze połowa biedy, jak jesteśmy w stanie planszę z tymi zakłóceniami wyświetlić, a czasem nawet tego nie jesteśmy w stanie, nie? Więc po prostu mamy brzydki błąd na produkcji przez ileś tam minut, dopóki ten revert nie przejdzie. A 5 minut to jest i tak optymistycznie przy takim systemie.
No dlatego im tak naprawdę częściej chcemy dostarczać w ogólności, jeśli chcemy dostarczać w czasie rzeczywistym prawie rzecz, czyli commit na produkcję, no tym więcej tego typu technik takich stabilizujących musimy użyć. No bo to nie da się… to jest coś za coś. To jest pewne jednak tutaj wzmocnienie i ustabilizowanie naszej aplikacji. Nie da się tego uzyskać za darmo.
Nie da się po prostu niestabilnych aplikacji regularnie wdrażać. Jeśli chcemy coś takiego sobie zrobić.
Koszty i infrastruktura CI/CD
Natomiast, czy ktoś jeszcze chciał poruszyć następne punkty? Bo moglibyśmy też już zadać sobie pytanie, albo biznes mógłby nam zadać pytanie: „No dobrze, ale ile to będzie kosztować te całe wasze pipeline’y? I w ogóle, kto to tam zrobi i gdzie to będzie w ogóle chodzić? I w ogóle, po co to komu?”.
No i teraz… Kiedyś, jeszcze pewnie parę lat temu, rzeczywiście to może nie było takie proste, albo przynajmniej wymagało troszkę więcej, że tak powiem, toolingu, żeby w ogóle takie pipeline’y sobie w łatwy sposób. Czarnej magii. No bo to najczęściej, najczęściej pewnie od razu przychodzi postawienie jakiegoś Jenkinsa, tego typu narzędzi, które by sobie ten nasz kod zasysały, pobierały. Wiadomo, jak postawić Jenkinsa, to trzeba jakiegoś DevOpsa, który to zrobi.
Jeszcze będzie pilnował.
Jeszcze będzie pilnował, bo oczywiście na Jenkinsie bardzo lubi się zapychać dysk. I w jednym z projektów, gdzie budowaliśmy kilkadziesiąt mikroserwisów i tam dziennie leciało bardzo dużo buildów, regularnie byliśmy zablokowani brakiem wolnego miejsca na Jenkinsie, co się wydaje po prostu absurdalną sytuacją.
Nie mogli tam dysku dokupić.
No chyba nie nadążali, albo ciężko mi powiedzieć, natomiast no to jest…
To chociaż jakąś taśmę.
To jest bardzo, bardzo dziwna sytuacja i tak naprawdę no musimy zapewnić, że ten nasz cały tutaj proces i od takiej strony sprzętowej będzie niezakłócony, no bo fajnie sobie zrobić CI/CD dostarczanie, no ale jeśli nam zabraknie tego dysku albo po prostu padnie nam ten Jenkins czy inne narzędzie, no to co dalej?
No to w tym momencie w ogóle nie możemy wdrożyć, bo tak naprawdę nie ma tego procesu ręcznego wtedy.
Nie ma alternatywy.
Albo nawet może jest, tylko że jest na tyle już skomplikowany, że ja bym się chyba nie chciał podjąć takiej rzeźby na piechotę. Tam tyle rzeczy w takim pipeline’ie dość prostym. Jest na tyle już dużo parametrów, że faktycznie to jakby to człowiek miał robić to to by trwało pewnie z 10 razy dłużej zakładając, że wiemy co trzeba robić, bo jak tam zgaśnie ten Jenkins to nawet czasami nie wiemy, bo w głowie to ciężko sobie przypomnieć wszystkie kroki.
No i jak to tam było w Jenkinsie zapisane, więc rzeczywiście, no jest to pewne.
Tak, no utrzymywanie swojej własnej infrastruktury pod tym względem jest no tak samo trudne pewnie jak i utrzymywanie swojej aplikacji.
No właśnie, w sensie infrastruktury do budowania, do wdrażania tego jest może nawet trudniejsze być niż utrzymywanie infrastruktury hostującej to wdrożenie, nie?
Alternatywy dla Jenkinsa i korzyści z CI/CD
Tak, natomiast warto chyba może zauważyć, podkreślić albo zaznaczyć, że dla sporej części aplikacji, tak naprawdę narzędzia, które używamy na co dzień mogą wystarczyć, czyli ten narzędnik GitHub, może być w zupełności dobrą alternatywą do skonstruowania właśnie takiego procesu CI-CD.
Mamy tam podziały na staging.
Nie wszyscy zatrudniają 20 zespołów po sześciu deweloperów.
Dokładnie, a nawet jeśli może zatrudniają, to może to też wystarczy mimo wszystko, bo aplikacje są na tyle małe, bo jeśli mamy małe mikroserwisy, które mają dobrze zdefiniowane funkcjonalności, no to te pipeline’y pewnie też nie są jakieś super skomplikowane.
No nie, no taki przeciętny pipeline na GitLabie, kiedy się oczywiście nie robi jakiś… dobra, nie ma jakiejś strasznie wielkiej bazy kodu, on tam trwa pojedyncze minuty.
Tak, to zawsze też możemy sobie jakieś osobne runnery własne dostawić, jeśli potrzebujemy szybszych maszyn.
To też tak naprawdę, można powiedzieć, takie sprzętowe przygotowanie czy w ogóle postawienie jakichś ekstra środowisk, to wcale nie musi być tutaj koniecznością. Możemy po prostu równie dobrze skonfigurować to wszystko na tych dwóch narzędziach, w zależności od tego, na którym akurat hostujemy nasz kod. I to pewnie będzie OK.
Te pipeline’y są również fajnie monitorowane. Widzimy logi, widzimy proces poszempłu.
I żeby nie było, to tak, mamy zrobione właśnie w ostatnim projekcie.
Dokładnie, w wielu ostatnich projektach tak naprawdę, nawet w tych takich…
W ostatnim najbardziej.
Średnich, czy zalatujących większymi, to jest coraz powszechniejszy trend. Pomijając, że tak naprawdę to się bardzo fajnie wtedy integruje ogólnie z naszą kontrolą wersji, czyli integracja pipeline’ów z merge’owaniem Merge Quest’ów i tego typu rzeczy.
Tak, tak. I to się wpisuje w filozofię Rapid Development. Taką dość świeżą, której też może kiedyś coś będziemy chcieli powiedzieć.
No na pewno przyspiesza to development.
Przyspiesza, bo jak już mamy właśnie cacka pokonfigurowane tak, żeby szybko działały, no to wtedy faktycznie… Coś tam się zakoduje i siup, wypycha się to i to od razu jest, nie?
Ląduje tam, gdzie trzeba.
No i raczej nie musimy się martwić, że nam zabraknie dysku albo padnie nam ten GitHub, co najwyżej zerkamy na stan konta raz na jakiś czas. Ja tak lubię zerknąć o tej dziewiątej rano. Tyle tych groszy było co wczoraj.
Lepsze to niż zerkanie na tego Jenkinsa, który chodzi na naszym komputerze pod biurkiem.
Bo później jeszcze musiał na fakturę Taurona zerkać. No właśnie, więc. Czyli da się to zrobić, nie chcę powiedzieć po kosztach, ale da się to zrobić w sensownych kosztach. Tak, właśnie to jest takie rozwiązanie, tutaj biznes startupowy na przykład, jak najbardziej. To są najczęściej cacka na tyle nieskomplikowane technicznie. No chyba, że mamy startup skomplikowany technicznie, stricte, no to wtedy inniejszość.
Ale jak mamy taki standardowy przypadek biznesowy, coś tam chcemy sobie obadać, biznes jest w miarę jakiś nieskomplikowany, no a w startupie to chyba raczej się wychodzi od pierwotnych wersji takich pomysłów, czyli raczej tych najprostszych. To jak najbardziej tego typu rozwiązanie załatwi sprawę, bo możemy mieć nie dość, że wszystko w jednym środowisku, to jeszcze w środowisku dającym gwarancje, tak, nawet w wersji darmowej to środowisko daje jakieś tam gwarancje.
Najczęściej właśnie mamy dostęp do albo jakiegoś planu takiego bonusowego, gdzie do pewnego momentu, nawet jeżeli idziemy w formie pay as you go, czy jak to tam się nazywa, różnie to się nazywa chyba w zależności od dostawca, ale chodzi o to samo, czyli dostajemy jakiś tam kredyt na początek, dopóki nie wykorzystamy tego kredytu, to nam nie naliczają, jak go przekroczymy, no to pay as you go, czyli tyle ile zużyjemy zasobów, za tyle zapłacimy. No i to jest taka sytuacja wygrywająca dla obydwu stron, bo my dostajemy środowisko, które jest ekonomicznie dla nas dobre, a z kolei dostawca środowiska też ma, że tak powiem, zapowiedź na przyszłość, że my jednak będziemy z tego środowiska korzystać, więc w którymś tam momencie coś my tam zaczniemy płacić za te zasoby.
Podsumowanie i pożegnanie
Czyli warto jednak, już tak podsumowując chyba całą dyskusję.
No dobra, chyba tak, chyba warto.
Chyba warto, no bo to jest element i jakby część procesów naszej pracy, o którym…
O którym tak naprawdę nie myślimy na co dzień, to już jest część tak zautomatyzowana. I chyba na tym też polega dobra automatyzacja, że jej nie zauważamy.
Chyba, że błędy lecą.
No chyba, że błędy lecą, ale to już jest najczęściej błędy po stronie naszego kodu, a nie tyle automatyzacji.
No tak. Nie, to jest czasem Docker.
Ale właśnie, no czas nam się zdarza. Ale właśnie ta automatyzacja jednak w tej codziennej pracy, którą inaczej byśmy musieli już, modlę, gdzieś tam sami wykonywać, na pewno sporo nam, że tak powiem, odciąża. Więc technicznie możemy rzeczywiście skupić się na naszych zadaniach, na naszych historiach, na naszych feature’ach, nie przejmując się jakby całym tym sposobem i mnogością kroków, które trzeba wykonać, żeby faktycznie zobaczyć to na produkcji.
No a z drugiej strony chyba biznesowo, no mimo wszystko, nawet może nie mimo wszystko, biznesowo to też ma jakąś wartość. To nie jest tak, że to jest tylko koszt. Że kto to będzie utrzymywał, kto będzie za to płacił. Tylko tak naprawdę tworzenie oprogramowania to jest kwestia pewnych kosztów, ale możemy dzięki temu szybciej to oprogramowanie iterować, zmieniać.
Otwiera to nowe możliwości dla biznesu. Właśnie o nich powiedzieliśmy, o niektórych, bo pewnie jeszcze można to mnożyć.
Tak, tak, to pewnie jeszcze pominęliśmy wiele aspektów, ale… No tak naprawdę chyba tutaj obu stronom, nie walczącym ze sobą, tylko współpracującym nad aplikacją, zależy na tym, żeby te zmiany jak najszybciej dostarczać użytkownikom, którzy faktycznie mogą z tego korzystać. No i po to jest cały ten proces naszego CI-CD.
RAmen.
Także dzięki Michał za dyskusję. Dzięki za wysłuchanie tego odcinka. Tak jak na początku mówiliśmy, zachęcamy do dalszego śledzenia naszego podcastu i podsuwania tematów.
I subskrybowania.
I subskrybowania. Trzymajcie się. Cześć.