Nieudana ponowna publikacja nigdy nie usuwa działającego backendu
25 września nieudana ponowna publikacja usunęła backend aplikacji, który działał bez zarzutu od około dwóch i pół godziny. Kod cofający nieudaną publikację usunął każdą aplikację serwerową, której publikacja dotknęła, w tym te, które już wcześniej obsługiwały ruch. Teraz usuwane są wyłącznie aplikacje utworzone przez daną publikację. Aplikacja, która już istniała, jest przywracana do dokładnie tej wersji, na której działała wcześniej. Dwie kolejne poprawki wprowadzone tego samego dnia zapewniły, że cofanie działa także wtedy, gdy narzędzie wdrożeniowe platformy hostingowej zawiedzie, oraz że zdrowa aplikacja nie jest oznaczana jako błędna tylko dlatego, że spała.
Jak publikowany jest backend
Gdy Twoja aplikacja Mythex ma backend, czyli API lub serwer, a nie tylko pliki statyczne, publikacja buduje go z Dockerfile (przepisu na spakowanie aplikacji w obraz) i wdraża ten obraz na maszyny naszej platformy hostingowej. Następnie kontrola stanu czeka, aż nowa wersja faktycznie wstanie i będzie stabilnie działać. Dopiero wtedy publikacja zostaje oznaczona jako aktywna.
Jeśli coś po drodze zawiedzie, uruchamia się wycofanie, które cofa zmiany. Poprawne wycofanie jest ważniejsze niż prawie cokolwiek innego w publikacji, bo uruchamia się dokładnie wtedy, gdy coś już idzie nie tak.
Problem 1: wycofanie usuwało to, co miało przywrócić
Wycofanie prowadziło listę aplikacji serwerowych, do których publikacja wdrażała, i przy błędzie niszczyło każdą z nich. Przy pierwszej publikacji to poprawne zachowanie: aplikacja została przed chwilą utworzona, nic od niej nie zależy, a jej usunięcie zostawia wszystko tak, jak było.
Przy ponownej publikacji to dokładnie błąd. Aplikacja już istniała i obsługiwała prawdziwych odwiedzających. 25 września API aplikacji, działające od około dwóch i pół godziny, zostało usunięte przez nieudaną ponowną publikację.
W tym samym kodzie kryła się druga awaria. Gdy usunięcie się nie powiodło, uszkodzony nowy obraz zostawał na maszynach, a my jednocześnie informowaliśmy właściciela, że obecna strona nadal działa. Do czasu, gdy kontrola stanu może zawieść, nowy obraz jest już wgrany na każdą maszynę. Nic nierobienie to nie to samo co cofnięcie.
Poprawka: usuwaj tylko to, co sam utworzyłeś, a resztę przywracaj
Każda publikacja zapisuje teraz, dla każdej aplikacji serwerowej, której dotyka:
- czy ta publikacja ją utworzyła, oraz
- jeśli nie, jakiego obrazu używała tuż przed nią.
Przy błędzie każda aplikacja dostaje jedno z trzech traktowań:
- Utworzona przez tę publikację: usuń ją, jak wcześniej.
- Istniała, poprzedni obraz znany: ponownie wdroż poprzedni obraz z tą samą konfiguracją. Bez budowania, przenoszony jest tylko obraz.
- Istniała, poprzedni obraz nieznany: nie ruszaj jej. Istniejąca aplikacja nigdy nie jest usuwana, nawet gdy nie da się jej przywrócić.
Te reguły to mała, czysta funkcja z własnymi testami, więc decyzja nie może wrócić do postaci „usuń wszystko” bez tego, że jakiś test zawiedzie.
Problem 2: narzędzie wdrożeniowe mogło zawieść, zanim zapisaliśmy, jak cofnąć
Wkrótce po tej poprawce znaleźliśmy w niej lukę. Narzędzie wdrożeniowe platformy hostingowej uruchamia własne testy dymne: jeśli nowe maszyny się wywrócą, kończy się błędem. Dzieje się to jednak po tym, jak nowy obraz trafił już na maszyny.
Nasz kod rejestrował aplikację do wycofania dopiero wtedy, gdy narzędzie zwróciło sukces. Gdy samo narzędzie zawiodło wdrożenie, aplikacji nie było jeszcze na liście wycofania i nic nie zostało przywrócone. Na naszym środowisku stagingowym zepsuta publikacja zostawiła w działaniu uszkodzony obraz.
Poprawka: zarejestruj cofnięcie przed startem
Aplikacja jest teraz rejestrowana do wycofania, wraz z informacją, czy została utworzona i jaki obraz uruchamiała, zaraz po przygotowaniu, a przed wgraniem czegokolwiek na nią. Cokolwiek zawiedzie potem, wycofanie wie, co przywrócić. Sprawdziliśmy to lokalnie: zepsuta ponowna publikacja zawiodła w testach dymnych samego narzędzia wdrożeniowego, a poprzednia wersja dalej odpowiadała.
Problem 3: uśpiona aplikacja została oznaczona jako „nigdy nie wystartowała”
Opublikowane aplikacje w Mythex usypiają, gdy są bezczynne, żeby oszczędzać kredyty. Ponowna publikacja zostawia uśpioną maszynę zatrzymaną, więc kontrola stanu musi ją obudzić. Prosiła platformę o uruchomienie maszyny raz i ignorowała odpowiedź.
25 września ta jedna prośba o start poszła donikąd. Zdrowe API stało zatrzymane przez pełne pięć minut kontroli stanu i zostało oznaczone jako błąd: „1 machine never started (last state: stopped)”.
Platforma czasem odmawia startu. Podczas odtwarzania problemu zwróciła konflikt „lease currently held” bez naszej prowokacji, a odmawia startów także wtedy, gdy maszyna jest w trakcie aktualizacji.
Poprawka: pytaj dalej i zapukaj do drzwi
Kontrola stanu teraz:
- pyta ponownie o uruchomienie zatrzymanej maszyny co 20 sekund, dopóki czeka,
- zapisuje, co platforma odpowiedziała, gdy odmówiła, oraz
- wysyła do aplikacji jedno zwykłe żądanie, tak jak zrobiłby to odwiedzający. Proxy platformy budzi uśpioną maszynę, gdy nadejdzie żądanie.
Odtworzyliśmy problem na prawdziwej platformie, na tymczasowej aplikacji, której pierwszy start został odrzucony. Przed poprawką publikacja zawiodła po 91 sekundach. Po poprawce opublikowała się w 20 sekund. Aplikacja, która naprawdę wywala się przy starcie, nadal zawiedzie, tak jak powinna.
Co z tego wynieśliśmy
- Wycofanie musi odróżniać nowe od istniejących. „Cofnięcie” czegoś, co utworzyłeś, oznacza usunięcie. „Cofnięcie” czegoś, co już było, oznacza przywrócenie. Traktowanie obu tak samo to sposób, w jaki mechanizm bezpieczeństwa kasuje działającą aplikację.
- Zapisz, jak cofnąć, zanim zaczniesz działać. Jeśli cofnięcie rejestrujesz dopiero po sukcesie kroku, krok, który zawiedzie w połowie, nie zostawia niczego do cofnięcia.
- Nigdy nie ignoruj odpowiedzi na prośbę, od której zależysz. Jedno zignorowane „nie” zamieniło zdrową aplikację w nieudaną publikację.
Powiązana poprawka z tego samego dnia: wykrywanie aplikacji, które padają tuż po publikacji. O tym, co dzieje się, gdy publikacja zawiedzie po Twojej stronie, przeczytasz w rozwiązywaniu problemów z publikacją w dokumentacji.