Khi bạn tạo một VM Windows trong Hyper-V Manager, nó mất hàng chục giây để khởi động và độc chiếm vài gigabyte bộ nhớ. Thế mà trên cùng một PC, gõ wsl trả về một shell Linux trong vài giây, và Windows Sandbox cũng mở một desktop dùng một lần trong vài giây.1
Cả hai đều dựa trên cùng hypervisor Windows (Phần 1, “Windows của bạn thực sự chạy ở đâu?”). Ở Phần 2 chúng ta thấy nền tảng này có thể tạo cô lập mạnh hơn kernel. Vậy vì sao cái này nặng còn cái kia nhẹ?
Câu hỏi kỳ cuối của loạt bài trả lời chỉ có một.
VM đầy đủ thì nặng — vậy vì sao WSL2 và Windows Sandbox lại nhẹ đến vậy?
Đối tượng là các nhà phát triển và vận hành dùng WSL2, Windows Sandbox và container Windows cho phát triển và xác thực, và muốn hiểu độ nhẹ cùng các ràng buộc từ cơ chế lên. Điều kiện tiên quyết là Windows 10/11; đi qua phần Windows Sandbox cần phiên bản Pro, Enterprise hoặc Education (Home và Windows Server không có tính năng này). Kiến thức nền là khái niệm phân vùng từ Phần 1. Độ khó là trung cấp.
1. Kết luận trước
Một VM nhẹ giữ đường cô lập (kernel chuyên dụng và ranh giới hypervisor) và làm nhẹ “bản sao của một hệ điều hành khách hoàn chỉnh”. Sandbox chia sẻ chính Windows của máy chủ; WSL2 thay khách bằng một Linux nhỏ, được xây cho mục đích; và ở cả hai trường hợp bộ nhớ không phải đặt chỗ cố định mà được cho mượn và vay động với máy chủ.
Nguồn gốc sức nặng của một VM đầy đủ không phải bản thân cô lập mà là sự nhân bản. Một ảnh hệ điều hành khác trên đĩa, một phần trang của một hệ điều hành khác trong RAM, và một lần boot đầy đủ nữa mỗi khi bạn khởi động. Các VM nhẹ cắt sự nhân bản đó bằng hai chính sách: “chia sẻ những gì an toàn để chia sẻ” (Sandbox) và “nếu không chia sẻ được, xây lại cho nhỏ” (WSL2).
flowchart TB
accTitle: Ba loại chia sẻ chống đỡ các VM nhẹ
accDescr: Ảnh hệ điều hành mà một VM đầy đủ từng nhân bản được cắt bằng chia sẻ ở Sandbox và bằng thu nhỏ ở WSL2; bộ nhớ là cấp phát cố định theo mặc định(bộ nhớ động là ngoại lệ)trở thành cho mượn và vay động với máy chủ; khởi động được thay bằng kernel nhẹ và thiết lập tối thiểu; chỉ ranh giới cô lập còn lại
heavy["VM đầy đủ: nhân bản"] --> d1["Đĩa: bản sao ảnh hệ điều hành"]
heavy --> more{"Bộ nhớ hay khởi động?"}
more --> d2["Bộ nhớ: mặc định cố định"]
more --> d3["Khởi động: boot đầy đủ"]
d1 -->|được thay bằng| s1["Chia sẻ(Sandbox)"]
s1 -.-> s1b["hoặc thu nhỏ(WSL2)"]
d2 -->|được thay bằng| s2["Cho mượn động từ máy chủ"]
d3 -->|được thay bằng| s3["Kernel nhẹ + tối thiểu"]
Hình 1: Khung xương câu trả lời cho “cùng hypervisor, vậy mà nhẹ” là họ dừng nhân bản, không phải dừng cô lập.
Dưới đây chúng ta lần lượt xem WSL2, Windows Sandbox và container, và từng cái cắt loại nhân bản nào.
2. Một VM đầy đủ đang mang gì
Làm đường cơ sở để so sánh, đây là những gì một VM truyền thống mang.
- Một ảnh hệ điều hành độc lập. Nó giữ mọi tệp của hệ điều hành khách bên trong một đĩa ảo. Dù máy chủ có cùng Windows, nó không chia sẻ.
- Phân bổ bộ nhớ thô. Mặc định của một VM truyền thống là cấp phát bộ nhớ máy chủ ở kích thước tĩnh. Các cơ chế như Hyper-V Dynamic Memory có thể lớn lên và thu lại phân bổ trong một khoảng đã cấu hình, nhưng các phương tiện điều chỉnh theo thay đổi nhu cầu thì hạn chế.2
- Một lần boot đầy đủ đa năng. Firmware, bộ nạp boot, và bộ dịch vụ khởi động theo cùng trình tự như trên máy vật lý.
flowchart TB
accTitle: Ba gánh nặng mà một VM đầy đủ mang
accDescr: Một VM đầy đủ mang ảnh hệ điều hành độc lập, phân bổ bộ nhớ tĩnh theo mặc định, và một lần boot đầy đủ đa năng, và những thứ đó hiện ra như chi phí ở đĩa, RAM và thời gian khởi động
fullvm["VM đầy đủ"] --> b1["Ảnh hệ điều hành độc lập"]
fullvm --> more{"Bộ nhớ hay boot?"}
more --> b2["Mặc định bộ nhớ tĩnh"]
more --> b3["Boot đa năng"]
b1 -.-> c1["Thêm đĩa cho một bản sao"]
b2 -.-> c2["Cũng giữ RAM không dùng"]
b3 -.-> c3["Mất hàng chục giây"]
Hình 2: Sự phân tách chi phí của một VM đầy đủ được trả không phải cho cô lập mà cho tính đa năng và sự nhân bản.
Những thứ này không phải khuyết điểm; chúng là cái giá của tính đa năng “bạn có thể nhét bất cứ thứ gì vào khách”. Với mục đích như chạy một Linux cũ cạnh Windows Server, tính đa năng đó chính là giá trị. Nhưng với mục đích như “tôi muốn chạy cùng (hoặc một) hệ điều hành đã định sẵn với máy chủ, ngay bây giờ, để phát triển hoặc xác thực”, phần lớn là hành lý thừa. Các VM nhẹ đặt hành lý đó xuống bằng cách thu hẹp mục đích.
3. WSL2 — Một VM tiện ích với kernel được xây cho mục đích
3.1. Cấu trúc: Một VM được quản lý và các bản phân phối bên trong
WSL2 là cơ chế chạy một kernel Linux thật bên trong một VM tiện ích nhẹ.3 Có ba điểm.
- Kernel thì thật, nhưng đó là sản phẩm chuyên biệt. Đó là một kernel Linux Microsoft xây từ nhánh Stable, đã được tinh chỉnh kích thước và hiệu năng cho WSL2. Trên chuẩn hiện tại, WSL phân phối qua Microsoft Store, kernel được cập nhật cùng gói WSL và áp dụng bằng
wsl --update(ở bản phân phối in-box cũ hơn nó đi qua Windows Update).4 Vì đó là kernel thật, tính tương thích lời gọi hệ thống là đầy đủ, và các công cụ như Docker chạy nguyên như vậy. - VM nằm phía sau. Việc tạo, khởi động và dừng VM do WSL quản lý; người dùng chỉ mở một shell. Không có màn hình cài đặt VM và không có cảm giác chờ boot.4
- Một bản phân phối là một container bên trong VM. Các bản phân phối như Ubuntu và Debian chạy như các container cô lập bên trong một VM được quản lý. Chúng chia sẻ không gian tên mạng và kernel, trong khi các không gian tên như PID, mount và user được tách.3
flowchart TB
accTitle: Kiến trúc WSL2
accDescr: Một Windows máy chủ và một VM tiện ích nhẹ ngồi cạnh nhau trên hypervisor; một kernel Linux do Microsoft xây chạy bên trong VM; và mỗi bản phân phối chạy như một container cô lập bên trong đó
hv["Hypervisor"] --> host["Windows máy chủ"]
hv --> uvm["VM tiện ích nhẹ"]
uvm --> lk["Kernel Linux(bản Microsoft; cập nhật bằng wsl --update)"]
lk --> u1["Ubuntu(container)"]
lk --> u2["Debian(container)"]
host <-->|"Interop(lệnh, tệp, mạng)"| uvm
Hình 3: Câu trả lời cho “WSL2 có phải là một VM?” là “có, nhưng là một VM được quản lý, nằm phía sau”, và dù bạn cài vài bản phân phối thì vẫn chỉ có một VM.
Khoảnh khắc bạn gõ wsl, phía sau trông như sau.
flowchart TB
accTitle: Từ khi chạy lệnh wsl tới khi một shell trở về trong vài giây
accDescr: Nếu VM tiện ích chưa chạy khi wsl được thực thi, VM nhẹ và kernel Linux khởi động; nếu đã chạy thì chúng được tái sử dụng; và một shell trở về trong container của bản phân phối
cmd["Chạy wsl"] --> vmq{"VM tiện ích đã chạy chưa?"}
vmq -->|Chưa| bootvm["Khởi động VM nhẹ và kernel Linux(vài giây)"]
vmq -->|Rồi| reuse["Tái sử dụng VM đang chạy"]
bootvm --> shell["Một shell trở về bên trong container"]
reuse --> shell
Hình 4: Thời gian chờ chỉ là một lần khởi động VM tối thiểu, và đây là chỗ việc đặt xuống hành lý của một lần boot đầy đủ hiện ra.
3.2. I/O tệp: Bạn đặt nó phía nào thì nó thành một thứ khác
Chủ đề luôn xuất hiện khi nói về hiệu năng WSL2 là bạn đặt tệp ở đâu.
- Thao tác trên tệp phía Linux (đĩa ảo ext4) thì nhanh. Đó là vì kernel Linux nói chuyện trực tiếp với hệ thống tệp của riêng nó, và các tăng tốc lên tới 20 lần so với WSL1 cho giải nén tarball, cùng 2–5 lần cho
git clonevànpm install, đã được báo cáo.4 - Thao tác trên tệp phía Windows (/mnt/c và tương tự) trở nên chậm vì chúng đi qua chia sẻ tệp vượt ranh giới hệ điều hành. Hiệu năng hệ thống tệp xuyên hệ điều hành là một hạng mục lớn duy nhất mà WSL2 kém hơn WSL1.4
Vì thế quy tắc là: “đặt tệp dự án phía cùng hệ điều hành với các công cụ thao tác trên chúng”.4 Một kho bạn xử lý bằng công cụ build Linux thì nằm phía Linux; một solution bạn build trong Visual Studio thì nằm phía Windows.
flowchart TB
accTitle: Ngã rẽ các đường I/O tệp của WSL2
accDescr: Truy cập đĩa ảo ext4 phía Linux là trực tiếp từ kernel Linux nên nhanh; truy cập tệp phía Windows đi qua chia sẻ tệp vượt ranh giới hệ điều hành nên chậm
io["Thao tác tệp bên trong WSL2"] --> place{"Tệp nằm phía nào?"}
place -->|"Phía Linux(home, v.v.)"| ext4["I/O trực tiếp tới đĩa ảo ext4"]
place -->|"Phía Windows(/mnt/c, v.v.)"| p9["Qua chia sẻ vượt ranh giới hệ điều hành"]
ext4 --> fast["Nhanh(ví dụ lên tới 20 lần so với WSL1)"]
p9 --> slow["Có xu hướng chậm"]
slow -.-> fix["Cách sửa: đặt tệp phía hệ điều hành dùng nó"]
Hình 5: Thứ chậm là đường đi, không phải WSL2, nên đổi chỗ đặt tệp thường làm vấn đề hiệu năng biến mất.
3.3. Bộ nhớ: Nó lớn lên, nó thu lại, nhưng không phải lúc nào cũng trả hết
Mức dùng bộ nhớ của WSL2 (bạn thấy nó như tiến trình vmmem trong Task Manager) không phải đặt chỗ cố định; nó lớn lên và thu lại theo mức dùng. Bộ nhớ mà các tiến trình đã nhả được tự động trả về Windows dưới thiết lập pageReporting, được bật mặc định.5 Các trang giữ như bộ nhớ đệm tệp từng không trở về Windows cho tới khi VM thoát.4 Trong WSL hiện tại, thiết lập thực nghiệm .wslconfig autoMemoryReclaim (mặc định là dropCache) cũng thu hồi bộ nhớ đệm tự động.5 Trong các môi trường thiết lập này là disabled, hoặc trên WSL cũ hơn, bộ nhớ đệm của một phiên dài có thể ở lại cho tới khi VM thoát và có thể gây áp lực bộ nhớ máy chủ.
flowchart TB
accTitle: Cách bộ nhớ WSL2 lớn lên, thu lại và được trả về
accDescr: Nhu cầu tăng bên trong WSL2 nâng mức dùng bộ nhớ của VM; các trang tiến trình đã nhả được trả về Windows dưới pageReporting, được bật mặc định; bộ nhớ đệm tệp được thu hồi tự động bởi autoMemoryReclaim theo mặc định; nhưng ở thiết lập tắt hoặc WSL cũ hơn nó ở lại cho tới khi VM thoát, và wsl --shutdown trả về tất cả
grow["Nhu cầu bộ nhớ tăng bên trong WSL2"] --> vm["Mức dùng vmmem tăng"]
vm --> freed{"Trang đó đã được nhả chưa?"}
freed -->|"Tiến trình đã nhả(khi pageReporting bật)"| ret["Tự động trả về Windows"]
freed -->|Giữ như bộ nhớ đệm tệp| amr["autoMemoryReclaim thu hồi tự động(mặc định)"]
amr -.-> old2["Ở thiết lập tắt hoặc WSL cũ hơn, ở lại tới khi VM thoát"]
old2 --> sd["wsl --shutdown trả về tất cả"]
Hình 6: Thứ trông như “nó chỉ toàn lớn lên” chủ yếu là bộ nhớ đệm (và, khi pageReporting tắt, cả các trang tiến trình đã nhả), nên hãy biết đường trả về trước khi kết luận đó là rò rỉ.
Nếu bạn muốn một giới hạn trên tường minh, %UserProfile%\.wslconfig có thể kiểm soát bộ nhớ tổng thể của VM, số CPU và swap.5
# %UserProfile%\.wslconfig
[wsl2]
memory=8GB
processors=4
swap=2GB
Sau khi đổi thiết lập, khởi động lại VM bằng wsl --shutdown để chúng có hiệu lực. Phân bổ động này — “giới hạn trên là một thiết lập, mức dùng thật theo nhu cầu” — được đẩy xa hơn nữa ở chủ đề tiếp theo, Windows Sandbox.
4. Windows Sandbox — Tái sử dụng Windows của máy chủ
4.1. Ảnh cơ sở động: Một Windows hoàn chỉnh trong 500 MB
Windows Sandbox là một desktop Windows dùng một lần được cô lập bởi hypervisor. Đóng nó thì mọi thứ biến mất; lần sau, nó khởi động trong vài giây từ trạng thái sạch.1
Câu đố đầu tiên là đĩa. Nó có thể boot một Windows hoàn chỉnh, vậy mà ảnh cơ sở của Sandbox chỉ khoảng 500 MB sau khi cài, và 30 MB nén lúc phân phối.2 Bí mật là ảnh cơ sở động.
- Hầu hết tệp hệ điều hành là bất biến, nên các bản sao của máy chủ có thể được chia sẻ nguyên như vậy.
- Số ít tệp biến đổi được thì không chia sẻ được, nên một bản sao sạch của chúng được giữ bên trong ảnh cơ sở.
- Lúc khởi động, các tệp bất biến của máy chủ cộng các bản sao cục bộ của các tệp biến đổi được được kết hợp để lắp một ảnh Windows hoàn chỉnh.2
Nói cách khác, Sandbox không tải về cũng không lưu một bản sao của Windows; nó tái sử dụng Windows đã cài trên máy chủ để khởi động.
flowchart TB
accTitle: Cách một ảnh cơ sở động được lắp
accDescr: Các tệp hệ điều hành bất biến từ Windows máy chủ được chia sẻ; chỉ các tệp biến đổi được được giữ như bản sao sạch trong ảnh cơ sở; và hai thứ được kết hợp để lắp ảnh Windows hoàn chỉnh của Sandbox
hostw["Windows hoàn chỉnh của máy chủ"] --> imm["Tệp hệ điều hành bất biến(phần lớn)"]
hostw --> mut["Tệp hệ điều hành biến đổi được(thiểu số)"]
imm -->|Chia sẻ nguyên như vậy| img["Ảnh boot của Sandbox"]
mut -->|Giữ một bản sao sạch| img
img --> boot["Boot như một Windows hoàn chỉnh"]
img -.-> size["Chỉ khoảng 500 MB cần được lưu"]
Hình 7: Hình dạng từ bỏ nhân bản đĩa không phải “sở hữu thêm một Windows” mà là “lắp nó từ Windows của máy chủ”.
Sự lắp ghép đó là thứ làm vòng đời sau đây khả thi. Thứ bị bỏ là trạng thái cục bộ bên trong Sandbox. Nếu bạn đã ánh xạ một thư mục ghi được từ máy chủ trong tệp cấu hình .wsb, các thay đổi ở đó ở lại trên máy chủ.6
flowchart TB
accTitle: Vòng đời Windows Sandbox
accDescr: Khởi động chuẩn bị một Windows sạch trong vài giây; sau xác thực ứng dụng hoặc thí nghiệm bạn đóng nó và mọi trạng thái bên trong Sandbox bị bỏ nên lần sau cũng khởi động sạch; nhưng các thay đổi tới một thư mục máy chủ được ánh xạ ghi được thì ở lại
launch["Khởi động(vài giây)"] --> clean["Một Windows sạch"]
clean --> work["Xác thực ứng dụng hoặc thí nghiệm"]
work --> close2["Đóng"]
close2 --> discard["Bỏ mọi trạng thái bên trong Sandbox"]
discard -.-> mapped["Thay đổi trong thư mục ghi được được ánh xạ ở lại trên máy chủ"]
discard -->|Lần khởi động tiếp| launch
Hình 8: Việc có thể trở về sạch mỗi lần là vì phần biến đổi được là một bản sao dùng một lần, và việc bỏ nó là một phần của thiết kế.
4.2. Ánh xạ trực tiếp: Cùng một ntdll.dll là cùng một trang vật lý
Không chỉ đĩa mà RAM cũng được chia sẻ. Vì Sandbox chạy cùng ảnh hệ điều hành với máy chủ, một kỹ thuật gọi là “ánh xạ trực tiếp” được dùng để, với các nhị phân hệ điều hành, nó dùng cùng các trang bộ nhớ vật lý với máy chủ. Khi ntdll.dll được nạp vào bộ nhớ bên trong Sandbox, nó trỏ tới cùng trang vật lý với cùng nhị phân đã nạp trên máy chủ. Mà không phơi các bí mật của máy chủ trước nguy hiểm, nó đạt dấu chân bộ nhớ nhỏ hơn nhiều so với một VM truyền thống.2
“Chia sẻ cùng một trang vật lý giữa vài người dùng” — đó là cùng ý tưởng với chia sẻ DLL qua đối tượng section, thứ chúng ta đã lần theo ở Phần 3 của loạt bài bộ nhớ (“Đối tượng section và Copy-on-Write”). Cơ chế đó là chia sẻ giữa các tiến trình; Sandbox làm điều đó vượt ranh giới VM.
flowchart TB
accTitle: Chia sẻ trang vật lý qua ánh xạ trực tiếp
accDescr: Một ứng dụng trên máy chủ và một ứng dụng bên trong Sandbox chia sẻ cùng một trang bộ nhớ vật lý cho các nhị phân hệ điều hành như ntdll, giảm mức dùng bộ nhớ
happ["Một ứng dụng trên máy chủ"] --> hva["Địa chỉ ảo phía máy chủ"]
sapp["Một ứng dụng bên trong Sandbox"] --> sva["Địa chỉ ảo phía Sandbox"]
hva --> phys["Cùng một trang vật lý(nhị phân hệ điều hành như ntdll.dll)"]
sva --> phys
phys -.-> save["Không cần nhân bản phần RAM của hệ điều hành"]
Hình 9: Ánh xạ trực tiếp là ý tưởng chia sẻ trang đã được dùng giữa các tiến trình, áp dụng vượt ranh giới VM.
4.3. Cho mượn và vay bộ nhớ: Giống một tiến trình hơn là một VM
Đối với phân bổ bộ nhớ tĩnh của một VM truyền thống, công nghệ container mà Sandbox ngồi trên quyết định phân bổ tài nguyên động với sự hợp tác của máy chủ. Nếu máy chủ thiếu bộ nhớ, nó có thể thu hồi bộ nhớ từ container theo cùng cách nó thu hồi từ một tiến trình thông thường.2 Hyper-V Dynamic Memory cũng lớn lên và thu lại phân bổ của một VM trong một khoảng đã cấu hình, nhưng Sandbox đi xa hơn: khác biệt là nó cho mượn và vay trên cùng sân với quản lý bộ nhớ của máy chủ.
flowchart TB
accTitle: Hợp tác bộ nhớ giữa máy chủ và Sandbox
accDescr: Mặc định của một VM truyền thống là cấp phát độc quyền kích thước tĩnh với phương tiện điều chỉnh hạn chế; Sandbox trở thành mục tiêu thu hồi khi áp lực bộ nhớ máy chủ tăng và cho mượn cùng vay bộ nhớ trên cùng sân với các tiến trình thông thường
pressure["Áp lực bộ nhớ máy chủ tăng"] --> from{"Thu hồi từ đâu?"}
from --> proc["Working Set của các tiến trình thông thường"]
from --> sbx["Mức dùng của Sandbox(container)"]
proc --> relief["Bộ nhớ trống được bảo đảm"]
sbx --> relief
relief -.-> contrast["Một VM truyền thống có phương tiện điều chỉnh hạn chế"]
Hình 10: Trong việc cho mượn và vay bộ nhớ, Sandbox đứng phía tiến trình chứ không phải phía VM, và dâng bộ nhớ khi máy chủ gặp khó.
Ở Phần 1 chúng ta nói “hiệu năng của một VM cũng phụ thuộc phía máy chủ”, nhưng với các VM nhẹ chúng ta đi thêm một bước: bản thân việc phân bổ bộ nhớ là công việc chung với máy chủ. Lý do Sandbox có thể được dùng với cảm giác “một ứng dụng khác” chứ không phải “một sản phẩm ảo hóa nặng” là sự hợp tác này.
Quy trình cụ thể dùng Sandbox để xác thực một ứng dụng nghiệp vụ được đề cập trong bài trước “Cách tăng tốc xác thực ứng dụng bằng Windows Sandbox”. Bài này là cơ chế nằm dưới đó.
5. Container — Bạn vẽ đường cô lập ở đâu
5.1. Cô lập tiến trình và cô lập Hyper-V
Container Windows có hai chế độ cô lập lúc chạy. Ảnh được chia sẻ; bạn chọn bằng một cờ lúc khởi động.7
- Cô lập tiến trình: vài container chia sẻ kernel với máy chủ và cô lập qua ảo hóa theo từng không gian tên của hệ thống tệp, registry, cổng mạng, không gian ID tiến trình, không gian tên Object Manager, và tương tự. Về bản chất đó là cùng cách tiếp cận với container Linux.
- Cô lập Hyper-V: mỗi container chạy bên trong một VM được tối ưu cao và có cái về hiệu quả là một kernel chuyên dụng. Sự có mặt của VM đặt cô lập cấp phần cứng giữa các container và máy chủ.7
Cô lập qua không gian tên có thể được mô tả như phiên bản triệt để của kỹ thuật chúng ta thấy trong bài ảo hóa registry (“Chuyển hướng và ảo hóa registry trên Windows”) — “hiện một thực tại khác dưới cùng một API”.
flowchart TB
accTitle: Cô lập tiến trình đối với cô lập Hyper-V
accDescr: Dưới cô lập tiến trình, các container chia sẻ kernel với máy chủ và cô lập qua không gian tên; dưới cô lập Hyper-V, mỗi container có kernel chuyên dụng bên trong một VM được tối ưu
subgraph pi ["Cô lập tiến trình"]
c1["Container A"] --> sk1["Kernel chia sẻ với máy chủ"]
c2["Container B"] --> sk1
end
subgraph hi ["Cô lập Hyper-V"]
c3["Container C"] --> k3["Kernel chuyên dụng(trong VM được tối ưu)"]
c4["Container D"] --> k4["Kernel chuyên dụng(trong VM được tối ưu)"]
end
sk1 ~~~ c3
Hình 11: Dù cùng một ảnh container, việc bạn vẽ đường cô lập phía trên kernel hay tách bản thân kernel là lựa chọn bạn làm lúc khởi động.
5.2. Cái nào bạn có thể gọi là “ranh giới bảo mật”
Khác biệt giữa hai chế độ này không chỉ là câu chuyện hiệu năng. Microsoft không coi một container cô lập tiến trình là ranh giới bảo mật vững. Các container được duy trì (với phản ứng lỗ hổng) như một ranh giới bảo mật là các container cô lập hypervisor, và cô lập Hyper-V là thứ bạn nên chọn trong kịch bản đa thuê bao đối địch.8
VBS chúng ta thấy ở Phần 2 cũng là thiết kế giả định “kernel có thể bị đột phá” rồi rút về một ranh giới hypervisor. Cùng tiêu chí đó áp dụng trong thế giới container. Đường giam mã không đáng tin được vẽ ở ranh giới hypervisor, không ở phía trong của một kernel dùng chung.
flowchart TB
accTitle: Cách chọn cô lập từ mức bạn tin mã đến đâu
accDescr: Nếu khối lượng công việc đáng tin, lấy mật độ và hiệu năng bằng cô lập tiến trình; nếu mã không đáng tin hoặc của người khác, chọn ranh giới hypervisor như container cô lập Hyper-V, Windows Sandbox được củng cố với mạng tắt, hoặc một VM cô lập
trust{"Bạn có tin mã đó không?"} -->|Có| dens["Cô lập tiến trình(ưu tiên mật độ và tốc độ)"]
trust -->|Không / mã của người khác| bound["Chọn một ranh giới hypervisor"]
bound --> opt1["Container cô lập Hyper-V"]
bound --> opt2["Sandbox được củng cố hoặc VM cô lập"]
Hình 12: Chế độ cô lập là câu chuyện bảo mật trước khi là câu chuyện hiệu năng, và lòng tin quyết định bạn vẽ đường ở đâu.
Nhân tiện, chạy một container cô lập Hyper-V bên trong một VM Hyper-V làm hypervisor sâu hai lớp — ảo hóa lồng nhau. Một cấp lồng được hỗ trợ trong sản xuất trên các môi trường đáp ứng điều kiện (bộ xử lý Intel với máy chủ Windows 10 / Windows Server 2016 trở lên, hoặc bộ xử lý AMD với máy chủ Windows 11 / Windows Server 2022 trở lên, và phiên bản cấu hình VM tương ứng trong mỗi trường hợp), và một điều kiện tiên quyết nữa là thiết lập phơi các phần mở rộng ảo hóa cho VM ngoài (ExposeVirtualizationExtensions trên Set-VMProcessor trong Hyper-V). Chạy WSL2 bên trong một VM được hỗ trợ theo cùng cách.9 Việc bạn có thể dùng WSL2 hoặc Docker trong một VM phát triển trên đám mây cũng được quyết định bởi việc kích thước và cấu hình VM đó có phơi ảo hóa lồng nhau hay không.
flowchart TB
accTitle: Cấu trúc của ảo hóa lồng nhau
accDescr: Một VM đám mây ngồi trên hypervisor của máy chủ vật lý, và bên trong nó một hypervisor khác(cấp lồng được hỗ trợ là một cấp)chạy để hỗ trợ WSL2 và container cô lập Hyper-V
phys3["Hypervisor của máy chủ vật lý"] --> cvm["VM đám mây(máy phát triển)"]
cvm --> nhv["Hypervisor bên trong VM(cấp lồng 1)"]
nhv --> w2["WSL2"]
nhv --> hvc["Container cô lập Hyper-V"]
nhv -.-> limit["Cấp lồng được hỗ trợ là một cấp"]
Hình 13: Lý do wsl chạy bên trong một VM đám mây là ảo hóa lồng nhau được hỗ trợ chính thức chỉ một cấp.
5.3. Phổ cô lập và độ nhẹ
Xếp dàn diễn viên đến đây trên một trục duy nhất, nó trông như sau.
flowchart TB
accTitle: Phổ độ mạnh cô lập và độ nhẹ
accDescr: Container cô lập tiến trình nhẹ nhất nhưng chia sẻ kernel; WSL2, Sandbox và container cô lập Hyper-V là các VM nhẹ với kernel chuyên dụng(Sandbox làm nhẹ bằng chia sẻ, WSL2 bằng kernel được xây cho mục đích); một VM đầy đủ nặng nhất nhưng đa năng
ax["Nhẹ ← → Nặng"] ~~~ p1
p1["Container process-isolation"] --> p2["WSL2 / Sandbox / Hyper-V"]
p2 --> p3["VM đầy đủ(bản sao đủ)"]
p1 -.-> n1["Ranh giới: không gian tên"]
p2 -.-> n2["Ranh giới: hypervisor"]
p3 -.-> n3["Ranh giới: hypervisor + độc lập"]
Hình 14: Nhóm VM nhẹ là giải pháp giữa giữ ranh giới hypervisor và cắt nhân bản; cách chúng cắt tách thành chia sẻ cho Sandbox và kernel được xây cho mục đích cho WSL2.
6. Tự xem trên máy của bạn
Độ nhẹ và sự chia sẻ là những thứ bạn có thể quan sát trên một máy trước mặt.
Thời gian khởi động và sự lên xuống của bộ nhớ (WSL2). Với Task Manager mở, thử những điều sau.
# 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
Nếu bạn làm một lần build lớn hoặc thao tác tệp bên trong WSL2, vmmem lớn lên, và bạn có thể quan sát nó được trả về một lần bằng wsl --shutdown.
Khác biệt tốc độ từ chỗ bạn đặt tệp (WSL2). Đặt cùng một kho phía Linux (~/repo) và phía Windows (/mnt/c/repo) rồi so sánh thời gian cho git status hoặc một lần giải nén, và khác biệt từ Mục 3.2 hiện ra bằng số.
Nền tảng cho ánh xạ trực tiếp (Sandbox). Khởi động Sandbox và nhìn phần tăng bộ nhớ trong Task Manager trên máy chủ. Việc phần tăng ở lại nhỏ hơn nhiều so với những gì “một Windows khác” khiến bạn tưởng tượng là hiệu quả của sự chia sẻ đang kể chuyện. Để đào sâu hơn vào sự phân tách bộ nhớ phía máy chủ, bài về các công cụ Sysinternals đề cập cách dùng RAMMap và VMMap (“Process Explorer / Handle / VMMap trong thực tiễn”) rất hữu ích. Tuy nhiên đây là các công cụ nhìn phân loại tiến trình phía máy chủ và bộ nhớ vật lý; chúng không quan sát trực tiếp sự chia sẻ với bản thân khách.
Các chế độ cô lập container (Docker / container Windows). Nếu bạn có môi trường container Windows, khởi động cùng một ảnh bằng docker run --isolation=process và --isolation=hyperv rồi so sánh thời gian khởi động và cách nó trông trong Task Manager (dưới cô lập tiến trình, các tiến trình bên trong container xuất hiện trong danh sách tiến trình của máy chủ), và bạn có thể cảm nhận đường cô lập nằm ở đâu.7 Tuy nhiên cô lập tiến trình giả định phiên bản máy chủ và ảnh khớp, và trên hệ điều hành client nó bị giới hạn ở mục đích phát triển và kiểm thử. Cô lập Hyper-V cho phép bộ tổ hợp rộng hơn, nên hãy so sánh trên một cặp tương thích.10
7. Ba cách đọc sai cần tránh trong thực tế
7.1. “WSL2 chậm”
Thứ chậm không phải WSL2 mà là đường I/O tệp vượt ranh giới hệ điều hành. Có nhiều trường hợp chỉ cần chuyển dự án sang phía Linux là cảm giác thành một thứ khác.4 Ngược lại, đặt các tệp mà công cụ Windows sẽ chạm phía Linux cũng bất lợi như nhau vì cùng lý do. Hãy phán bằng “đặt nó phía cùng hệ điều hành với phía dùng nó”.
7.2. “vmmem lớn lên là rò rỉ bộ nhớ”
Bộ nhớ WSL2 lớn lên và thu lại theo nhu cầu, và các phần đã nhả được trả về. Trên WSL hiện tại, bộ nhớ đệm tệp cũng được thu hồi tự động bởi autoMemoryReclaim (mặc định là dropCache), nên “nó ở lại lớn” thường tự giải quyết theo thời gian.5 Nếu nó vẫn ở lại, hãy xác nhận autoMemoryReclaim chưa bị đặt thành disabled và pageReporting, thứ chịu trách nhiệm trả về các phần đã nhả, chưa bị tắt (hoặc bạn không đang trên WSL cũ hơn), rồi hoặc làm giới hạn trên tường minh bằng memory trong .wslconfig hoặc trả về tất cả bằng wsl --shutdown tại ranh giới phiên. Cách nghĩ về việc phân biệt rò rỉ với không-phải-rò-rỉ giống như ở kỳ mở đầu của loạt bài bộ nhớ, ““Mức dùng bộ nhớ” của Windows thực sự nghĩa là gì?”.
7.3. “Nó ở trong container, nên an toàn”
Một container cô lập tiến trình chia sẻ kernel, và theo tiêu chí của Microsoft đó không phải ranh giới bảo mật.8 Để chạy mã không đáng tin hoặc một mẫu, hãy chọn cô lập có ranh giới hypervisor, như container cô lập Hyper-V, Windows Sandbox, hoặc một VM chuyên dụng. Tuy nhiên ranh giới hypervisor không phải miễn trừ toàn diện. Thiết lập mặc định của Windows Sandbox có kết nối mạng được bật, và có thể phơi một ứng dụng không đáng tin ra mạng nội bộ.1 Nếu bạn dùng nó để chạy một mẫu, hãy củng cố cô lập bằng cách tắt mạng và chuyển hướng clipboard trong tệp cấu hình .wsb, hoặc dùng một VM chuyên dụng trên mạng cô lập.
8. Tóm tắt — Đóng loạt bài
Các điểm của Phần 3.
- Độ nhẹ của một VM nhẹ là kết quả của “dừng nhân bản”, không phải của “làm yếu cô lập”.
- WSL2 chạy một kernel Linux thật trong một VM tiện ích nhẹ được quản lý, và các bản phân phối được cô lập như container bên trong VM đó.3 Quy tắc hiệu năng là đặt tệp phía hệ điều hành dùng chúng, và bộ nhớ lớn lên rồi thu lại động, với giới hạn trên kiểm soát được trong
.wslconfig.45 - Windows Sandbox chia sẻ các tệp hệ điều hành bất biến của máy chủ qua ảnh cơ sở động và cũng chia sẻ các trang vật lý của các nhị phân hệ điều hành mục tiêu qua ánh xạ trực tiếp, nên nó không giữ một bản sao của một Windows hoàn chỉnh.2 Bạn vẫn cần khoảng 500 MB cho các tệp biến đổi được, cộng bộ nhớ của các ứng dụng bạn chạy bên trong.
- Chế độ cô lập container được chọn lúc khởi động, và phía bạn có thể gọi là ranh giới bảo mật là cô lập Hyper-V.78
Và nếu chúng ta đặt cả loạt lên một trang, nó trông như sau.
- Phần 1: Có một lớp hypervisor dưới Windows, và chính hệ điều hành máy chủ chạy như phân vùng gốc. Việc trọng tài CPU và bộ nhớ (SLAT) được lớp này làm trực tiếp, và I/O của thiết bị tổng hợp được phân vùng gốc (VSP) làm trung gian phía kia của VMBus.
- Phần 2: Lớp đó được dùng không chỉ để cô lập các VM với nhau mà còn để vẽ một ranh giới mạnh hơn kernel (VTL) bên trong cùng một hệ điều hành. Bảo mật mặc định của Windows 11 được xây trên đó.
- Phần 3: Trên cùng lớp đó, việc cắt nhân bản là thứ làm “một máy ảo khởi động trong vài giây” khả thi. Đường cô lập được giữ, và nó đã trở thành công cụ đời thường.
flowchart TB
accTitle: Một bức tranh của cả loạt
accDescr: Hypervisor trực tiếp trên phần cứng là Phần 1; sự tách VTL0 và VTL1 bên trong Windows máy chủ là Phần 2; độ nhẹ của WSL2, Sandbox và cô lập Hyper-V trên cùng lớp là Phần 3; container cô lập tiến trình chia sẻ kernel máy chủ; Sandbox làm nhẹ bằng chia sẻ, WSL2 bằng kernel được xây cho mục đích
hw3["Phần cứng"] --> hv3["Hypervisor(Phần 1)"]
hv3 --> rp3["Windows máy chủ(cô lập VTL là Phần 2)"]
hv3 --> lw3["WSL2, Sandbox, cô lập Hyper-V(Phần 3)"]
rp3 --> pc3["Container process-isolation"]
lw3 -.-> mech3["Sandbox chia sẻ; WSL2 kernel riêng"]
Hình 15: Xếp chồng ba kỳ và bạn có bức tranh tổng thể của nền đất dưới Windows hiện tại.
Ảo hóa không còn là công nghệ phòng máy chủ, cũng không phải công nghệ chỉ dành cho người dựng VM. Ở nền đất dưới Windows của bạn, nó lặng lẽ chống đỡ cả bảo mật lẫn trải nghiệm phát triển — đó là chỗ chúng ta đang đứng.
Bài viết liên quan
- Bên trong ảo hóa Windows (Phần 1) — Windows của bạn thực sự chạy ở đâu? Hypervisor và phân vùng
- Bên trong ảo hóa Windows (Phần 2) — Bộ nhớ ngay cả kernel cũng không thấy: VBS, HVCI và Credential Guard
- Chiều sâu bộ nhớ Windows (Phần 3) — Đối tượng section và Copy-on-Write: DLL và ánh xạ tệp thực sự là gì
- Cách tăng tốc xác thực ứng dụng bằng Windows Sandbox
- Những cái bẫy chuyển hướng và ảo hóa registry 32-bit/64-bit — Wow6432Node và vấn đề “Giá trị tôi vừa ghi chẳng thấy đâu”
Lĩnh vực tư vấn liên quan
KomuraSoft LLC đảm nhận thiết lập môi trường phát triển dùng WSL2 và container, thiết kế môi trường xác thực ứng dụng Windows, và điều tra hiệu năng cùng tính tương thích trong môi trường ảo hóa.
- Phát triển ứng dụng Windows
- Điều tra lỗi và phân tích nguyên nhân gốc rễ
- Tái sử dụng và di chuyển tài sản hiện có
- Liên hệ với chúng tôi
Liên kết tham khảo
-
Microsoft Learn, Windows Sandbox. Về việc Windows Sandbox khởi động trong vài giây như một VM dùng một lần và bỏ mọi thứ khi đóng; về việc chạy một kernel riêng với hypervisor Microsoft để cô lập nó khỏi máy chủ; và về việc kết nối mạng được bật mặc định và có thể tắt trong tệp cấu hình. ↩ ↩2 ↩3
-
Microsoft Learn, Windows Sandbox architecture. Về việc một ảnh cơ sở động lắp một ảnh Windows hoàn chỉnh từ việc chia sẻ các tệp hệ điều hành bất biến của máy chủ cộng một bản sao sạch của các tệp biến đổi được (khoảng 500 MB sau khi cài); về việc một container cấp phát động với sự hợp tác của máy chủ, đối với phân bổ bộ nhớ tĩnh của một VM truyền thống, để máy chủ có thể thu hồi bộ nhớ; và về việc ánh xạ trực tiếp làm các nhị phân hệ điều hành như ntdll.dll dùng cùng các trang vật lý với máy chủ. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, What is the Windows Subsystem for Linux?. Về việc WSL2 chạy một kernel Linux bên trong một VM tiện ích nhẹ; về việc mỗi bản phân phối chạy như một container cô lập, chia sẻ không gian tên mạng và kernel trong khi tách các không gian tên như PID, mount và user. ↩ ↩2 ↩3
-
Microsoft Learn, Comparing WSL Versions. Về việc kernel WSL2 được Microsoft xây từ nhánh Stable; về việc WSL phân phối qua Store nhận cập nhật như một gói tách khỏi ảnh hệ điều hành và áp dụng chúng bằng
wsl --update(ở bản phân phối in-box cũ hơn, qua Windows Update); về các ví dụ hiệu năng như lên tới 20 lần cho giải nén tarball; về việc WSL1 nhanh hơn cho hiệu năng hệ thống tệp xuyên hệ điều hành, nên tệp nên được đặt phía hệ điều hành dùng chúng; và về việc bộ nhớ lớn lên rồi thu lại với các phần đã nhả được trả về, trong khi bộ nhớ đệm có thể không trở về cho tới khi VM thoát. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 -
Microsoft Learn, Advanced settings configuration in WSL. Về việc có thể đặt trần bộ nhớ tổng thể của VM WSL2, số bộ xử lý, swap, và pageReporting (bật mặc định; chịu trách nhiệm phát hiện và trả về bộ nhớ không dùng) trong mục [wsl2] của .wslconfig; và về thiết lập thực nghiệm autoMemoryReclaim mặc định là dropCache, nên bộ nhớ đệm được thu hồi tự động. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Use and configure Windows Sandbox. Về việc MappedFolders trong tệp cấu hình .wsb có thể chia sẻ một thư mục máy chủ ở chế độ chỉ đọc hoặc ghi được. ↩
-
Microsoft Learn, Isolation Modes. Về việc cô lập tiến trình của container Windows chia sẻ kernel với máy chủ và cô lập qua không gian tên; về việc cô lập Hyper-V có cái về hiệu quả là một kernel chuyên dụng bên trong một VM được tối ưu; và về việc cùng một ảnh chạy được ở cả hai chế độ qua một cờ lúc khởi động. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Secure Windows containers. Về việc chỉ các container cô lập hypervisor được coi là ranh giới bảo mật; về việc các container cô lập tiến trình không được coi là ranh giới bảo mật vững; và về việc cô lập hypervisor là thứ bạn nên chọn trong kịch bản đa thuê bao đối địch. ↩ ↩2 ↩3
-
Microsoft Learn, What is Nested Virtualization?. Về việc chạy container cô lập Hyper-V bên trong một VM Hyper-V (một cấp lồng) được hỗ trợ trong sản xuất; về các yêu cầu là bộ xử lý Intel với Windows Server 2016 / Windows 10 trở lên, hoặc bộ xử lý AMD với Windows Server 2022 / Windows 11 trở lên, cộng phiên bản cấu hình VM tương ứng trong mỗi trường hợp; về việc phơi các phần mở rộng ảo hóa cho VM ngoài (ExposeVirtualizationExtensions) là điều kiện tiên quyết; và về việc chạy WSL2 bên trong một VM Hyper-V được hỗ trợ. ↩
-
Microsoft Learn, Windows container version compatibility. Về việc cô lập tiến trình giả định phiên bản máy chủ và ảnh container khớp; về việc cô lập Hyper-V có thể chạy một ảnh phiên bản hệ điều hành khác với máy chủ; và về việc cô lập tiến trình trên hệ điều hành client bị giới hạn ở mục đích phát triển và kiểm thử. ↩
Bài viết liên quan
Các bài viết gần đây có cùng thẻ để tìm hiểu sâu hơn những chủ đề lân cận.
Bên trong ảo hóa Windows (Phần 1) — Windows của bạn thực sự chạy ở đâu? Hypervisor và phân vùng
Khi bạn bật Hyper-V, chính Windows máy chủ chạy trên hypervisor như phân vùng gốc. Bài viết này giải thích nền tảng ảo hóa qua vai trò củ...
Bên trong ảo hóa Windows (Phần 2) — Bộ nhớ ngay cả kernel cũng không thấy: VBS, HVCI và Credential Guard
Khi cài sạch trên phần cứng tương thích, VBS được bật mặc định và dùng hypervisor cùng SLAT để tạo cô lập mạnh hơn kernel. Bài viết này g...
API thread pool Win32 — Đồng thời mà không tạo luồng, với CreateThreadpoolWork
Bạn đang rải các lời gọi CreateThread khắp mã native? Bài viết này giải thích API thread pool Win32 được thiết kế lại từ Vista — bốn đối ...
Named pipe trong thực tiễn — IPC chuẩn của Windows, từ thiết kế đến bảo mật
Hướng dẫn thực tiễn về named pipe, cơ chế giao tiếp giữa các tiến trình chuẩn của Windows. Bài viết sắp xếp, từ nguồn gốc, việc chọn giữa...
Giúp website xuất hiện khi khách tìm theo tên khu vực — Hướng dẫn Local SEO thực tiễn cho doanh nghiệp vừa và nhỏ (trang khu vực và Google Business Profile)
Dành cho các doanh nghiệp vừa và nhỏ có website không xuất hiện khi ai đó tìm kiếm "tên khu vực + ngành nghề". Bài viết này trình bày thứ...
Chủ đề liên quan
Các trang này đặt chủ đề trong bối cảnh rộng hơn của dịch vụ và quyết định.
Chủ đề kỹ thuật Windows
Cổng vào phát triển Windows, điều tra lỗi và khai thác tài sản hiện có.
Dịch vụ liên quan đến chủ đề này
Bài viết liên quan trực tiếp đến các dịch vụ sau.
Phát triển ứng dụng Windows
Ứng dụng nghiệp vụ, tích hợp thiết bị và công cụ liên lạc, từ yêu cầu đến phát triển.
Câu hỏi thường gặp
Các câu hỏi thường gặp khi tư vấn về chủ đề của bài viết.
- WSL2 có phải là một VM không?
- Có. WSL2 chạy một kernel Linux thật do Microsoft xây bên trong một VM tiện ích nhẹ. VM được WSL quản lý phía sau, nên thiết kế không bao giờ khiến người dùng nghĩ tới cài đặt VM hay chờ boot. Mỗi bản phân phối Linux chạy như một container cô lập bên trong VM được quản lý này.
- Vì sao thao tác tệp dưới /mnt/c chậm trong WSL2?
- Vì truy cập từ kernel Linux của WSL2 tới hệ thống tệp phía Windows đi qua chia sẻ tệp vượt ranh giới hệ điều hành. Thao tác trên hệ thống tệp Linux (đĩa ảo ext4) thì nhanh, nên quy tắc là giữ tệp dự án phía cùng hệ điều hành với các công cụ thao tác trên chúng.
- Mức dùng bộ nhớ lớn của tiến trình vmmem có phải rò rỉ không?
- Hầu hết trường hợp không phải rò rỉ. Bộ nhớ WSL2 lớn lên và thu lại theo mức dùng, và bộ nhớ mà các tiến trình đã nhả được trả về Windows dưới thiết lập pageReporting, được bật mặc định. Các trang bộ nhớ đệm tệp cũng được thu hồi tự động bởi WSL hiện tại qua autoMemoryReclaim trong .wslconfig (mặc định là dropCache). Trong các môi trường các thiết lập này đã bị tắt, hoặc trên WSL cũ hơn, bộ nhớ có thể ở lại cho tới khi VM thoát; khi đó hãy đặt giới hạn trên bằng thiết lập memory, hoặc trả về bằng wsl --shutdown.
- Làm sao Windows Sandbox boot một Windows hoàn chỉnh từ vài trăm megabyte đĩa?
- Qua cơ chế gọi là ảnh cơ sở động. Nó chia sẻ các tệp hệ điều hành bất biến từ Windows đã cài trên máy chủ, và giữ một bản sao sạch chỉ của số ít tệp biến đổi được. Điều đó cho phép nó lắp một ảnh hoàn chỉnh, boot được mà không lưu một bản sao đầy đủ của Windows.
- Container có an toàn hơn VM không?
- Tùy chế độ cô lập. Container cô lập tiến trình chia sẻ kernel với máy chủ, và Microsoft không coi đây là ranh giới bảo mật vững. Khi bạn xử lý mã đối địch, bạn cần cô lập Hyper-V, thứ cho mỗi container kernel chuyên dụng riêng.