Неуспешно повторно објавување никогаш не брише работечки backend
На 25 септември, неуспешно повторно објавување ја избриша backend-от на една апликација, кој беше жив и работеше околу два и пол часа. Кодот што го поништува неуспешното објавување ги избриша сите серверски апликации што објавувањето ги допрело, вклучително и оние што веќе работеле пред да започне. Сега се бришат само апликациите што ги создало објавувањето; апликација што веќе постоела се враќа на точната верзија што ја користела пред тоа. Две последователни поправки истиот ден обезбедија поништувањето да се изврши и кога алатката за распоредување на хостинг платформата ќе падне, и дека здрава апликација не се прогласува за неуспешна само затоа што спиела.
Како се објавува backend
Кога вашата Mythex апликација има backend, односно API или сервер, а не само статички фајлови, објавувањето го гради од Dockerfile (рецепт за пакување на апликацијата во слика) и ја распоредува сликата на машини на нашата хостинг платформа. Потоа здравствена проверка (health check) чека новата верзија навистина да се подигне и да остане активна, пред објавувањето да се означи како живо.
Ако нешто падне по патот, се извршува rollback за да се поништи. Правилното поништување е речиси најважното во објавувањето, бидејќи се извршува точно кога нешто веќе не е во ред.
Проблем 1: rollback-от избриша што требаше да врати
Rollback-от водеше листа на серверските апликации на кои објавувањето било распоредено, и при неуспех ги уништуваше сите. Тоа е точно за прво објавување: апликацијата е создадена пред момент, ништо не зависи од неа, а нејзиното бришење ја враќа состојбата во претходна.
Тоа е точно погрешно за повторно објавување. Апликацијата веќе постоела и ги опслужувала вистинските посетители. На 25 септември, API на една апликација што била жива околу два и пол часа била избришана од неуспешно повторно објавување.
Во истиот код имаше и втор начин на неуспех. Таму каде што бришењето не успеало, расипаната нова слика останувала на машините, додека ние му кажувавме на сопственикот дека неговата моментална страница сè уште е жива. Кога здравствената проверка може да падне, новата слика веќе е распоредена на сите машини. Ако не направите ништо, тоа не е исто што и поништување.
Поправката: уништи само она што си го создал, врати го остатокот
Секое објавување сега запишува, за секоја серверска апликација што ја допира:
- дали ова објавување ја создало, и
- ако не, која слика ја извршувала непосредно пред тоа.
При неуспех, секоја апликација добива една од три постапки:
- Создадена од ова објавување: се уништува, како и порано.
- Веќе постоела, претходната слика е позната: повторно се распоредува претходната слика со истата конфигурација. Без градење, само сликата се враќа назад.
- Веќе постоела, претходната слика е непозната: се остава по страна. Постоечка апликација никогаш не се брише, дури ни кога не можеме да ја вратиме.
Овие правила се мала чиста функција со свои тестови, така што одлуката не може повторно да се врати на „уништи сè“ без тест да падне.
Проблем 2: алатката за распоредување можеше да падне пред да запишеме како да се поништи
Наскоро по таа поправка, најдовме празнина. Алатката за распоредување на хостинг платформата извршува свои smoke проверки: ако новите машини се срушат, таа враќа грешка. Но тоа го прави откако новата слика е веќе на машините.
Нашиот код ја регистрираше апликацијата за rollback дури кога алатката ќе врати успех. Кога самата алатка го обележеше распоредувањето како неуспешно, апликацијата уште не била на листата за rollback, па ништо не се врати. На нашата staging средина, расипано повторно објавување остави расипаната слика да работи.
Поправката: регистрирај го поништувањето пред да почнеш
Апликацијата сега се регистрира за rollback, со тоа дали е создадена и која слика ја извршувала, штом се подготви и пред било што да се распореди на неа. Што и да падне понатаму, rollback-от знае што да врати. Проверивме локално: неуспешно повторно објавување падна при smoke проверките на самата алатка, а претходната верзија продолжи да одговара.
Проблем 3: спиачка апликација беше прогласена за „никогаш не стартувана“
Објавените апликации на Mythex спијат кога се неактивни, за да ги зачуваат вашите кредити. Повторното објавување остава запрена машина што спие, па здравствената проверка мора да ја разбуди. Таа го бараше од платформата да ја стартува машината еднаш и го игнорираше одговорот.
На 25 септември, тоа едно барање за стартување не стигна никаде. Здрав API остана запрен цели пет минути на здравствената проверка и беше прогласен за неуспешен со „1 машина никогаш не се стартувала (последна состојба: stopped)“.
Платформата понекогаш навистина одбива стартување. Додека го реплициравме проблемот, таа врати конфликт „lease currently held“ без да го предизвикаме, а одбива стартувања и додека машината се ажурира.
Поправката: продолжи да прашуваш и потропај на вратата
Здравствената проверка сега:
- бара повторно да се стартува запрена машина на секои 20 секунди додека чека,
- ги бележи одговорите на платформата кога одбива, и
- испраќа еден обичен барање до апликацијата, како вистински посетител. Проксито на платформата ја буди спиачката машина кога ќе стигне барање.
Го реплициравме на вистинската платформа со привремена апликација чие прво стартување беше одбиено. Пред поправката, објавувањето падна по 91 секунда. По неа, се објави за 20 секунди. Апликација што навистина се срушува при подигнување сè уште паѓа, како што и треба.
Што научивме
- Rollback мора да знае разлика помеѓу нови и постоечки. „Поништи“ за нешто што си го создал значи бриши. „Поништи“ за нешто што веќе постоело значи врати. Ако ги третираш исто, токму така еден безбедносен механизам ќе избрише работечка апликација.
- Запиши како да се поништи пред да дејствуваш. Ако поништувањето се запишува дури откако чекор ќе успее, чекор што ќе падне на половина не остава ништо со што да се врати.
- Никогаш не игнорирај го одговорот на барање од кое зависиш. Едно игнорирано „не“ претвори здрава апликација во неуспешно објавување.
Поврзана поправка од истиот ден: фаќање апликации што се срушуваат веднаш по објавувањето. За она што се случува кога објавувањето ќе падне од ваша страна, видете решавање проблеми со објавување во документацијата.