
Operațiuni4 min read
mstdn.ro: cum operăm o instanță publică de Mastodon
Infrastructură comunitară pe fediverse: un stack Rails complet, trei niveluri separate de Sidekiq, conexiuni Postgres puse în pool și o disciplină lunară de upgrade — pe o amprentă deliberat modestă.
- Operations
- Mastodon
- Self-hosted
- Ruby on Rails
Context
mstdn.ro este o instanță publică românească de Mastodon pe care o operăm noi. A rula un server din fediverse este un alt fel de responsabilitate decât a-ți rula propriul site: pe el sunt oameni reali cu conturi reale, iar federarea înseamnă că serverul schimbă trafic cu mii de alte instanțe după programul lor, nu al nostru. Postările sosesc indiferent dacă ne uităm sau nu.
Este și unul dintre cei mai buni profesori operaționali pe care îi avem. Mastodon este o aplicație Rails de dimensiune completă — web worker-i, cozi de background, un API de streaming, Postgres, Redis, Elasticsearch — și fiecare lecție de scalare scrisă despre el a trebuit aplicată, nu doar citită.
Constrângeri
- O amprentă modestă. Instanța împarte o mașină cu restul infrastructurii noastre. Infrastructura comunitară nu vine cu un buget comunitar, așa că eficiența este o cerință, nu o optimizare.
- Trafic pe care nu îl controlăm. Ingest-ul de federare vine în rafale. Momentul viral al altei instanțe devine backlog-ul cozii noastre.
- Cadența de release a upstream-ului. Mastodon livrează release-uri cu migrări și breaking changes după propriul program. A rămâne în urmă este o problemă de securitate; a face upgrade neglijent este o întrerupere.
Abordare
Deployment-ul este arhitectura completă Mastodon, fiecare parte un container separat:
Trei niveluri de Sidekiq, nu unul. Aceasta este decizia care duce greul. Ingest-ul de federare rulează în propriul serviciu Sidekiq, separat de coada default și de lucrul programat. Când sosește o rafală de federare, aceasta se așază la coadă în nivelul de ingress — iar job-urile pe care utilizatorii chiar le simt, cum ar fi propriile postări care se propagă, continuă să curgă prin nivelul default. O singură coadă partajată este modul clasic de eșec al lui Mastodon: timeline-ul pare mort în timp ce serverul este ocupat să digere traficul altcuiva.
PgBouncer în fața lui Postgres. Web worker-ii Rails plus trei servicii Sidekiq se înmulțesc în mai multe conexiuni la baza de date decât ar trebui Postgres să țină deschise. PgBouncer le pune în pool; Postgres vede un număr rezonabil de conexiuni indiferent de cum este reglată concurența deasupra lui.
Restul stack-ului, separat pe sarcini. Redis pentru cozi și cache, Elasticsearch pentru căutare full-text, iar API-ul de streaming ca serviciu propriu — conexiunile WebSocket de lungă durată au un ciclu de viață diferit de web worker-ii request/response și repornesc independent.
Imagini construite de noi, cu tag lunar. Instanța rulează imagini pe care le
construim noi, cu tag după lună. Fără :latest, fără upgrade-uri surpriză.
Imaginea noii luni este construită, release notes-urile sunt citite mai întâi,
migrările sunt rulate deliberat, iar tag-ul anterior rămâne pe disc ca rollback.
A construi singuri imaginile înseamnă și că putem purta patch-uri atunci când
este nevoie, fără să așteptăm packaging-ul upstream.
Ce a fost greu
Înfometarea cozilor a fost prima lecție adevărată — layout-ul Sidekiq pe trei niveluri există pentru că default-ul cu o singură coadă pedepsește în cele din urmă orice instanță cu federare activă. Aritmetica conexiunilor a fost a doua: fiecare buton de concurență din Rails și Sidekiq se înmulțește în conexiuni Postgres, iar PgBouncer este diferența dintre a regla liber și a regla cu frică.
Munca mai discretă, continuă, este disciplina: cititul release notes-urilor înainte de fiecare upgrade, tratarea migrărilor ca schimbări de repetat, nu doar de aplicat, și a fi un bun cetățean al unei rețele federate — obligațiile de moderare incluse — în care comportamentul serverului nostru este vizibil fiecărui server cu care vorbește.
Unde suntem acum
Instanța rulează astăzi așa cum este descrisă. Măsura noastră a succesului pentru infrastructura comunitară este ca ea să fie plictisitoare: upgrade-urile trec fără evenimente, cozile se golesc și nimeni nu se gândește la server — exact așa cum ar trebui să îl simtă oamenii care îl folosesc.
Dacă operezi infrastructură comunitară — sau infrastructură care ar trebui să fie la fel de plictisitoare — vorbește cu noi.