Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)

Nasz blog zaczniemy od publikacji opartych na najnowszych wystąpieniach naszego dyrektora technicznego dysstol (Dmitrij Stolarow). Wszystkie odbyły się w 2016 roku na różnych wydarzeniach branżowych i poświęcone były tematyce DevOps i Docker. Mamy już jeden film ze spotkania Docker Moskwa w biurze Badoo opublikowany Online. Nowym towarzyszyć będą artykuły oddające istotę raportów. Więc…

31 maja na konferencji RootConf 2016, odbywającego się w ramach festiwalu „Russian Internet Technologies” (RIT++ 2016), sekcję „Continuous Deployment and Deployment” otworzył raport „Najlepsze praktyki ciągłego dostarczania z Dockerem”. Podsumowano i usystematyzowano najlepsze praktyki budowania procesu ciągłego dostarczania (CD) przy użyciu Dockera i innych produktów Open Source. Z tymi rozwiązaniami współpracujemy na produkcji, co pozwala nam bazować na praktycznym doświadczeniu.

Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)

Jeśli masz możliwość spędzenia godziny wideo z raportu, zalecamy obejrzenie go w całości. W przeciwnym razie poniżej znajduje się główne podsumowanie w formie tekstowej.

Ciągłe dostarczanie za pomocą Dockera

pod Ciągłe dostawy rozumiemy łańcuch zdarzeń, w wyniku którego kod aplikacji z repozytorium Git najpierw trafia na produkcję, a następnie trafia do archiwum. Ona wygląda tak: Git → Kompiluj → Testuj → Wydaj → Działaj.

Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)
Większość raportu poświęcona jest etapowi kompilacji (montażu aplikacji), a tematy związane z wydaniem i działaniem są krótko poruszane. Porozmawiamy o problemach i wzorcach, które pozwalają je rozwiązać, a konkretne implementacje tych wzorców mogą być różne.

Dlaczego Docker jest tu w ogóle potrzebny? Nie bez powodu postanowiliśmy porozmawiać o praktykach Continuous Delivery w kontekście tego narzędzia Open Source. Chociaż cały raport jest poświęcony jego wykorzystaniu, wiele powodów ujawnia się, gdy weźmiemy pod uwagę główny schemat wdrażania kodu aplikacji.

Główny wzór wdrożenia

Tak więc, kiedy wdrażamy nowe wersje aplikacji, z pewnością mamy do czynienia problem z przestojami, generowane podczas przełączania serwera produkcyjnego. Ruchu ze starej wersji aplikacji na nową nie można przełączyć od razu: najpierw musimy upewnić się, że nowa wersja została nie tylko pomyślnie pobrana, ale także „rozgrzana” (czyli całkowicie gotowa do obsługi żądań).

Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)
Tym samym przez pewien czas obie wersje aplikacji (stara i nowa) będą działać jednocześnie. Co automatycznie prowadzi do konflikt zasobów współdzielonych: sieć, system plików, IPC itp. Dzięki Dockerowi problem ten można łatwo rozwiązać, uruchamiając różne wersje aplikacji w oddzielnych kontenerach, dla których gwarantowana jest izolacja zasobów w ramach tego samego hosta (serwera/maszyny wirtualnej). Oczywiście można sobie poradzić z niektórymi sztuczkami bez izolacji, ale jeśli istnieje gotowe i wygodne narzędzie, to jest powód odwrotny - nie można go zaniedbywać.

Konteneryzacja zapewnia wiele innych korzyści po wdrożeniu. Każde zastosowanie zależy od konkretna wersja (lub zakres wersji) interpretator, dostępność modułów/rozszerzeń itp. oraz ich wersje. I dotyczy to nie tylko bezpośredniego środowiska wykonywalnego, ale także całego środowiska, w tym oprogramowanie systemowe i jego wersję (w zależności od używanej dystrybucji Linuksa). Dzięki temu, że kontenery zawierają nie tylko kod aplikacji, ale także preinstalowane oprogramowanie systemowe i aplikacyjne w wymaganych wersjach, można zapomnieć o problemach z zależnościami.

Uogólnijmy główny wzór wdrożenia nowe wersje biorąc pod uwagę następujące czynniki:

  1. Na początku w pierwszym kontenerze działa stara wersja aplikacji.
  2. Nowa wersja jest następnie rozwijana i „rozgrzewana” w drugim pojemniku. Warto zauważyć, że sama ta nowa wersja może zawierać nie tylko zaktualizowany kod aplikacji, ale także dowolne z jego zależności, a także komponenty systemu (na przykład nową wersję OpenSSL lub całą dystrybucję).
  3. Gdy nowa wersja będzie w pełni gotowa do obsługi żądań, ruch zostanie przełączony z pierwszego kontenera do drugiego.
  4. Można teraz zatrzymać starą wersję.

Takie podejście polegające na wdrażaniu różnych wersji aplikacji w oddzielnych kontenerach zapewnia kolejną wygodę - szybki powrót do starej wersji (w końcu wystarczy przełączyć ruch na żądany kontener).

Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)
Ostatnia pierwsza rekomendacja brzmi jak coś, czemu nawet Kapitan nie mógł nic zarzucić: „[podczas organizowania ciągłego dostarczania za pomocą Dockera] Użyj Dockera [i zrozum, co to daje]" Pamiętaj, że to nie jest złoty środek, który rozwiąże każdy problem, ale narzędzie, które stanowi wspaniałą podstawę.

Powtarzalność

Przez „odtwarzalność” rozumiemy uogólniony zestaw problemów napotykanych podczas obsługi aplikacji. Mówimy o takich przypadkach:

  • Scenariusze sprawdzone przez dział jakości pod kątem inscenizacji muszą zostać dokładnie odtworzone w produkcji.
  • Aplikacje publikowane są na serwerach, które mogą odbierać pakiety z różnych repozytoriów lustrzanych (z biegiem czasu są one aktualizowane, a wraz z nimi wersje zainstalowanych aplikacji).
  • „U mnie wszystko działa lokalnie!” (...a programiści nie mają wstępu do produkcji.)
  • Musisz sprawdzić coś w starej (archiwalnej) wersji.
  • ...

Ich ogólna istota sprowadza się do tego, że konieczna jest pełna zgodność stosowanych środowisk (a także brak czynnika ludzkiego). Jak możemy zagwarantować powtarzalność? Twórz obrazy Dockera w oparciu o kod z Gita, a następnie wykorzystywać je do dowolnego zadania: na stanowiskach testowych, w produkcji, na lokalnych maszynach programistów... Jednocześnie ważne jest minimalizowanie wykonywanych czynności później składanie obrazu: im prostsze, tym mniejsze prawdopodobieństwo wystąpienia błędów.

Infrastruktura to kod

Jeśli wymagania infrastrukturalne (dostępność oprogramowania serwera, jego wersja itp.) nie zostaną sformalizowane i „zaprogramowane”, wówczas wdrożenie jakiejkolwiek aktualizacji aplikacji może mieć katastrofalne skutki. Na przykład w stagingu przerzuciłeś się już na PHP 7.0 i odpowiednio przepisałeś kod - wtedy jego pojawienie się na produkcji z jakimś starym PHP (5.5) z pewnością kogoś zaskoczy. Być może nie zapomnicie o dużej zmianie w wersji interpretera, ale „diabeł tkwi w szczegółach”: niespodzianką może być drobna aktualizacja dowolnej zależności.

Podejście do rozwiązania tego problemu jest znane jako IaC (Infrastruktura jako kod, „infrastruktura jako kod”) i polega na przechowywaniu wymagań infrastrukturalnych wraz z kodem aplikacji. Dzięki niemu programiści i specjaliści DevOps mogą pracować z tym samym repozytorium aplikacji Git, ale w różnych jego częściach. Z tego kodu tworzony jest obraz Dockera w Git, w którym wdrażana jest aplikacja z uwzględnieniem całej specyfiki infrastruktury. Mówiąc najprościej, skrypty (reguły) składania obrazów powinny znajdować się w tym samym repozytorium z kodem źródłowym i być ze sobą scalone.

Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)

W przypadku wielowarstwowej architektury aplikacji - np. jest nginx, który stoi przed aplikacją działającą już w kontenerze Dockera - obrazy Dockera muszą zostać utworzone z kodu w Git dla każdej warstwy. Następnie pierwszy obraz będzie zawierał aplikację z interpreterem i innymi „bliskimi” zależnościami, a drugi obraz będzie zawierał nadrzędny nginx.

Obrazy Dockera, komunikacja z Git

Wszystkie obrazy Dockera zebrane z Git dzielimy na dwie kategorie: tymczasowe i wydania. Obrazy tymczasowe oznaczone nazwą gałęzi w Git, mogą zostać nadpisane przez następne zatwierdzenie i są wdrażane tylko w celu podglądu (nie do produkcji). Na tym właśnie polega ich zasadnicza różnica w porównaniu z wersjami z wydania: nigdy nie wiadomo, jakie konkretne zatwierdzenie się w nich znajduje.

Sensowne jest gromadzenie w obrazach tymczasowych: gałęzi master (można ją automatycznie przenieść na osobną stronę, aby na bieżąco widzieć aktualną wersję mastera), gałęzi z wydaniami, gałęzi konkretnych innowacji.

Praktyki ciągłego dostarczania z Dockerem (recenzja i wideo)
Gdy podgląd obrazów tymczasowych wymaga przełożenia na wersję produkcyjną, programiści umieszczają określony znacznik. Zbierane automatycznie według tagu zwolnij obraz (jego tag odpowiada tagowi z Git) i jest wdrażany do etapu testowania. Jeżeli zostanie pomyślnie zweryfikowany przez dział jakości, trafia do produkcji.

Dapp

Wszystko, co opisano (wdrożenie, montaż obrazu, późniejsza konserwacja) można wdrożyć samodzielnie, korzystając ze skryptów Bash i innych „improwizowanych” narzędzi. Ale jeśli to zrobisz, w pewnym momencie wdrożenie doprowadzi do dużej złożoności i słabej sterowalności. Rozumiejąc to, stworzyliśmy własne, wyspecjalizowane narzędzie Workflow do budowania CI/CD - Dapp.

Jego kod źródłowy jest napisany w języku Ruby, open source i opublikowany na GitHub. Niestety dokumentacja jest obecnie najsłabszym punktem narzędzia, ale pracujemy nad tym. A o dappie będziemy pisać i rozmawiać jeszcze nie raz, bo... Szczerze nie możemy się doczekać, aż udostępnimy jego możliwości całej zainteresowanej społeczności, ale w międzyczasie będziemy przesyłać swoje zgłoszenia i pull requesty i/lub śledzić rozwój projektu na GitHubie.

Aktualizacja 13 sierpnia 2019 r.: obecnie projekt Dapp zmieniono nazwę na werf, jego kod został całkowicie przepisany w Go, a dokumentacja została znacznie ulepszona.

Kubernetes

Kolejnym gotowym narzędziem Open Source, które zyskało już spore uznanie w środowisku zawodowym, jest Kubernetes, klaster zarządzania Dockerem. Tematyka jego wykorzystania w działaniu projektów zbudowanych na Dockerze wykracza poza zakres raportu, dlatego prezentacja ograniczyła się do przeglądu kilku ciekawych funkcjonalności.

Do wdrożenia Kubernetes oferuje:

  • sonda gotowości — sprawdzenie gotowości nowej wersji aplikacji (w celu przełączenia na nią ruchu);
  • aktualizacja krocząca - sekwencyjna aktualizacja obrazu w klastrze kontenerów (wyłączenie, aktualizacja, przygotowanie do uruchomienia, przełączanie ruchu);
  • aktualizacja synchroniczna - aktualizacja obrazu w klastrze innym podejściem: najpierw na połowie kontenerów, potem na pozostałych;
  • canary releases - uruchomienie nowego obrazu na ograniczonej (małej) liczbie kontenerów w celu monitorowania anomalii.

Ponieważ Continuous Delivery to nie tylko wydanie nowej wersji, Kubernetes ma szereg możliwości późniejszej konserwacji infrastruktury: wbudowane monitorowanie i logowanie dla wszystkich kontenerów, automatyczne skalowanie itp. To wszystko już działa i tylko czeka na właściwe wdrożenia w Twoich procesach.

Ostateczne zalecenia

  1. Użyj Dockera.
  2. Twórz obrazy platformy Docker aplikacji dostosowanych do wszystkich Twoich potrzeb.
  3. Kieruj się zasadą „Infrastruktura to kod”.
  4. Połącz Gita z Dockerem.
  5. Reguluj kolejność wdrażania.
  6. Skorzystaj z gotowej platformy (Kubernetes lub innej).

Filmy i slajdy

Film z występu (około godziny) opublikowane na YouTubie (sama relacja zaczyna się od 5 minuty - kliknij link, aby zagrać od tego momentu).

Prezentacja raportu:

PS

Inne relacje na ten temat na naszym blogu:

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

Dodaj komentarz