Štiri plasti stroškovne zaščite: kako naš Auto-Scaler ne razstreli računa
Stranka naloži pokvarjeno sceno, orchestrator zažene pod, pod teče v neskončni OOM, poskuša tri retryje, vsak pod nas stane 0,80 ameriškega dolarja na minuto. Brez zaščite to v eni uri pomeni trimestni račun. Štiri neodvisne plasti morajo odpovedati, da to doživimo.
Pri cloud-rendering-setupu ni najdražja napaka počasen render — je render, ki teče v neskončnost. GPU-pod pri US$0,80/minuto pri 60 minutah postane $48, pri 12 urah $576, čez vikend $2.300. Če software lahko crashne in orchestrator „samo znova zažene“, to ni auto-recovery — to je račun, ki poskrbi, da se stranka nikoli več ne vrne.
Naš cinema-orch backend ima štiri neodvisne plasti Cost-Protection. Po Sprintu 3.5 (2026-06-15) so vse štiri v produkciji. Vsaka plast odpoveduje drugače kot ostale — zato morata odpovedati vsaj dve, preden vidimo napihnjene račune.
Plast 1: Ex-ante Estimate + Client-Confirm
Preden se sploh spawna kakšen pod, orchestrator izračuna Kosten-Estimate na podlagi:
- Sample-Count × Tile-Count × Frame-Count × ocenjeni čas/sličica na izbranem GPU
- Baseline iz zgodovinskih opravil iste scene-signature (hash iz Blender-verzije + render-nastavitev)
- Bufferja 20 % za neznanke
Estimate se stranki prikaže pred zagonom. Stranka mora aktivno klikniti „Potrdi“. Če je estimate nad strankinim budgetom (vsak uporabnik nastavi hard-cap v svojem računu), se opravilo avtomatsko zavrne — ne queued, ne confirmed-with-warning, temveč rejected.
Učinek: ~70 % vseh teoretično dragih opravil nikoli ne pride v orchestrator, ker stranka prej vidi, da bo predrago, in sceno optimizira.
Plast 2: Per-Job Budget-Cap z live tickerjem
Vsako opravilo ima polje max_budget_cents, ki ga nastavi uporabnik (tipično estimate + 20 %). Orchestrator v Postgresu vozi ticker — vsako minuto se izračuna trenutno akumulirani strošek in preveri proti max_budget_cents.
Ko opravilo doseže cap, se pod hard-terminira. Uporabnik dobi notifikacijo, cap lahko ročno dvigne ali vzame delni output.
Učinek: runaway-render lahko pristane največ ~5–10 % nad capom (do naslednjega ticker-tickov). Pri $50-opravilu je to $2,50 overshoot namesto $2.300.
Plast 3: Pod-Timeout na systemd-nivoju
Vsak GPU-pod ima trdo časovno omejitev, ki se nastavi pri Pod-init — analogno Kubernetes-ActiveDeadline. Pri standardni render-seji: 4 ure. Po poteku: pod umre, orchestrator vidi prekinitev in opravilo označi kot budget_exceeded.
Zakaj je to potrebno, čeprav plast 2 obstaja: sam orchestrator lahko crashne (network-partition, Postgres-izpad, procesni OOM). Pod-timeout je fallback-garancija — konfiguriran je na samem podu in ne potrebuje zunanjega triggerja.
Učinek: tudi pri popolnoma nemem orchestratorju posamezen pod stane največ 4-urno marko, potem se sam terminira.
Plast 4: Spending-Alert na strani ponudnika
Runpod (naš primary GPU-provider) ima svoje Budget-Alerte na račun. Pri $50/dan spend pride e-pošta na [email protected]; pri $200/dan Slack-alert na naš Ops-kanal. Oba sta konservativno nastavljena.
Če vse tri druge plasti odpovedo, nas vsaj ta alert ročno pripelje noter. Do zdaj (4 tedne bete) se ni nikoli sprožil, ker plasti 1–3 vse ujamejo.
Zakaj štiri
En sam zaščitni layer ni zaščita — je Single Point of Failure. Če se zanašamo na „stranka potrdi estimate“ in ima UI bug, ki prikaže prenizek estimate, smo v godlji. Štiri neodvisne plasti pomenijo: en bug v katerem koli softwaru (naš UI, naš orchestrator, systemd, Runpodov portal) ne ujame nepričakovanega računa — to storijo ostale tri.
Trik je neodvisnost. Plast 1 živi v frontendu (Next.js). Plast 2 v orchestratorju (Python/asyncpg). Plast 3 na podu (systemd). Plast 4 pri ponudniku (Runpodov API). Če en software crashne, je malo verjetno, da bi ostali trije istočasno enako odpovedali.
Kaj smo se naučili
- Natančnost estimatea je najpomembnejši vzvod za plast 1. Če je estimate 30 % mimo, je cap-buffer izčrpan, preden je opravilo končano. Veliko časa smo vložili v kalibracijo sample-count × čas/sličica.
- Ticker-interval v plasti 2 je trade-off med overshoot in DB-load. 60 sekund je naš kompromis — 30 sekund zmanjša overshoot, a podvoji DB-load na tekoče opravilo.
- Pod-Timeout v plasti 3 ne sme biti prekratek. V zgodnji verziji smo imeli 60 minut — razdejalo je legitimno 4K-opravilo, ki bi potrebovalo 90 minut. Zdaj 4 ure default, konfigurabilno na opravilo.
Če sam gradiš auto-scaling-sistem z eksternim GPU-računskim tveganjem: ne začni z enim samim capom. Zgradi tri neodvisne plus ponudnikov alert. Dodatni napor je majhen, delta tveganja je enormen.
To arhitekturo dokumentiramo javno, ker mislimo, da mora biti cloud-rendering iskren glede lastnih tveganj. Če želiš, da si vzorec ogledam za tvoj lasten sistem: [email protected] — ZER0ONE Studio izvaja ta tip Distributed-Systems-svetovanja kot Engineering-Service.