1. 程式人生 > >【探索docker儲存之路】一、窺探docker中的volume plugin內幕

【探索docker儲存之路】一、窺探docker中的volume plugin內幕

重構前言

本來想後續一篇文章專門寫docker volume plugin。這篇可以簡單粗暴的拉通docker的程式碼。之前看《Docker容器和容器雲》感覺原理解析部分沒有進一步深入到volume plugin的層次。本想以此作為第3篇的主要內容。最近看了一下新出的書《Docker進階與實踐》2016年2月出版,第6章對容器卷管理做出了比較接地氣的的講解,並對卷外掛做了描述。於是把原來計劃中的第3篇整合到第一篇,把這一篇內容昇華一下。下面分析的原始碼版本基於docker1.10
  • 1
  • 2

Volume Plugin Introduction

通過volume機制,docker可以輕易地將主機目錄掛載到容器中;通過docker的volume plugin機制,使docker能夠方便地整合第三方儲存,為docker提供volume。

volume plugin

Container and Volume

container如何使用volume?

volume機制可以使容器訪問儲存都使用統一的介面(檔案介面),對於容器中的程序來說,volume就是一個已掛載的目錄,容器內程序使用該目錄就與普通目錄一樣。

docker使用Container結構管理容器,Container結構中有map型別的MountPoints變數,用於儲存container中所有已掛載的volume即是MountPoint結構,MountPoint結構儲存掛載目錄和volume結構的基本資訊,並且管理目錄的許可權控制、掛載傳播方式等特性。

Volume是個interface,docker實現兩種volume。①基於主機檔案系統。②基於Volume Plugin。 
這裡寫圖片描述

基於主機檔案系統提供volume

容器啟動:docker run -i -v /data ubuntu:latest /bin/bash 
容器內看到的掛載資訊: 
這裡寫圖片描述

/etc/resolv.conf、/etc/hostname和/etc/hosts三個檔案是為了解決每個container都擁有自己的hostname和DNS配置,使用了bind mount將主機的檔案,掛載到container內部。/data也是使用了同樣的方式將主機的目錄掛載到container中。下面是主機掛載到container的檔案: 
這裡寫圖片描述

檢視/dev/disk/by-uuid/88f22c9e-9d5d-4c7e-8984-eba8446361e6是連結檔案指向/dev/sda2,這是主機的根目錄檔案系統。 
這裡寫圖片描述

container中的volume

容器啟動:docker run -i -v cvol1:/data --volume-driver=convoy ubuntu:latest /bin/bash 。將volume: dockervol掛載到容器目錄/data
容器內看到的掛載資訊:
  • 1
  • 2
  • 3

這裡寫圖片描述
此時掛載卷資訊: 
這裡寫圖片描述

Docker Volume Plugin

docker volume plugin框架

docker volume框架

docker daemon對volume的管理

docker daemon中的volume 
如上圖,docker daemon結構中有個成員volumes,型別是VolumeStore型別,包含一組管理volume的函式:Create、Remove、List、Get、Refs …。通過兩個變數,管理container和volume的關係。

names : map結構,key是volume的name,value是實現Volume介面的結構物件。儲存該daemon內所有的volume。 
refs : map結構,key是volume的name,value是string陣列儲存引用該volume的container id。 
docker daemon通過volumes變數,就可以管理所有的volume,提供如下命令: 
這裡寫圖片描述

docker volume 管理

基於本地檔案系統的volume框架

① 基於本地檔案系統的volume 
可以在執行docker create或docker run時,通過-v引數將主機的目錄作為容器的資料卷。這部分功能便是基於本地檔案系統的volume管理。上圖中藍色部分localVolume和Root。這兩個結構就是對主機目錄和檔案進行管理,具體的對應關係如下圖: 
這裡寫圖片描述 
從上圖可以看出,基於本地檔案系統的卷管理,Driver便是卷的根目錄/var/lib/docker/volumes。一個卷就是根目錄下的一個子目錄。

② 適配plugin的Volume 
docker為了支援第三方儲存方案,在1.8版本引入volume plugin機制,volumeAdapter和volumeDriverAdapter分別實現了介面Volume和Driver介面,用於表示由plugin提供的volume和plugin driver。在下一小節詳細描述。 
上圖中,全域性變數drivers儲存了所有註冊到docker daemon的Driver。docker daemon需要對volume進行管理操作時,通過GetDriver函式從drivers變數中獲取指定名稱的Driver,通過Driver可以通過Create,Remove,List,Get對Driver中volume進行管理。通過Get函式獲取Volume結構,可以對捲進行管理操作:Name,DriverName,Path,Mount,Unmount。

docker plugin 實現原理

volume plugin實現原理
① docker plugin機制 
上一節已經說過docker針對volume plugin實現了兩個適配型別volumeDriverAdapter和volumeAdapter。 
volumeDriverAdapter : 實現Driver介面,用於抽象各種plugin的驅動,該型別可以適配所有符合規範的volume plugin,對plugin進行管理。 
volumeAdapter : 實現Volume介面,用於抽象所有plugin提供的volume,該型別可以適配所有符合規範的volume plugin提供的型別,對volume進行管理。 
通過抽象,對於plugin和其提供的volume,docker daemon結構和container結構使用上述兩個適配型別,對plugin和volume進行管理和使用。

上述兩個型別都有一個volumeDriverProxy結構變數proxy,用於與plugin進行通訊。volumeDriverProxy結構實現了與plugin通訊的介面volumeDriver,提供Create、Remove、Path、Mount、Unmount、List、Get介面與通訊。volumeDriverProxy結構的client變數,使用這個變數與Plugin Daemon進行通訊。client變數是Plugin結構中的Client變數是Client結構型別,包含了http.Client型別物件。 
上圖左下方,plugins結構型別的全域性變數storage儲存所有被docker daemon發現的Plugin結構,Plugin結構代表外部外掛。

② docker plugin的發現過程 
docker daemon通過unix域套接字與plugin daemon進行通訊。所以plugin需要讓docker daemon知道plugin的unix域套接字檔案的路徑。在執行命令:docker run … -v volumename:/data –volume-driver=convoy。

plugin發現步驟: 
* docker daemon首先會在/run/docker/plugins搜尋對應的套接字檔案,套接字檔名必須和VolumeDriver名一致,如上述命令,便是搜尋convoy.sock。 
* 如果上一步搜尋不到,則到/etc/docker/plugins和/usr/lib/docker/plugins兩個目錄搜尋spec或json檔案。檔案中指定套接字檔案的URL。如:unix:///var/run/convoy/convoy.sock 。 
* 根據前面兩步發現的unix域套接字URL,構建Plugin物件,並將新建物件加入到全域性變數storage的plugins欄位中。

③ docker volume plugin的使用 
執行docker run命令時,指定引數–volume-driver=convoy。docker daemon會先從storage.plugins中尋找Plugin結構,如果沒有找到,就發起②的發現流程。找到則直接使用Client構建volumeDriverProxy。

④ docker daemon與plugin daemon通訊的API 
前面已經提到過,docker daemon和plugin daemon基於unix域套接字,使用Restful API進行通訊,下面是詳細的API: 
Plugin.Activate : 傳送一個請求到Plugin,plugin返回其型別,如convoy就返回VolumeDriver。相當於Docker和Plugin daemon直接的連線建立的握手報文。 
VolumeDriver.Create : 建立一個卷,Docker會發送卷名稱和引數傳送給外掛,卷外掛會根據Docker傳送過來的引數建立一個卷,並和這個卷名稱關聯。 
VolumeDriver.Mount : 掛載一個捲到本機,Docker會把卷名稱和引數傳送給引數。外掛會返回一個本地路徑給Docker,這個路徑就是卷所在的位置。Docker在建立容器的時候,會將這個路徑掛載到容器中。 
VolumeDriver.Path : 一個卷建立成功後,Docker會呼叫Path API來獲取這個卷的路徑,隨後Docker通過呼叫Mount API,讓外掛將這個卷掛載到本機。 
VolumeDriver.Unmount : 當容器退出時,Docker daemon會發送Umount API給外掛,通知外掛這個卷不再被使用,外掛可以對該卷做些清理工作(比如引用計數減一,不同的外掛行為不同)。 
VolumeDriver.Remove : 刪掉特定的卷時呼叫,當執行”docker rm -v”命令時,Docker會呼叫該API傳送請求給外掛。 
VolumeDriver.List : 執行docker volume ls命令時,會向plugin傳送該請求,獲取volume list。 
VolumeDriver.Get : 獲取plugin volume的詳細資訊。

自定義volume plugin

為了方便實現volume plugin,docker提供go-plugins-helper包,提供基礎的功能,僅僅需要實現一個介面volume.Driver,並啟動http server便可。 
這裡寫圖片描述 
例子:GlusterFS就是使用這個包,基於glusterfs提供volume。docker-volume-glusterfs


相關推薦

探索docker儲存窺探dockervolume plugin內幕

重構前言 本來想後續一篇文章專門寫docker volume plugin。這篇可以簡單粗暴的拉通docker的程式碼。之前看《Docker容器和容器雲》感覺原理解析部分沒有進一步深入到volume plugin的層次。本想以此作為第3篇的主要內容。最近看了一下新出

探索docker儲存docker的映象儲存與Overlayfs

docker中的映象儲存 docker中映象的概念其實就是一組只讀目錄。每一個目錄是一個layer,多個layer按照一定的順序組成一個stack。在容器建立時,docker增加在stack之上一個thin和writable layer,如下圖 基

Vue實戰Vue-cli全面詳解及進階操作。

image 腳本 js基礎 這一 命令執行 bsp row 編譯 服務器 全面的Vue-cli學習,這一篇就夠了! 一、下載 使用vue-cli前,需先安裝node.js,node的安裝就不贅述,不過在此需要註意: 1. node版本需在4.x以上,首推6.x以上版本

SSH進階Struts + Spring + Hibernate 進階開端(

height 一段 ioc 效率 陽光大道 面向對象的思想 text ase 們的 Long Long ago。就聽說過SSH。起初還以為是一個東東,詳細內容更是不詳,總認為高端大氣上檔次,經過學習之後才發現,不不過高大上,更是低調奢華有內涵,經過一段時間的

SSH進階Hibernate基本原理(

      在開始學Hibernate之前,一直就有人說:Hibernate並不難,無非是對JDBC進一步封裝。一句不難,難道是真的不難還是眼高手低?       如果只是停留在使用的層面上,我相信什

javascript面向物件讓我們起來坦克大戰吧01

提問 不知道大家發現沒有,執行時候瀏覽器或者電腦會變得很卡哦。根據我們之前的學習,你知道是什麼原因導致的嗎? 若是各位有興趣,請你回答卡的原因,並提出優化方案。  前言 PS 各位要看效果還是使用ff或者google吧,ie7以下好像有問題。 最近大家都在坦克大戰,

SSH進階Hibernate對映——多對單向關聯對映(四)

【SSH進階之路】Hibernate基本原理(一) ,小編介紹了Hibernate的基本原理以及它的核心,採用物件化的思維操作關係型資料庫。 【SSH進階之路】Hibernate搭建開發環境+簡單例項

SSH進階Hibernate映射——一對一單向關聯映射(五)

技術 iyu 標識 tails for sso 3.0 sdn 例如 【SSH進階之路】Hibernate基本原理(一) ,小編介紹了Hibernate的基本原理以及它的核心,採用對象化的思維操作關系型數據庫。 【SSH進階之路】Hibernate搭建開發環境+簡單實例

SSH進階Hibernate基本映射(三)

tor res 主動 tran clas oid 支持包 lose 包括 【SSH進階之路】Hibernate基本原理(一) ,小編介紹了Hibernate的基本原理以及它的核心。採用對象化的思維操作關系型數據庫。 【SSH進階之路】Hibernate搭建開發環境+簡單

SSH進階Struts基本原理 + 實現簡單登錄(二)

target doctype 掌握 pack insert enter snippet file manage 上面博文,主要簡單的介紹了一下SSH的基本概念,比較宏觀。作為剛開始學習的人可以有一個總體上的認識,個人覺得對學習有非常好的輔助功能,它不不過

Docker 學習

Docker: 啟動docker:service docker start 搜尋映象:docker search centos 獲取映象:docker pull centos 檢視映象:docker images 刪除映象:docker rmi 啟動容器 dock

SSH進階Hibernate基本對映(三)

【SSH進階之路】Hibernate基本原理(一) ,小編介紹了Hibernate的基本原理以及它的核心,採用物件化的思維操作關係型資料庫。 【SSH進階之路】Hibernate搭建開發環境+簡單例項

1>test.obj : error LNK2005: _main 已經在 main.obj 定義c的學習

下決心要在空餘時間學習C語言,從今天開始。 遇到的一個小問題,查詢資料結果如下。 造成LNK2005錯誤主要有以下幾種情況: 1.重複定義全域性變數。可能存在兩種情況: A、對於一些初學程式設計的程式設計師,有時候會以為需要使用全域性變數的地方就可

GOF設計模式-- Factory

自從開始工作,就感覺精力相比在大學時有很大幅度的下降。大二那一年精力最旺盛,自從大二結束開始工作到現在,兩年時間,似乎精力都已經不受自己控制了。如果對一些技術研究工作不是很感興趣,下班之後基本上到晚上10點左右就想睡覺。工作兩年加上大二的一年,一直到現在都堅持每天必須有新的

SSH進階Struts基本原理 + 實現簡單登入(二)

      上面博文,主要簡單的介紹了一下SSH的基本概念,比較巨集觀,作為初學者能夠有一個整體上的認識,個人認為對學習有很好的輔助功能,它不僅僅是一個“瞭望塔”,更是檢驗是否真正掌握所有內容的一個前

我的區塊鏈- go實現區塊鏈常見的各類演算法

咳咳,為什麼要出這一篇文章呢?首先,這段時間本人在找工作,然後被問到了各類演算法的底層細節,有些確實很懵逼。這裡做個總結,也順便給大家歸納歸納一下! 上主題: 橢圓曲線加密: 我們先來說一說最常用的 ECC 吧,ECC 就是 Elliptic Curve Crypt

SSH進階Spring的IOC逐層深入——依賴注入的兩種實現型別(四)

        上篇博文,我們介紹了為什麼使用IOC容器,和IOC的設計思想以及IOC容器的優缺點,並且給大家轉載了一篇介紹IOC原理的博文,我們這篇主要給大家依賴注入的兩種方式,以及他們的優缺點。

SSH進階Spring的IOC逐層深入——Spring的IOC原理[通俗解釋一下](三)

1. IoC理論的背景 我們都知道,在採用面向物件方法設計的軟體系統中,它的底層實現都是由N個物件組成的,所有的物件通過彼此的合作,最終實現系統的業務邏輯。 圖1:軟體系統中耦合的物件 如果我們開啟機械式手錶的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針

GOF設計模式-- Singleton

之前一直徘徊第一篇該寫哪一種設計模式,最後決定還是以Singleton模式開始吧。之所以以它開始,原因在我於個人認為,相對來說它在設計上比較單一,比較簡單一些。在通常情況下,它是最容易理解的。同樣也正因為它容易理解,細節才更值得注意,越是簡單的東西,往往會被我們忽略一些細節。

Python高階工程師入門+進階+實戰+爬蟲+資料分析整套教程

基礎入門篇 課程介紹: Python是一種解釋型的程式語言,所有解釋型語言的特點就是快,同時資料型別轉換靈活,指令碼化開發快速。通常在Linux系統上執行,因為支援多程序,windows不支援多程序。網際網路公司應用較為普遍,而且通常與Mysql資料搭配使用。希望同學