Docker核心技術預覽
本文簡單介紹docker使用到的部分核心技術,但不做深入探究,因為每一個技術都是一個獨立的項目,有機會再分別詳細介紹。
Linux Namespace (實例隔離)
The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource.
每個用戶實例之間相互隔離,互不影響。一般的硬件虛擬化方法給出的方法是VM,而LXC給出的方法是container,更細一點講就是 kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace將container的進程、網絡、消息、文件系統、 UTS(“UNIX Time-sharing System”)和用戶空間隔離開。
pid namespace
不同用戶的進程就是通過pid namespace隔離開的,且不同 namespace 中可以有相同pid。所有的LXC進程在docker中的父進程為docker進程,每個lxc進程具有不同的namespace。同時由于允許嵌套,因 此可以很方便的實現 Docker in Docker。
net namespace
有了 pid namespace, 每個namespace中的pid能夠相互隔離,但是網絡端口還是共享host的端口。網絡隔離是通過net namespace實現的, 每個net namespace有獨立的 network devices, IP addresses, IP routing tables, /proc/net 目錄。這樣每個container的網絡就能隔離開來。LXC在此基礎上有5種網絡類型,docker默認采用veth的方式將container中的虛 擬網卡同host上的一個docker bridge—docker0連接在一起。
ipc namespace
container中進程交互還是采用linux常見的進程間交互方法(interprocess communication – IPC), 包括常見的信號量、消息隊列和共享內存。然而與VM不同,container 的進程間交互實際上還是host上具有相同pid namespace中的進程間交互,因此需要在IPC資源申請時加入namespace信息 – 每個IPC資源有一個唯一的 32bit ID。
mnt namespace
類似chroot,將一個進程放到一個特定的目錄執行。mnt namespace允許不同namespace的進程看到的文件結構不同,這樣每個 namespace 中的進程所看到的文件目錄就被隔離開了。同chroot不同,每個namespace中的container在/proc/mounts`的信息只包含所 在namespace的mount point。
uts namespace
UTS(“UNIX Time-sharing System”) namespace允許每個container擁有獨立的hostname和domain name, 使其在網絡上可以被視作一個獨立的節點而非Host上的一個進程。
user namespace
每個container可以有不同的 user 和 group id, 也就是說可以以container內部的用戶在container內部執行程序而非Host上的用戶。
有了以上6種namespace從進程、網絡、IPC、文件系統、UTS和用戶角度的隔離,一個container就可以對外展現出一個獨立計算機 的能力,并且不同container從OS層面實現了隔離。 然而不同namespace之間資源還是相互競爭的,仍然需要類似ulimit來管理每個container所能使用的資源——LXC 采用的是cgroup。
參考
cgroup (資源配額)
cgroups 實現了對資源的配額和度量。cgroups 的使用非常簡單,提供類似文件的接口,在/cgroup目錄下新建一個文件夾即可新建一個group,在此文件夾中新建task文件,并將pid寫入該文 件,即可實現對該進程的資源控制。具體的資源配置選項可以在該文件夾中新建子subsystem,{子系統前綴}.{資源項}是典型的配置方法, 如memory.usage_in_bytes就定義了該group 在subsystem memory中的一個內存限制選項。
我們主要關心cgroups可以限制哪些資源,即有哪些subsystem是我們關心。
cpu
在cgroup中,并不能像硬件虛擬化方案一樣能夠定義CPU能力,但是能夠定義CPU輪轉的優先級,因此具有較高CPU優先級的進程會更可能得到CPU 運算。 通過將參數寫入cpu.shares,即可定義改cgroup的CPU優先級 – 這里是一個相對權重,而非絕對值。當然在cpu這個subsystem中還有其他可配置項,手冊中有詳細說明。
cpuacct
產生cgroup任務的cpu資源報告
cpuset
cpusets 定義了有幾個CPU可以被這個group使用,或者哪幾個CPU可以供這個group使用。在某些場景下,單CPU綁定可以防止多核間緩存切換,從而提高效率
memory
設置每個cgroup的內存限制以及產生內存資源報告
blkio
block IO相關的統計和限制,byte/operation統計和限制(IOPS等),讀寫速度限制等,但是這里主要統計的都是同步IO
net_cls
標記每個網絡包以供cgroup方便使用
devices
允許或拒絕cgroup任務對設備的訪問
freezer
暫停和恢復cgroup任務
參考
- PaaS Under the Hood, Episode 2: cgroups
- https://www.kernel.org/doc/Documentation/cgroups/
-
Control groups (cgroups)
LXC 旨在提供一個共享kernel的 OS 級虛擬化方法,在執行時不用重復加載Kernel,且container的kernel與host共享,因此可以大大加快container的 啟動過程,并顯著減少內存消耗。