1. 程式人生 > >docker 的體系結構

docker 的體系結構

周期 啟動 mon 資源管理 inux 分支 設計 linux內核 模板

Docker的體系結構
Docker 的體系結構
docker使用C/S 架構,docker daemon 作為 server 端接受 client 的請求,並處理(創建、運
行、分發容器),他們可以運行在一個機器上,也通過socket或者RESTful API 通信
技術分享圖片
Docker daemon 一般在宿主主機後臺運行。
Docker client以系統命令的形式存在,用戶用docker命令來跟docker daemon 交互。Docker 守護進程(Docker daemon)
如上圖所示,Docker 守護進程運行在一臺主機上。用戶並不直接和守護進程進行交互,而是通過 Docker 客戶端間接和其通信。
Docker 客戶端(Docker client)
Docker 客戶端,實際上是docker的二進制程序,是用戶與 Docker 交互方式。它接收用戶指
令並且與背後的 Docker 守護進程通信
技術分享圖片
Docker 內部:
要理解 Docker 內部構建,需要理解以下三大核心概念:
Docker 鏡像 - Docker images
Docker 倉庫 - Docker repository
Docker 容器 - Docker containers
只有理解了這三個核心概念,才能順利地理解Docker容器的整個生命周期。
Docker鏡像
Docker鏡像是Docker容器運行時的只讀模板,鏡像可以用來創建Docker容器。每一個鏡像由
一系列的層 (layers) 組成。Docker使用UnionFS(聯合文件系統)來將這些層聯合到單獨
的鏡像中。UnionFS允許獨立文件系統中的文件和文件夾(稱之為分支)被透明覆蓋,形成一
個單獨連貫的文件系統。正因為有了這些層的存在,Docker是如此的輕量。當你改變了一個
Docker鏡像,比如升級到某個程序到新的版本,一個新的層會被創建。因此,不用替換整個原先的鏡像或者重新建立(在使用虛擬機的時候你可能會這麽做),只是一個新的層被添加或升級了。現在你不用重新發布整個鏡像,只需要升級,層使得分發Docker 鏡像變得簡單和快速。
例如:centos鏡像中安裝nginx,就成了“nginx鏡像”,其在此時Docker鏡像的層級概念就體現出來了。底層一個centos操作系統鏡像,上面疊加一個nginx層,就完成了一個nginx鏡像的構建。層級概念就不難理解,此時我們一般centos操作系統鏡像稱為nginx鏡像層的父鏡像。
nginx鏡像的構建。層級概念就不難理解,此時我們一般centos操作系統鏡像稱為nginx鏡像層的父鏡像。
鏡像是創建Docker容器的基礎。通過版本管理和增量的文件系統,Docker提供了一套十分簡單的機制來創建和更新現有的鏡像,用戶甚至可以從網上下載一個已經做好的鏡像,並直接使用。
Docker倉庫
Docker倉庫類似於代碼倉庫,它是Docker集中存放鏡像文件的場所不要將Docker倉庫和倉庫註冊服務器(Registry)混為一談。實際上,倉庫註冊服務器是存放倉庫的地方,其上往往存放著多個倉庫。每個倉庫集中存放某一類鏡像,往往包括多個鏡像文件,通過不同的標簽(tag)來進行區分。例如存放Ubuntu操作系統鏡像的倉庫稱為Ubuntu倉庫,其中可能包括14.04、12.04等不同版本的鏡像。倉庫註冊服務器的示例如圖
所示。技術分享圖片
Docker容器
Docker利用容器來運行應用,一個Docker容器包含了所有的某個應用運行所需要的環境。每一個Docker 容器都是從Docker 鏡像創建的,是通過鏡像創建的運行實例。Docker容器可以運行、開始、停止、移動和刪除。每一個Docker容器都是獨立和安全的應用平臺,彼此相互隔離、互不見
可以把容器看做是一個簡易版的Linux環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。
*註:鏡像是只讀的,容器在啟動的時候創建一層可寫層作為最上層
技術分享圖片
與虛擬機相比,容器有一個很大的差異,它們被設計用來運行"單進程",無法很好地模擬一個完整的環境。Docker設計者極力推崇“一個容器一個進程的方式”,如果你要選擇在一個容器中運行多個進程,那唯一情況是:出於調試目的。容器是設計來運行一個應用的,而非一臺機器。你可能會把容器當虛擬機用,但你將失去很多的靈活性,因為Docker提供了用於分離應用與數據的工具,使得你可以快捷地更新運行中的代碼/系統,而不影響數據
Docker 底層技術
docker底層的2個核心技術分別是 Namespaces和Control groups
Namespaces用來隔離各個容器
1) pid namespace
不同用戶的進程就是通過pid namespace隔離開的,且不同namespace中可以有相同pid。所有的LXC進程在docker中的父進程為docker進程,每個lxc進程具有不同的namespace 。
2) net namespace有了pid namespace, 每個namespace中的pid能夠相互隔離,但是網絡端口還是共享host的端口。網絡隔離是通過net namespace實現的,每個netnamespace有獨立的network
devices, IP addresses, IP routing tables, /proc/net 目錄。這樣每個container的網絡就能隔離開來。docker默認采用veth的方式將container中的虛擬網卡同host上的一個
docker bridge: docker0 連接在一起。
3) ipc namespace
container中進程交互還是采用linux常見的進程間交互方法 (interprocess communication- IPC),包括常見的信號量、消息隊列和共享內存。container的進程間交互實際上還host
上具有相同pid namespace中的進程間交互。
4) mnt namespace
類似chroot,將一個進程放到一個特定的目錄執行。mnt namespace 允許不同namespace的進程看到的文件結構不同,這樣每個namespace中的進程所看到的文件目錄就被隔離開了。
在container裏頭,看到的文件系統,就是一個完整的linux系統,有/etc、/lib 等,通過chroot實現。
5) uts namespace
UTS("UNIX Time-sharing System") namespace 允許每個container擁有獨立的hostname和domain name, 使其在網絡上可以被視作一個獨立的節點而非Host上的一個進程。
6) user namespace
每個container可以有不同的user和group id,也就是說可以在container內部用container內部的用戶執行程序而非Host上的用戶。有了以上6種namespace從進程、網絡、IPC、文件系統、UTS和用戶角度的隔離,一個container就可以對外展現出一個獨立計算機的能力,並且不container從OS層面實現了隔離。然而不同namespace之間資源還是相互競爭的,仍然需要類似ulimit來管理每個container所能使用的資源--cgroup。
cgroups(Control groups)實現了對資源的配額和度量。
cgroups(Control Groups)最初叫Process Container,由Google工程師(PaulMenage和Rohit Seth)於2006年提出,後來因為Container有多重含義容易引起誤解,就在
2007年更名為Control Groups,並被整合進Linux內核。顧名思義就是把進程放到一個組裏面統一加以控制。官方的定義如下:cgroups是Linux內核提供的一種機制,這種機制可以根據特定的行為,把一系列系統任務及其子任務整合(或分隔)到按資源劃分等級的不同組內,從而為系統資源管理提供一個統一的框架。
通俗的來說,cgroups可以限制、記錄、隔離進程組所使用的物理資源(包括:CPU、memory、IO等),為容器實現虛擬化提供了基本保證,是構建Docker等一系列虛擬化管理工具的基石。
實現cgroups的主要目的是為不同用戶層面的資源管理,提供一個統一化的接口。從單個進程的資源控制到操作系統層面的虛擬化。Cgroups提供了以下四大功能:資源限制(Resource Limitation):cgroups可以對進程組使用的資源總額進行限制。如設定應用運行時使用內存的上限,一旦超過這個配額就發出OOM(Out ofMemory)。優先級分配(Prioritization):通過分配的CPU時間片數量及硬盤IO帶寬大小,實際上就相當於控制了進程運行的優先級。
資源統計(Accounting): cgroups可以統計系統的資源使用量,如CPU使用時長、內存用量等等,這個功能非常適用於計費。進程控制(Control):cgroups可以對進程組執行掛起、恢復等操作。

docker 的體系結構