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