Неуспешно повторно публикуване никога не изтрива работещ бекенд
На 25 септември неуспешно повторно публикуване изтри бекенда на едно приложение, който беше жив и работещ от около два и половина часа. Кодът, който отменя неуспешна публикация, премахна всяко сървърно приложение, до което публикуването се беше докоснало — включително онези, които вече обслужваха преди да започне. Сега само приложенията, създадени от дадена публикация, могат да бъдат изтривани; приложение, което вече е съществувало, се връща към точно версията, която е работела преди това. Две допълнителни корекции същия ден гарантираха, че отмяната се изпълнява и когато собственият инструмент за внедряване на хостинг платформата се провали, и че здраво приложение не се обявява за неуспешно само защото е било в режим на заспиване.
Как се публикува бекенд
Когато вашето Mythex приложение има бекенд — API или сървър, а не само статични файлове — публикуването го изгражда от Dockerfile (рецепта за опаковане на приложението в образ) и разгръща този образ върху машини в хостинг платформата ни. След това проверка на състоянието изчаква новата версия наистина да се стартира и да работи стабилно, преди публикуването да се отбележи като активно.
Ако нещо се провали по пътя, се пуска връщане назад, за да го отмени. Правилното изпълнение на това връщане е по-важно от почти всичко друго при публикуването, защото се задейства точно когато нещо вече се обърка.
Проблем 1: връщането изтриваше това, което трябваше да възстанови
Връщането пазеше списък със сървърните приложения, към които публикуването е разгърнало, и при неуспех унищожаваше всяко едно от тях. За първо публикуване това е правилно: приложението е създадено преди миг, нищо не зависи от него и изтриването му връща нещата в първоначалното състояние.
За повторно публикуване това е точно грешното. Приложението вече съществува и обслужва реални посетители. На 25 септември API на едно приложение, което беше живо около два и половина часа, беше изтрито от неуспешно повторно публикуване.
В същия код се криеше и втори начин на отказ. Когато изтриването не минеше, счупеният нов образ оставаше на машините — докато ние казвахме на собственика, че текущият му сайт е все още жив. Към момента, в който проверката на състоянието може да се провали, новият образ вече е разгърнат на всяка машина. Липсата на действие не е същото като отмяна.
Корекцията: изтриване само на това, което е създадено, и възстановяване на останалото
Сега всяка публикация записва за всяко сървърно приложение, до което се докосва:
- дали тази публикация го е създала, и
- ако не, кой образ е работел непосредствено преди това.
При неуспех всяко приложение получава едно от три третирания:
- Създадено от тази публикация: изтрива се, както преди.
- Вече е съществувало, предишният образ е известен: разгръща се отново предишният образ със същата конфигурация. Без изграждане — движи се само образът назад.
- Вече е съществувало, предишният образ е неизвестен: оставя се на мира. Съществуващо приложение никога не се изтрива, дори когато не можем да го възстановим.
Тези правила са малка чиста функция със собствени тестове, така че решението не може отново да се върне към „изтрий всичко“ без тестът да падне.
Проблем 2: инструментът за внедряване можеше да се провали, преди да сме записали как да отменим
Скоро след тази корекция открихме празнина в нея. Инструментът за внедряване на хостинг платформата изпълнява собствени проверки: ако новите машини се срутят, той завършва с грешка. Но го прави след като новият образ вече е върху машините.
Нашият код регистрираше приложение за връщане едва след като инструментът върнеше успешен резултат. Когато самият инструмент провалеше внедряването, приложението още не беше в списъка за връщане, така че нищо не се възстановяваше. В нашата тестова среда неуспешно повторно публикуване остави счупения образ да обслужва.
Корекцията: регистрираме отмяната преди да започнем
Приложението вече се регистрира за връщане — със стойността дали е създадено и какъв образ е работил — веднага щом е подготвено и преди нещо да бъде разгърнато върху него. Каквото и да се провали след това, връщането знае какво да възстанови. Проверихме локално: счупено повторно публикуване се провали при собствените проверки на инструмента за внедряване, а предишната версия продължи да отговаря.
Проблем 3: спящо приложение беше обявено за „никога не стартирало“
Публикуваните приложения в Mythex заспиват при бездействие, за да пазят вашите кредити. Повторното публикуване оставя спяща машина спряна, затова проверката на състоянието трябва да я събуди. Тя поиска от платформата да стартира машината веднъж и игнорира отговора.
На 25 септември тази единствена заявка за стартиране не стигна доникъде. Здраво API, което стоеше спряно, премина целите пет минути на проверката на състоянието и беше обявено за неуспешно с „1 машина никога не стартира (последно състояние: спряна)“.
Платформата понякога отказва стартиране. Докато възпроизвеждахме проблема, тя върна конфликт „lease currently held“ без да сме я провокирали, а отказва стартирания и докато машината се обновява.
Корекцията: продължаваме да питаме и хлопаме на вратата
Проверката на състоянието сега:
- пита отново за стартиране на спряна машина на всеки 20 секунди, докато чака,
- записва какво е отговорила платформата, когато откаже, и
- изпраща една обикновена заявка към приложението, както би направил посетител — прокситата на платформата събужда спящата машина, когато пристигне заявка.
Възпроизведохме проблема на реалната платформа с едно временно приложение, чието първо стартиране беше отказано. Преди корекцията публикуването се провали след 91 секунди. След нея публикува за 20 секунди. Приложение, което наистина се срива при старт, все още се проваля, както трябва.
Какво взехме от случая
- Връщането трябва да знае разликата между новото и съществуващото. „Отмяна“ на нещо, което си създал, е изтриване. „Отмяна“ на нещо, което вече е било там, е възстановяване. Третирането им еднакво е начинът, по който механизъм за безопасност изтрива работещо приложение.
- Запиши как да отмениш, преди да действаш. Ако отмяната се записва едва след като една стъпка успее, стъпка, която се провали по средата, не оставя с какво да се отмени.
- Никога не преглъщай отговора на заявка, от която зависиш. Едно игнорирано „не“ превърна здраво приложение в неуспешно публикуване.
Свързана корекция от същия ден: приложения, които се срутват веднага след публикуване. За това какво се случва, когато публикуването се провали от ваша страна, вижте отстраняване на проблеми при публикуване в документацията.