每個優(yōu)秀的容器平臺都應該使用命名空間和控制組技術來構建容器。最佳的容器平臺還會集成其他容器安全技術,例如系統(tǒng)權限、強制訪問控制系統(tǒng)(如 SELinux 和 AppArmor)以及安全計算。正如用戶所期望的,Docker 中集成了上述全部安全技術!
下面主要對 Docker 中用到的主要 Linux 技術進行簡要介紹。
內核命名空間屬于容器中非常核心的一部分! 該技術能夠將操作系統(tǒng)(OS)進行拆分,使一個操作系統(tǒng)看起來像多個互相獨立的操作系統(tǒng)一樣。
這種技術可以用來做一些非??岬氖虑椋热缭谙嗤?OS 上運行多個 Web 服務,同時還不存在端口沖突的問題。該技術還允許多個應用運行在相同 OS 上并且不存在競爭,同時還能共享配置文件以及類庫。
舉兩個簡單的例子。
用戶可以在相同的 OS 上運行多個 Web 服務,每個端口都是 443。為了實現(xiàn)該目的,可以將兩個 Web 服務應用分別運行在自己的網(wǎng)絡命名空間中。這樣可以生效的原因是每個網(wǎng)絡命名空間都擁有自己的 IP 地址以及對應的全部端口。
也可能需要將每個 IP 映射到 Docker 主機的不同端口之上,但是使用 IP 上的哪個端口則無須其他額外配置。
用戶還可以運行多個應用,應用間共享類庫和配置文件,但是版本可能不同。為了實現(xiàn)該目標,需要在自己的掛載命名空間中運用每個應用程序。這樣做能生效的原因,是每個掛載命名空間內都有系統(tǒng)上任意目錄的獨立副本。
下圖展示了一個抽象的例子,兩個應用運行在相同的主機上,并且同時使用 443 端口。每個 Web 服務應用都運行在自己的網(wǎng)絡命名空間之內。
Linux Docker 現(xiàn)在利用了下列內核命名空間。
? 進程ID(PID)。
? 網(wǎng)絡(NET)。
? 文件系統(tǒng)/掛載(MNT)。
? 進程內通信(IPC)。
? 用戶(USER)。
? UTS。
下面會簡要介紹每種技術都做了些什么。但重要的是要理解,Docker 容器是由各種命名空間組合而成的。再次強調一遍,Docker 容器本質就是命名空間的有組織集合。
例如,每個容器都由自己的 PID、NET、MNT、IPC、UTS 構成,還可能包括 USER 命名空間。這些命名空間有機的組合就是所謂的容器。下圖展示了兩個運行在相同 Linux 主機上的容器。
接下來簡要介紹一下 Docker 是如何使用每個命名空間的。
⒈ 進程 ID 命名空間
Docker 使用 PID 命名空間為每個容器提供互相獨立的容器樹。每個容器都擁有自己的進程樹,意味著每個容器都有自己的 PID 為 1 的進程。PID 命名空間也意味著容器不能看到其他容器的進程樹,或者其所在主機的進程樹。
⒉ 網(wǎng)絡命名空間
Docker 使用 NET 命名空間為每個容器提供互相隔離的網(wǎng)絡棧。網(wǎng)絡棧中包括接口、ID 地址、端口地址以及路由表。例如,每個容器都有自己的 eth0 網(wǎng)絡接口,并且有自己獨立的 IP 和端口地址。
⒊ 掛載點命名空間
每個容器都有互相隔離的根目錄 /。這意味著每個容器都有自己的 /etc、/var、/dev 等目錄。容器內的進程不能訪問 Linux 主機上的目錄,或者其他容器的目錄,只能訪問自己容器的獨立掛載命名空間。
⒋ 進程內通信命名空間
Docker 使用 IPC 命名空間在容器內提供共享內存。IPC 提供的共享內存在不同容器間也是互相獨立的。
⒌ 用戶命名空間
Docker 允許用戶使用 USER 命名空間將容器內用戶映射到 Linux 主機不同的用戶上。常見的例子就是將容器內的 root 用戶映射到 Linux 主機的非 root 用戶上。用戶命名空間對于 Docker 來說還屬于新生事物且非必選項。該部分內容在未來可能出現(xiàn)改變。
⒍ UTS 命名空間
Docker 使用 UTS 命名空間為每個容器提供自己的主機名稱。
如下圖所示,容器本質就是命名空間的有機組合!
如果說命名空間用于隔離,那么控制組就是用于限額。
假設容器就是酒店中的房間。每個容器間都是互相獨立的,但是每個房間都共享一部分公共資源,比如供應水電、共享游泳池、共享健身、共享早餐餐吧等。
CGroup 允許用戶設置一些限制(以酒店作為類比)來保證不會存在單一容器占用全部的公共資源,如用光全部水或者吃光早餐餐吧的全部食物。
拋開酒店的例子,在 Docker 的世界中,容器之間是互相隔離的,但卻共享 OS 資源,比如 CPU、RAM 以及硬盤 I/O。CGroup 允許用戶設置限制,這樣單個容器就不能占用主機全部的 CPU、RAM 或者存儲 I/O 資源了。
以 root 身份運行容器不是什么好主意,root 擁有全部的權限,因此很危險。但是,如果以非 root 身份在后臺運行容器的話,非 root 用戶缺少權限,處處受限。所以用戶需要一種技術,能選擇容器運行所需的 root 用戶權限。了解一下 Capability!
在底層,Linux root 用戶是由許多能力組成的。其中一部分包括以下幾點。
? CAP_CHOWN:允許用戶修改文件所有權。
? CAP_NET_BIND_SERVICE:允許用戶將socket綁定到系統(tǒng)端口號。
? CAP_SETUID:允許用戶提升進程優(yōu)先級。
? CAP_SYS_BOOT:允許用戶重啟系統(tǒng)。
Docker 采用 Capability 機制來實現(xiàn)用戶在以 root 身份運行容器的同時,還能移除非必須的 root 能力。如果容器運行只需要 root 的綁定系統(tǒng)網(wǎng)絡端口號的能力,則用戶可以在啟動容器的同時移除全部 root 能力,然后再將 CAP_NET_BIND_SERVICE 能力添加回來。
Docker 采用主流 Linux MAC 技術,例如 AppArmor 以及 SELinux。
基于用戶的 Linux 發(fā)行版本,Docker 對新容器增加了默認的 AppArmor 配置文件。根據(jù) Docker 文檔的描述,默認配置文件提供了“適度的保護,同時還能兼容大部分應用”。
Docker 允許用戶在啟動容器的時候不設置相應策略,還允許用戶根據(jù)需求自己配置合適的策略。
Docker 使用過濾模式下的 Seccomp 來限制容器對宿主機內核發(fā)起的系統(tǒng)調用。
按照 Docker 的安全理念,每個新容器都會設置默認的 Seccomp 配置,文件中設置了合理的默認值。這樣做是為了在不影響應用兼容性的前提下,提供適度的安全保障。
用戶同樣可以自定義 Seccomp 配置,同時也可以通過向 Docker 傳遞指定參數(shù),使 Docker 啟動時不設置任何 Seccomp 配置。
Docker 基本支持所有的 Linux 重要安全技術,同時對其進行封裝并賦予合理的默認值,這在保證了安全的同時也避免了過多的限制,如下圖所示。
自定義設置某些安全技術會非常復雜,因為這需要用戶深入理解安全技術的運作原理,同時還要了解 Linux 內核的工作機制。希望這些技術在未來能夠簡化配置的過程,但就現(xiàn)階段而言,使用 Docker 在對安全技術的封裝中提供的默認值是很不錯的選擇。