Nasadenie prešlo, ale web nefunguje
Dashboard hlási, že aplikácia beží, no používatelia vidia chybu. Zistite, prečo sú úspešné nasadenie a zdravie aplikácie odlišné signály a ako zabezpečiť, aby zelené nasadenie znamenalo, že aplikácia skutočne odpovedá.
Existuje špecifický druh zlého rána, ktorý sa začína zelenou fajkou. Nasadenie prešlo, ale web nefunguje, dashboard hlási running a niekto vám posiela screenshot chyby 502.
Nie je to zriedkavý okrajový prípad. Je to predvídateľný dôsledok toho, že platforma hlási jednu vec a meria inú. Oplatí sa tomu presne porozumieť, pretože riešením nie je „kontrolovať dôkladnejšie“ — treba zmeniť, čo smie pojem running znamenať.
Tri rôzne otázky, jedno stavové svetlo
Keď platforma hlási, že služba beží, môže odpovedať na ktorúkoľvek z týchto otázok:
- Spustil sa kontajner? Proces existuje a neskončil.
- Je port otvorený? Na porte, ktorý platforma očakáva, niečo počúva.
- Odpovedá aplikácia správne? Na požiadavku prichádza odpoveď, ktorá znamená, že aplikácia je pripravená pracovať.
Ide o úplne odlišné garancie a väčšina incidentov tohto typu vzniká preto, že dashboard odpovedá na otázku 1, zatiaľ čo vy ste predpokladali otázku 3.
Proces Node, ktorý sa spustí, nedokáže sa pripojiť k databáze a zostane v retry slučke, spĺňa otázku 1 navždy. Nespadol. Nikdy však neobslúži požiadavku. Kontajner je „spustený“ v každom zmysle, na ktorom orchestrátoru záleží.
Medzera, v ktorej vzniká výpadok
Nebezpečné obdobie nastáva medzi „nová verzia sa spustila“ a „nová verzia dokáže fungovať“. Naivná platforma v tomto období už presmerovala traffic, pretože merala iba spustenie.
Horšie než obyčajný pád je to najmä z pohľadu rollbacku. Crash loop je hlučný: kontajner skončí, reštartuje sa, znova skončí a platforma si to napokon všimne. Spustenie a následné zamrznutie je tiché. Nič sa nereštartuje, nič nevyvolá alarm a predchádzajúca funkčná verzia už zvyčajne bola odstránená.
Práve posledná časť spôsobuje skutočné škody. Stará verzia bola v poriadku. Odstránili ju preto, že sa spustila nová, pričom spustenie sa mylne považovalo za fungovanie.
Ako funguje skutočná health gate
Riešenie je štrukturálne, nie procedurálne. Traffic sa nemá presmerovať, kým nová verzia neodpovie na požiadavku.
V Dockup prebieha release takto: nová verzia sa zostaví izolovane, spustí sa súbežne s verziou, ktorá momentálne obsluhuje požiadavky, a následne dostane otázku. Až keď odpovie, doména začne smerovať na novú verziu. Ak nikdy neodpovie, release sa v tomto bode zastaví a predchádzajúca verzia pokračuje v obsluhe požiadaviek — nikto mimo vášho dashboardu sa nikdy nedozvie, že sa o nasadenie niekto pokúsil.
Preto neúspešné nasadenie v Dockup neznamená výpadok. Starý kontajner sa nikdy neodstránil len na základe predpokladu, že nový bude v poriadku.
# The health gate is per-service configuration, not a platform default you inherit
dockup info my-project/my-api --json
Blok healthCheck vo výstupe je celým kontraktom: ktorá cesta sa volá, ako dlho sa čaká na odpoveď, koľkokrát sa požiadavka zopakuje a aká dlhá pauza je medzi pokusmi.
Nastavte check tak, aby odpovedal na otázku 3
Health endpoint, ktorý bezpodmienečne vracia 200, je horší než žiadny endpoint, pretože zo skutočnej brány spraví iba formálne potvrdenie. Zmyslom checku je zlyhať vtedy, keď aplikácia nedokáže plniť svoju úlohu.
Užitočný readiness endpoint overuje veci, bez ktorých aplikácia nedokáže fungovať:
// Not this — it proves only that the process is alive
app.get('/healthz', (req, res) => res.send('ok'))
// This — it proves the app can actually serve a request
app.get('/healthz', async (req, res) => {
try {
await db.query('select 1') // the dependency that is usually the problem
if (!cacheReady) throw new Error('cache warming')
res.status(200).json({ ok: true })
} catch (err) {
res.status(503).json({ ok: false, reason: err.message })
}
})
V praxi to funguje vďaka dvom pravidlám:
Kontrolujte závislosti, bez ktorých nedokážete obslúžiť požiadavku, a nič iné. Ak sa vaša aplikácia dokáže riadne degradovať pri výpadku search indexu, readiness na ňom nezakladajte — zablokovali by ste nasadenia kvôli niečomu, čo nie je výpadok.
Udržujte check lacný. Endpoint sa počas každého release volá opakovane. Readiness check, ktorý spúšťa náročný query, vytvára zbytočný load.
Dajte mu dostatok času, ale nie neobmedzene
O tom, či gate pomôže alebo uškodí, rozhodujú dve nastavenia:
- Timeout pre jeden pokus by mal byť dlhší než váš najpomalší legitímny cold start. Aplikácia, ktorá sa pripája k databáze a zahrieva cache osem sekúnd, zlyhá pri trojsekundovom checku zakaždým a vy to „vyriešite“ vypnutím gate — čím sa vrátite na začiatok.
- Retries by mali pokrývať celkový čas spúšťania, nie iba jeden pokus. Interval × retries predstavuje skutočný rozpočet.
V Dockup ide o nastavenia healthCheckInterval, healthCheckTimeout a healthCheckRetries. Sú definované pre každú službu samostatne, pretože Rails monolit a Go sidecar sa nespúšťajú podľa rovnakého harmonogramu.
Keď už je web nedostupný
Ak toto čítate počas incidentu, najrýchlejšie ho vyriešite v tomto poradí:
- Skontrolujte, či aplikácia odpovedá priamo, teda bez domény. Ak odpovedá na svojom porte, ale nie cez doménu, ide o routing problém, nie o problém aplikácie, takže prestaňte hľadať chybu v kóde.
- Prečítajte si runtime logs, nie build logs. Build prešiel — to je východiskový predpoklad. Potrebujete zistiť, čo proces urobil po spustení.
- Vykonajte rollback ešte pred diagnostikou. Diagnostika je lacnejšia, keď nikto nečaká na výsledok.
dockup logs my-project/my-api --follow # what the running process is saying
dockup deployments my-project/my-api # what was live before this
dockup rollback <deployment-id> my-project/my-api # put that back
V Dockup je rollback prepnutie, nie nové zostavenie, pretože predchádzajúca verzia je stále na disku. O tretej ráno na tom záleží: najrýchlejšia obnova je tá, pri ktorej netreba nič kompilovať.
Otázka, ktorú sa treba opýtať platformy
Keď si vyberáte, kde budete prevádzkovať produkciu, toto sa oplatí zámerne otestovať: nasaďte aplikáciu, ktorá sa úspešne spustí, ale následne sa nedokáže pripojiť k databáze. Sledujte, čo hlási dashboard.
Ak hlási running, teraz presne viete, akú hodnotu bude mať toto slovo počas vášho ďalšieho incidentu.
Často kladené otázky
Prečo môj dashboard hlási running, keď je web nedostupný? Pretože „running“ zvyčajne znamená, že proces kontajnera existuje, nie že aplikácia dokáže obslúžiť požiadavku. Proces, ktorý uviazol pri opakovaných pokusoch o pripojenie k databáze, túto definíciu spĺňa neobmedzene dlho.
Mal by health check volať databázu? Áno, ak bez nej vaša aplikácia nedokáže obsluhovať požiadavky. Kontrolujte závislosti, ktoré skutočne potrebujete, a vynechajte tie, bez ktorých sa dokážete zaobísť.
Aký je rozdiel medzi liveness a readiness? Liveness zisťuje, či treba proces reštartovať. Readiness zisťuje, či má proces prijímať traffic. Gate, ktorá zabraňuje tomuto typu zlyhania, je readiness a musí sa spustiť ešte pred presmerovaním trafficu.
Ako úplne zabrániť tomu, aby chybné nasadenie zhodilo web? Traffic prepnite až vtedy, keď nová verzia odpovie na skutočnú požiadavku, a predchádzajúcu verziu ponechajte aktívnu, kým sa prepnutie nepotvrdí. Neúspešný release sa tak stane releaseom, ktorý sa nikdy neuskutočnil, a nie výpadkom.
