Blog ·
Ce interval de VMID alegeți pentru găzduire
Un VMID este o identitate, nu un contor. Ce decide intervalul ales: ce are voie platforma să creeze, ce are voie să citească și ce se întâmplă când se umple.
De Provibr
Orice instalare de Proxmox vă pornește de la 100 și numără în sus. Asta merge bine până când mașina încetează să fie numai a dumneavoastră: până când există un panou de control care creează invitați pe ea, un coleg care creează invitați pe ea de mână, o bibliotecă de șabloane și o sarcină de copiere de siguranță care restaurează ceva la trei dimineața.
În acel punct VMID-ul încetează să fie un contor și devine o identitate, iar intervalul pe care îl dați automatizării dumneavoastră încetează să fie o comoditate și devine o graniță. Merită ales deliberat, pentru că două dintre cele trei lucruri pe care le decide un interval sunt invizibile până în clipa în care o iau razna.
Ce permite de fapt Proxmox
Spațiul complet este mai larg decât presupun cei mai mulți:
| Valoare | |
|---|---|
| Cel mai mic VMID acceptat de Proxmox | 100 |
| Cel mai mare VMID acceptat de Proxmox | 999999999 |
| Utilizare manuală obișnuită | de la 100 până la câteva sute |
Nouă cifre. Nu este o invitație de a le folosi pe toate, dar înseamnă că grija obișnuită, „voi rămâne fără numere?”, este grija greșită. Veți epuiza un interval prost ales cu mult înainte să epuizați numerele.
Acele două limite sunt singurele impuse de hipervizor. Tot restul, partea care contează, este o decizie pe care o luați dumneavoastră.
Un interval este o graniță de permisiuni înainte de a fi un alocator
Iată partea ușor de ratat. Dacă unei platforme i se spune „alocă de la 5000 la 8999”, i s-au spus două lucruri deodată:
- Ce are voie să creeze. Invitații noi primesc un număr din acea fereastră și de nicăieri altundeva.
- Ce nu vă aparține. Tot ce se află în afara acelei ferestre a fost făcut de altcineva, iar platforma nu are ce căuta acolo.
Al doilea merită scris pe perete. Când am construit integrarea Proxmox, intervalul de vmid din setările integrării este descris în cod exact așa: platforma alocă doar în interiorul lui [vmidRangeStart, vmidRangeEnd], așa că o integrare nu poate, prin construcție, să ajungă la o mașină din afara lui. Cine își ține mașinile de producție în afara intervalului le ține la adăpost.
Acest mod de a privi lucrurile schimbă felul în care alegeți numerele. Nu alegeți de unde începe automatizarea dumneavoastră să numere. Trasați o linie în jurul mașinilor pe care sunteți dispus să lăsați un program să le șteargă.
Partea de citire este o întrebare separată și mușcă mai târziu
Crearea este jumătatea evidentă. Citirea este jumătatea care ne-a surprins.
Agentul nostru interoghează clusterul o dată pe rundă cu un singur GET /cluster/resources?type=vm, care nu atinge niciun invitat. Dar pentru fiecare invitat care rulează din acel răspuns făcea apoi încă două apeluri către agentul QEMU din invitat, network-get-interfaces și get-fsinfo, ca să afle adresele și utilizarea discului. Acea listă venea direct din interogarea clusterului, nefiltrată.
Pe un hipervizor de test care rulează și sarcini de producție, acea listă cuprindea mașinile de producție. Citirile sunt inofensive în sensul că nu se scrie nimic. Nu sunt inofensive în sensul care contează, pentru că „doar citire” nu este un răspuns la întrebarea de ce vorbește agentul dumneavoastră cu agentul din invitatul unei mașini care nu vă aparține.
Reparația este că același interval mărginește acum și citirile. Dacă vă construiți singur așa ceva, lecția se generalizează: o graniță care acoperă doar scrierile este o jumătate de graniță, iar jumătatea de citire este cea a cărei lipsă nu o observă nimeni.
Unde trebuie să stea intervalul
A trebuit să răspundem o dată la asta și merită spus raționamentul, pentru că răspunsul evident este greșit.
Răspunsul evident este să puneți intervalul lângă datele de autentificare, în orice pachet împinge platforma către agent la crearea integrării. Este un singur mesaj, sosește împreună cu tot restul, gata.
Asta eșuează la o repornire. Datele de autentificare sunt împinse o singură dată; după o repornire agentul își reconstruiește integrările din seiful local, fără nicio împingere. O graniță livrată pe acel traseu dispare în tăcere prima dată când procesul repornește, iar o graniță care încetează în tăcere să se mai aplice este mai rea decât nicio graniță, pentru că nimeni nu se duce să o caute.
Așa că intervalul călătorește într-un mesaj propriu, trimis la fiecare inițiere de sesiune, purtând starea completă. Două trasee de livrare, o singură sursă a adevărului. Există și o variabilă de mediu la nivel de gazdă, ca soluție de rezervă, iar ordinea dintre ele este deliberată:
| Sursă | Când câștigă |
|---|---|
| Setarea platformei | Ori de câte ori a trimis una |
| Variabila de mediu de pe gazdă | Doar când platforma nu a spus nimic |
| Nicio limită | Când niciuna dintre ele nu a spus nimic |
Ordinea tentantă este cea inversă, pe teoria că o centură strânsă pe gazdă este mai puternică. Ea produce o stare pe care nimeni nu o poate vedea: un administrator care a setat cândva o variabilă păstrează în tăcere o graniță care nu mai corespunde cu ce arată panoul, iar un client care lărgește intervalul din interfață nu poate înțelege de ce nu s-a schimbat nimic.
Un detaliu mic, cu un mod de eșec mare: o valoare imposibil de citit este tratată drept „nimeni”, nu drept „toată lumea”. Cine cere o graniță și greșește o tastă nu primește nicio citire, plus o linie în jurnal care spune de ce. Costul este cosmetic: o adresă și o cifră de disc care lipsesc din panou. Alternativa, căderea pe „totul este permis”, este eșecul clasic al unei liste de permisiuni: cedează deschis, în tăcere, exact în cazul în care cineva încerca să fie atent.
Șabloanele stau în afara intervalului. Întotdeauna.
Aceasta este o regulă, nu o preferință, și este greșeala care se mănâncă singură.
Un alocator împarte numere din interval. Puneți un șablon înăuntrul intervalului și într-o zi alocatorul ajunge la el, se creează o comandă nouă pe acel număr, iar șablonul devine mașina unui client. Comanda de după clonează dintr-o mașină care nu mai este un șablon. Așa că validatorul refuză un VMID de șablon Proxmox care cade în interiorul intervalului integrării, iar alocatorul tratează în plus fiecare șablon legat drept ocupat, în caz că cineva a lărgit intervalul după ce a legat unul.
În afara intervalului, un șablon poate sta oriunde. Intervalul mărginește ce creează platforma, nu unde are voie să stea materialul sursă.
Nu refolosiți niciodată un număr, nici după ce mașina a dispărut
Alocatorul împarte cel mai mic VMID liber din interval, iar „liber” este mai strict decât v-ați aștepta: fiecare VMID pe care integrarea l-a împărțit vreodată contează drept ocupat, inclusiv cele care aparțin unor servere șterse.
Asta pare risipitor vreme de vreo cinci secunde, până când vă gândiți ce ar însemna refolosirea. Un eveniment de stare întârziat de la vechea mașină aterizează pe rândul nou. Istoricul de audit a două servere diferite curge împreună într-o singură cronologie. Cineva restaurează copia de siguranță de ieri peste un număr care acum aparține altui client.
Interesant este că facem alegerea opusă pentru adresele IP din același produs, și dintr-un motiv bun: o adresă este o adresă, iar a nu refolosi niciodată una ar epuiza definitiv un /24 după 254 de mașini. Un VMID este un nume pentru istoricul unei mașini. Intervalele sunt ieftine; confuzia nu este.
Există o a treia categorie de „ocupat”, care apare abia când aveți mai mult de un singur lucru care creează mașini. O restaurare care încă rulează și-a revendicat VMID-ul țintă, dar nu are încă un rând de server, așa că o a doua restaurare din același minut ar primi altfel același număr „liber”. Orice rezervă un VMID înainte să existe rândul trebuie numărat.
Ce se întâmplă când intervalul se umple
Două răspunsuri, și amândouă ar trebui să existe.
Cel prietenos este o chestiune de aritmetică: alocatorul parcurge intervalul, nu găsește nimic liber și întoarce un eșec anume, care numește începutul și sfârșitul intervalului. Clientul citește „acest interval este plin, de la 5000 la 8999”, nu o eroare de hipervizor de patru straturi mai jos.
Cel real este baza de date. Constrângerea de unicitate pe (integrare, identificator extern) este arbitrul: două comenzi plasate în aceeași clipă pot vedea amândouă același cel mai mic număr liber, iar exact o inserare supraviețuiește. Cea care pierde reîncearcă, până la un număr mic și fix de încercări. A verifica întâi și a insera apoi deschide exact cursa pe care o închide constrângerea, așa că mecanismul este constrângerea, iar mesajul prietenos este o curtoazie deasupra ei.
Observați ce nu folosim: Proxmox are un endpoint pentru următorul identificator liber, iar aici este unealta greșită. El răspunde la „ce număr este liber pe acest cluster”, ceea ce este o altă întrebare decât „ce număr este liber și înăuntrul ferestrei care îmi aparține”. Întrebați hipervizorul și veți primi până la urmă un număr din afara propriei granițe.
Așadar, practic
- Porniți de sus și lăsați numerele mici în pace. De la 100 până la câteva sute este locul unde stau mașinile făcute de mână pe orice instalare de Proxmox, inclusiv pe a dumneavoastră peste trei ani, când veți fi uitat această decizie.
- Alegeți un interval cu o formă evidentă. De la 5000 la 8999 se citește ca „al nostru” dintr-o privire în interfața web. Un interval de 4096 de numere înseamnă patru mii de mașini pe o singură integrare.
- Puneți șabloanele în afara lui, într-un bloc propriu, departe.
- Scrieți intervalul unde îl poate vedea platforma, nu doar într-un fișier de configurare de pe gazdă, și asigurați-vă că este retrimis, nu trimis o singură dată.
- Verificați că și citirile sunt mărginite, nu doar crearea și ștergerea.
Numărul în sine nu contează prea mult. Ce contează este ca granița să fie un singur lucru, vizibil într-un singur loc, aplicat deopotrivă citirilor și scrierilor, și să cedeze închis când nu poate fi citită.
Asta a ieșit din construirea integrării Proxmox pentru Provibr, unde agentul rulează în rețeaua proprie a clientului și se conectează numai spre exterior.