Săriți la conținut

Blog ·

VM sau container? Ce vindeți pe Proxmox

Un invitat KVM și un container LXC împart un hipervizor, un spațiu de numere și o listă de prețuri, și cam nimic altceva. Diferențele care vă costă bani.

De Provibr

Proxmox VE rulează două feluri de invitat. O mașină virtuală KVM își pornește propriul nucleu în spatele unui firmware emulat, iar un container LXC împarte nucleul gazdei pe care stă. Pentru un client care cumpără un VPS, amândouă sunt „un server cu root pe el”, motiv pentru care comparația se face de obicei într-un tabel de marketing, cu rânduri despre densitate și consum suplimentar.

Acele rânduri sunt adevărate și nu ele sunt cele care vă vor costa. Ce vă costă este mulțimea de locuri în care cele două arată identic în API și se comportă diferit dedesubt, pentru că acolo un panou, un sistem de facturare sau un flux de comandă face în tăcere lucrul greșit și nimeni nu observă timp de o lună.

Am adăugat recent un al doilea fel de calcul în propria noastră integrare Proxmox, ceea ce a însemnat să citim API-ul cu întrebarea precisă „unde diverg acestea două”. Iată ce a ieșit din asta, în ordinea în care ne-a surprins.

Un cluster, un singur spațiu de numere

Începeți cu identificatorul, pentru că de el atârnă tot restul. Un invitat Proxmox este adresat printr-un număr și este tentant să presupuneți că mașinile virtuale și containerele primesc fiecare propriul interval: 100 ar putea fi o mașină și 100 ar putea fi și un container, deosebite prin tip.

Nu se poate. Spațiul de numere este comun întregului cluster, iar trei proprietăți ale API-ului spun asta. Endpointul care dă următorul identificator liber nu primește niciun parametru de tip, deci nu poate ști ce fel de invitat sunteți pe cale să creați. Listarea resurselor din cluster întoarce mașinile și containerele împreună, pe același câmp numeric. Iar lista proprie de invitați a clusterului este indexată după acel număr.

Asta are o consecință directă pentru orice stochează invitați Proxmox în propria bază de date. Puneți felul invitatului în constrângerea de unicitate, astfel încât „mașina 5001” și „containerul 5001” să fie două rânduri diferite, și aveți o schemă care poate ține două înregistrări pentru un singur invitat și le poate lăsa să se certe pe el. Identificatorul este unic de unul singur, iar felul este o observație stocată alături de el. Dacă alegeți intervale pentru o flotă, aritmetica din ce interval de VMID alegeți pentru găzduire nu se schimbă la apariția containerelor, și tocmai asta este ideea.

Un container se despachetează, nu se clonează

A doua divergență este traseul de creare și este mai mare decât pare.

O mașină virtuală se produce în mod normal prin clonarea unui șablon: numiți o sursă, alegeți clonă completă sau legată și primiți o copie a unei imagini de disc. Un container se produce prin despachetarea unei arhive pe un volum nou. Nu există un invitat-sursă, nu există alegerea între complet și legat și nu există unitate cloud-init, pentru că nu există la ce să atașați o unitate.

Așadar, corpul cererii nu are aproape niciun câmp comun cu cel care creează o mașină. Un container vrea ostemplate, care indică o arhivă de pe o stocare, un indicator unprivileged, un hostname, un rootfs și o valoare swap. O mașină vrea scsi0, scsihw, bios, boot și un ide2 când pornește de pe un ISO. Refolosirea unui vocabular pentru celălalt este greșeala pe care trebuie să o evitați în mod deliberat: cuvintele sunt destul de asemănătoare încât un câmp numit disk să însemne două lucruri diferite în aceeași bază de cod în decurs de un an.

Două detalii din acel corp merită împrumutate, indiferent pe ce construiți.

rootfs=<storage>:<size> este o alocare, nu o referință. Înseamnă „creează un volum nou de atâția gigaocteți pe această stocare”. Forma care numește un volum existent arată aproape identic și face un lucru categoric diferit: adoptă un volum care poate să mai țină încă datele altcuiva.

Omiterea unui parametru este răspunsul sigur. Imbricarea, keyctl, FUSE, montările bind și accesul direct la dispozitive sunt toate oprite dacă nu le trimiteți, iar nu există o valoare „goală” pe care să vă amintiți să o scrieți. Prin urmare, postura implicită corectă pentru o platformă de găzduire este o cerere scurtă, nu una lungă. Cu câmpul de arhitectură povestea este aceeași: Proxmox îl deduce din arhivă, iar trimiterea unuia care nu se potrivește eșuează în momentul despachetării.

Trei lucruri pe care un container nu le va face niciodată

Unele lipsuri sunt elemente de plan. Trei sunt structurale, iar confundarea celor două categorii în propriul produs este felul în care ajungeți să promiteți o funcție care nu poate exista.

AcțiuneInvitat KVMContainer LXC
Pornire, oprire, închidere, ștergeredada, aceeași formă, alt segment de cale
Pauză sau hibernaredanu: acela este monitorul QEMU
Pornire din rețea cu PXEdaniciodată
Instalare dintr-un ISOdaniciodată
Alegerea ordinii de pornire, BIOS sau UEFIdaniciodată
Consolăframebuffer VNCun terminal, pe alt protocol
Swapinvizibil pentru gazdăo setare de hipervizor, cu un număr

Cinci dintre acele rânduri au nevoie de mai mult decât o celulă, în trei grupuri.

Netboot, instalarea din ISO și alegerea firmware-ului sunt imposibile dintr-un singur motiv, nu din trei: un container nu are firmware. Nu rulează un încărcător de pornire, nu are o ordine de pornire, iar pornirea lui nu implică nimic căruia i s-ar putea spune să încerce mai întâi rețeaua. Dacă vindeți un produs în care „reinstalarea din biblioteca noastră de imagini” este o funcție, rețineți că traseul PXE de la un răspuns DHCP la o instalare completă nu are echivalent pentru containere. Reconstruirea unui container este un mecanism diferit, cu garanții diferite, și merită un ecran propriu, nu un buton dezactivat.

Consola este același fel de diferență purtând un nume familiar. Proxmox vă va da o consolă pentru un container, dar este un terminal peste un websocket, nu framebufferul unui adaptor grafic, iar un client VNC nu îl va reda. O singură filă de consolă are acum două implementări în spate, iar răspunsul cinstit, pentru moment, este să spuneți că fila nu este încă disponibilă, în loc să deschideți un vizualizator care arată un dreptunghi negru.

Pauza și hibernarea merită o notă de subsol, pentru că ele prind în capcană logica de sancționare. Dacă platforma dumneavoastră suspendă o mașină atunci când un client depășește o limită, iar „suspendare” înseamnă pauză, atunci containerele ies complet din sancționare: comanda este refuzată, niciun lucrător nu raportează nimic, iar clientul continuă să ruleze. Granița aparține modului, nu comenzii. Oprirea unui container este perfect posibilă.

Swapul este o decizie de produs, nu o valoare implicită

Iată-l pe cel care va apărea în tichetele de asistență.

Proxmox dă unui container nou 512 MiB de swap dacă nu spuneți altfel. Moșteniți asta în tăcere și un plan vândut ca „2 GiB de memorie” livrează 2,5 GiB de memorie utilizabilă, iar diferența nu apare nicăieri ca un număr mai mare: apare ca un container care devine lent în loc să atingă o condiție cinstită de memorie epuizată, luni mai târziu, pe o gazdă care a început să facă swap.

Noi trimitem valoarea explicit la fiecare creare, cu zero ca valoare implicită a noastră. Zero este o alegere, nu o absență. Orice ați alege, alegeți deliberat, scrieți pe plan și asigurați-vă că numărul pe care îl vede un client este numărul pe care îl primește hipervizorul.

Măsurarea swapului are prețul ei. Listarea în bloc, cea care vă dă contoarele de procesor, memorie, disc și rețea pentru fiecare invitat dintr-un cluster, nu poartă niciun câmp de swap, pentru niciunul dintre cele două feluri. Singurul loc în care Proxmox îl raportează este endpointul de stare pentru un invitat, deci este un apel HTTP în plus pentru fiecare container care rulează, pentru totdeauna. Noi îl citim o dată pe minut: de trei ori pe minut triplează sarcina pe hipervizorul altcuiva pentru un număr care se mișcă în minute, iar o dată la cinci minute pune exact o probă într-un interval de agregare de cinci minute, ceea ce face coloana maximului egală cu media și, prin urmare, decorativă.

Două defecte pe care le-am livrat presupunând că sunt același lucru

Amândouă fuseseră în funcțiune de luni de zile înainte de runda care s-a dus să caute.

Primul: ecranul nostru de import lista containerele drept mașini virtuale. Listarea resurselor din cluster cu type=vm nu este un filtru QEMU, ea întoarce ambele feluri, iar câmpul care spune care dintre ele este pur și simplu nu era citit. Nimic nu a eșuat. Lista era greșită.

Al doilea a fost mai tăcut. Fiecare container care rula primea două apeluri către agentul de invitat la fiecare rundă de interogare, plus unul după fiecare comandă, către o cale care există numai pentru QEMU. Fiecare era un eșec garantat și nimic nu ieșea la suprafață, pentru că o îmbogățire opțională eșuată trebuie să fie supraviețuibilă, și chiar era. A fost găsit de un test care numără ce căi sunt apelate, în loc să afirme lucruri despre rezultate, ceea ce este un obicei de copiat: dacă afirmați numai despre rezultate, o categorie întreagă de muncă inutilă rămâne invizibilă.

Ce am scrie înainte de a vinde vreunul dintre ele

Dacă hotărâți ce ar trebui să ofere un produs de găzduire pe Proxmox, patru întrebări vă duc aproape tot drumul.

  1. Felul invitatului este o proprietate a planului sau o alegere la finalizarea comenzii? Amândouă sunt de apărat. O valoare implicită sub alegere nu este: un client care a comandat un container și a primit o mașină a primit alt model de securitate, alt nucleu și alt set de capabilități decât cel pe care l-a ales.
  2. Care refuzuri sunt permanente și care sunt temporare? Spuneți-o în interfață, chiar cu acele cuvinte. „Nu este posibil pentru un container” și „nu este construit încă” sunt promisiuni diferite.
  3. De unde vine protecția împotriva falsificării adresei? Lipsa cinstită din munca noastră: o mașină clonată primește filtrare de IP la livrare, iar un container încă nu. Proxmox are aceleași endpointuri de firewall pentru amândouă, deci este un pas de construit, nu un obstacol, dar un container predat fără ea poate trimite trafic pretinzând că este altcineva.
  4. Ce arată monitorizarea pentru un container? Orice derivă dintr-un agent de invitat, dintr-un framebuffer sau din firmware este gol. Gol este în regulă. Gol prezentat ca un zero sănătos nu este.

Avem câmpul de plan, traseul de comandă și cererea de creare construite și măsurate față de forma HTTP brută a API-ului. Ce nu am făcut este să creăm un container pe hipervizorul de producție al cuiva, așa că descrierea cinstită a suportului nostru pentru containere este „forma este corectă, iar dus-întorsul este netestat”, ceea ce este un lucru util de putut spune cu voce tare despre propria platformă.

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. Obiceiul înrudit, acela de a nu avea încredere în răspunsul de succes al unui hipervizor, se află în de ce un 200 de la Proxmox nu este un rezultat.

Începeți cu o gazdă și un agent

Creați un cont, instalați agentul cu o singură comandă și conectați primul dumneavoastră host Proxmox. Perioada de probă durează 14 zile și nu cere date de plată.