容器(container)
容器(container)是比虛擬機器更輕量的隔離形式:它不去跑一整套獨立的作業系統,而只是主機上的一群行程,被賦予它們自己私有、隔牆而立的系統視角,卻暗地裡共用主機唯一的核心。把它想成一間開放式辦公室,所有人共用同一棟樓與同一套空調(核心),但每個團隊被分到一塊隔間,有自己的門、自己貼了標籤的物資、與固定的桌位額度——他們覺得自己有獨立的辦公室,但底下的大樓是同一棟。
技術上,容器是由兩項普通的核心功能打造而成。命名空間(namespace)給容器隔離的視角:自己的行程編號(所以它只看得到自己的行程)、自己的檔案系統根目錄、自己的網路介面、自己的使用者 ID,使它從內部看起來像一台全新的機器。控制群組(cgroups)則限制它能消耗多少:這麼多 CPU、這麼多記憶體、這麼多輸入輸出頻寬,使一個容器無法餓死其他容器。再加上一個分層的檔案系統映像(一個覆疊層),把應用程式與它的程式庫打包在一起,你就有了一個容器:一個可攜、自足的單元,在任何跑同一個核心的地方都以相同方式執行。
容器之所以重要,是因為相較於虛擬機器它又快又省:沒有第二套作業系統要開機、沒有虛擬硬體要模擬,所以容器在不到一秒內就啟動,用的記憶體也少得多,這正是它們能密集堆疊、支撐現代雲端部署的原因。誠實的取捨是隔離強度:因為每個容器都共用那唯一的主機核心,一個讓程式碼逃出核心的瑕疵會一次破壞所有容器——而虛擬機器有自己的核心,還多了一道超管理器邊界。容器更輕、更快;虛擬機器隔離更強。
一個網頁應用程式與一個資料庫,以兩個容器的形式跑在同一台 Linux 主機上。每個都看到自己的檔案與自己的行程清單(網頁容器甚至看不到資料庫的行程),每個都被限制在比方說 1 GB 記憶體——然而兩者其實都只是共用底下那一個主機核心的行程群組。
兩個隔離的容器,底下是同一個共用的主機核心。
容器共用主機核心,所以隔離比虛擬機器弱:一個核心層級的漏洞可以逃出容器,伸向主機或其同伴,而虛擬機器自己的核心加上超管理器邊界讓這困難得多。更輕量不等於更安全。