Le profondità della virtualizzazione Windows (parte 3) — Macchine virtuali che si avviano in pochi secondi: perché WSL2, Windows Sandbox e i container sono così leggeri
· Go Komura · Windows, Virtualizzazione, WSL2, Windows Sandbox, Container, Hyper-V
Quando si crea una VM Windows in Gestione Hyper-V, ci vogliono decine di secondi per partire e monopolizza diversi gigabyte di memoria. Eppure sullo stesso PC, digitare wsl restituisce una shell Linux in pochi secondi, e Windows Sandbox apre un desktop usa-e-getta in pochi secondi altrettanto.1
Entrambi poggiano sullo stesso hypervisor Windows (parte 1, «Dove gira davvero il vostro Windows?»). Nella parte 2 abbiamo visto che questo fondamento può creare un isolamento più forte del kernel. Allora perché uno è pesante e l’altro è leggero?
La domanda a cui risponde l’ultima puntata della serie è una sola.
Le VM complete sono pesanti — allora perché WSL2 e Windows Sandbox sono così leggeri?
I destinatari sono sviluppatori e operatori che usano WSL2, Windows Sandbox e i container Windows per sviluppo e convalida, e vogliono capire la loro leggerezza e i loro vincoli dai meccanismi in su. I prerequisiti sono Windows 10/11; per percorrere la sezione su Windows Sandbox serve un’edizione Pro, Enterprise o Education (Home e Windows Server non hanno questa funzione). Lo sfondo è la nozione di partizioni della parte 1. La difficoltà è intermedia.
1. Prima di tutto, la conclusione
Una VM leggera tiene la linea di isolamento (un kernel dedicato e un confine di hypervisor) e alleggerisce la «copia di un sistema operativo guest completo». Sandbox condivide il Windows dell’host stesso; WSL2 sostituisce il guest con un Linux piccolo e costruito allo scopo; e in entrambi i casi la memoria non è una prenotazione fissa ma viene prestata e ripresa in modo dinamico con l’host.
La fonte del peso di una VM completa non è l’isolamento in sé ma la duplicazione. Un’altra immagine di sistema operativo su disco, un’altra quantità di pagine pari a un sistema operativo in RAM, e un altro avvio completo ogni volta che si parte. Le VM leggere tagliano quella duplicazione con due politiche: «condividi ciò che è sicuro condividere» (Sandbox) e «se non lo puoi condividere, ricostruiscilo piccolo» (WSL2).
flowchart TB
accTitle: Tre tipi di condivisione che sostengono le VM leggere
accDescr: L'immagine del sistema operativo che una VM completa usava per duplicare viene tagliata condividendo in Sandbox e restringendo in WSL2; la memoria che è un'allocazione fissa per default (la memoria dinamica è l'eccezione) diventa prestito e ripresa dinamici con l'host; l'avvio è sostituito da un kernel leggero e da un setup minimo; resta solo il confine di isolamento
heavy["VM completa: duplicazione"] --> d1["Disco: copia dell'immagine OS"]
heavy --> more{"Memoria o avvio?"}
more --> d2["Memoria: default fisso"]
more --> d3["Avvio: boot completo"]
d1 -->|sostituito da| s1["Condividi(Sandbox)"]
s1 -.-> s1b["o restringi(WSL2)"]
d2 -->|sostituito da| s2["Prestito dinamico dall'host"]
d3 -->|sostituito da| s3["Kernel leggero + min."]
Figura 1: Lo scheletro della risposta a «lo stesso hypervisor, eppure leggero» è che hanno smesso di duplicare, non che hanno smesso di isolare.
Sotto guardiamo WSL2, Windows Sandbox e i container in quest’ordine, e quale tipo di duplicazione ciascuno di essi taglia.
2. Cosa porta una VM completa
Come baseline di confronto, ecco cosa porta una VM tradizionale.
- Un’immagine di sistema operativo indipendente. Tiene ogni file del sistema operativo guest dentro un disco virtuale. Anche se l’host ha lo stesso Windows, non lo condivide.
- Un’allocazione di memoria grossolana. Il default di una VM tradizionale è allocare la memoria host a una dimensione statica. Meccanismi come Hyper-V Dynamic Memory possono far crescere e ridursi l’allocazione entro un intervallo configurato, ma i mezzi per adattarsi ai cambiamenti di domanda sono limitati.2
- Un avvio completo di uso generale. Firmware, boot loader e l’insieme dei servizi partono nella stessa sequenza che su una macchina fisica.
flowchart TB
accTitle: I tre carichi che una VM completa porta
accDescr: Una VM completa porta un'immagine di sistema operativo indipendente, un'allocazione di memoria statica per default e un avvio completo di uso generale, e quelli si presentano come costi in disco, RAM e tempo di avvio
fullvm["VM completa"] --> b1["Immagine OS indipendente"]
fullvm --> more{"Memoria o avvio?"}
more --> b2["Memoria statica di default"]
more --> b3["Avvio di uso generale"]
b1 -.-> c1["Disco extra per una copia"]
b2 -.-> c2["Tiene anche la RAM inutilizzata"]
b3 -.-> c3["Ci vogliono decine di secondi"]
Figura 2: La scomposizione del costo di una VM completa si paga non per l’isolamento ma per generalità e duplicazione.
Questi non sono difetti; sono il prezzo della generalità che «nel guest ci si può mettere qualsiasi cosa». Per un uso come far girare un Linux vecchio accanto a Windows Server, quella generalità è il valore. Ma per un uso come «voglio far girare lo stesso (o un predeterminato) sistema operativo dell’host, adesso, per sviluppo o convalida», la maggior parte è bagaglio sprecato. Le VM leggere posano quel bagaglio restringendo lo scopo.
3. WSL2 — Una utility VM con un kernel costruito allo scopo
3.1. Struttura: Una VM gestita e le distribuzioni dentro di essa
WSL2 è un meccanismo che gira un vero kernel Linux dentro una utility VM leggera.3 Ci sono tre punti.
- Il kernel è genuino, ma è un prodotto specializzato. È un kernel Linux che Microsoft costruisce dal ramo Stable, già tarato in dimensione e prestazioni per WSL2. Sullo standard attuale, WSL distribuito da Microsoft Store, il kernel viene aggiornato insieme al pacchetto WSL stesso e applicato con
wsl --update(sulla distribuzione in-box più vecchia arrivava tramite Windows Update).4 Poiché è un kernel genuino, la compatibilità delle system call è completa, e strumenti come Docker girano così come sono. - La VM è dietro le quinte. Creazione, avvio e arresto della VM sono gestiti da WSL; l’utente apre solo una shell. Non c’è una schermata di impostazioni della VM e non si sente l’attesa di un avvio.4
- Una distribuzione è un container dentro la VM. Distribuzioni come Ubuntu e Debian girano come container isolati dentro una sola VM gestita. Condividono lo spazio dei nomi di rete e il kernel, mentre spazi dei nomi come PID, mount e user sono separati.3
flowchart TB
accTitle: Architettura di WSL2
accDescr: Un Windows host e una utility VM leggera stanno fianco a fianco sull'hypervisor; un kernel Linux costruito da Microsoft gira dentro la VM; e ciascuna distribuzione gira come un container isolato dentro quella
hv["Hypervisor"] --> host["Windows host"]
hv --> uvm["Utility VM leggera"]
uvm --> lk["Kernel Linux(build Microsoft; aggiornato con wsl --update)"]
lk --> u1["Ubuntu(container)"]
lk --> u2["Debian(container)"]
host <-->|"Interop(comandi, file, rete)"| uvm
Figura 3: La risposta a «WSL2 è una VM?» è «sì, ma una VM gestita, dietro le quinte», e anche se si installano più distribuzioni c’è comunque una sola VM.
Il momento in cui si digita wsl, il retroscena è questo.
flowchart TB
accTitle: Dall'esecuzione del comando wsl a una shell che torna in pochi secondi
accDescr: Se la utility VM non è in esecuzione quando si esegue wsl, partono la VM leggera e il kernel Linux; se è già in esecuzione vengono riusati; e una shell torna nel container della distribuzione
cmd["Esegui wsl"] --> vmq{"La utility VM è già in esecuzione?"}
vmq -->|No| bootvm["Avvia la VM leggera e il kernel Linux(pochi secondi)"]
vmq -->|Sì| reuse["Riusa la VM già in esecuzione"]
bootvm --> shell["Una shell torna dentro il container"]
reuse --> shell
Figura 4: L’attesa è solo un avvio minimo di VM, ed è qui che si vede il posare il bagaglio di un avvio completo.
3.2. I/O dei file: Da che lato li si mette fa una cosa diversa
L’argomento che torna sempre nel discorso sulle prestazioni di WSL2 è dove si mettono i file.
- Le operazioni sui file lato Linux (il disco virtuale ext4) sono veloci. Perché il kernel Linux parla direttamente con il proprio file system, e sono stati riportati accelerazioni fino a 20x rispetto a WSL1 per l’estrazione di tarball, e 2–5x per
git cloneenpm install.4 - Le operazioni sui file lato Windows (/mnt/c e simili) diventano lente perché passano attraverso una condivisione di file che attraversa un confine di sistema operativo. Le prestazioni del file system cross-OS sono l’unico grande punto in cui WSL2 è peggiore di WSL1.4
Quindi la regola è: «mettere i file di progetto sullo stesso lato di sistema operativo degli strumenti che li operano».4 Un repository che si gestisce con strumenti di build Linux va sul lato Linux; una soluzione che si compila in Visual Studio va sul lato Windows.
flowchart TB
accTitle: Il bivio dei percorsi I/O dei file di WSL2
accDescr: L'accesso al disco virtuale ext4 lato Linux è diretto dal kernel Linux e quindi veloce; l'accesso ai file lato Windows passa attraverso una condivisione di file che attraversa un confine di sistema operativo e quindi è lento
io["Operazioni sui file dentro WSL2"] --> place{"Da che lato sta il file?"}
place -->|"Lato Linux(home, ecc.)"| ext4["I/O diretto al disco virtuale ext4"]
place -->|"Lato Windows(/mnt/c, ecc.)"| p9["Via condivisione che attraversa un confine OS"]
ext4 --> fast["Veloce(esempi fino a 20x vs. WSL1)"]
p9 --> slow["Tende a essere lento"]
slow -.-> fix["Correzione: metti il file sull'OS che lo usa"]
Figura 5: Ciò che è lento è il percorso, non WSL2, quindi cambiare dove si mettono i file spesso fa sparire il problema di prestazioni.
3.3. Memoria: Cresce, si riduce, ma non sempre restituisce tutto
L’uso di memoria di WSL2 (lo si vede come processo vmmem in Gestione attività) non è una prenotazione fissa; cresce e si riduce con l’uso. La memoria che i processi hanno rilasciato viene restituita automaticamente a Windows sotto l’impostazione pageReporting, che è abilitata per default.5 Le pagine tenute come file cache un tempo non tornavano a Windows fino all’uscita della VM.4 Nel WSL attuale, l’impostazione sperimentale .wslconfig autoMemoryReclaim (il default è dropCache) recupera automaticamente anche la cache.5 Negli ambienti in cui questa impostazione è disabled, o su WSL più vecchio, la cache di una sessione lunga può restare fino all’uscita della VM e può fare pressione sulla memoria dell’host.
flowchart TB
accTitle: Come la memoria di WSL2 cresce, si riduce e viene restituita
accDescr: La crescita della domanda dentro WSL2 alza l'uso di memoria della VM; le pagine rilasciate dai processi vengono restituite a Windows sotto pageReporting, che è abilitata per default; la file cache viene recuperata automaticamente da autoMemoryReclaim per default; ma su un'impostazione disabilitata o su WSL più vecchio resta fino all'uscita della VM, e wsl --shutdown restituisce tutto
grow["La domanda di memoria cresce dentro WSL2"] --> vm["L'uso di vmmem cresce"]
vm --> freed{"Quella pagina è stata rilasciata?"}
freed -->|"Rilasciata(pageReporting)"| ret["Restituita a Windows"]
freed -->|Tenuta come file cache| amr["autoMemoryReclaim(default)"]
amr -.-> old2["Resta fino a uscita VM (WSL vecchio)"]
old2 --> sd["wsl --shutdown restituisce tutto"]
Figura 6: Ciò che sembra «è cresciuta soltanto» è soprattutto la cache (e, quando pageReporting è spento, anche le pagine rilasciate dai processi), quindi conoscere il percorso di restituzione prima di decidere che è una perdita.
Se si vuole un tetto esplicito, %UserProfile%\.wslconfig può controllare la memoria complessiva della VM, il numero di CPU e lo swap.5
# %UserProfile%\.wslconfig
[wsl2]
memory=8GB
processors=4
swap=2GB
Dopo aver cambiato le impostazioni, riavviare la VM con wsl --shutdown perché abbiano effetto. Questa allocazione dinamica — «il tetto è un’impostazione, l’uso effettivo segue la domanda» — è portata ancora oltre nel prossimo argomento, Windows Sandbox.
4. Windows Sandbox — Riusare il Windows dell’host
4.1. Dynamic base image: Un Windows completo in 500 MB
Windows Sandbox è un desktop Windows usa-e-getta isolato dall’hypervisor. Lo si chiude e tutto scompare; la volta successiva parte in pochi secondi da uno stato pulito.1
Il primo enigma è il disco. Può avviare un Windows completo, eppure l’immagine di base di Sandbox è solo circa 500 MB dopo l’installazione, e 30 MB compressi al momento della distribuzione.2 Il segreto è la dynamic base image.
- La maggior parte dei file del sistema operativo è immutabile, quindi le copie dell’host si possono condividere così come sono.
- Il piccolo numero di file mutabili non si può condividere, quindi se ne tiene una copia pulita dentro l’immagine di base.
- All’avvio, i file immutabili dell’host più le copie locali dei file mutabili vengono combinati per assemblare un’immagine Windows completa.2
In altre parole, Sandbox non scarica né archivia una copia di Windows; riusa il Windows già installato sull’host per partire.
flowchart TB
accTitle: Come viene assemblata una dynamic base image
accDescr: I file immutabili del sistema operativo dal Windows host vengono condivisi; solo i file mutabili sono tenuti come copia pulita nell'immagine di base; e i due vengono combinati per assemblare l'immagine Windows completa di Sandbox
hostw["Il Windows completo dell'host"] --> imm["File OS immutabili(la maggioranza)"]
hostw --> mut["File OS mutabili(una minoranza)"]
imm -->|Condivisi così come sono| img["Immagine di avvio di Sandbox"]
mut -->|Tieni una copia pulita| img
img --> boot["Si avvia come un Windows completo"]
img -.-> size["Bastano circa 500 MB da archiviare"]
Figura 7: La forma di rinunciare alla duplicazione su disco non è «possedere un altro Windows» ma «assemblarlo dal Windows dell’host».
Quella composizione è ciò che rende possibile il ciclo di vita seguente. Ciò che viene scartato è lo stato locale dentro Sandbox. Se si è mappata una cartella scrivibile dall’host nel file di configurazione .wsb, le modifiche lì restano sull’host.6
flowchart TB
accTitle: Il ciclo di vita di Windows Sandbox
accDescr: L'avvio prepara un Windows pulito in pochi secondi; dopo la convalida di un'app o gli esperimenti lo si chiude e tutto lo stato dentro Sandbox viene scartato così la volta successiva parte di nuovo pulito; ma le modifiche a una cartella host mappata come scrivibile restano
launch["Avvio(pochi secondi)"] --> clean["Un Windows pulito"]
clean --> work["Convalida di un'app o esperimenti"]
work --> close2["Chiudi"]
close2 --> discard["Scarta tutto lo stato dentro Sandbox"]
discard -.-> mapped["Le modifiche in una cartella scrivibile mappata restano sull'host"]
discard -->|Prossimo avvio| launch
Figura 8: Potere tornare al pulito ogni volta è perché la parte mutabile è una copia usa-e-getta, e scartarla fa parte del progetto.
4.2. Direct map: Lo stesso ntdll.dll è la stessa pagina fisica
Non solo il disco ma anche la RAM è condivisa. Poiché Sandbox gira la stessa immagine di sistema operativo dell’host, si usa una tecnica chiamata «direct map» così che, per i binari del sistema operativo, usi le stesse pagine di memoria fisica dell’host. Quando ntdll.dll viene caricato in memoria dentro Sandbox, punta alla stessa pagina fisica dello stesso binario già caricato sull’host. Senza esporre i segreti dell’host a pericolo, ottiene un’impronta di memoria molto più piccola di una VM tradizionale.2
«Condividere la stessa pagina fisica tra più utenti» — è la stessa idea della condivisione delle DLL tramite section object, che abbiamo seguito nella parte 3 della serie sulla memoria («Section object e copy-on-write»). Quel meccanismo era condivisione tra processi; Sandbox lo fa attraverso un confine di VM.
flowchart TB
accTitle: Condivisione di pagine fisiche tramite direct map
accDescr: Un'app sull'host e un'app dentro Sandbox condividono la stessa pagina di memoria fisica per i binari del sistema operativo come ntdll, riducendo l'uso di memoria
happ["Un'app sull'host"] --> hva["Indirizzo virtuale lato host"]
sapp["Un'app dentro Sandbox"] --> sva["Indirizzo virtuale lato Sandbox"]
hva --> phys["La stessa pagina fisica(binari OS come ntdll.dll)"]
sva --> phys
phys -.-> save["Non serve duplicare la RAM di un OS"]
Figura 9: Direct map è l’idea di condivisione di pagine usata tra processi, applicata attraverso un confine di VM.
4.3. Prestito e ripresa della memoria: Più un processo che una VM
Contro l’allocazione statica di memoria di una VM tradizionale, la tecnologia dei container su cui sta Sandbox decide l’allocazione delle risorse in modo dinamico in cooperazione con l’host. Se l’host è a corto di memoria, può recuperare memoria dal container nello stesso modo in cui la recupera da un processo ordinario.2 Anche Hyper-V Dynamic Memory fa crescere e ridursi l’allocazione di una VM entro un intervallo configurato, ma Sandbox va oltre: la differenza è che presta e riprende sullo stesso campo della gestione della memoria dell’host.
flowchart TB
accTitle: Cooperazione sulla memoria tra host e Sandbox
accDescr: Il default di una VM tradizionale è un'allocazione esclusiva a dimensione statica con mezzi di regolazione limitati; Sandbox diventa un obiettivo di recupero in risposta alla pressione di memoria dell'host e presta e riprende memoria sullo stesso campo dei processi ordinari
pressure["La pressione di memoria dell'host sale"] --> from{"Da dove recuperiamo?"}
from --> proc["I Working Set dei processi ordinari"]
from --> sbx["L'uso di Sandbox(del container)"]
proc --> relief["Si assicura memoria libera"]
sbx --> relief
relief -.-> contrast["Una VM tradizionale ha mezzi di regolazione limitati"]
Figura 10: Nel prestito e nella ripresa della memoria, Sandbox sta dal lato processo piuttosto che dal lato VM, e offre memoria quando l’host è in difficoltà.
Nella parte 1 abbiamo detto «le prestazioni di una VM dipendono anche dal lato host», ma con le VM leggere facciamo un altro passo: l’allocazione della memoria stessa è un lavoro congiunto con l’host. La ragione per cui Sandbox si può usare con la sensazione di «un’altra app» piuttosto che di «un prodotto di virtualizzazione pesante» è questa cooperazione.
La procedura concreta per usare Sandbox per convalidare un’app aziendale è trattata nel precedente «Come accelerare la convalida delle app con Windows Sandbox». Questo articolo è il meccanismo sotto quello.
5. I container — Dove si traccia la linea di isolamento
5.1. Isolamento di processo e isolamento Hyper-V
I container Windows hanno due modalità di isolamento a runtime. L’immagine è condivisa; si sceglie con un flag all’avvio.7
- Isolamento di processo: più container condividono il kernel con l’host e isolano tramite virtualizzazione per spazio dei nomi del file system, del registro, delle porte di rete, dello spazio degli ID di processo, dello spazio dei nomi di Object Manager, e così via. È essenzialmente lo stesso approccio dei container Linux.
- Isolamento Hyper-V: ciascun container gira dentro una VM altamente ottimizzata e ha quello che di fatto è un kernel dedicato. La presenza della VM mette isolamento a livello hardware tra i container e l’host.7
L’isolamento tramite spazi dei nomi si può descrivere come una versione radicale della tecnica vista nell’articolo sulla virtualizzazione del registro («Reindirizzamento e virtualizzazione del registro su Windows») — «mostrare una realtà diversa sotto la stessa API».
flowchart TB
accTitle: Isolamento di processo rispetto a isolamento Hyper-V
accDescr: Sotto l'isolamento di processo, i container condividono il kernel con l'host e isolano tramite spazi dei nomi; sotto l'isolamento Hyper-V, ciascun container ha un kernel dedicato dentro una VM ottimizzata
subgraph pi ["Isolamento di processo"]
c1["Container A"] --> sk1["Kernel condiviso con l'host"]
c2["Container B"] --> sk1
end
subgraph hi ["Isolamento Hyper-V"]
c3["Container C"] --> k3["Kernel dedicato(dentro una VM ottimizzata)"]
c4["Container D"] --> k4["Kernel dedicato(dentro una VM ottimizzata)"]
end
sk1 ~~~ c3
Figura 11: Anche con la stessa immagine di container, se si traccia la linea di isolamento sopra il kernel o si spezza il kernel stesso è una scelta che si fa all’avvio.
5.2. Quale si può chiamare un «confine di sicurezza»
La differenza tra queste due modalità non è solo una storia di prestazioni. Microsoft non considera un container a isolamento di processo un confine di sicurezza robusto. I container che sono mantenuti (con risposta alle vulnerabilità) come confine di sicurezza sono i container isolati dall’hypervisor, e l’isolamento Hyper-V è ciò che si dovrebbe scegliere in uno scenario multi-tenant avversario.8
Il VBS che abbiamo visto nella parte 2 era anche un progetto che presuppone «il kernel può essere violato» e si ritira a un confine di hypervisor. Lo stesso criterio vale nel mondo dei container. La linea che confina il codice non fidato si traccia al confine di hypervisor, non all’interno di un kernel condiviso.
flowchart TB
accTitle: Come scegliere l'isolamento da quanto ci si fida del codice
accDescr: Se il carico di lavoro è fidato, prendere densità e prestazioni con l'isolamento di processo; se il codice non è fidato o è di qualcun altro, scegliere un confine di hypervisor come un container isolato Hyper-V, un Windows Sandbox indurito con rete disabilitata, o una VM isolata
trust{"Ci si può fidare di quel codice?"} -->|Sì| dens["Isolamento di processo(priorità a densità e velocità)"]
trust -->|No / codice di altri| bound["Scegli un confine di hypervisor"]
bound --> opt1["Container isolati Hyper-V"]
bound --> opt2["Un Sandbox indurito o una VM isolata"]
Figura 12: La modalità di isolamento è una storia di sicurezza prima di essere una storia di prestazioni, e la fiducia decide dove si traccia la linea.
Incidentalmente, far girare un container isolato Hyper-V dentro una VM Hyper-V rende l’hypervisor profondo due strati — virtualizzazione nidificata. Un livello di nidificazione è supportato in produzione sugli ambienti che soddisfano le condizioni (un processore Intel con un host Windows 10 / Windows Server 2016 o successivo, o un processore AMD con un host Windows 11 / Windows Server 2022 o successivo, e la corrispondente versione di configurazione della VM in ciascun caso), e un ulteriore prerequisito è un’impostazione che espone le estensioni di virtualizzazione alla VM esterna (ExposeVirtualizationExtensions su Set-VMProcessor in Hyper-V). Far girare WSL2 dentro una VM è supportato allo stesso modo.9 Se si possono usare WSL2 o Docker in una VM di sviluppo nel cloud è deciso anche da se quella dimensione e configurazione di VM espongono la virtualizzazione nidificata.
flowchart TB
accTitle: La struttura della virtualizzazione nidificata
accDescr: Una VM cloud sta sull'hypervisor dell'host fisico, e dentro di essa gira un altro hypervisor (la nidificazione supportata è un livello) per sostenere WSL2 e i container isolati Hyper-V
phys3["L'hypervisor dell'host fisico"] --> cvm["VM cloud(macchina di sviluppo)"]
cvm --> nhv["Hypervisor dentro la VM(livello di nidificazione 1)"]
nhv --> w2["WSL2"]
nhv --> hvc["Container isolato Hyper-V"]
nhv -.-> limit["La nidificazione supportata è un livello"]
Figura 13: La ragione per cui wsl gira dentro una VM cloud è che la virtualizzazione nidificata è ufficialmente supportata per un solo livello.
5.3. Lo spettro di isolamento e leggerezza
Allineando il cast fin qui su un solo asse, è questo.
flowchart TB
accTitle: Lo spettro di forza di isolamento e leggerezza
accDescr: I container a isolamento di processo sono i più leggeri ma condividono il kernel; WSL2, Sandbox e i container isolati Hyper-V sono VM leggere con un kernel dedicato (Sandbox alleggerisce condividendo, WSL2 con un kernel costruito allo scopo); una VM completa è la più pesante ma di uso generale
ax["Leggero ← → Pesante"] ~~~ p1
p1["Container process-isolation"] --> p2["WSL2 / Sandbox / Hyper-V"]
p2 --> p3["VM completa(copia intera)"]
p1 -.-> n1["Confine: spazi dei nomi"]
p2 -.-> n2["Confine: hypervisor"]
p3 -.-> n3["Confine: hypervisor + indip."]
Figura 14: Il gruppo delle VM leggere è la soluzione di mezzo che ha tenuto il confine di hypervisor e ha tagliato la duplicazione; il modo in cui la taglia si spezza in condivisione per Sandbox e un kernel costruito allo scopo per WSL2.
6. Verificatelo voi stessi
Leggerezza e condivisione sono cose che si possono osservare su una macchina di fronte a voi.
Tempo di avvio e salita e discesa della memoria (WSL2). Con Gestione attività aperto, provare quanto segue.
# Felt startup time (the first run starts the VM; the second and later are faster still)
Measure-Command { wsl -e true }
# Memory usage of the WSL2 VM (vmmem / Virtual Machine Memory)
Get-Process -Name vmmem* | Select-Object Name, WorkingSet64
# End the whole VM and watch the memory come back
wsl --shutdown
Se si fa una build grande o un’operazione sui file dentro WSL2, vmmem cresce, e si può osservare che viene restituito tutto in una volta con wsl --shutdown.
La differenza di velocità da dove si mettono i file (WSL2). Mettere lo stesso repository sul lato Linux (~/repo) e sul lato Windows (/mnt/c/repo) e confrontare il tempo di git status o di un’estrazione, e la differenza della sezione 3.2 si vede in numeri.
Sfondo per direct map (Sandbox). Avviare Sandbox e guardare l’incremento di memoria in Gestione attività sull’host. Che l’incremento resti di gran lunga più piccolo di ciò che «un altro Windows» porterebbe a immaginare è l’effetto della condivisione che racconta la sua storia. Per scavare oltre nella scomposizione della memoria lato host, è utile l’articolo sugli strumenti Sysinternals che copre come usare RAMMap e VMMap («Process Explorer / Handle / VMMap in pratica»). Questi sono, però, strumenti per guardare la classificazione dei processi lato host e della memoria fisica; non osservano direttamente la condivisione con il guest stesso.
Modalità di isolamento dei container (Docker / container Windows). Se si ha un ambiente di container Windows, avviare la stessa immagine con docker run --isolation=process e --isolation=hyperv e confrontare il tempo di avvio e come appare in Gestione attività (sotto l’isolamento di processo, i processi dentro il container compaiono nell’elenco processi dell’host), e si può sentire dove sta la linea di isolamento.7 L’isolamento di processo, però, presuppone che le versioni di host e immagine coincidano, e su un sistema operativo client è limitato all’uso di sviluppo e test. L’isolamento Hyper-V consente un insieme più ampio di combinazioni, quindi fare il confronto su una coppia compatibile.10
7. Tre equivoci da evitare nella pratica
7.1. «WSL2 è lento»
Ciò che è lento non è WSL2 ma il percorso di I/O dei file che attraversa un confine di sistema operativo. Ci sono molti casi in cui semplicemente spostare il progetto sul lato Linux rende la sensazione una cosa diversa.4 Viceversa, mettere file che gli strumenti Windows toccheranno sul lato Linux è altrettanto sfavorevole per la stessa ragione. Giudicare da «mettilo sullo stesso sistema operativo del lato che lo usa».
7.2. «vmmem che diventa grande è una perdita di memoria»
La memoria di WSL2 cresce e si riduce con la domanda, e le porzioni rilasciate vengono restituite. Sul WSL attuale, anche la file cache viene recuperata automaticamente da autoMemoryReclaim (il default è dropCache), quindi «è restata grande» spesso si risolve col tempo.5 Se resta ancora, confermare che autoMemoryReclaim non sia stato impostato su disabled e che pageReporting, responsabile di restituire le porzioni rilasciate, non sia stato spento (o che non si sia su WSL più vecchio), poi o rendere esplicito il tetto con memory in .wslconfig o restituire tutto con wsl --shutdown a un confine di sessione. Il modo di pensare a distinguere una perdita da una non-perdita è lo stesso della puntata introduttiva della serie sulla memoria, «Cosa significa davvero l’«uso della memoria» di Windows?».
7.3. «È in un container, quindi è sicuro»
Un container a isolamento di processo condivide il kernel, e secondo il criterio di Microsoft non è un confine di sicurezza.8 Per far girare codice non fidato o un campione, scegliere un isolamento che ha un confine di hypervisor, come un container isolato Hyper-V, Windows Sandbox o una VM dedicata. Un confine di hypervisor, però, non è un’esenzione in blocco. Le impostazioni predefinite di Windows Sandbox hanno la connettività di rete abilitata, e possono esporre un’app non fidata alla rete interna.1 Se lo si usa per far girare un campione, rafforzare l’isolamento disabilitando rete e reindirizzamento degli appunti nel file di configurazione .wsb, oppure usare una VM dedicata su una rete isolata.
8. Riepilogo — Chiudere la serie
I punti della parte 3.
- La leggerezza di una VM leggera è il risultato di «smettere di duplicare», non di «indebolire l’isolamento».
- WSL2 gira un vero kernel Linux in una utility VM leggera gestita, e le distribuzioni sono isolate come container dentro quella VM.3 La regola sulle prestazioni è mettere i file sul sistema operativo che li usa, e la memoria cresce e si riduce in modo dinamico, con il tetto controllabile in
.wslconfig.45 - Windows Sandbox condivide i file immutabili del sistema operativo dell’host tramite una dynamic base image e condivide anche le pagine fisiche dei binari del sistema operativo di destinazione tramite direct map, quindi non tiene una copia di un Windows completo.2 Servono comunque circa 500 MB per i file mutabili, più la memoria delle app che si fanno girare dentro.
- La modalità di isolamento dei container si sceglie all’avvio, e il lato che si può chiamare un confine di sicurezza è l’isolamento Hyper-V.78
E se mettiamo l’intera serie su una sola pagina, è questo.
- Parte 1: C’è uno strato hypervisor sotto Windows, e il sistema operativo host stesso gira come partizione root. L’arbitraggio della CPU e della memoria (SLAT) è fatto direttamente da questo strato, e l’I/O dei dispositivi sintetici è mediato dalla partizione root (VSP) al di là di VMBus.
- Parte 2: Quello strato è usato non solo per isolare le VM tra loro ma anche per tracciare un confine più forte del kernel (VTL) dentro lo stesso sistema operativo. La sicurezza predefinita di Windows 11 è costruita sopra questo.
- Parte 3: Sullo stesso strato, tagliare la duplicazione è ciò che rende possibile «una macchina virtuale che parte in pochi secondi». La linea di isolamento è tenuta, ed è diventato uno strumento quotidiano.
flowchart TB
accTitle: Un quadro dell'intera serie
accDescr: L'hypervisor direttamente sull'hardware è la parte 1; la scissione di VTL0 e VTL1 dentro il Windows host è la parte 2; la leggerezza di WSL2, Sandbox e isolamento Hyper-V sullo stesso strato è la parte 3; i container a isolamento di processo condividono il kernel host; Sandbox alleggerisce condividendo, WSL2 con un kernel costruito allo scopo
hw3["Hardware"] --> hv3["Hypervisor(parte 1)"]
hv3 --> rp3["Windows host(VTL = parte 2)"]
hv3 --> lw3["WSL2 / Sandbox / Hyper-V(p.3)"]
rp3 --> pc3["Container process-isolation"]
lw3 -.-> mech3["Sandbox condivide; WSL2 ha kernel dedicato"]
Figura 15: Impilare le tre puntate e si ha il quadro complessivo del terreno sotto il Windows attuale.
La virtualizzazione non è più una tecnologia da sala server, né una tecnologia solo per chi alza le VM. Sul terreno sotto il vostro Windows, sostiene in silenzio sia la sicurezza sia l’esperienza di sviluppo — è lì che siamo ora.
Articoli correlati
- Le profondità della virtualizzazione Windows (parte 1) — Dove gira davvero il vostro Windows? L’hypervisor e le partizioni
- Le profondità della virtualizzazione Windows (parte 2) — Memoria che nemmeno il kernel può vedere: come funzionano VBS, HVCI e Credential Guard
- Le profondità della memoria Windows (parte 3) — Section object e copy-on-write: cosa sono davvero le DLL e i mapping di file
- Come accelerare la convalida delle app con Windows Sandbox
- Le trappole del reindirizzamento e della virtualizzazione del registro a 32 bit/64 bit — Wow6432Node e il problema «il valore che ho scritto non c’è»
Aree di consulenza correlate
KomuraSoft LLC si occupa di allestire ambienti di sviluppo che usano WSL2 e i container, di progettare ambienti di convalida delle app Windows e di indagare prestazioni e compatibilità in ambienti virtualizzati.
- Sviluppo di app Windows
- Indagine sui difetti e analisi delle cause
- Riutilizzo di asset esistenti e supporto alla migrazione
- Contattaci
Riferimenti
-
Microsoft Learn, Windows Sandbox. Sul fatto che Windows Sandbox parta in pochi secondi come VM usa-e-getta e scarti tutto quando viene chiusa; sul fatto che giri un kernel separato con l’hypervisor Microsoft per isolarla dall’host; e sul fatto che la connettività di rete sia abilitata per default e disabilitabile nel file di configurazione. ↩ ↩2 ↩3
-
Microsoft Learn, Windows Sandbox architecture. Sul fatto che una dynamic base image assembla un’immagine Windows completa da una condivisione dei file immutabili del sistema operativo dell’host più una copia pulita dei file mutabili (circa 500 MB dopo l’installazione); sul fatto che un container alloca in modo dinamico in cooperazione con l’host, contro l’allocazione statica di memoria di una VM tradizionale, così che l’host possa recuperare memoria; e sul fatto che direct map faccia sì che i binari del sistema operativo come ntdll.dll usino le stesse pagine fisiche dell’host. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, What is the Windows Subsystem for Linux?. Sul fatto che WSL2 giri un kernel Linux dentro una utility VM leggera; sul fatto che ciascuna distribuzione giri come un container isolato, condividendo lo spazio dei nomi di rete e il kernel mentre separa spazi dei nomi come PID, mount e user. ↩ ↩2 ↩3
-
Microsoft Learn, Comparing WSL Versions. Sul fatto che il kernel WSL2 sia costruito da Microsoft dal ramo Stable; sul fatto che WSL distribuito dallo Store riceva aggiornamenti come pacchetto staccato dall’immagine del sistema operativo e li applichi con
wsl --update(sulla distribuzione in-box più vecchia, tramite Windows Update); su esempi di prestazioni come fino a 20x per l’estrazione di tarball; sul fatto che WSL1 sia più veloce per le prestazioni del file system cross-OS, quindi i file vadano collocati sul sistema operativo che li usa; e sul fatto che la memoria cresca e si riduca con le porzioni rilasciate restituite, mentre la cache può non tornare fino all’uscita della VM. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 -
Microsoft Learn, Advanced settings configuration in WSL. Sul fatto di poter impostare il tetto di memoria complessivo della VM WSL2, il numero di processori, lo swap e pageReporting (abilitato per default; responsabile di rilevare e restituire la memoria inutilizzata) nella sezione [wsl2] di .wslconfig; e sul fatto che l’impostazione sperimentale autoMemoryReclaim abbia default dropCache, così che la memoria cache venga recuperata automaticamente. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Use and configure Windows Sandbox. Sul fatto che MappedFolders nel file di configurazione .wsb possa condividere una cartella host come sola lettura o scrivibile. ↩
-
Microsoft Learn, Isolation Modes. Sul fatto che l’isolamento di processo dei container Windows condivida il kernel con l’host e isoli tramite spazi dei nomi; sul fatto che l’isolamento Hyper-V abbia quello che di fatto è un kernel dedicato dentro una VM ottimizzata; e sul fatto che la stessa immagine sia eseguibile in entrambe le modalità tramite un flag all’avvio. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Secure Windows containers. Sul fatto che solo i container isolati dall’hypervisor siano trattati come confine di sicurezza; sul fatto che i container a isolamento di processo non siano considerati un confine di sicurezza robusto; e sul fatto che l’isolamento hypervisor sia ciò che si dovrebbe scegliere in uno scenario multi-tenant avversario. ↩ ↩2 ↩3
-
Microsoft Learn, What is Nested Virtualization?. Sul fatto che far girare container isolati Hyper-V dentro una VM Hyper-V (un livello di nidificazione) sia supportato in produzione; sul fatto che i requisiti siano un processore Intel con Windows Server 2016 / Windows 10 o successivo, o un processore AMD con Windows Server 2022 / Windows 11 o successivo, più la corrispondente versione di configurazione della VM in ciascun caso; sul fatto che esporre le estensioni di virtualizzazione alla VM esterna (ExposeVirtualizationExtensions) sia un prerequisito; e sul fatto che far girare WSL2 dentro una VM Hyper-V sia supportato. ↩
-
Microsoft Learn, Windows container version compatibility. Sul fatto che l’isolamento di processo presupponga che le versioni di host e immagine del container coincidano; sul fatto che l’isolamento Hyper-V possa far girare un’immagine di una versione di sistema operativo diversa dall’host; e sul fatto che l’isolamento di processo su un sistema operativo client sia limitato all’uso di sviluppo e test. ↩
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Le profondità della virtualizzazione Windows (parte 1) — Dove gira davvero il vostro Windows? L'hypervisor e le partizioni
Quando si abilita Hyper-V, il Windows host stesso gira sopra l'hypervisor come partizione root. Questo articolo spiega i fondamenti della...
Le profondità della virtualizzazione Windows (parte 2) — Memoria che nemmeno il kernel può vedere: come funzionano VBS, HVCI e Credential Guard
Su un'installazione pulita su hardware compatibile, VBS è abilitata per default e usa l'hypervisor e SLAT per creare un isolamento più fo...
L'API thread pool Win32 — Concorrenza senza creare thread, tramite CreateThreadpoolWork
State spargendo chiamate CreateThread per tutto il codice nativo? Questo articolo spiega l'API thread pool Win32 ridisegnata in Vista — i...
Named pipe in pratica — L'IPC standard di Windows, dalla progettazione alla sicurezza
Guida pratica alle named pipe, il meccanismo standard di comunicazione tra processi su Windows. L'articolo organizza, a partire dalle fon...
Come comprendere l'isolamento delle sessioni di Windows — Session 0, RDP ed esecuzione simultanea di più utenti
Questo articolo chiarisce il concetto di «sessione» di Windows, un argomento che genera costante confusione tra gli sviluppatori di appli...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Sviluppo di applicazioni Windows
Applicazioni aziendali, integrazione di dispositivi e strumenti di comunicazione, dai requisiti allo sviluppo.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- WSL2 è una VM?
- Sì. WSL2 gira un vero kernel Linux costruito da Microsoft dentro una utility VM leggera. La VM è gestita da WSL dietro le quinte, quindi il progetto non fa mai pensare l'utente a impostazioni di VM o ad aspettare un avvio. Ogni distribuzione Linux gira come un container isolato dentro questa VM gestita.
- Perché le operazioni sui file sotto /mnt/c sono lente in WSL2?
- Perché l'accesso dal kernel Linux di WSL2 al file system lato Windows passa attraverso una condivisione di file che attraversa un confine di sistema operativo. Le operazioni sul file system Linux (un disco virtuale ext4) sono veloci, quindi la regola è tenere i file di progetto sullo stesso lato di sistema operativo degli strumenti che ci lavorano.
- Un uso di memoria grande del processo vmmem è una perdita?
- Nella maggior parte dei casi non è una perdita. La memoria di WSL2 cresce e si riduce con l'uso, e la memoria che i processi hanno rilasciato viene restituita a Windows sotto l'impostazione pageReporting, che è abilitata per default. Anche le pagine di file cache vengono recuperate automaticamente dal WSL attuale tramite autoMemoryReclaim in .wslconfig (il default è dropCache). Negli ambienti in cui queste impostazioni sono state disabilitate, o su WSL più vecchio, la memoria può restare fino all'uscita della VM; in quel caso si imposta un tetto con l'impostazione memory, oppure la si restituisce con wsl --shutdown.
- Come può Windows Sandbox avviare un Windows completo da poche centinaia di megabyte di disco?
- Attraverso un meccanismo chiamato dynamic base image. Condivide i file immutabili del sistema operativo dal Windows già installato sull'host, e tiene una copia pulita solo del piccolo numero di file mutabili. Così può assemblare un'immagine completa e avviabile senza archiviare una copia intera di Windows.
- I container sono più sicuri delle VM?
- Dipende dalla modalità di isolamento. I container a isolamento di processo condividono il kernel con l'host, e Microsoft non considera questo un confine di sicurezza robusto. Quando si gestisce codice avversario, serve l'isolamento Hyper-V, che dà a ciascun container un kernel dedicato.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.