Kanarek to mały ptak, który ciągle śpiewa. Te ptaki są wrażliwe na metan i czad. Nawet przy niskim stężeniu szkodliwych gazów w powietrzu tracą przytomność lub umierają. Złotnicy i górnicy zabierali ze sobą ptaki: jeśli kanarki śpiewały, można było pracować, gdy przestały — w kopalni był gaz i trzeba było wychodzić. Górnicy poświęcali małego ptaka, aby wydostać się z kopalni żywym.

Podobna praktyka występuje także w IT. Na przykład w standardowym zadaniu wdrażania nowej wersji usługi lub aplikacji na produkcję z wcześniejszym testowaniem. Środowisko testowe może być zbyt kosztowne, a zautomatyzowane testy nie pokrywają wszystkiego, co byśmy chcieli, więc testowanie i poświęcanie jakości jest ryzykowne. W takich przypadkach pomaga podejście Canary Deployment, kiedy na nową wersję puszczany jest niewielki ruch z rzeczywistej produkcji. Podejście to pomaga bezpiecznie sprawdzić nową wersję na produkcji, poświęcając mało dla większego celu. Szczegóły dotyczące działania podejścia, jego zalet oraz sposobu realizacji przedstawi Andriej Markelov (), na przykładzie wdrożenia w firmie Infobip.
Andriej Markelov — wiodący inżynier-programista w Infobip, od 11 lat zajmuje się tworzeniem aplikacji w języku Java w obszarze finansów i telekomunikacji. Opracowuje produkty open source, aktywnie uczestniczy w społeczności Atlassian i pisze wtyczki do produktów Atlassian. Evangelista Prometheus, Docker i Redis.

O firmie Infobip
To globalna platforma telekomunikacyjna, która pozwala bankom, detalistom, sklepom internetowym i firmom transportowym wysyłać wiadomości do swoich klientów za pomocą SMS, powiadomień push, e-maili i wiadomości głosowych. W takim biznesie ważna jest stabilność i niezawodność, aby klienci na czas otrzymywali wiadomości.
Infrastruktura IT Infobip w liczbach:
- 15 centrów danych na całym świecie;
- 500 unikalnych usług w eksploatacji;
- 2500 instancji usług, co jest znacznie więcej niż zespołów;
- 4,5 TB miesięcznego ruchu;
- 4,5 miliarda numerów telefonów;
Biznes rośnie, a wraz z nim liczba wydania. Przeprowadzamy około 60 wydań dziennie, ponieważ klienci oczekują większych możliwości i zasobów. Ale to trudne — jest wiele usług, a mało zespołów. Musimy szybko pisać kod, który ma działać w produkcji bez błędów.
Wydania
Typowy proces wydania u nas przebiega w ten sposób. Na przykład, są usługi A, B, C, D i E, z których każda jest rozwijana przez oddzielny zespół.

W pewnym momencie zespół usługi A postanawia wdrożyć nową wersję, ale zespoły usług B, C, D i E o tym nie wiedzą. Istnieją dwa sposoby, w jaki zespół usługi A może postąpić.
Przeprowadzi wydanie inkrementalne: najpierw zamieni jedną wersję, a potem drugą.

Ale jest drugi wariant: zespół znajdzie dodatkowe zasoby i maszyny, wdroży nową wersję, a potem przełączy router, a wersja zacznie działać w produkcji.

W każdym wariancie po wdrożeniu niemal zawsze pojawiają się problemy, nawet jeśli wersja została przetestowana. Można testować ręcznie, można automatycznie, można nie testować — problemy i tak się pojawią. Najprostszym i najwłaściwszym sposobem ich rozwiązania jest powrót do działającej wersji. Potem można już zająć się stratami, przyczynami i je naprawić.
Więc czego chcemy?
Problemy są nam niepotrzebne. Jeśli klienci odkryją je szybciej niż my, wpłynie to na naszą reputację. Dlatego musimy znajdować problemy szybciej niż klienci.Działając wyprzedzająco, minimalizujemy straty.
Jednocześnie chcemy przyspieszyć wdrożenie, aby odbywało się szybko, łatwo, naturalnie i bez napięcia ze strony zespołu. Inżynierów, inżynierów DevOps i programistów trzeba chronić — wydanie nowej wersji to stres. Zespół nie jest materiałem eksploatacyjnym, dążymy do racjonalnego wykorzystania zasobów ludzkich..
Problemy z wdrożeniem
Ruch klientów jest nieprzewidywalny.Nie można przewidzieć, kiedy ruch klientów będzie minimalny. Nie wiemy, gdzie i kiedy klienci rozpoczną swoje kampanie — może dziś w nocy w Indiach, a jutro w Hongkongu. Biorąc pod uwagę dużą różnicę czasową, wdrożenie nawet o 2 w nocy nie gwarantuje, że klienci nie ucierpią.
Problemy dostawców.Komunikatory i dostawcy są naszymi partnerami. Czasami mają awarie, które powodują błędy podczas wdrożeń nowych wersji.
Rozproszone zespoły.Zespoły, które rozwijają część kliencką i backend, znajdują się w różnych strefach czasowych. Z tego powodu często nie mogą się ze sobą dogadać.
Centra danych nie mogą być powielane w środowisku testowym.W jednym centrum danych jest 200 szaf — nawet zbliżone powtórzenie tego w piaskownicy nie jest możliwe.
Czasy przestojusą niedopuszczalne! Mamy dopuszczalny poziom dostępności (Budżet Błędów), gdy pracujemy 99,99% czasu, a pozostałe procenty to «prawo do błędu». Osiągnięcie 100% niezawodności jest niemożliwe, ale ważne jest, aby stale monitorować awarie i przestoje.
Klasyczne opcje rozwiązania
Pisanie kodu bez błędów. Gdy byłem młodym programistą, menedżerowie przychodzili do mnie z prośbą o wydanie bez błędów, ale to nie zawsze jest możliwe.
Pisanie testów. Testy działają, ale czasami zupełnie inaczej, niż oczekuje biznes. Zarabianie pieniędzy to nie jest zadanie testów.
Testowanie na etapie. Przez 3,5 roku mojej pracy w Infobip nigdy nie widziałem, aby stan etapu chociaż częściowo pokrywał się z produkcją.

Nawet próbowaliśmy rozwinąć ten pomysł: najpierw mieliśmy etap, potem preprodukcję, a następnie preprodukcję preprodukcji. Ale to też nie pomogło — nie zgadzały się nawet pod względem mocy. Z etapem możemy zapewnić podstawową funkcjonalność, ale nie wiemy, jak będzie działać pod obciążeniem.
Wydanie robi ten, kto rozwijał. To dobra praktyka: nawet jeśli ktoś zmienia nazwę komentarza, od razu dodaje do produkcji. To pomaga rozwijać odpowiedzialność i nie zapominać o wprowadzonych zmianach.
Dodatkowe trudności też istnieją. Dla programisty to stres — tracić dużo czasu na ręczne sprawdzanie wszystkiego.
Uzgodnione wydania. Ta opcja jest zazwyczaj proponowana przez zarząd: „Zgódźmy się, że codziennie będziecie testować i dodawać nowe wersje”. To nie działa: zawsze jest zespół, który czeka na wszystkich innych lub odwrotnie.
Testy smoke
Jeszcze jeden sposób na rozwiązanie naszych problemów z wdrożeniem. Zobaczmy, jak działają testy smoke na poprzednim przykładzie, kiedy zespół A chce wdrożyć nową wersję.
Na początku zespół wdraża jeden instans na produkcję. Wiadomości do instancji od mocków imitują rzeczywisty ruch, aby odpowiadał normalnemu codziennemu ruchowi. Jeśli wszystko jest w porządku, zespół przełącza nową wersję na ruch użytkowników.

Druga opcja — wdrożenie z dodatkowym sprzętem. Zespół testuje go na produkcji, potem przełącza i wszystko działa.

Wady testów smoke:
- Testom nie można ufać. Gdzie zdobyć ten sam ruch, co na produkcji? Można użyć ruchu z wczoraj lub sprzed tygodnia, ale nie zawsze będzie on zgodny z aktualnym.
- Trudno utrzymać. Będzie trzeba utrzymywać konta testowe, ciągle je resetując przed każdym wdrożeniem, gdy w magazynie zostaną wysłane aktywne zapisy. To trudniejsze niż pisanie testu w swoim piaskownicy.
Jedynym bonusem tutaj jest możliwość sprawdzenia wydajności.
Wydania canary
Z powodu wad testów smoke zaczęliśmy używać wydań canary.
Praktyka podobna do tej, jaką górnicy używali kanarek do sygnalizowania poziomu gazów, znalazła swoje miejsce również w IT. Wpuszczamy trochę prawdziwego ruchu produkcyjnego na nową wersję, starając się jednocześnie zmieścić w umowie poziomu usług (SLA). SLA to nasze "prawo do błędu", które możemy wykorzystać raz w roku (lub w jakimś innym przedziale czasowym). Jeśli wszystko pójdzie dobrze, dodamy więcej ruchu. Jeśli nie — przywrócimy poprzednie wersje.

Realizacja i szczegóły
Jak zrealizowaliśmy wydania canary? Na przykład grupa klientów wysyła wiadomości przez nasz serwis.

Wdrożenie przebiega tak: usuwamy jeden węzeł z równoważenia obciążenia (1), zmieniamy wersję (2) i osobno puszczamy trochę ruchu (3).

Ogólnie rzecz biorąc, w grupie wszyscy będą zadowoleni, nawet jeśli jeden użytkownik będzie niezadowolony. Jeśli wszystko pójdzie dobrze — zmieniamy wszystkie wersje.

Pokażę schematycznie, jak to wygląda dla mikroserwisów w większości przypadków.
Istnieje Odkrywanie Usług i jeszcze dwa serwisy: S1N1 i S2. Pierwszy serwis (S1N1) informuje Odkrywanie Usług, gdy uruchamia się, a Odkrywanie Usług go zapamiętuje. Drugi serwis z dwoma węzłami (S2N1 i S2N2) również informuje Odkrywanie Usług podczas uruchamiania.

Drugi serwis dla pierwszego działa jako serwer. Pierwszy pyta Odkrywanie Usług o informacje o swoich serwerach, a gdy je otrzyma, szuka i sprawdza je ("health check"). Po sprawdzeniu, wysyła im wiadomości.
Gdy ktoś chce wdrożyć nową wersję drugiego serwisu, informuje Odkrywanie Usług, że drugi węzeł będzie węzłem canary: ruch będzie do niego kierowany w mniejszej ilości, ponieważ teraz odbędzie się wdrożenie. Usuwamy węzeł canary z równoważenia obciążenia, a pierwszy serwis nie wysyła do niego ruchu.

Zmiana wersji, a Service Discovery wie, że druga węzeł to teraz canary — można jej przydzielić mniejsze obciążenie (5%). Jeśli wszystko pójdzie dobrze, zmieniamy wersję, przywracamy obciążenie i kontynuujemy pracę.
Aby to wszystko zrealizować, potrzebujemy:
- równoważenia obciążenia;
- monitoring, ponieważ ważne jest, aby wiedzieć, czego oczekuje każdy użytkownik i jak szczegółowo działają nasze usługi;
- analizy wersji, aby zrozumieć, jak dobrze nowa wersja będzie działać w środowisku produkcyjnym;
- automatyzacja — piszemy sekwencję wdrożenia (deployment pipeline).

Równoważenie
To pierwsze, o czym musimy pomyśleć. Istnieją dwie strategie równoważenia obciążenia.
Najprostsza opcja, w której jeden węzeł zawsze jest canary. Ten węzeł zawsze otrzymuje mniej ruchu, a my zaczynamy wdrożenie od niego. W przypadku problemów porównamy jego działanie przed wdrożeniem i podczas niego. Na przykład, jeśli liczba błędów wzrosła dwukrotnie, to również szkody wzrosły dwukrotnie.
Węzeł canary jest ustalany w procesie wdrożenia. Gdy wdrożenie się zakończy i usuniemy status węzła canary, równowaga ruchu zostanie przywrócona. Z mniejszą liczbą maszyn uzyskamy uczciwą dystrybucję.
Monitoring
Kamień węgielny wydań canary. Musimy dokładnie rozumieć, dlaczego to robimy i jakie metryki chcemy zbierać.
Przykłady metryk, które zbieramy z naszych usług.
- Liczba błędów, które są zapisywane w logach. To oczywisty wskaźnik, że wszystko działa jak należy. Generalnie, to dobra metryka.
- Czas przetwarzania zapytań (latency). Tę metrykę monitorują wszyscy, ponieważ wszyscy chcą działać szybko.
- Rozmiar kolejki (throughput).
- Liczba udanych odpowiedzi na sekundę.
- Czas przetwarzania 95% wszystkich zapytań.
- Metryki biznesowe: ile pieniędzy zarabia biznes w określonym czasie lub odpływ użytkowników. Te metryki mogą być ważniejsze dla naszej nowej wersji niż te, które dodają inżynierowie.
Przykłady metryk w większości popularnych systemów monitorowania.
Counter. To pewna rosnąca wartość, na przykład liczba błędów. Tę metrykę łatwo interpolować i analizować wykres: wczoraj było 2 błędy, a dziś 500, to znaczy, że coś poszło nie tak.
Liczba błędów na minutę lub na sekundę, to najważniejszy wskaźnik, który można obliczyć za pomocą Counter. Te dane dają wyraźny obraz działania systemu na dystansie. Rozważmy na przykład wykres liczby błędów na sekundę dla dwóch wersji systemu produkcyjnego.

W pierwszej wersji było mało błędów, być może audyt nie działał. W drugiej wersji jest znacznie gorzej. Możemy z całą pewnością stwierdzić, że występują problemy, więc musimy cofnąć tę wersję.
Gauge. Metryki są podobne do Counter, ale rejestrujemy wartości, które mogą zarówno wzrastać, jak i maleć. Na przykład czas realizacji zapytań lub rozmiar kolejki.
Na wykresie przykład czasu opóźnienia (latency). Widać, że wersje są podobne, można z nimi pracować. Ale jeśli się przyjrzeć, widać, jak zmienia się rozmiar. Jeśli czas realizacji zapytań wzrasta w miarę dodawania użytkowników, od razu widać, że są problemy — wcześniej tak nie było.

Summary. Jednym z najważniejszych wskaźników dla biznesu są percentyle. Metryka pokazuje, że w 95% przypadków nasz system działa tak, jak chcemy. Możemy pogodzić się z problemami, gdzieś, ponieważ rozumiemy ogólną tendencję, jak dobrze lub źle to wszystko wygląda.
Narzędzia
ELK Stack. Można zaimplementować canary, korzystając z Elasticsearch — zapisujemy w nim błędy, gdy występują zdarzenia. Prostym wywołaniem API możemy uzyskać liczbę błędów w dowolnym momencie i porównać z poprzednimi okresami: GET /applg/_cunt?q=level:errr.
Prometheus. Dobrze sprawdził się w Infobip. Umożliwia realizację wielowymiarowych metryk, ponieważ używane są etykiety.
Możemy używać level, instance, service, łącząc je w jednym systemie. Dzięki offset można zobaczyć na przykład wartość wielkości sprzed tygodnia jednym poleceniem GET /api/v1/query?query={query}, gdzie {query}:
rate(logback_appender_total{
level="error",
instance=~"$instance"
}[5m] offset $offset_value)Analiza wersji
Istnieje kilka strategii analizy wersji.
Patrzeć na metryki tylko canary-nody. Jedna z najprostszych opcji: wdrożono nową wersję i badamy tylko działanie. Ale jeśli w tym czasie inżynier zacznie przeglądać logi, ciągle nerwowo odświeżając strony, to to rozwiązanie niewiele różni się od innych.
Canary-noda jest porównywana z dowolną inną nodą. To porównanie z innymi instancjami, które działają na pełnym ruchu. Na przykład, jeśli przy małym ruchu sytuacja jest gorsza lub nie lepsza niż na prawdziwych instancjach, to coś jest nie tak.
Canary-noda jest porównywana z samą sobą w przeszłości. Węzły przydzielone dla canary można porównywać z danymi historycznymi. Na przykład, jeśli tydzień temu wszystko było w porządku, możemy się oprzeć na tych danych, aby zrozumieć obecną sytuację.
Automatyzacja
Chcemy uwolnić inżynierów od ręcznego porównywania, dlatego ważne jest wdrożenie automatyzacji. Proces wdrożenia (deployment pipeline) zazwyczaj wygląda następująco:
- rozpoczynamy;
- usuwamy węzeł z pod balansownika;
- stawiamy węzeł canary;
- włączamy balansownik z ograniczoną ilością ruchu;
- porównujemy.

Na tym etapie realizujemy automatyczne porównanie. Jak może to wyglądać i dlaczego jest lepsze niż sprawdzanie po wdrożeniu, omówimy na przykładzie z Jenkins.
To jest pipeline w Groovy.
while (System.currentTimeMillis() < endCanaryTs) {
def isOk = compare(srv, canary, time, base, offset, metrics)
if (isOk) {
sleep DEFAULT SLEEP
} else {
echo "Canary nie powiodło się, trzeba cofnąć"
return false
}
} Tutaj w pętli określamy, że będziemy porównywać nowy węzeł przez godzinę. Jeśli proces canary jeszcze się nie zakończył — wywołujemy funkcję. Informuje nas ona, czy wszystko jest w porządku, czy nie: def isOk = compare(srv, canary, time, base, offset, metrics).
Jeśli wszystko dobrze — sleep DEFAULT SLEEP, na przykład, na sekundę, i kontynuujemy. Jeśli nie, wychodzimy — wdrożenie nie powiodło się.
Opis metryki. Zobaczmy, jak może wyglądać funkcja compare na przykładzie DSL.
metric(
'errorCounts',
'rate(errorCounts{node=~"$canaryInst"}[5m] offset $offset)',
{ baseValue, canaryValue ->
if (canaryValue > baseValue * 1.3) return false
return true
}
)Załóżmy, że porównujemy liczbę błędów i chcemy wiedzieć, ile błędów na sekundę wystąpiło w ciągu ostatnich 5 minut.
Mamy dwie wartości: podstawową i węzła canary. Wartość w węźle canary — to wartość aktualna. Podstawowa — baseValue — to wartość jakiegokolwiek innego węzła, który nie jest canary. Porównujemy wartości między sobą na podstawie formuły, którą ustalamy na podstawie swojego doświadczenia i obserwacji. Jeśli wartość canaryValue jest zła, wdrożenie się nie udało, i wracamy do poprzedniej wersji.
Po co to wszystko?
Człowiek nie jest w stanie sprawdzić setek i tysięcy metryk, tym bardziej zrobić to szybko. Automatyczne porównanie pomaga sprawdzić wszystkie metryki i szybko powiadamia o problemach. Czas powiadomienia jest krytyczny: jeśli coś stało się w ciągu ostatnich 2 sekund, to szkody będą mniejsze, niż gdyby wydarzyło się to 15 minut temu. Zanim ktoś zauważy problem, napisze do wsparcia, a wsparcie nas o cofnięcie, możemy stracić klientów.
Jeśli proces się powiódł i wszystko jest w porządku, automatycznie wdrażamy pozostałe węzły. W tym czasie inżynierowie nic nie robią. Dopiero gdy uruchamiają wersję canary, decydują, które metryki wziąć, jak długo porównywać, jaką strategię zastosować.

Jeśli pojawią się problemy — automatycznie wycofujemy węzeł canary, pracujemy na poprzednich wersjach i rozwiązujemy znalezione błędy. Na podstawie metryk łatwo je znaleźć i zobaczyć szkody spowodowane nową wersją.
Przeszkody
Osiągnięcie tego nie jest łatwe. Przede wszystkim potrzebna jest ogólna system monitorowania. Inżynierowie mają swoje metryki, wsparcie i analitycy — inne, a biznes ma jeszcze inne. Ogólny system to wspólny język, którym posługują się biznes i rozwój.
Musimy sprawdzić w praktyce stabilność metryk. Weryfikacja pomaga zrozumieć, jaki minimalny zestaw metryk jest potrzebny, aby zapewnić jakość..
Jak to osiągnąć? Używać usługi canary nie w momencie wdrożenia. Dodajemy do starej wersji pewną usługę, która w każdej chwili będzie mogła zająć dowolny przydzielony węzeł, zmniejszyć ruch bez wdrożenia. Następnie porównujemy: analizujemy błędy i szukamy granicy, w której osiągamy jakość.

Jaką korzyść uzyskaliśmy z wydań canary
Zminimalizowaliśmy procent szkód spowodowanych błędami. Większość błędów podczas wdrożeń wynika z niespójności danych lub priorytetów. Takich błędów jest znacznie mniej, ponieważ możemy rozwiązać problemy w ciągu pierwszych sekund.
Zoptymalizowaliśmy pracę zespołów. Nowicjusze mają 'prawo do błędu': mogą wdrażać na produkcję bez obaw o pomyłki, co daje dodatkową inicjatywę i motywację do pracy. Jeśli coś zepsują, nie będzie to krytyczne, a osoba, która popełniła błąd, nie zostanie zwolniona.
Zautomatyzowaliśmy wdrożenie. To już nie jest ręczny proces, jak wcześniej, lecz prawdziwie zautomatyzowany. Jednak trwa to dłużej.
Wydzieliliśmy ważne metryki. Cała firma, od biznesu po inżynierów, rozumie, co jest rzeczywiście ważne w naszym produkcie, jakie metryki, na przykład odpływ i napływ użytkowników. Kontrolujemy proces: testujemy metryki, wprowadzamy nowe, obserwujemy, jak działają stare, aby budować system, który będzie bardziej wydajny w generowaniu przychodów.
Mamy wiele świetnych praktyk i systemów, które nam pomagają. Niemniej jednak, dążymy do tego, aby być profesjonalistami i wykonywać swoją pracę na wysokim poziomie, niezależnie od tego, czy mamy system, który nas wspiera, czy nie.
Podejścia i praktyki inżynieryjne — . Jeśli osiągnęliście sukcesy w drodze do technicznej doskonałości i chcecie podzielić się tym, co Wam w tym pomogło — .
Planujemy zorganizować 8 czerwca. Rozumiemy, że obecnie trudno podjąć decyzję o udziale w konferencji. Jednak uważamy, że kwarantanna nie jest powodem do zatrzymania profesjonalnej komunikacji i rozwoju. Dlatego w każdym przypadku znajdziemy sposób, aby omówić wyzwania liderów technicznych i podejścia do ich rozwiązywania — jeśli zajdzie taka potrzeba, przeniesiemy się online i rozwinemy networking tam!
Źródło: habr.com
