Блог
Da li svaki zakupac treba da dobije sopstvenu VM?
Birajte između kontejnera po zakupcu, VM-ova i hibridnih postavki koristeći okvir za odlučivanje zasnovan na riziku i korake za jačanje sistema koji svaku opciju čine odbranjivom.
Sažetak
Hosting sa više zakupaca vas tera da odlučite koliko daleko zakupci mogu dopreti jedni do drugih. Kontejneri koriste Linux imenske prostore (namespaces) i cgroups za izolaciju procesa i resursa, ali dele kernel domaćina. Virtuelne mašine dodaju granicu na nivou hardvera, po cenu brzine i operativnog opterećenja. Hibridni pristup—kontejneri unutar VM-ova—može vam dati oboje, ali udvostručuje površinu koju morate zakrpati. Ovaj članak vas vodi kroz odlučivanje zasnovano na riziku, uporednu analizu i korake za jačanje Docker sistema koji su važni čak i unutar VM-a. Na kraju ćete znati koji model izolacije odgovara vašim zakupcima i šta treba konfigurisati pre pokretanja.
Vaša aplikacija sa više zakupaca je skoro spremna. Imate Docker Compose datoteku koja pokreće stack za svakog korisnika, i to je brzo. Onda vas prijatelj koji vodi hosting kompaniju pita: 'Da li svakom zakupcu dajete sopstvenu VM?' Ukočite se. Niste planirali to pitanje. Ovaj članak vam daje način da odgovorite danas, bez sigurnosnog tima. Ovo radite sami, tako da odluka mora biti dovoljno jednostavna da je možete odbraniti u 2 ujutru.
Prestanite da tražite 'najbolji' model. Počnite tako što ćete zapisati šta se dešava ako kod zakupca preuzme vaš host. Definišite radijus eksplozije pre nego što izaberete bilo koji alat. Ta vežba će vam reći više nego bilo koje merenje performansi.
Kernel je cimer koga ne možete izbaciti
Kontejneri su efikasni jer dele kernel domaćina. To deljenje je cela fora i ceo rizik. Linux imenski prostori (namespaces) daju svakom kontejneru sopstveni pogled na procese, mrežu i datotečni sistem. Control groups (cgroups) vam omogućavaju da ograničite CPU, memoriju i disk I/O tako da jedan zakupac ne može da izgladni ostale. Ali nijedan od ova dva ne stvara hardverski zid.
Zamislite kontejner kao proces sa veoma dobrom lažnom ličnom kartom. Veruje da je na sopstvenoj mašini. Kernel je, međutim, jedna kopija Linuxa koja radi na vašem hostu. Ako zakupac iskoristi ranjivost kernela, imenski prostori postaju metapodaci i ništa više. Napadač koji može pozivati funkcije kernela može dosegnuti druge imenske prostore na istom kernelu. To je bekstvo iz kontejnera o kome stalno slušate.
Recimo da hostujete mali B2B alat sa jednim kontejnerom po klijentu. Klijent instalira sumnjiv dodatak sa ranjivošću koja omogućava izvršavanje koda na daljinu. Uz podrazumevana Docker podešavanja, taj proces se pokreće kao root unutar kontejnera. Root u kontejneru je i dalje UID 0, a kernel ne razlikuje taj UID od root-a na hostu osim ako eksplicitno ne mapirate korisnike. Napadač može pokušati da pobegne, a deljeni kernel im je meta.
Kvar ne mora biti dramatičan. Jedan zakupac koji curi memoriju može gurnuti host u swap, usporavajući sve ostale zakupce. Bez cgroups ograničenja, jedna petlja koja se loše ponaša je napad na dostupnost. Sa njima, to je blokiran proces i upozorenje.
Da li to znači da su kontejneri nesigurni? Ne. Znači da kernel morate tretirati kao zajedničku zonu poverenja. Pre nego što odaberete, napišite iskaz rizika od jednog pasusa: 'Ako je kontejner zakupca kompromitovan, napadač može pristupiti: [lista]. Poslovni trošak bi bio: [iznos ili uticaj].' Ako vas taj pasus plaši, niste paranoični. Pošteni ste.
Za dublji uvid u spektar izolacije, od deljenih kontejnera do potpuno odvojenih stack-ova, pogledajte naš vodič za dizajniranje multi-tenant Docker arhitekture.
Tri načina da to isečete (Izaberite jedan pre nego što objavite)
Zaista postoje tri arhitekture za izolaciju sa više zakupaca. Svaka 'najbolja praksa' je kombinacija ovih.
| Pristup | Barijera izolacije | Najbolje kada | Najveća mana |
|---|---|---|---|
| Kontejneri po zakupcu | Kernel imenski prostori + cgroups | Mnogo malih zakupaca, nizak rizik po zakupcu, potrebna gustina | Jedan napad na kernel može oboriti sve zakupce na tom hostu |
| Jedna VM po zakupcu | Hipervizor/hardverska virtualizacija | Regulisani podaci, neprijateljski zakupci, visoka vrednost po zakupcu | Teža, sporija za kreiranje, zakrpate OS za svakog zakupca |
| Kontejneri unutar VM-ova | VM granica oko kontejnerizovanih opterećenja | Gustina plus tvrda ljuska između grupa | Troškovi i operativni režijski troškovi se skoro udvostručavaju |
Kontejneri po zakupcu. Ovo je podrazumevano za većinu SaaS osnivača. Svaki zakupac dobija sopstveni kontejner ili mali Compose stack. Obezbeđivanje je trenutno, slike su male, CI/CD je jednostavan. Ograničenja resursa sprečavaju bučne susede da pojedu server. Kompromis je deljeni kernel. Ako možete zadržati opterećenja neprivilegovana i redovno zakrpavati host, ovo je često pravi prvi potez.
Ne stavljajte dva zakupca u isti kontejner. To je deljeni kernel plus deljeni runtime plus deljeni datotečni sistem. Ako jedan zakupac otpremi datoteku koja kreira proces, drugi zakupac je već u istoj tabeli procesa. Kontejner je vaša jedinica izolacije; napravite ga jednim zakupcem po kontejneru.
Šta je sa bazom podataka? Ako se svaki zakupac povezuje na jednu MongoDB ili PostgreSQL instancu sa istim kredencijalima, već ste dodali ogromnu deljenu komponentu. Dajte svakom zakupcu odvojene kredencijale, a idealno i odvojenu bazu podataka ili šemu. Kontejneri izoluju aplikaciju; baza podataka je često prvo curenje koje će napadač testirati.
Jedna VM po zakupcu. Dajte svakom zakupcu punu virtuelnu mašinu. Hipervizor dodaje granicu na nivou hardvera, što je tačno ono što napad na kernel mora preći da bi dosegao host. Ovo je važno za regulisana okruženja ili kada su zakupci nepoverljivi. Cena je gustina i vreme. Sada upravljate flotom operativnih sistema, ne samo kontejnerima. Svaka VM zahteva ažuriranja, sigurnosne agente i praćenje. Za solo osnivača, to je pravi posao.
Obrasci koji funkcionišu na ovom nivou: koristite infrastrukturu kao kod za kreiranje VM-a iz iste osnovne slike, upecite ažuriranja u nove slike umesto zakrpanja živih sistema, i ugasite opterećenja koja ne prepoznajete. Držite upravljački port VM-a zatvorenim za internet.
Kontejneri unutar VM-ova. Ovaj hibrid se retko pominje u tutorijalima za početnike. Stavite malu VM oko svakog zakupca (ili male grupe zakupaca), a zatim pokrenete kontejnere unutar te VM. VM je kontejner radijusa eksplozije; kontejneri su samo jedinice za implementaciju. Ovo vam daje tvrdu ivicu virtualizacije i reproduktivnost slika. Košta više, jer plaćate režiju virtualizacije i fleksibilnost kontejnera, ali može biti najmudriji dugoročni model kada ne možete u potpunosti verovati zakupcima.
Jedan čest mikro-primer: zakupac pokreće Node API i pozadinskog radnika. Umesto jednog ogromnog kontejnera sa oba procesa, koristite jednu VM, zatim dva kontejnera sa različitim ograničenjima resursa, deljenom mrežom i bez direktnog izlaganja internetu za radnika. VM pruža tvrdu ivicu; kontejneri pružaju strukturu.
Koji biste trebali izabrati? Tabela je vaša uža lista. Sledeći odeljci čine odluku konkretnom.
Ako izaberete kontejnere, uradite ovih šest stvari ili nemojte ni pokušavati
Kontejneri po zakupcu su u redu ako svaki kontejner tretirate kao potencijalnog napadača. To počinje konfiguracijom, a ne željnim razmišljanjem.
0. Ograničite resurse pre nego što nekome poverujete. Cgroups su mehanizam pravednosti i odbrana dostupnosti. Postavite --memory i --cpus po kontejneru. Zakupac koji curi memoriju treba da udari u sopstveno ograničenje, a ne u ograničenje vašeg servera. Ovo nije sigurnosna granica, ali bučni sused je napad bez ijedne linije koda. Praktičan početak: --memory 512m --cpus 0.5. Za radni proces, počnite niže i povećavajte.
1. Pokrenite kao ne-root korisnik. Nikada ne dozvolite procesu u kontejneru da koristi UID 0 osim ako vam to apsolutno nije potrebno. Postavite korisnika u Dockerfile-u i prosledite --user kao dodatnu zaštitu. Eksploatacija koja radi kao neprivilegovani korisnik ima mnogo manje puteva do kernela. U vašem Dockerfile-u kreirajte korisnika: RUN useradd -u 10001 app i USER app. Ne preskačite ovo da biste uštedeli vreme.
2. Uklonite svaku sposobnost (capability) koja vam nije potrebna. Linux sposobnosti (capabilities) dele root-ovu moć na male delove. Većini veb aplikacija ne treba gotovo nijedna. Počnite sa --cap-drop=ALL i dodajte nazad samo ono za šta znate da vam treba. Kontejner bez CAP_SYS_ADMIN je mnogo teže iskoristiti za trikove sa imenskim prostorima. Ako vaša aplikacija pokuša da se veže na privilegovani port, pokrenite je na visokom portu i stavite proxy ispred, umesto da dodelite NET_BIND_SERVICE.
3. Učinite datotečni sistem samo za čitanje. Vaša aplikacija ne bi trebalo da piše u sopstveni sloj kontejnera. Montirajte tmpfs za stanje. Napadač koji ne može da piše na disk ima mnogo teže vreme da usadi trajnost. Kompromitovana PHP aplikacija koja pokušava da napiše webshell neće uspeti kada je koreni datotečni sistem samo za čitanje. Možete montirati imenovani volumen za direktorijum za pisanje koji vaša aplikacija zaista treba.
4. Primenite seccomp i AppArmor ili SELinux. Ovi šalju rizične sistemske pozive u gomilu za odbacivanje. Docker isporučuje podrazumevani seccomp profil; koristite ga. Dodajte AppArmor profil za još jedan sloj. Ne morate da savladate svaki sistemski poziv. Treba da odbijete ono što normalan veb radnik nikada ne zahteva. Nikada nemojte pokretati sa --privileged. Ta zastavica onemogućava skoro svaku odbranu koju ste upravo postavili.
5. Segmentirajte mrežu. Ne dajte svakom kontejneru rutu do svakog drugog kontejnera. Podrazumevano odbijanje, zatim otvorite samo portove koji su vam potrebni. Kompromitovan kontejner baze podataka ne bi trebalo da može da skenira vaš administrativni panel. Ako su zakupci u odvojenim mrežama, proboj u jednoj mreži ne može se širiti lateralno.
Praktičan početak:
docker run --user 10001 --cap-drop=ALL --security-opt no-new-privileges --read-only --tmpfs /tmp:rw,size=64M --security-opt seccomp=default.json --memory 512m --cpus 0.5 myimage
Stavite iste zastavice u Compose datoteku i primenite ih na svakog zakupca. Ovo nije kompletno, ali je mnogo jača podrazumevana postavka od one koju docker run daje odmah iz kutije.
Za detaljniji vodič, koristite naš vodič za postepeno jačanje Docker kontejnera u hosting okruženju sa više zakupaca.
Docker-ovo poboljšano izolovanje kontejnera je izuzetak koji treba da znate
Ako radite unutar upravljanog Docker okruženja, potražite Docker-ovo poboljšano izolovanje kontejnera (Enhanced Container Isolation, ECI). Ono koristi izolaciju korisničkog imenskog prostora i sigurni runtime za kontejnere ispod haube. Root unutar kontejnera se mapira na neprivilegovanog korisnika na hostu, tako da čak ni kontejner koji radi kao root ne dobija root privilegije na hostu. Takođe blokira opasne sposobnosti i sistemske pozive po podrazumevanoj vrednosti. Ovo nije nešto što možete recreirati sa nekoliko zastavica na običnom Docker-u. Ako vaša platforma to podržava, uključite ga. To ne uklanja potrebu za ne-root korisnicima i ograničenjima resursa, ali menja matematiku rizika.
Možete približno postići deo ovoga remapiranjem korisničkog imenskog prostora (userns-remap) u Docker daemonu. To nije tako kompletno kao sigurni runtime, ali je bolje nego ništa. Ako ga koristite, proverite da UID mapiranje radi pre nego što mu verujete.
VM zabluda: prelazak na virtuelne mašine nije jačanje sistema
Ovo je kontradiktorni deo, i to je deo koji većina ljudi preskače. Ako pređete na jednu VM po zakupcu i zatim rasporedite svoje normalne kontejnere unutar nje, niste uklonili problem sigurnosti kontejnera. Dodali ste širok kavez. Bekstvo iz kontejnera i dalje radi; napadač samo sleti u VM umesto na host. To je stvarno poboljšanje, ali i dalje vam treba šest koraka.
Druga zamka je pretpostavka da je sama VM sigurna. Podrazumevana slika sa slabom SSH lozinkom, nezakrpljenim osnovnim paketima ili otvorenim upravljačkim portom je poklon. Granica hipervizora je važna samo ako je gost ojačan i ažuriran. U suprotnom, vaša 'sigurna VM' je brži put do kompromitacije jer se osećate sigurno i prestanete da proveravate.
Ono što VM dobijate je svodljiv radijus eksplozije. Katastrofa jednog zakupca ostaje u jednoj VM. Ono što vas košta je vaše vreme. Postajete sistemski administrator za onoliko operativnih sistema koliko imate zakupaca. Ako ste solo osnivač koji isporučuje proizvod, zapitajte se da li imate sate za zakrpanje i praćenje flote. Ako da, VM po zakupcu može biti pravi izbor. Ako ne, kontejneri sa snažnim jačanjem mogu biti iskreniji.
Takođe zapamtite da je vaš hipervizor domaćin kritična meta. Kompromitovan hipervizor može videti sve goste. Zakrpajte host, ne samo goste. VM vas ne oslobađa zakrpanja hosta; podiže uloge za propuštanje.
Napomena o hibridu: ne pretpostavljajte da kontejneri unutar VM-a daju 'dva sloja sigurnosti' besplatno. VM dodaje granicu; kontejner i dalje zahteva ne-root, ograničenja sposobnosti i seccomp. U suprotnom, prvi sloj je samo onoliko jak koliko i najslabiji kontejner.
Četiri pitanja koja rešavaju debatu za deset minuta
Ne optimizujte u apstraktu. Postavite sebi ova četiri pitanja redom. Zapišite odgovore.
1. Čemu moj zakupac ima pristup? Ako zakupac može dosegnuti samo svoju veb aplikaciju i bazu podataka, kontejneri po zakupcu sa strogim mrežnim pravilima su odbranjivi. Ako su podaci zakupca regulisani ili finansijski osetljivi, krenite ka VM-ovima.
2. Koliko bi me koštala kompromitacija jednog zakupca? Saberite izgubljene kupce, pravnu izloženost i poverenje. Ako je broj veći od troška pokretanja VM-ova, potrošite novac. Ako nije, kontejneri su racionalan izbor.
3. Koliko zakupaca imam i koliko oni plaćaju? Mnogo malih pretplatnika: gustina kontejnera je važna. Šačica velikih naloga: dajte svakome VM i naplatite u skladu s tim. Zakupci koji vam plaćaju manje od kafe ne bi trebalo da svaki zahtevaju OS za upravljanje.
4. Mogu li zakrpavati stvari po rasporedu? Kontejneri dele jedan kernel hosta, tako da zakrpanje hosta štiti sve. VM-ovi umnožavaju vaše mete zakrpanja. Ako znate da ćete preskakati ažuriranja, izaberite arhitekturu sa manje pokretnih delova i jačim podrazumevanim postavkama.
Vaši odgovori će se grupisati. Dva ili više odgovora usmerenih na VM znači da ne biste trebali podrazumevano koristiti kontejnere po zakupcu. Tri ili više odgovora usmerenih na kontejnere znači da su VM-ovi preuranjeni. Jedan kontraintuitivan rezultat: zakupac sa niskim prihodom koji ima pristup osetljivim podacima i dalje treba VM, jer regulatorni trošak nema veze sa tim koliko plaćaju.
Isporučite najmanje što možete verovati, pa zaradite više izolacije
Vaša prva arhitektura ne mora biti vaša finalna. Počnite sa najčvršćom postavkom koju zapravo možete održavati, a zatim dodajte izolaciju kako vaša baza zakupaca to opravdava. Za većinu solo operatera, to znači kontejneri po zakupcu sa ne-root korisnikom, ograničenim sposobnostima, datotečnim sistemom samo za čitanje, seccomp-om i mrežnom segmentacijom. Za regulisane ili visokovredne zakupce, pređite direktno na jednu VM po zakupcu, sa kontejnerima samo kao slojem za pakovanje unutar.
Šta god izaberete, zapišite odluku i revidirajte je kvartalno. Kada dobijete prvo pitanje 'treba li pomeriti ovog zakupca na VM?', imaćete odgovor i listu za proveru koja to potkrepljuje. To je ono što izolacija zapravo znači: kompromis kojim upravljate, a ne tehnologija koju kupujete.
Pre pokretanja, prođite kroz naš praktični kontrolni spisak za Docker izolaciju — on pretvara ove odluke u listu koju možete proveriti pre nego što pokažete stranicu kupcu.

