Deployment, заседнал в опашката: какво да проверите първо
Deployment, заседнал в опашката, обикновено чака нещо извън вашия build. Научете какво означава queueing, как да различите изчакване от блокиране и как да задвижите заседнал release.
Deployment, заседнал в queued, е един от най-малко информативните проблеми, които една платформа може да ви покаже. Нищо не е сринато. Няма логове, защото нищо не е стартирало. Release-ът просто стои там и при всяко презареждане виждате същата дума.
Най-дразнещото е, че „queued“ обхваща поне четири различни ситуации, които нямат нищо общо помежду си. Да разберете в коя от тях се намирате, отнема около тридесет секунди и определя дали трябва да изчакате, да направите retry или да потърсите причината някъде съвсем другаде.
Какво всъщност означава „queued“
Queued deployment е приет и записан, но все още не му е назначен worker. Между тези два момента трябва да са изпълнени няколко условия:
- Платформата трябва да изтегли source кода ви, което обикновено означава API call към вашия Git provider.
- Трябва да има свободен build slot.
- Всеки prerequisite в release-а трябва да е приключил — migration стъпка, volume операция или по-ранен deployment на същия service.
Ако някое от тези неща е блокирано, записът съществува, но работата не започва. Това е целият механизъм. Не е мистерия, но повечето dashboard-и визуализират и четирите случая с една и съща дума.
Четирите случая в реда, в който е най-разумно да ги проверите
1. Вашият Git provider има проблеми
Това е най-честата причина и тази, по която не можете да направите нищо. Платформата е поискала repository-то ви и е получила бавен отговор или грешка. Ако няколко несвързани service-а влязат в queue по едно и също време и нямат общ код, shared dependency-то е provider-ът.
Проверете status page-а на provider-а си преди всичко останало. Deploy, който чака upstream API, ще се изчисти сам, а retry-ването само добавя още един запис към купчината — затова заседналата queue толкова често се превръща в пет заседнали queue-и.
2. Нещо преди него още не е приключило
Повечето платформи сериализират deployment-ите за всеки service, и с основание: два build-а, които записват един и същ image tag, не са race condition, която искате да спечелите. Ако по-ранен deployment на този service все още се изпълнява — или, още по-лошо, системата все още смята, че се изпълнява, защото worker-ът е прекъснал работа, без да докладва — следващият изчаква.
В Dockup dockup deployments показва историята, започвайки с най-скорошния запис, заедно със status-а на всеки от тях. Ако записът над вашия queued release не е в terminal state, това е отговорът ви, а cancel-ването му или изчакването да изтече timeout-ът е това, което освобождава опашката.
dockup deployments my-project/my-api --json
Изходът с --json включва status-а и duration-а на всеки deployment, което прави очевидно, че „предишният така и не е приключил“ — по начин, по който един spinner не може.
3. Няма capacity
Всяка платформа разполага с краен брой build worker-и. При shared tier внезапен пик на активността в платформата може да ви постави зад build-овете на други потребители. Това е реална ситуация, обикновено е краткотрайна и е единственият случай, в който изчакването наистина е правилното действие.
Важно е дали можете да го видите. Позиция в queue или приблизително време за изчакване превръщат изживяването, наподобяващо outage, в нормална ситуация. Самото „queued“ не го прави.
4. Deployment-ът изобщо няма да стартира
Неприятният случай: записът е създаден, но нещото, което е трябвало да го поеме, така и не го е направило. Worker е crash-нал, webhook е изгубен или token е изтекъл между trigger-а и fetch-а.
Показателно е времето. Изчакването в queue обикновено се измерва в секунди до няколко минути. Deployment, който е queued от десет минути без друг release преди него, не изчаква — той е заседнал и ще си остане такъв.
Как да различите изчакване от блокиране
Преди да направите retry, съберете три факта:
- Изпълнява ли се друг deployment? Ако друг release на същия service се изпълнява, това е случай 2 и трябва да го оставите да приключи.
- Колко време е queued? Под две минути е нормално. Над десет — не.
- Влязоха ли други service-и в queue по същото време? Ако несвързани service-и са спрели едновременно, потърсете причината upstream, а не в кода си.
Тези три отговора почти винаги разделят „изчакай“ от „действай“.
Защо retry обикновено влошава проблема
Инстинктивната реакция при заседнал release е отново да натиснете deploy. При сериализиран pipeline това е контрапродуктивно: добавяте втори запис зад първия, а ако първият наистина е заседнал, вторият наследява блокирането. Разработчиците, които попаднат в тази ситуация, често накрая получават колона от queued записи, нито един от които няма да се изпълни, докато началото на опашката не се освободи.
Ако ще правите retry, първо cancel-нете заседналия deployment. Един queued deployment, който видимо се провали, е много по-полезен от пет, които просто стоят.
Как решаваме този проблем в Dockup
Важното дизайнерско решение тук е, че deployment никога не остава в състояние, в което системата смята, че се изпълнява. Всеки deployment има terminal state и достигането му освобождава опашката. Build, който прекъсне работа, без да докладва, също изтича по timeout и освобождава service-а.
Още две неща помагат повече, отколкото изглежда:
Етапите са именувани. Deployment-ът в Dockup преминава през извличане на source кода, build и health gate, като всеки етап записва собствената си duration. Когато нещо е бавно, виждате кое точно е бавно, вместо да наблюдавате една дума. stageTimings присъства във всеки deployment record, включително при използване на --json.
След вече провалил се release не се натрупват queued deployment-и. Ако health check-ът никога не мине, deployment-ът приключва — той не заема service-а, докато се чудите какво се случва. Предишната версия продължава да обслужва трафика през цялото време, което е и другата причина заседналият release да не води до outage в Dockup.
# What is the current state, and how long has each stage taken?
dockup status my-project/my-api --json
# Follow the build as it happens rather than waiting for a summary
dockup logs my-project/my-api --build --follow
Общото правило
Queueing не е failure mode. Queueing без посочена причина е. Всяка платформа понякога ще ви накара да изчакате Git provider или build slot; разликата между петминутно раздразнение и изгубен следобед е дали интерфейсът ви показва в кой от четирите случая се намирате.
Когато преценявате къде да стартирате нещо, струва си умишлено да проверите това: задействайте deploy и вижте какво показва платформата между приемането му и стартирането. Ако отговорът е една-единствена дума без timestamp, рано или късно ще изгубите цял следобед заради това.
Често задавани въпроси
Колко време трябва да остане deployment-ът queued? Секунди до няколко минути при изправна платформа. Всичко над десет минути, когато пред него няма нищо, трябва да се счита за заседнало, а не просто за бавно.
Трябва ли да направя retry на queued deployment? Не и преди да го cancel-нете. При сериализиран pipeline retry-ят се нарежда зад заседналия deployment и наследява същото блокиране.
Може ли заседнал deployment да спре сайта ми? Не би трябвало. При платформа, която пренасочва трафика едва след като новият release премине health check-а, работещата версия продължава да обслужва трафика през цялото време — queued или failed deploy е release, който така и не се е случил, а не outage.
Защо няколко service-а влизат в queue едновременно? Защото споделят dependency и почти винаги причината е Git provider-ът или build fleet-ът, а не нещо в кода ви.
