成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Docker底層原理及源碼分析Docker架構

云計算
Docker 是 Docker 公司開源的一個基于輕量級虛擬化技術的容器引擎項目, 整個項目基于 Go 語言開發,并遵從 Apache 2.0 協議。

 [[279395]]

前言

Docker 簡介

Docker 是 Docker 公司開源的一個基于輕量級虛擬化技術的容器引擎項目, 整個項目基于 Go 語言開發,并遵從 Apache 2.0 協議。目前,Docker 可以在容器內部快速自動化部署應用,并可以通過內核虛擬化技術(namespaces 及 cgroups 等)來提供容器的資源隔離與安全保障等。由于 Docker 通過操作系統層的虛擬化實現隔離,所以 Docker 容器在運行時,不需要類似虛擬機(VM)額外的操作系統開銷,提高資源利用率,并且提升諸如 IO 等方面的性能。

由于眾多新穎的特性以及項目本身的開放性,Docker 在不到兩年的時間里迅速獲得諸多廠商的青睞,其中更是包括 Google、Microsoft、VMware 等業界行業領導者。 Google 在今年六月份推出了 Kubernetes ,提供 Docker 容器的調度服務,而今年 8 月 Microsoft 宣布 Azure 上支持 Kubernetes ,隨后傳統虛擬化巨頭VMware 宣布與Docker 強強合作。今年9 月中旬, Docker 更是獲得 4000 萬美元的 C 輪融資,以推動分布式應用方面的發展。

從目前的形勢來看,Docker 的前景一片大好。本系列文章從源碼的角度出發,詳細介紹 Docker 的架構、Docker 的運行以及 Docker 的卓越特性。本文是 Docker 源碼分析系列的第一篇­­­——Docker 架構篇。

Docker 版本

本文關于 Docker 架構的分析都是基于 Docker 的源碼與 Docker 相應版本的運行結果,其中 Docker 為最新的 1.2 版本。

Docker 架構分析內容目錄

本文的目的是:在理解 Docker 源代碼的基礎上,分析 Docker 架構。分析過程中主要按照以下三個步驟進行:

  • Docker 的總架構圖展示
  • Docker 架構圖內部各模塊功能與實現分析
  • 以 Docker 命令的執行為例,進行 Docker 運行流程闡述

Docker 總架構圖

學習 Docker 的源碼并不是一個枯燥的過程,反而可以從中理解 Docker 架構的設計原理。Docker 對使用者來講是一個 C/S 模式的架構,而 Docker 的后端是一個非常松耦合的架構,模塊各司其職,并有機組合,支撐 Docker 的運行。

在此,先附上 Docker 總架構,如圖 

Docker底層原理及源碼分析 Docker 架構

Docker 總架構圖

不難看出,用戶是使用 Docker Client 與 Docker Daemon 建立通信,并發送請求給后者。

而 Docker Daemon 作為 Docker 架構中的主體部分,首先提供 Server 的功能使其可以接受 Docker Client 的請求;而后 Engine 執行 Docker 內部的一系列工作,每一項工作都是以一個 Job 的形式的存在。

Job 的運行過程中,當需要容器鏡像時,則從 Docker Registry 中下載鏡像,并通過鏡像管理驅動 graphdriver 將下載鏡像以 Graph 的形式存儲;當需要為 Docker 創建網絡環境時,通過網絡管理驅動 networkdriver 創建并配置 Docker 容器網絡環境;當需要限制 Docker 容器運行資源或執行用戶指令等操作時,則通過 execdriver 來完成。

而 libcontainer 是一項獨立的容器管理包,networkdriver 以及 execdriver 都是通過 libcontainer 來實現具體對容器進行的操作。

當執行完運行容器的命令后,一個實際的 Docker 容器就處于運行狀態,該容器擁有獨立的文件系統,獨立并且安全的運行環境等。

Docker 架構內各模塊的功能與實現分析

接下來,我們將從 Docker 總架構圖入手,抽離出架構內各個模塊,并對各個模塊進行更為細化的架構分析與功能闡述。主要的模塊有:Docker Client、Docker Daemon、Docker Registry、Graph、Driver、libcontainer 以及 Docker container。

Docker Client

Docker Client 是 Docker 架構中用戶用來和 Docker Daemon 建立通信的客戶端。用戶使用的可執行文件為 docker,通過 docker 命令行工具可以發起眾多管理 container 的請求。

Docker Client 可以通過以下三種方式和 Docker Daemon 建立通信:tcp://host:port,unix://path_to_socket 和 fd://socketfd。為了簡單起見,本文一律使用第一種方式作為講述兩者通信的原型。與此同時,與 Docker Daemon 建立連接并傳輸請求的時候,Docker Client 可以通過設置命令行 flag 參數的形式設置安全傳輸層協議 (TLS) 的有關參數,保證傳輸的安全性。

Docker Client 發送容器管理請求后,由 Docker Daemon 接受并處理請求,當 Docker Client 接收到返回的請求相應并簡單處理后,Docker Client 一次完整的生命周期就結束了。當需要繼續發送容器管理請求時,用戶必須再次通過 docker 可執行文件創建 Docker Client。

Docker Daemon

Docker Daemon 是 Docker 架構中一個常駐在后臺的系統進程,功能是:接受并處理 Docker Client 發送的請求。該守護進程在后臺啟動了一個 Server,Server 負責接受 Docker Client 發送的請求;接受請求后,Server 通過路由與分發調度,找到相應的 Handler 來執行請求。

Docker Daemon 啟動所使用的可執行文件也為 docker,與 Docker Client 啟動所使用的可執行文件 docker 相同。在 docker 命令執行時,通過傳入的參數來判別 Docker Daemon 與 Docker Client。

Docker Daemon 的架構,大致可以分為以下三部分:Docker Server、Engine 和 Job。Daemon 架構。 

Docker底層原理及源碼分析 Docker 架構

圖Docker Daemon 架構示意圖

Docker Server 在 Docker 架構中是專門服務于 Docker Client 的 server。該 server 的功能是:接受并調度分發 Docker Client 發送的請求。Docker Server 的架構如圖 4.2。 

Docker底層原理及源碼分析 Docker 架構

圖 4.2 Docker Server 架構示意圖

在 Docker 的啟動過程中,通過包 gorilla/mux,創建了一個 mux.Router,提供請求的路由功能。在 Golang 中,gorilla/mux 是一個強大的 URL 路由器以及調度分發器。該 mux.Router 中添加了眾多的路由項,每一個路由項由 HTTP 請求方法(PUT、POST、GET 或 DELETE)、URL、Handler 三部分組成。

若 Docker Client 通過 HTTP 的形式訪問 Docker Daemon,創建完 mux.Router 之后,Docker 將 Server 的監聽地址以及 mux.Router 作為參數,創建一個 httpSrv=http.Server{},最終執行 httpSrv.Serve() 為請求服務。

在 Server 的服務過程中,Server 在 listener 上接受 Docker Client 的訪問請求,并創建一個全新的 goroutine 來服務該請求。在 goroutine 中,首先讀取請求內容,然后做解析工作,接著找到相應的路由項,隨后調用相應的 Handler 來處理該請求,最后 Handler 處理完請求之后回復該請求。

需要注意的是:Docker Server 的運行在 Docker 的啟動過程中,是靠一個名為"serveapi"的 job 的運行來完成的。原則上,Docker Server 的運行是眾多 job 中的一個,但是為了強調 Docker Server 的重要性以及為后續 job 服務的重要特性,將該"serveapi"的 job 單獨抽離出來分析,理解為 Docker Server。

4.2.2 Engine

Engine 是 Docker 架構中的運行引擎,同時也 Docker 運行的核心模塊。它扮演 Docker container 存儲倉庫的角色,并且通過執行 job 的方式來操縱管理這些容器。

在 Engine 數據結構的設計與實現過程中,有一個 handler 對象。該 handler 對象存儲的都是關于眾多特定 job 的 handler 處理訪問。舉例說明,Engine 的 handler 對象中有一項為:{"create": daemon.ContainerCreate,},則說明當名為"create"的 job 在運行時,執行的是 daemon.ContainerCreate 的 handler。

4.2.3 Job

一個 Job 可以認為是 Docker 架構中 Engine 內部最基本的工作執行單元。Docker 可以做的每一項工作,都可以抽象為一個 job。例如:在容器內部運行一個進程,這是一個 job;創建一個新的容器,這是一個 job,從 Internet 上下載一個文檔,這是一個 job;包括之前在 Docker Server 部分說過的,創建 Server 服務于 HTTP 的 API,這也是一個 job,等等。

Job 的設計者,把 Job 設計得與 Unix 進程相仿。比如說:Job 有一個名稱,有參數,有環境變量,有標準的輸入輸出,有錯誤處理,有返回狀態等。

4.3 Docker Registry

Docker Registry 是一個存儲容器鏡像的倉庫。而容器鏡像是在容器被創建時,被加載用來初始化容器的文件架構與目錄。

在 Docker 的運行過程中,Docker Daemon 會與 Docker Registry 通信,并實現搜索鏡像、下載鏡像、上傳鏡像三個功能,這三個功能對應的 job 名稱分別為"search","pull" 與 "push"。

其中,在 Docker 架構中,Docker 可以使用公有的 Docker Registry,即大家熟知的 Docker Hub ,如此一來,Docker 獲取容器鏡像文件時,必須通過互聯網訪問 Docker Hub;同時 Docker 也允許用戶構建本地私有的 Docker Registry,這樣可以保證容器鏡像的獲取在內網完成。

4.4 Graph

Graph 在 Docker 架構中扮演已下載容器鏡像的保管者,以及已下載容器鏡像之間關系的記錄者。一方面,Graph 存儲著本地具有版本信息的文件系統鏡像,另一方面也通過 GraphDB 記錄著所有文件系統鏡像彼此之間的關系。Graph 的架構如圖 4.3。 

Docker底層原理及源碼分析 Docker 架構

圖 4.3 Graph 架構示意圖

其中,GraphDB 是一個構建在 SQLite 之上的小型圖數據庫,實現了節點的命名以及節點之間關聯關系的記錄。它僅僅實現了大多數圖數據庫所擁有的一個小的子集,但是提供了簡單的接口表示節點之間的關系。

同時在 Graph 的本地目錄中,關于每一個的容器鏡像,具體存儲的信息有:該容器鏡像的元數據,容器鏡像的大小信息,以及該容器鏡像所代表的具體 rootfs。

4.5 Driver

Driver 是 Docker 架構中的驅動模塊。通過 Driver 驅動,Docker 可以實現對 Docker 容器執行環境的定制。由于 Docker 運行的生命周期中,并非用戶所有的操作都是針對 Docker 容器的管理,另外還有關于 Docker 運行信息的獲取,Graph 的存儲與記錄等。因此,為了將 Docker 容器的管理從 Docker Daemon 內部業務邏輯中區分開來,設計了 Driver 層驅動來接管所有這部分請求。

在 Docker Driver 的實現中,可以分為以下三類驅動:graphdriver、networkdriver 和 execdriver。

graphdriver 主要用于完成容器鏡像的管理,包括存儲與獲取。即當用戶需要下載指定的容器鏡像時,graphdriver 將容器鏡像存儲在本地的指定目錄;同時當用戶需要使用指定的容器鏡像來創建容器的 rootfs 時,graphdriver 從本地鏡像存儲目錄中獲取指定的容器鏡像。

在 graphdriver 的初始化過程之前,有 4 種文件系統或類文件系統在其內部注冊,它們分別是 aufs、btrfs、vfs 和 devmapper。而 Docker 在初始化之時,通過獲取系統環境變量”DOCKER_DRIVER”來提取所使用 driver 的指定類型。而之后所有的 graph 操作,都使用該 driver 來執行。

graphdriver 的架構如圖 4.4: 

Docker底層原理及源碼分析 Docker 架構

圖 4.4 graphdriver 架構示意圖

networkdriver 的用途是完成 Docker 容器網絡環境的配置,其中包括 Docker 啟動時為 Docker 環境創建網橋;Docker 容器創建時為其創建專屬虛擬網卡設備;以及為 Docker 容器分配 IP、端口并與宿主機做端口映射,設置容器防火墻策略等。networkdriver 的架構如圖 4.5: 

Docker底層原理及源碼分析 Docker 架構

圖 4. 5 networkdriver 架構示意圖

execdriver 作為 Docker 容器的執行驅動,負責創建容器運行命名空間,負責容器資源使用的統計與限制,負責容器內部進程的真正運行等。在 execdriver 的實現過程中,原先可以使用 LXC 驅動調用 LXC 的接口,來操縱容器的配置以及生命周期,而現在 execdriver 默認使用 native 驅動,不依賴于 LXC。具體體現在 Daemon 啟動過程中加載的 ExecDriverflag 參數,該參數在配置文件已經被設為"native"。這可以認為是 Docker 在 1.2 版本上一個很大的改變,或者說 Docker 實現跨平臺的一個先兆。execdriver 架構如圖 4.6: 

Docker底層原理及源碼分析 Docker 架構

圖 4.6 execdriver 架構示意圖

4.6 libcontainer

libcontainer 是 Docker 架構中一個使用 Go 語言設計實現的庫,設計初衷是希望該庫可以不依靠任何依賴,直接訪問內核中與容器相關的 API。

正是由于 libcontainer 的存在,Docker 可以直接調用 libcontainer,而最終操縱容器的 namespace、cgroups、apparmor、網絡設備以及防火墻規則等。這一系列操作的完成都不需要依賴 LXC 或者其他包。libcontainer 架構如圖 4.7: 

Docker底層原理及源碼分析 Docker 架構

libcontainer 示意圖

另外,libcontainer 提供了一整套標準的接口來滿足上層對容器管理的需求。或者說,libcontainer 屏蔽了 Docker 上層對容器的直接管理。又由于 libcontainer 使用 Go 這種跨平臺的語言開發實現,且本身又可以被上層多種不同的編程語言訪問,因此很難說,未來的 Docker 就一定會緊緊地和 Linux 捆綁在一起。而于此同時,Microsoft 在其著名云計算平臺 Azure 中,也添加了對 Docker 的支持,可見 Docker 的開放程度與業界的火熱度。

暫不談 Docker,由于 libcontainer 的功能以及其本身與系統的松耦合特性,很有可能會在其他以容器為原型的平臺出現,同時也很有可能催生出云計算領域全新的項目。

4.7 Docker container

Docker container(Docker 容器)是 Docker 架構中服務交付的最終體現形式。

Docker 按照用戶的需求與指令,訂制相應的 Docker 容器:

用戶通過指定容器鏡像,使得 Docker 容器可以自定義 rootfs 等文件系統;

用戶通過指定計算資源的配額,使得 Docker 容器使用指定的計算資源;

用戶通過配置網絡及其安全策略,使得 Docker 容器擁有獨立且安全的網絡環境;

用戶通過指定運行的命令,使得 Docker 容器執行指定的工作。

Docker 容器示意圖如圖 4.8: 

Docker底層原理及源碼分析 Docker 架構

圖 4.8 Docker 容器示意圖

5 Docker 運行案例分析

上一章節著重于 Docker 架構中各個部分的介紹。本章的內容,將以串聯 Docker 各模塊來簡要分析,分析原型為 Docker 中的 docker pull 與 docker run 兩個命令。

5.1 docker pull

docker pull 命令的作用為:從 Docker Registry 中下載指定的容器鏡像,并存儲在本地的 Graph 中,以備后續創建 Docker 容器時的使用。docker pull 命令執行流程如圖 5.1。 

Docker底層原理及源碼分析 Docker 架構

圖 5.1 docker pull 命令執行流程示意圖

如圖,圖中標記的紅色箭頭表示 docker pull 命令在發起后,Docker 所做的一系列運行。以下逐一分析這些步驟。

(1) Docker Client 接受 docker pull 命令,解析完請求以及收集完請求參數之后,發送一個 HTTP 請求給 Docker Server,HTTP 請求方法為 POST,請求 URL 為"/images/create? "+"xxx";

(2) Docker Server 接受以上 HTTP 請求,并交給 mux.Router,mux.Router 通過 URL 以及請求方法來確定執行該請求的具體 handler;

(3) mux.Router 將請求路由分發至相應的 handler,具體為 PostImagesCreate;

(4) 在 PostImageCreate 這個 handler 之中,一個名為"pull"的 job 被創建,并開始執行;

(5) 名為"pull"的 job 在執行過程中,執行 pullRepository 操作,即從 Docker Registry 中下載相應的一個或者多個 image;

(6) 名為"pull"的 job 將下載的 image 交給 graphdriver;

(7) graphdriver 負責將 image 進行存儲,一方創建 graph 對象,另一方面在 GraphDB 中記錄 image 之間的關系。

5.2 docker run

docker run 命令的作用是在一個全新的 Docker 容器內部運行一條指令。Docker 在執行這條命令的時候,所做工作可以分為兩部分:第一,創建 Docker 容器所需的 rootfs;第二,創建容器的網絡等運行環境,并真正運行用戶指令。因此,在整個執行流程中,Docker Client 給 Docker Server 發送了兩次 HTTP 請求,第二次請求的發起取決于第一次請求的返回狀態。Docker run 命令執行流程如圖 5.2。 

Docker底層原理及源碼分析 Docker 架構

圖 5.2 docker run 命令執行流程示意圖

如圖,圖中標記的紅色箭頭表示 docker run 命令在發起后,Docker 所做的一系列運行。以下逐一分析這些步驟。

(1) Docker Client 接受 docker run 命令,解析完請求以及收集完請求參數之后,發送一個 HTTP 請求給 Docker Server,HTTP 請求方法為 POST,請求 URL 為"/containers/create? "+"xxx";

(2) Docker Server 接受以上 HTTP 請求,并交給 mux.Router,mux.Router 通過 URL 以及請求方法來確定執行該請求的具體 handler;

(3) mux.Router 將請求路由分發至相應的 handler,具體為 PostContainersCreate;

(4) 在 PostImageCreate 這個 handler 之中,一個名為"create"的 job 被創建,并開始讓該 job 運行;

(5) 名為"create"的 job 在運行過程中,執行 Container.Create 操作,該操作需要獲取容器鏡像來為 Docker 容器創建 rootfs,即調用 graphdriver;

(6) graphdriver 從 Graph 中獲取創建 Docker 容器 rootfs 所需要的所有的鏡像;

(7) graphdriver 將 rootfs 所有鏡像,加載安裝至 Docker 容器指定的文件目錄下;

(8) 若以上操作全部正常執行,沒有返回錯誤或異常,則 Docker Client 收到 Docker Server 返回狀態之后,發起第二次 HTTP 請求。請求方法為"POST",請求 URL 為"/containers/"+container_ID+"/start";

(9) Docker Server 接受以上 HTTP 請求,并交給 mux.Router,mux.Router 通過 URL 以及請求方法來確定執行該請求的具體 handler;

(10)mux.Router 將請求路由分發至相應的 handler,具體為 PostContainersStart;

(11) 在 PostContainersStart 這個 handler 之中,名為"start"的 job 被創建,并開始執行;

(12) 名為"start"的 job 執行完初步的配置工作后,開始配置與創建網絡環境,調用 networkdriver;

(13)networkdriver 需要為指定的 Docker 容器創建網絡接口設備,并為其分配 IP,port,以及設置防火墻規則,相應的操作轉交至 libcontainer 中的 netlink 包來完成;

(14)netlink 完成 Docker 容器的網絡環境配置與創建;

(15) 返回至名為"start"的 job,執行完一些輔助性操作后,job 開始執行用戶指令,調用 execdriver;

(16)execdriver 被調用,初始化 Docker 容器內部的運行環境,如命名空間,資源控制與隔離,以及用戶命令的執行,相應的操作轉交至 libcontainer 來完成;

(17)libcontainer 被調用,完成 Docker 容器內部的運行環境初始化,并最終執行用戶要求啟動的命令。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2020-11-05 11:14:29

Docker底層原理

2024-04-11 11:04:05

Redis

2021-08-09 11:15:28

MybatisJavaSpring

2014-11-26 10:44:33

DockerOpenStack云計算

2021-12-01 06:50:50

Docker底層原理

2017-10-20 15:25:17

DockerOpenStack Cvolume

2021-01-27 18:15:01

Docker底層宿主機

2019-09-20 08:54:38

KafkaBroker消息

2021-07-20 10:26:53

源碼底層ArrayList

2024-03-07 07:47:04

代碼塊Monitor

2022-12-14 15:34:33

架構開發雙線程

2022-07-26 07:14:52

Docker宿主命令

2014-12-11 13:37:13

WPF架構

2018-06-05 08:58:38

Docker存儲容器

2021-10-25 09:41:04

架構運維技術

2021-11-26 17:17:43

Android廣播運行原理源碼分析

2021-02-03 11:20:41

Docker架構容器

2023-08-26 19:04:40

配置write轉換器

2023-08-11 08:42:49

泛型工廠繼承配置

2020-04-27 07:13:37

Nginx底層進程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品九九九 | 国产精品日本一区二区不卡视频 | www.国产91 | 欧美精品欧美精品系列 | 亚洲人人舔人人 | 偷拍第一页 | 播放一级黄色片 | 久久国产精品-国产精品 | 爱爱视频在线观看 | 国内久久精品 | 中文字幕乱码一区二区三区 | 久久av网 | 亚洲国产精久久久久久久 | 成人欧美 | 欧美精品一区三区 | 国产精品久久久久久网站 | 免费的色网站 | 亚洲欧美日韩一区 | 日日摸夜夜爽人人添av | 断背山在线观看 | 一级欧美一级日韩片免费观看 | 国产清纯白嫩初高生在线播放视频 | 欧美一级毛片久久99精品蜜桃 | 国产真实精品久久二三区 | 电影午夜精品一区二区三区 | 中文字幕亚洲一区 | 嫩草视频网站 | 国产精品久久久久久婷婷天堂 | 91亚洲国产成人久久精品网站 | 亚州综合一区 | 91精品国产综合久久久久久丝袜 | 色伊人久久 | 欧美一二三 | 欧美精品一区二区三区在线四季 | 人人做人人澡人人爽欧美 | 亚洲综合色婷婷 | 中文字幕免费视频 | 日韩一区在线视频 | 国产在线观看不卡一区二区三区 | 色婷婷国产精品综合在线观看 | 久久精品91久久久久久再现 |