Egy sikertelen újrapublikálás soha nem töröl működő backendet
Szeptember 25-én egy sikertelen újrapublikálás letörölt egy app backendjét, amely körülbelül két és fél órája élőben és hibátlanul működött. A sikertelen publikálást visszavonó kód eltávolított minden szerveres appot, amelyet a publikálás érintett — beleértve azokat is, amelyek már a publikálás előtt is szolgálták a látogatókat. Mostantól csak azokat az appokat törli a rendszer, amelyeket maga a publikálás hozott létre; a már meglévő app pontosan arra a verzióra áll vissza, amelyen korábban futott. Két további javítás még aznap gondoskodott arról, hogy a visszavonás akkor is lefusson, ha a hosting platform saját deploy eszköze hibázik, és arról, hogy egy egészséges app ne bukjon el csak azért, mert aludt.
Hogyan publikálódik egy backend
Ha a Mythex-appodnak van backendje — vagyis API vagy szerver, nem csak statikus fájlok —, a publikálás egy Dockerfile-ból (recept arra, hogy az appot egy image-be csomagoljuk) építi fel, majd ezt az image-et a hosting platformunk gépeire gurítja ki. Ezután egy health check vár, amíg az új verzió valóban elindul és stabilan fut, és csak utána jelöljük a publikálást élőnek.
Ha közben bármi meghiúsul, visszavonás fut le, hogy visszaállítsa a korábbi állapotot. Ennek a visszavonásnak a helyes működése szinte minden más publikálási részletnél fontosabb, mert pont akkor fut, amikor valami már félrement.
1. probléma: a visszavonás azt törölte, amit vissza kellett volna állítania
A visszavonás nyilvántartta azokat a szerveres appokat, amelyekre a publikálás deployolt, és hiba esetén mindegyiket megsemmisítette. Ez egy első publikálásnál helyes: az app percekkel korábban jött létre, semmi nem függ tőle, a törlés pedig visszaállítja az eredeti helyzetet.
Republikálásnál viszont pont az ellenkezője volna helyes. Az app már létezett, és valódi látogatókat szolgált ki. Szeptember 25-én egy sikertelen újrapublikálás törölt egy app API-t, amely körülbelül két és fél órája élőben volt.
Egy második hibamód is ugyanebben a kódban rejtőzött. Ha a törlés nem járt sikerrel, a hibás új image a gépeken maradt — miközben az app tulajdonosának azt jeleztük, hogy a jelenlegi oldala továbbra is él. Amikor a health check meghiúsul, az új image már rá van gurítva minden gépre. Nem csinálni semmit nem ugyanaz, mint visszavonni.
A javítás: csak azt töröld, amit létrehoztál, a többit állítsd vissza
Minden publikálás most minden általa érintett szerveres appra feljegyzi:
- hogy ez a publikálás hozta-e létre, és
- ha nem, melyik image-et futtatta közvetlenül előtte.
Hiba esetén minden app három kezelés valamelyikét kapja:
- Ezt a publikálást hozta létre: töröljük, ahogy eddig is.
- Már létezett, és ismert a korábbi image: a korábbi image-et ugyanazzal a konfigurációval újra deployoljuk. Nincs build — csak az image áll vissza.
- Már létezett, de a korábbi image nem ismert: nem nyúlunk hozzá. Egy meglévő appot soha nem törlünk, még akkor sem, ha nem tudjuk visszaállítani.
Ezek a szabályok egy kis, tiszta függvényben vannak, saját tesztekkel, így a döntés nem csúszhat vissza az „mindent töröljünk” irányba anélkül, hogy egy teszt el ne bukna.
2. probléma: a deploy eszköz hibázhatott, mielőtt leírtuk volna a visszavonás módját
Rövid idő múlva találtunk egy rést ebben a javításban. A hosting platform deploy eszköze saját smoke ellenőrzéseket futtat: ha az új gépek összeomlanak, hibával lép ki. Ez viszont azután történik, hogy az új image már a gépeken van.
A kódunk csak akkor regisztrálta az appot visszavonásra, amikor az eszköz sikeresen visszatért. Ha maga az eszköz buktatta meg a deployt, az app még nem volt a visszavonási listán, így semmi nem állt vissza. A staging környezetünkön egy hibás újrapublikálás után a hibás image maradt élesben.
A javítás: a visszavonást a kezdés előtt rögzítjük
Az app most azonnal regisztrálva van visszavonásra — azzal, hogy létrejött-e, és milyen image futott rajta —, amint előkészítettük, és mielőtt bármit ráguritanánk. Bármi is hibázik utána, a visszavonás tudja, mit kell visszatenni. Helyben ellenőriztük: egy hibás újrapublikálás a deploy eszköz saját smoke ellenőrzésén bukott el, és a korábbi verzió tovább válaszolt.
3. probléma: egy alvó appot „soha nem indult el” hibával buktattunk meg
A publikált Mythex-appok tétlenség esetén elalszanak, hogy megspóroljuk a kreditjeidet. Egy újrapublikálás után az alvó gép leállva marad, ezért a health checknek fel kell ébresztenie. A kód a platformtól egyszer kérte a gép indítását, a választ pedig figyelmen kívül hagyta.
Szeptember 25-én ez az egyetlen indítási kérés nem járt eredménnyel. Egy egészséges API leállva maradt az egész öt perces health check ideje alatt, és a „1 gép soha nem indult el (utolsó állapot: leállítva)” hibával bukott meg.
A platform néha valóban visszautasít egy indítást. A probléma reprodukálása közben egy „lease currently held” ütközést adott vissza anélkül, hogy kiprovokáltuk volna, és nem enged indítani olyan gépet, amely éppen frissítés alatt van.
A javítás: kérdezz újra, és kopogj az ajtón
A health check most:
- 20 másodpercenként újra kéri egy leállt gép elindítását, amíg vár,
- naplózza, mit válaszolt a platform, amikor visszautasított, és
- küld egy egyszerű kérést az appnak, ahogy egy látogató tenné — a platform proxy-ja felébreszti az alvó gépet, amint kérés érkezik.
A valódi platformon, egy eldobható appal reprodukáltuk, amelynek az első indítását visszautasították. A javítás előtt a publikálás 91 másodperc után bukott el. Utána 20 másodperc alatt publikálódott. Az az app, amely valóban összeomlik indításkor, továbbra is elbukik — ahogy kell.
Amit ebből tanultunk
- A visszavonásnak tudnia kell a különbséget az új és a meglévő között. Egy általad létrehozott dolog „visszavonása” törlés. Egy már meglévő dolog „visszavonása” visszaállítás. Ha ugyanúgy kezeled a kettőt, egy biztonsági mechanizmus töröl egy működő appot.
- Írd le, hogyan vonsz vissza, mielőtt cselekszel. Ha a visszavonás csak akkor rögzül, amikor egy lépés már sikerült, akkor egy félbe maradt lépés után nincs mivel visszavonni.
- Soha ne nyeld le egy olyan kérés válaszát, amelytől függsz. Egy figyelmen kívül hagyott „nem” egészséges appot buktatott meg sikertelen publikálássá.
Ezen a napon készült egy kapcsolódó javítás is: az összeomló appok elkapása közvetlenül a publikálás után. Arról, mi történik, ha egy publikálás a te oldaladon hibázik, a dokumentációban olvashatsz: publikálási hibaelhárítás.