Blogg

Hvilke kunder trenger faktisk sin egen VM? En lagdelt Docker-isolasjonsplan

VM for hver kunde er overkill. Her er hvordan du bestemmer hvor mye isolasjon hver leietaker trenger – og automatiserer beslutningen.

Sammendrag

Byråer får ofte panikk når en kunde spør hvor virkelig isolert dataene deres er fra andre leietakere. Docker sine namespaces og cgroups gir deg reell isolasjon, men de er ikke det samme som en maskinvaregrense. I stedet for å kjøre hver klient på en VM – eller verre, behandle alle kunder likt – bygg et lite sett med isolasjonsnivåer og match hver kunde til ett basert på datasensitivitet, tillit og samsvar. En nedlåst container (ikke-root, fjernede kapabiliteter, seccomp, skrivebeskyttet rot) dekker de fleste nettsteder; regulerte eller fiendtlige arbeidsbelastninger får en VM eller en container-i-VM-hybrid. Dette innlegget gir en repeterbar beslutningsflyt, en sammenligningstabell og et ærlig blikk på når mer isolasjon er overkill.

Er du på det punktet i en salgssamtale der den nye kunden sier «vi er helsevesenet, vis meg at dataene våre er isolert fra dine andre kunder» og du heller vil snakke om noe annet?

Dette er byråproblemet: ikke én perfekt utrulling, men den samme pålitelige utrullingen gjentatt på tvers av et dusin kunder med ulike budsjetter, risikoprofiler og samsvarskrav. Her er den ærlige versjonen. Docker-isolasjon er reell, men den er spesifikk. Namespaces gir hver container sitt eget syn på prosesser, nettverk og filsystem; cgroups setter grenser for CPU, minne og disk I/O slik at leietakere ikke kan sulte hverandre. Det du ikke får, er en maskinvarevegg mellom containeren og vertskjernen. Hvis en angriper rømmer containeren, er de inne i den eneste kjernen du har. Resten av denne artikkelen gjør det ubehagelige faktum til en repeterbar beslutning: klassifiser hver klient etter datasensitivitet og tillit, bruk en grunnleggende herdingsprofil, og strekk deg bare etter en VM når kostnaden for et brudd er høyere enn kostnaden for VM-en.

Vent, er ikke containere allerede isolert?

Docker kjører på Linux-namespaces og cgroups, og de ordene gjør virkelig arbeid. Namespaces skiller prosess-ID-er, nettverksstakker, monteringspunkter og brukere, slik at en prosess i én container ikke kan se prosesstabellen til en annen. Cgroups setter grenser: gi en container 0,5 CPU, 512 MB minne og en fast blokk-I/O-vekt, og det er nøyaktig det den får. En løpsk løkke i én leietaker blir strupet i stedet for å ta ned naboen. Hvis du ikke har konfigurert grenser, har du hoppet over det mest grunnleggende som cgroups er til for.

Ta en enkel PHP-app i container A. Den ser sitt eget filsystem, sitt eget nettverksgrensesnitt, sin egen PID 1. Container B har det samme, men et annet syn. Det er namespaces. Gå så vekk og hopp over minnegrensen: container A kan fylle vertens RAM og få container B til å krype. Det er det cgroups er til for å forhindre. Men to containere kan være isolert fra hverandre med namespaces og fortsatt dele vertskjernen, som er den delen enhver container-unnslipningshistorie handler om. En utnyttelse som når kjernen, kan potensielt nå hver leietaker på den verten.

«Docker er isolert» er en halv sannhet. Den nøyaktige versjonen er «Docker isolerer med namespaces og cgroups, og en kjernesårbarhet er blast radius.» Før du stoler på at en leietaker kjører upålitelig kode, sitt et øyeblikk med den tanken. Svaret er ikke «aldri bruk containere» – det er den enkle panikken. Svaret er et nivåsystem.

Så hvorfor trenger noen kunder mer enn namespaces?

Det ærlige svaret er at isolasjon ikke er en bryter, det er et spekter. I den ene enden har du en fullstendig delt container der alle i praksis er i én app. I den andre enden har du en separat VM per leietaker med sin egen kjerne. Det meste av byråarbeid lever i den ubehagelige midten, og midten er ikke et binært valg mellom «Docker er greit» og «kjør en VM for alle.»

Det som presser en klient til høyre, er ikke størrelsen. Det er fire spørsmål:

  • Lagrer de regulerte data? Helsejournaler, betalingskortdetaljer, alt en regulator vil kalle sensitivt.
  • Har et brudd på deres leietaker en realistisk vei til en annen leietaker? Hvis de kan kjøre vilkårlig kode, ja.
  • Stoler du på koden og folkene som distribuerer den? En klient som ansetter den billigste frilanseren, er ikke samme tillitsnivå som en klient hvis utviklingsteam du kjenner.
  • Sier kontrakten deres «dedikert», «isolert» eller «privat»? Hvis den gjør det, har du allerede lovet et nivå; den eneste jobben nå er å velge det riktige.

Hvis du ikke kan svare på disse spørsmålene ennå, sett klienten i et grunnleggende nivå og skriv ned antakelsene. Det er ikke en sikkerhetsrevisjon; det er en sjekk du gjentar ved hver onboarding.

Hvordan bestemmer jeg per klient uten å kjøre en sikkerhetsrevisjon hver gang?

Lag en liten tabell og hold deg til den. Du trenger ikke en matrise med førti celler. Fire nivåer dekker nesten enhver klient et byrå ser.

KlientposisjonHva som faktisk skiller demBruk når
Nivå 1: Delt app/containerKun applikasjonslogikkInterne verktøy, lavrisikodata, prosjekter der alle eksplisitt er i ett påloggingssystem
Nivå 2: Samme vert, separate containereNamespaces og cgroupsDe fleste markedsføringssider, kontaktformularer, ingen sensitive data
Nivå 3: Nedlåst containerNivå 2 + ikke-root, fjernede kapabiliteter, seccomp, skrivebeskyttet rot, nettverkssegmenteringE-handel, PII, tilpasset kode du ikke fullt ut stoler på
Nivå 4: Per-leietaker VMHypervisor og en separat kjerneHelsevesen, finans, samsvarsdokumentasjon, upålitelig kode, støyende naboer

Slik spiller det ut i praksis. En bakerikunde med et kontaktformular og en Instagram-lenke går til Nivå 2: én container på en delt vert, standard Docker-nettverk, ressursgrenser, ferdig arbeid. En nettbutikk som lagrer kundenavn, adresser og betalingsomdirigeringer går til Nivå 3: samme delte vert, men containeren kjører som en ikke-root-bruker, har ingen ekstra kjernekapabiliteter, bruker en seccomp-profil, og eksponerer kun port 443. En medisinsk inntakportal som lagrer beskyttet helseinformasjon går til Nivå 4: en VM per leietaker, fordi kostnaden for et brudd ikke er «vi rydder opp», men «vi kan ikke vise klienten at vi tok dem seriøst.»

Hele trikset er at du ikke tenker nytt rundt arkitekturen for hver klient. Du velger en rad fra en tabell du allerede er enige om. Slik kan et fempersonsbyrå drive hundre nettsteder uten hundre separate sikkerhetsobsesjoner. Det betyr også at den neste klienten ikke får et svar som avhenger av hvilket teammedlem som tok telefonen. For den dypere arkitekturdebatten bak disse valgene, dekker denne guiden om utforming av isolasjonsnivåer for flere leietakere avveiningene mer detaljert.

Hvordan ser en nedlåst container faktisk ut?

La oss slutte å si «nedlåst» og bli konkrete. Dette er hva Nivå 3 betyr for en typisk WordPress- eller PHP-klient.

Først, endre brukeren. De fleste offisielle bilder kjører fortsatt som root som standard; i Dockerfilen din oppretter du en ikke-root-bruker og kjører appen som den brukeren. Det fjerner umiddelbart den vanligste måten et containerkompromiss blir et vertskompromiss. For det andre, fjern kapabilitetene du ikke trenger. Kjør med --cap-drop ALL og legg bare tilbake én, vanligvis NET_BIND_SERVICE slik at appen kan lytte på port 80. Bare det er en større endring enn de fleste forventer. For det tredje, gjør rotfilsystemet skrivebeskyttet med --read-only, og monter skrivbare kataloger (opplastinger, databasekatalogen) som volumer eller tmpfs. For det fjerde, bruk en seccomp-profil og, hvis verten din støtter det, AppArmor eller SELinux. Til slutt, plasser containeren på et dedikert Docker-nettverk og eksponer bare portene som faktisk må være tilgjengelige.

La oss gå gjennom et WordPress-eksempel. Basebildet kjører sannsynligvis som root, så du legger til et useradd-trinn og en USER-direktiv. Du kjører containeren med en minnegrense og en CPU-grense, så et utbrudd av plugin-trafikk ikke skader naboen. Du monterer /var/www/html/wp-content/uploads som et skrivbart volum. Du setter --read-only. Du fester den til et nettverk som ikke har noe --privileged-flagg i nærheten. Resultatet er en container som pleide å være «et WordPress-nettsted» og nå er «et WordPress-nettsted som tilfeldigvis er mer nedlåst enn de fleste virtuelle private servere.»

Hvis det føles skjørt å gjøre alt dette manuelt, finnes det en enklere mellomvei: Enhanced Container Isolation fra Docker, som bruker brukernavneområde-isolasjon og en sikker containerkjøring. Det er en legitim snarvei, men det er ikke et frittpass til å hoppe over ikke-root eller fjerning av kapabiliteter. Leietakeren trenger fortsatt et fornuftig bilde. Forskjellen er at den kjernefacing angrepsflaten blir mindre uten at du blir en seccomp-ekspert over natten. Hvis du vil ha den nøyaktige sekvensen for en enkelt leietaker, gjør steg-for-steg-guiden for isolasjonsherding denne delen om til kopier-og-lim-kommandoer.

Når slutter jeg å legge på lag og bare gir dem en VM?

Her er den kontrære delen: mer isolasjon er ikke automatisk bedre. VM-er gir deg isolasjon på maskinvarenivå, en separat kjerne, og et mye mindre angrepsflate hvis gjestekjernen faller. Det er akkurat det helse- og finansklienter forventer når de sier «vi vil være isolert.» Men hver VM legger til patching, backup og beregningskostnader, og det multipliserer arbeidet med å holde en flåte oppdatert. Hvis du gir hver klient en VM fordi én klient en gang sa at Docker skremte dem, har du kjøpt sikkerhetsteater med ekte penger.

En VM er det riktige svaret når risikoen per leietaker er høyere enn driftskostnaden for en VM per leietaker. Det betyr regulerte data, skriftlige samsvarskrav, upålitelig tredjepartskode, eller en klient som trenger å få fjernet en støyende nabo. Det er også det riktige svaret når klientens kontrakt bokstavelig talt lover et dedikert miljø, fordi «container» ikke er det de ser for seg når de signerer «dedikert.»

Men en VM unnskylder ikke en slurvete container. En vanlig felle er å sette klienten i en VM og deretter hoppe over herdingen fordi «VM-en beskytter dem.» VM-en beskytter verten mot leietakeren, ikke leietakeren mot sitt eget dårlige bilde. Du vil fortsatt ha ikke-root, fjernede kapabiliteter og seccomp inne i den VM-en. Hybridtilnærmingen – containere inni en VM – er ofte det søte punktet: VM-en gir grensen for samtalene om samsvar, og containeren gir deg distribusjonsarbeidsflyten du allerede kjenner. Det finnes en lengre versjon av den debatten i Bør hver leietaker få sin egen VM?, men det korte svaret er at VM-en er for kontrakten, ikke for frykten.

Hvordan gjør jeg dette repeterbart på tvers av hver klient?

Du gjør det repeterbart ved å gjøre nivåsystemet til en mal, ikke et minne. Ha en katalog med Compose-filer, én per nivå: tier2-baseline, tier3-locked, tier4-vm-hybrid. Når en ny klient dukker opp, kopier malen, endre miljøvariablene, og du vet allerede isolasjonsformen før du har skrevet en linje med ny infrastruktur.

Skriv deretter ned beslutningen. Ikke en 400-siders sikkerhetsrapport, men et kort avsnitt i klientens repository: hvilke data de lagrer, hvilket nivå de er på, hvorfor, og hva som ville flyttet dem opp et nivå. Det avsnittet er verdt mer enn hundre brannmurregler, fordi det er tingen du kan vise til neste revisor eller neste bekymrede klient. Det hindrer deg også fra å måtte huske hvorfor bakeriet fikk Nivå 2 og nettbutikken fikk Nivå 3 etter at den opprinnelige salgssamtalen har falmet.

Automatiser de kjedelige sjekkene. La CI-en din skanne hvert klientbilde og feile en bygg hvis den kjører som root, hvis den har alle kapabiliteter, eller hvis den prøver å publisere en annen port enn de nivået tillater. Ingenting av det er eksotisk; det handler bare om å sørge for at malen ikke blir utilsiktet ødelagt av en velmenende utvikler. Hvis du uansett bygger den omkringliggende hosting-arbeidsflyten, dekker produksjonsklare Docker-hostingstrategier delen som kommer etter at containerne er definert.

Ingenting av dette er glamorøst. Ingen blogginnlegg kommer til å få «leietakerisolering» til å høres like spennende ut som et greenfield-arkitekturdiagram. Men dette er forskjellen mellom et byrå som svarer «hvor isolert er vi?» med et kryssede fingre «helt» og et som kan vise et nivå, en konfigurasjon og en grunn. Containere er ikke en magisk vegg. VM-er er ikke en magisk kule. Et nivåsystem er bare en beslutning du skriver ned og gjenbruker – og for et byrå er repeterbarhet hele spillet.

Sources (5)