9張圖帶你深入理解Docker架構(gòu)!
Docker 的總體架構(gòu)
Docker 是一個 C/S 模式的架構(gòu),后端是一個松耦合架構(gòu),模塊各司其職。下圖是它的總體架構(gòu)圖:
1、用戶是使用 Docker Client 與 Docker Daemon 建立通信,并發(fā)送請求給后者。
2、Docker Daemon 作為 Docker 架構(gòu)中的主體部分,首先提供 Docker Server 的功能使其可以接受 Docker Client 的請求。
3、Docker Engine 執(zhí)行 Docker 內(nèi)部的一系列工作,每一項工作都是以一個 Job 的形式的存在。
4、Job 的運行過程中,當(dāng)需要容器鏡像時,則從 Docker Registry 中下載鏡像,并通過鏡像管理驅(qū)動 Graphdriver 將下載鏡像以 Graph 的形式存儲。
5、當(dāng)需要為 Docker 創(chuàng)建網(wǎng)絡(luò)環(huán)境時,通過網(wǎng)絡(luò)管理驅(qū)動 Networkdriver 創(chuàng)建并配置 Docker容器網(wǎng)絡(luò)環(huán)境。
6、當(dāng)需要限制 Docker 容器運行資源或執(zhí)行用戶指令等操作時,則通過 Execdriver 來完成。
7、Libcontainer 是一項獨立的容器管理包,Networkdriver 以及 Execdriver 都是通過 Libcontainer 來實現(xiàn)具體對容器進(jìn)行的操作。
Docker 各模塊組件分析
一、Docker Client「發(fā)起請求」
1、Docker Client 是 和 Docker Daemon 建立通信的客戶端。用戶使用的可執(zhí)行文件為 docker(一個命令行可執(zhí)行文件),docker 命令使用后接參數(shù)的形式來實現(xiàn)一個完整的請求命令(例如:docker images,docker 為命令不可變,images 為參數(shù)可變)。
2、Docker Client 可以通過以下三種方式和 Docker Daemon 建立通信:tcp://host:port、unix://pathtosocket 和 fd://socketfd
3、Docker Client 發(fā)送容器管理請求后,由 Docker Daemon 接受并處理請求,當(dāng) Docker Client 接收到返回的請求相應(yīng)并簡單處理后,Docker Client 一次完整的生命周期就結(jié)束了。(一次完整的請求:發(fā)送請求→處理請求→返回結(jié)果),與傳統(tǒng)的 C/S 架構(gòu)請求流程并無不同。
二、Docker Daemon(后臺守護(hù)進(jìn)程)
Docker daemon 架構(gòu)圖:
Docker Server 架構(gòu)圖:
1、Docker Server 相當(dāng)于 C/S 架構(gòu)的服務(wù)端。功能為接受并調(diào)度分發(fā) Docker Client 發(fā)送的請求。接受請求后,Docker Server 通過路由與分發(fā)調(diào)度,找到相應(yīng)的 Handler 來執(zhí)行請求。
2、在 Docker 的啟動過程中,通過包 gorilla/mux 創(chuàng)建了一個 mux.Router 來提供請求的路由功能。在 Golang 中 gorilla/mux 是一個強大的 URL 路由器以及調(diào)度分發(fā)器。該 mux.Router 中添加了眾多的路由項,每一個路由項由 HTTP 請求方法(PUT、POST、GET 或DELETE)、URL、Handler 三部分組成。
3、創(chuàng)建完 mux.Router 之后,Docker 將 Server 的監(jiān)聽地址以及 mux.Router 作為參數(shù)來創(chuàng)建一個 httpSrv=http.Server{},最終執(zhí)行 httpSrv.Serve() 為請求服務(wù)。
4、在 Docker Server 的服務(wù)過程中,Docker Server 在 listener 上接受 Docker Client 的訪問請求,并創(chuàng)建一個全新的 goroutine 來服務(wù)該請求。在 goroutine 中,首先讀取請求內(nèi)容并做解析工作,接著找到相應(yīng)的路由項并調(diào)用相應(yīng)的 Handler 來處理該請求,最后 Handler 處理完請求之后回復(fù)該請求。
三、Docker Engine
1、Docker Engine 是 Docker 架構(gòu)中的運行引擎,同時也 Docker 運行的核心模塊。它扮演 Docker Container 存儲倉庫的角色,并且通過執(zhí)行 Job 的方式來操縱管理這些容器。
2、在 Docker Engine 數(shù)據(jù)結(jié)構(gòu)的設(shè)計與實現(xiàn)過程中,有一個 Handler 對象。該 Handler 對象存儲的都是關(guān)于眾多特定 Job 的 Handler 處理訪問。舉例說明: Docker Engine 的Handler 對象中有一項為:{“create”: daemon.ContainerCreate,},則說明當(dāng)名為”create” 的 Job 在運行時,執(zhí)行的是 daemon.ContainerCreate 的 Handler。
Job
1、一個 Job 可以認(rèn)為是 Docker 架構(gòu)中 Docker Engine 內(nèi)部最基本的工作執(zhí)行單元。Docker 可以做的每一項工作,都可以抽象為一個 Job。例如:在容器內(nèi)部運行一個進(jìn)程,這是一個 Job;創(chuàng)建一個新的容器,這是一個 Job。Docker Server 的運行過程也是一個 Job,名為 ServeApi。
2、Job 的設(shè)計者,把 Job 設(shè)計得與 Unix 進(jìn)程相仿。比如說:Job 有一個名稱、有參數(shù)、有環(huán)境變量、有標(biāo)準(zhǔn)的輸入輸出、有錯誤處理,有返回狀態(tài)等。
四、Docker Registry(鏡像注冊中心)
1、Docker Registry 是一個存儲容器鏡像的倉庫(注冊中心),可理解為云端鏡像倉庫。按 Repository 來分類,docker pull 按照 [repository]:[tag] 來精確定義一個具體的 Image。
2、在 Docker 的運行過程中,Docker Daemon 會與 Docker Registry 通信,并實現(xiàn)搜索鏡像、下載鏡像、上傳鏡像三個功能,這三個功能對應(yīng)的 Job 名稱分別為:“search”、”pull” 與 “push”。
3 Docker Registry 可分為公有倉庫( Docker Hub)和私有倉庫。
五、Graph 「Docker 內(nèi)部數(shù)據(jù)庫」
Graph 架構(gòu)圖:
Repository
1、已下載鏡像的保管者(包括下載的鏡像和通過 Dockerfile 構(gòu)建的鏡像)。
搜索公眾號頂級架構(gòu)師回復(fù)關(guān)鍵字“架構(gòu)整潔”,獲取一份驚喜禮包。
2、一個 Repository 表示某類鏡像的倉庫(例如:Ubuntu),同一個 Repository 內(nèi)的鏡像用 Tag 來區(qū)分(表示同一類鏡像的不同標(biāo)簽或版本)。一個 Registry 包含多個Repository,一個 Repository 包含同類型的多個 Image。
3、鏡像的存儲類型有 Aufs、Devicemapper、Btrfs、Vfs等。其中 CentOS 系統(tǒng) 7.x 以下版本使用 Devicemapper 的存儲類型。
4、同時在 Graph 的本地目錄中存儲有關(guān)于每一個的容器鏡像具體信息,包含有:該容器鏡像的元數(shù)據(jù)、容器鏡像的大小信息、以及該容器鏡像所代表的具體 rootfs。
GraphDB
1、已下載容器鏡像之間關(guān)系的記錄者。
2、GraphDB 是一個構(gòu)建在 SQLite 之上的小型數(shù)據(jù)庫,實現(xiàn)了節(jié)點的命名以及節(jié)點之間關(guān)聯(lián)關(guān)系的記錄。
六、Driver 「執(zhí)行部分」
Driver 是 Docker 架構(gòu)中的驅(qū)動模塊。通過 Driver 驅(qū)動,Docker 可以實現(xiàn)對 Docker 容器執(zhí)行環(huán)境的定制。即 Graph 負(fù)責(zé)鏡像的存儲,Driver 負(fù)責(zé)容器的執(zhí)行。
Graphdriver
Graphdriver 架構(gòu)圖:
1、Graphdriver 主要用于完成容器鏡像的管理,包括存儲與獲取。
2、存儲:docker pull 下載的鏡像由 Graphdriver 存儲到本地的指定目錄( Graph 中 )。
3、獲?。篸ocker run(create)用鏡像來創(chuàng)建容器的時候由 Graphdriver 到本地 Graph中獲取鏡像。
Networkdriver
Networkdriver 架構(gòu)圖:
Networkdriver 的用途是完成 Docker 容器網(wǎng)絡(luò)環(huán)境的配置,其中包括:
- Docker 啟動時為 Docker 環(huán)境創(chuàng)建網(wǎng)橋。
- Docker 容器創(chuàng)建時為其創(chuàng)建專屬虛擬網(wǎng)卡設(shè)備。
- Docker 容器分配IP、端口并與宿主機(jī)做端口映射,設(shè)置容器防火墻策略等。
Execdriver
Execdriver 架構(gòu)圖:
1、Execdriver 作為 Docker 容器的執(zhí)行驅(qū)動,負(fù)責(zé)創(chuàng)建容器運行命名空間、容器資源使用的統(tǒng)計與限制、容器內(nèi)部進(jìn)程的真正運行等。
2、現(xiàn)在 Execdriver 默認(rèn)使用 Native 驅(qū)動,不依賴于 LXC。
七、Libcontainer 「函數(shù)庫」
Libcontainer 架構(gòu)圖:
1、Libcontainer 是 Docker 架構(gòu)中一個使用 Go 語言設(shè)計實現(xiàn)的庫,設(shè)計初衷是希望該庫可以不依靠任何依賴,直接訪問內(nèi)核中與容器相關(guān)的 API。
2、Docker 可以直接調(diào)用 Libcontainer 來操縱容器的 Namespace、Cgroups、Apparmor、網(wǎng)絡(luò)設(shè)備以及防火墻規(guī)則等。
3、Libcontainer 提供了一整套標(biāo)準(zhǔn)的接口來滿足上層對容器管理的需求?;蛘哒f Libcontainer 屏蔽了 Docker 上層對容器的直接管理。
八、Docker Container 「服務(wù)交付的最終形式」
Docker Container 架構(gòu):
1、Docker Container( Docker 容器 )是 Docker 架構(gòu)中服務(wù)交付的最終體現(xiàn)形式。
2、Docker 按照用戶的需求與指令,訂制相應(yīng)的 Docker 容器:
- 用戶通過指定容器鏡像,使得 Docker 容器可以自定義 rootfs 等文件系統(tǒng)。
- 用戶通過指定計算資源的配額,使得 Docker 容器使用指定的計算資源。
- 用戶通過配置網(wǎng)絡(luò)及其安全策略,使得 Docker 容器擁有獨立且安全的網(wǎng)絡(luò)環(huán)境。
- 用戶通過指定運行的命令,使得 Docker 容器執(zhí)行指定的工作。