跳轉到

7.1 傳統虛擬機的沉重代價:每一個 VM 都要打包一整套冗餘的 guest OS#

VM 的帳單:你為「完整」付了多少錢#

VM 的本質是「完整機器的複製品」,這份完整是有代價的。拆開一個典型雲端 VM 的資源帳單:

一個最小 Linux VM(例如雲端上的 micro instance):
  · 完整的 guest 核心(數十 MB,且持續占用記憶體)
  · 完整的使用者空間(libc、shell、套件管理器……數百 MB)
  · 虛擬 BIOS/韌體、虛擬裝置的模擬層
  · VMEXIT、上下文切換的固有開銷
  · 啟動時間:數十秒(核心初始化、服務逐個啟動)

問題不是單一成本高,而是冗餘的乘法效應:

一台 128 GB 記憶體的實體機:
  方案 A:跑 8 個 VM → 8 份完整核心+8 份使用者空間
  方案 B:跑 8 個行程 → 1 份核心+8 個輕量執行環境
  B 的資源效率可以高出一個數量級

部署的噩夢:MLC(「在我機器上明明可以跑」)#

比資源更痛的是部署一致性。2010 年代初,業界有個自嘲式縮寫:

"Works on My Machine" ——在我機器上明明可以跑!

傳統部署流程的痛點:

  1. VM 映像龐大(數 GB 到數十 GB),傳輸與儲存昂貴;
  2. 映像內部狀態不透明:這個鏡像裡的 nginx 是哪個版本?誰改過設定?
  3. 建立映像的流程靠手工與口耳相傳,無法程式化重現;
  4. 啟動慢:組態管理工具(Puppet/Chef)在 VM 裡逐項安裝,幾十分鐘起步。

虛擬機解決了「機器不夠」的問題,卻沒有解決「機器太重」的問題。

PaaS 的啟示:dotCloud 的內部工具#

2013 年前的世界已經出現了答案的碎片:

  • 2000 年代:FreeBSD jail 與 Solaris Zones——作業系統層級的輕量分區,證明「共享核心+資源隔離」可行,只是限於各自系統、生態封閉;
  • 2003–2008:Google 的內部容器基礎設施——Google 把所有工作負載跑在「容器」裡(外號 Borg 的叢集排程系統管理),證明此路可以支撐整個公司的規模;
  • 2008:Google 向 Linux 核心貢獻 cgroups(由 Paul Menage 與 Rohit Seth 等人推動),把 Google 內部隔離思想帶進主流 Linux;
  • 2008–2013:dotCloud——巴黎/舊金山的小型 PaaS 公司,用 Linux 核心的 cgroups 與 namespaces 打造內部隔離工具。公司經營艱難,卻在 2013 年 3 月做了一個改變歷史的決定:把這個內部工具開源,命名為 Docker。

Docker 的天才:不是發明,而是「產品化」#

Docker 沒有發明容器——cgroups、namespaces、聯合檔案系統(AuFS/OverlayFS)、LXC 都是現成的。Docker 的天才在於把碎片組裝成一個優雅的開發者體驗:

Docker 的三把鑰匙:
1. Dockerfile:環境定義 = 一份可版本控制的文字檔
   「機器的狀態」第一次可以被 git 管理
2. 分層映像(Layered Image)+註冊中心(Registry):
   映像可拆層共用、秒級下載、隨處分發
3. 一條命令的體驗:
   docker run -d -p 80:80 nginx   ← 就是這麼簡單

2013 年 3 月 Solomon Hykes 在 PyCon 上五分鐘 demo;一個月內 GitHub 上掀起風暴;2014 年 dotCloud 更名 Docker Inc.,專注容器事業。開源+開發者體驗+雲端時代的部署痛點——三股力量疊加,容器以史上罕見的速度從玩具變成標準。

容器 vs VM:同一台機器的兩種人生#

維度 虛擬機 容器
隔離層次 硬體(hypervisor) 作業系統(核心)
guest 核心 每個 VM 一份 共用 host 核心
啟動時間 數十秒 毫秒級
映像大小 GB 級 MB 級
隔離強度 硬體邊界,強 核心機制,相對弱
資源開銷 高(每 VM 完整 OS) 低(共享核心)
錯誤半徑 VM 當機不影響他者 核心出事全船俱沉

歷史關聯:容器的思想譜系直通 1960 年代——CTSS 的分時、Unix 的 fork/exec、chroot(1979)、jail/Zones/Borg,全是「共享核心、邏輯分區」的迭代。虛擬機與容器不是新舊替代,而是 1974 年戈德堡「共享、模擬、安全」三大用途中不同分支的現代化。下一節拆解容器的核心機械。