Deployment utknął w kolejce: co sprawdzić najpierw
Deployment utknął w kolejce zwykle dlatego, że czeka na coś poza procesem builda. Dowiedz się, co oznacza kolejkowanie, jak odróżnić oczekiwanie od zawieszenia i jak uruchomić zablokowany release.
Deployment utknął w kolejce to jeden z najmniej informacyjnych komunikatów o błędzie, jakie może pokazać platforma. Nic się nie zawiesiło. Nie pojawiły się żadne logi, ponieważ nic się jeszcze nie uruchomiło. Release po prostu pozostaje w miejscu, a po każdym odświeżeniu widzisz to samo słowo.
Najbardziej frustrujące jest to, że „queued” może oznaczać co najmniej cztery różne sytuacje, które nie mają ze sobą nic wspólnego. Ustalenie, z którą z nich masz do czynienia, zajmuje około trzydziestu sekund i pozwala zdecydować, czy należy poczekać, ponowić próbę, czy sprawdzić coś zupełnie innego.
Co tak naprawdę oznacza „queued”
Deployment w kolejce został zaakceptowany i zapisany, ale nie przydzielono mu jeszcze workera. Pomiędzy tymi dwoma momentami musi zostać spełnionych kilka warunków:
- Platforma musi pobrać kod źródłowy, co zwykle oznacza wywołanie API dostawcy Git.
- Musi być dostępny slot builda.
- Każdy warunek wstępny release’a musi zostać ukończony — krok migracji, operacja na volume albo wcześniejszy deployment tej samej usługi.
Jeśli którykolwiek z tych elementów jest zablokowany, rekord istnieje, ale praca się nie rozpoczyna. To cały mechanizm. Nie ma w nim żadnej tajemnicy, ale większość dashboardów pokazuje wszystkie cztery przypadki za pomocą tego samego słowa.
Cztery przypadki — w kolejności, w jakiej warto je sprawdzać
1. Twój dostawca Git ma gorszy dzień
To najczęstsza przyczyna i jedyna, na którą nie masz wpływu. Platforma poprosiła o dostęp do repozytorium, ale otrzymała opóźnioną odpowiedź albo błąd. Jeśli kilka niezależnych usług trafia do kolejki w tym samym czasie, a żadna z nich nie korzysta ze wspólnego kodu, wspólną zależnością jest właśnie dostawca.
Najpierw sprawdź stronę statusu swojego dostawcy. Deployment oczekujący na upstream API zakończy oczekiwanie sam, a ponowienie próby tylko doda kolejny rekord do stosu — dlatego zablokowana kolejka tak często zamienia się w pięć zablokowanych kolejek.
2. Coś, co było przed nim, jeszcze się nie zakończyło
Większość platform szeregowo wykonuje deploymenty dla danej usługi — i słusznie: dwa buildy zapisujące ten sam tag obrazu to wyścig, którego nie chcesz wygrać. Jeśli wcześniejszy deployment tej usługi nadal działa — albo, co gorsza, system nadal uważa, że działa, ponieważ worker zakończył pracę bez wysłania informacji — kolejny deployment czeka.
W Dockup polecenie dockup deployments wyświetla historię od najnowszych wpisów, wraz ze statusem każdego z nich. Jeśli deployment znajdujący się nad zablokowanym release’em nie ma jeszcze statusu końcowego, to właśnie znalazłeś odpowiedź — anulowanie go albo zaczekanie, aż przekroczy limit czasu, odblokuje kolejkę.
dockup deployments my-project/my-api --json
Dane wyjściowe --json zawierają status i czas trwania każdego deploymentu, dzięki czemu „poprzedni nigdy się nie zakończył” widać od razu — w przeciwieństwie do samego spinnera.
3. Brak dostępnych zasobów
Każda platforma ma ograniczoną liczbę workerów builda. Na współdzielonym planie nagły wzrost aktywności w całej platformie może sprawić, że trafisz za buildy innych użytkowników. To realna sytuacja, zwykle krótkotrwała, i jedyny przypadek, w którym czekanie jest rzeczywiście właściwym rozwiązaniem.
Ważne jest to, czy możesz to zobaczyć. Pozycja w kolejce albo szacowany czas oczekiwania zmieniają doświadczenie przypominające awarię w coś zupełnie normalnego. Samo „queued” nie daje takiej informacji.
4. Deployment nigdy nie miał się uruchomić
Najgorszy przypadek: rekord został utworzony, ale element, który miał go przejąć, nigdy tego nie zrobił. Worker uległ awarii, webhook został utracony albo token wygasł pomiędzy wyzwoleniem procesu a pobraniem kodu.
Najważniejszą wskazówką jest czas. Oczekiwanie w kolejce mierzy się w sekundach lub najwyżej kilku minutach. Deployment, który pozostaje w kolejce przez dziesięć minut, mimo że przed nim nie ma żadnego innego release’a, nie czeka — jest zablokowany i taki pozostanie.
Jak odróżnić oczekiwanie od zawieszenia
Zanim ponowisz próbę, zbierz trzy informacje:
- Czy trwa inny deployment? Jeśli działa inny release tej samej usługi, masz do czynienia z przypadkiem 2 i powinieneś niczego nie zmieniać.
- Jak długo deployment jest w kolejce? Mniej niż dwie minuty to norma. Ponad dziesięć — już nie.
- Czy inne usługi trafiły do kolejki w tym samym czasie? Jeśli niezależne usługi zatrzymały się jednocześnie, sprawdź upstream, a nie swój kod.
Te trzy odpowiedzi niemal zawsze pozwalają odróżnić „poczekaj” od „działaj”.
Dlaczego ponawianie próby zwykle pogarsza sytuację
Naturalną reakcją na zablokowany release jest ponowne kliknięcie przycisku deploy. W szeregowym pipeline’ie przynosi to efekt przeciwny do zamierzonego: dodajesz drugi rekord za pierwszym, a jeśli pierwszy rzeczywiście jest zablokowany, drugi dziedziczy tę blokadę. Deweloperzy, którzy często na to trafiają, kończą z kolumną wpisów w kolejce — żaden z nich nie uruchomi się, dopóki pierwszy element kolejki nie zostanie usunięty.
Jeśli zamierzasz ponowić próbę, najpierw anuluj zablokowany deployment. Jeden deployment w kolejce, który kończy się widocznym błędem, jest znacznie bardziej użyteczny niż pięć wpisów, które po prostu czekają.
Jak rozwiązujemy ten problem w Dockup
Najważniejsza decyzja projektowa polega na tym, że deployment nigdy nie jest tylko uznawany za uruchomiony. Każdy deployment ma status końcowy, a jego osiągnięcie zwalnia kolejkę. Build, który zakończy się bez wysłania informacji, również przekroczy limit czasu i zwolni usługę.
Dwie inne rzeczy pomagają bardziej, niż mogłoby się wydawać:
Etapy mają nazwy. Deployment w Dockup przechodzi przez pobieranie kodu źródłowego, build i health gate, a każdy etap zapisuje własny czas trwania. Gdy coś działa wolno, widzisz, co dokładnie jest wolne, zamiast obserwować jedno słowo. stageTimings znajduje się w każdym rekordzie deploymentu, także w danych zwracanych przez --json.
Za release’em, który już zakończył się błędem, nic nie pozostaje w kolejce. Jeśli health check nigdy się nie powiedzie, deployment się kończy — nie zajmuje usługi, gdy zastanawiasz się, co się dzieje. Poprzednia wersja przez cały czas nadal obsługuje ruch, co jest drugim powodem, dla którego zablokowany release nie oznacza awarii w Dockup.
# Jaki jest bieżący stan i ile trwał każdy etap?
dockup status my-project/my-api --json
# Śledź build w czasie rzeczywistym zamiast czekać na podsumowanie
dockup logs my-project/my-api --build --follow
Ogólna zasada
Kolejkowanie samo w sobie nie jest trybem awarii. Jest nim kolejkowanie bez podanego powodu. Każda platforma od czasu do czasu każe ci czekać na dostawcę Git albo dostępny slot builda; różnica między pięciominutową niedogodnością a straconym popołudniem polega na tym, czy interfejs informuje, z którym z czterech przypadków masz do czynienia.
Gdy oceniasz, gdzie uruchomić daną usługę, warto sprawdzić to celowo: uruchom deployment i zobacz, co platforma pokazuje pomiędzy jego zaakceptowaniem a startem. Jeśli odpowiedzią jest jedno słowo bez znacznika czasu, prędzej czy później stracisz na tym całe popołudnie.
Najczęściej zadawane pytania
Jak długo deployment powinien pozostawać w kolejce? Od kilku sekund do kilku minut na sprawnej platformie. Wszystko powyżej dziesięciu minut, jeśli przed deploymentem nie ma niczego w kolejce, należy traktować jako zablokowanie, a nie zwykłe opóźnienie.
Czy powinienem ponowić deployment znajdujący się w kolejce? Nie, najpierw go anuluj. W szeregowym pipeline’ie ponowiona próba trafi za zablokowany deployment i odziedziczy tę samą blokadę.
Czy zablokowany deployment wyłączy moją stronę? Nie powinien. Na platformie, która przełącza ruch dopiero po przejściu health checku przez nowy release, działająca wersja nadal obsługuje ruch — deployment znajdujący się w kolejce lub zakończony błędem to release, który nigdy nie został uruchomiony, a nie awaria.
Dlaczego kilka usług trafia do kolejki jednocześnie? Ponieważ korzystają ze wspólnej zależności — niemal zawsze jest nią dostawca Git albo infrastruktura buildów, a nie coś w twoim kodzie.
