精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Docker使用OpenStack Cinder持久化volume原理分析及實踐

開發 開發工具 云計算 OpenStack
Docker容器本身是無狀態的,意味著容器退出后不會保存任何數據。但實際使用場景,肯定是需要保存業務數據的,Docker通過volume實現數據的持久化存儲以及共享。

 1 背景知識

1.1 OpenStack Cinder簡介

OpenStack Cinder為OpenStack提供塊存儲服務,其功能類似AWS的EBS服務,目前使用最多的是為OpenStack Nova虛擬機提供虛擬硬盤功能,即把volume掛載到虛擬機中,作為附加彈性硬盤使用,關于OpenStack Cinder volume掛載到虛擬機的過程分析可以參考之前寫的博客OpenStack虛擬機掛載數據卷過程分析,這篇博客也是了解本文內容的基礎。

[[207107]]

但是,OpenStack Cinder不僅僅是為Nova虛擬機提供云硬盤功能,事實上,Cinder并不關心是誰在消費它的volume,除了虛擬機,還有可能是物理機和容器。Cinder volume掛載到物理機前面已經介紹過,可以參考OpenStack中那些很少見但很有用的操作。Cinder volume掛載到虛擬機以及物理機都介紹過了,剩下最后一個內容,Cinder volume如何掛載到Docker容器中呢,本文接下來將詳細介紹并通過兩個driver實例實踐。

1.2 Docker volume簡介

我們知道Docker容器本身是無狀態的,意味著容器退出后不會保存任何數據。但實際使用場景,肯定是需要保存業務數據的,Docker通過volume實現數據的持久化存儲以及共享。

默認情況下,Docker會使用本地目錄作為容器的volume掛載到容器實例指定的路徑。用戶可以指定已經存在的路徑作為Docker volume,如下:

  1. mkdir data 
  2. docker run -t -i --rm -v `pwd`/data:/data busybox 

以上把本地data目錄掛載到容器/data路徑中,注意源目錄路徑必須使用絕對路徑,否則Docker會當作volume name。

你也可以不指定本地路徑,此時Docker會自動創建一個新的空目錄作為Docker volume:

  1. docker run -t -i --rm -v /data busybox 

可以使用docker volume ls查看創建的volume:

  1. $ docker volume ls 
  2. DRIVER              VOLUME NAME 
  3. local               0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788 

通過inspect子命令查看源路徑path:

  1. $ docker volume inspect 0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788 
  2.     { 
  3.         "CreatedAt""2017-09-30T17:21:56+08:00"
  4.         "Driver""local"
  5.         "Labels"null
  6.         "Mountpoint""/var/lib/docker/volumes/0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788/_data"
  7.         "Name""0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788"
  8.         "Options": {}, 
  9.         "Scope""local" 
  10.     } 

從以上輸出的結果可看出本地源目錄為/var/lib/docker/volumes/0e8d4d3936ec3b84c2ee4db388f45cbe5c84194d89d69be6b7a616fbdf1ea788/_data,這個目錄是Docker自動創建的。

由此我們也得出結論,Docker創建的volume只能用于當前宿主機的容器使用,不能掛載到其它宿主機的容器中,這種情況下只能運行些無狀態服務,對于需要滿足HA的有狀態服務,則需要使用分布式共享volume持久化數據,保證宿主機掛了后,容器能夠遷移到另一臺宿主機中。而Docker本身并沒有提供分布式共享存儲方案,而是通過插件(plugin)機制實現與第三方存儲系統對接集成,下節我們詳細介紹。

1.3 Docker volume plugin介紹

前面提到Docker本身并沒有提供分布式共享volume方案實現,而是提供了一種靈活的插件機制,通過插件能夠集成第三方的分布式共享系統,用戶只需要實現plugin driver的接口就可以對接自己的任何存儲系統。如當前非常流行的開源分布式存儲系統Ceph、AWS EBS、OpenStack Cinder等,這些外部存儲系統我們稱為Provider。

值得一提的是,官方在volume plugin協議文檔中強調:

  • If a plugin registers itself as a VolumeDriver when activated, it must provide the Docker Daemon with writeable paths on the host filesystem.

這句話的理解就是說,Docker不能直接讀寫外部存儲系統,而必須把存儲系統掛載到宿主機的本地文件系統中,Docker當作本地目錄掛載到容器中,換句話說,只要外部存儲設備能夠掛載到本地文件系統就可以作為Docker的volume。比如對于ceph rbd,需要先map到本地,并掛載到宿主機指定的路徑中,這個路徑稱為path。這里和虛擬機不一樣,rbd掛載到虛擬機,QEMU能夠直接通過rbd協議讀寫,不需要map到本地。

我們要想了解Docker掛載分布式存儲系統的原理,首先需要了解下官方定義的plugin協議接口:

  • create: 創建一個volume。
  • remove: 刪除一個volume。
  • mount: 掛載一個volume到容器中。
  • umount: 從容器中卸載一個volume。
  • get/list: 獲取volume信息。

以上create和remove都比較簡單,最為核心的兩個接口為mount和umount,不同的存儲系統,接口實現不一樣,我們這里只關心Cinder接口的實現。在此之前我沒有過多研究,不妨我們就用前面了解的知識大膽猜想下Docker使用Cinder volume的實現原理。

1.4 Docker使用Cinder volume原理猜想

前面我們介紹了Docker plugin接口,現在假設我們需要對接OpenStack Cinder,Cinder存儲后端(backend)使用LVM,猜測Docker plugin接口實現如下:

  • create: 直接調用Cinder API創建一個volume。
  • remote: 直接調用Cinder API刪除一個volume。
  • get/list: 直接調用Cinder API獲取volume列表。
  • mount: 前面提到Docker volume必須先掛載到本地,而這不正是恰好對應Cinder的local-attach么,具體內容可以參考OpenStack中那些很少見但很有用的操作。local attach到本地設備后,如果塊設備沒有安裝文件系統,則mount操作還需要執行文件系統格式化。創建完文件系統后,只需要mount到宿主機文件系統就可以了,Docker并不關心底層到底是什么存儲系統,它只是把它當作宿主機的一個目錄,剩下的工作就和Docker掛載本地目錄一樣了。
  • umount: 不需要解釋,已經非常明了,只需要從本地文件系統umount,然后從本地設備detach。

目前Docker掛載Cinder volume的方案還挺多的,如:

  • docker cinder driver: Docker Volume Plugin to enable consumption of OpenStack-Cinder Block Storage with containers.
  • fuxi: Enable Docker container to use Cinder volume and Manila share.
  • REX-Ray:storage management solution designed to support container runtimes such as Docker and Mesos.
  • Flocker: Flocker is an open-source container data volume orchestrator for your Dockerized applications.

以上原理只是我們的猜想,猜想是不是成立,我們接下來通過以上方案研究實踐下即可驗證。

2 docker cinder driver實踐

2.1 docker cinder driver簡介

docker-cinder-driver是由john griffith開發的,實現了Docker掛載Cinder卷Driver。作者還寫了篇專門的博客介紹Cinder - Block Storage for things other than Nova,也可以參考作者于OpenStack Days East 2016的分享pptslides: Consuming Cinder from Docker以及2016年奧斯汀分享視頻cinder and docker like peanut butter and chocolate

2.2 環境準備

實驗之前本人已經使用DevStack工具部署了一個allinone OpenStack測試環境,代碼基于最新的master分支,對應Cinder commit為2b58f2bb04c229c738b5cc806575ed3503fd1bfe。 Cinder使用LVM后端存儲(backend),配置如下:

  1. [lvmdriver-1] 
  2. image_volume_cache_enabled = True 
  3. volume_clear = zero 
  4. lvm_type = auto 
  5. iscsi_helper = tgtadm 
  6. volume_group = stack-volumes-lvmdriver-1 
  7. volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver 
  8. volume_backend_name = lvmdriver-1 

后續操作都是在這個DevStack環境中進行,不再強調。

docker cinder driver文檔中說可以直接通過install.sh腳本下載:

  1. curl -sSl https://raw.githubusercontent.com/j-griffith/cinder-docker-driver/master/install.sh | sh 

但這樣下載的可能不是最新代碼編譯的(親測有坑),為了使用最新的版本,我們只能手動編譯,首先需要安裝go開發環境,關于go語言開發環境可以參考官方安裝文檔。

ubuntu可以直接使用apt-get安裝:

  1. sudo apt-get install golang-go 

下載cinder-docker-driver源碼到本地:

  1. git clone https://github.com/j-griffith/cinder-docker-driver 

使用go build直接編譯:

  1. cd cinder-docker-driver 
  2. mkdir -p vendor/src 
  3. ln -s `pwd`/vendor/golang.org/ vendor/src 
  4. ln -s `pwd`/vendor/github.com vendor/src 
  5. export GOPATH=`pwd`/vendor 
  6. go build 

創建配置文件,主要包含Cinder的認證信息:

  1. mkdir -p /var/lib/cinder/dockerdriver 
  2. cat >/var/lib/cinder/dockerdriver/config.json <<EOF 
  3.   "Endpoint""http://10.0.2.15/identity/v3"
  4.   "Username""admin"
  5.   "Password""nomoresecret"
  6.   "TenantID""ae21d957967d4df0865411f0389ed7e8"
  7.   "DomainName""Default"
  8.   "Region""RegionOne" 
  9. EOF 

其中Endpoint為認證URL,注意包含版本/v3,且必須包含DomainName配置項。

配置完成后就可以直接運行cinder-docker-driver服務了:

  1. nohup ./cinder-docker-driver &  
  2. tailf ./nohup 

2.3 功能驗證

使用docker創建一個volume,如下:

  1. root@devstack:~# docker volume create -d cinder --name int32bit-test-1 -o size=2 
  2. int32bit-test-1 
  3. root@devstack:~# docker volume ls 
  4. DRIVER              VOLUME NAME 
  5. cinder              int32bit-test-1 

啟動一個容器并掛載int32bit-test-1:

  1. root@devstack:~# docker run -t -i --rm -v int32bit-test-1:/int32bit-test-1 busybox 
  2. / # cd /int32bit-test-1/ 
  3. /int32bit-test-1 # ls 
  4. lost+found 
  5. /int32bit-test-1 # echo "HelloWorld" >hello.txt 
  6. /int32bit-test-1 # ls 
  7. hello.txt   lost+found 
  8. /int32bit-test-1 # 

以上我們掛載剛剛創建的volume到/int32bit-test-1中,并寫了HelloWorld到hello.txt文件中。

啟動容器時cinder-docker-driver日志如下:

  1. time="2017-09-29T21:29:44+08:00" level=debug msg="Found Volume ID: 58837c2b-af79-4f89-97ea-40e2622d2c52" 
  2. time="2017-09-29T21:29:44+08:00" level=debug msg="Gather up initiator IQNs..." 
  3. time="2017-09-29T21:29:44+08:00" level=debug msg="Found the following iqns: [iqn.1993-08.org.debian:01:19a8a9ca754f]" 
  4. time="2017-09-29T21:29:44+08:00" level=debug msg="Value of IPs is=[127.0.0.1/8 10.0.2.15/24 192.168.99.101/24 192.168.122.1/24 172.17.0.1/16 ::1/128 fe80::a00:27ff:fe94:2f20/64 fe80::a00:27ff:fe69:2326/64 fe80::42:bcff:fee4:89ac/64]\n" 
  5. time="2017-09-29T21:29:44+08:00" level=debug msg="Issue InitializeConnection..." 
  6. time="2017-09-29T21:29:47+08:00" level=debug msg="Create the node entry using args:  [-m node -T iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52 -p 10.0.2.15:3260]" 
  7. time="2017-09-29T21:29:47+08:00" level=debug msg="Update username to: 36eDQkERhAAKXGi8CMFC" 
  8. time="2017-09-29T21:29:47+08:00" level=debug msg="Update password to: GLFkwC6eV8abbtk8" 
  9. time="2017-09-29T21:29:48+08:00" level=info msg="Logged into iSCSI target without error: [-m node -T iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52 -p 10.0.2.15:3260 --login]" 
  10. time="2017-09-29T21:29:48+08:00" level=info msg="Waiting for path" 
  11. time="2017-09-29T21:29:49+08:00" level=debug msg="path found: /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1" 
  12. time="2017-09-29T21:29:49+08:00" level=debug msg="Begin utils.getDeviceFileFromIscsiPath: /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1" 
  13. time="2017-09-29T21:29:49+08:00" level=debug msg="Found device: [lrwxrwxrwx 1 root root 9 Sep 29 21:29 /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1 ->  sdd\n]" 
  14. time="2017-09-29T21:29:49+08:00" level=debug msg="using base of: /dev/sdd" 
  15. time="2017-09-29T21:29:49+08:00" level=debug msg="Attached volume at (path, devfile): /dev/disk/by-path/ip-10.0.2.15:3260-iscsi-iqn.2010-10.org.openstack:volume-58837c2b-af79-4f89-97ea-40e2622d2c52-lun-1, /dev/sdd" 
  16. time="2017-09-29T21:29:49+08:00" level=debug msg="iSCSI connection done" 
  17. time="2017-09-29T21:29:49+08:00" level=debug msg="Begin utils.GetFSType: /dev/sdd" 
  18. time="2017-09-29T21:29:49+08:00" level=debug msg="Formatting device" 
  19. time="2017-09-29T21:29:49+08:00" level=debug msg="Begin utils.FormatVolume: /dev/sdd, ext4" 
  20. time="2017-09-29T21:29:49+08:00" level=debug msg="Perform mkfs.ext4 on device: /dev/sdd" 
  21. time="2017-09-29T21:29:50+08:00" level=debug msg="Result of mkfs cmd: mke2fs 1.42.13 (17-May-2015)\nCreating filesystem with 524288 4k blocks and 131072 inodes\nFilesystem UUID: 02318688-7448-4d25-98dd-0527a2bd9733 
  22. Superblock backups stored on blocks:  
  23.     32768, 98304, 163840, 229376, 294912 
  24.     Allocating group tables: 0/16 done                             
  25.     Writing inode tables:  0/16 done                             
  26.     Creating journal (16384 blocks): done 
  27.     Writing superblocks and filesystem accounting information:  0/16 done" 
  28. time="2017-09-29T21:29:50+08:00" level=debug msg="Begin utils.Mount device: /dev/sdd on: /var/lib/cinder/mount/int32bit-test-1" 
  29. time="2017-09-29T21:29:50+08:00" level=debug msg="Response from mount /dev/sdd at /var/lib/cinder/mount/int32bit-test-1: " 
  30. time="2017-09-29T21:29:50+08:00" level=debug msg="Call gophercloud Attach..." 
  31. time="2017-09-29T21:29:50+08:00" level=debug msg="Attach results: {ErrResult:{Result:{Body:<nil> Header:map[] Err:<nil>}}}" 

從日志中可以看出掛載volume本質就是通過iscsi把volume attach到本地(local attach),格式化為ext4文件系統,然后掛載到宿主機/var/lib/cinder/mount目錄中,與我們猜想過程基本一致。

可以通過lsblk確認:

  1. root@devstack:~/cinder-docker-driver# lsblk -s | grep int32bit-test  
  2. sdd 8:48 0 2G 0 disk /var/lib/cinder/mount/int32bit-test-1 

從docker容器實例中退出,此時會自動把volume從本地detach。

我們使用cinder把創建的卷手動attach到本地并掛載,關于Cinder的local attach,可參考OpenStack中那些很少見但很有用的操作。

  1. root@devstack:~# cinder list 
  2. +--------------------------------------+-----------+-----------------+------+-------------+----------+-------------+ 
  3. | ID                                   | Status    | Name            | Size | Volume Type | Bootable | Attached to | 
  4. +--------------------------------------+-----------+-----------------+------+-------------+----------+-------------+ 
  5. | 58837c2b-af79-4f89-97ea-40e2622d2c52 | available | int32bit-test-1 | 2    | lvmdriver-1 | false    |             | 
  6. +--------------------------------------+-----------+-----------------+------+-------------+----------+-------------+ 
  7. root@devstack:~# cinder local-attach 58837c2b-af79-4f89-97ea-40e2622d2c52 
  8. +----------+-----------------------------------+ 
  9. | Property | Value                             | 
  10. +----------+-----------------------------------+ 
  11. | path     | /dev/sdd                          | 
  12. | scsi_wwn | 360000000000000000e00000000010001 | 
  13. | type     | block                             | 
  14. +----------+-----------------------------------+ 
  15. root@devstack:~# mount /dev/sdd /mnt 

查看前面我們寫的文件:

  1. root@devstack:~# cat /mnt/hello.txt 
  2. HelloWorld 

可見輸出了我們通過容器寫的HelloWorld。

通過docker cinder driver基本驗證了我們之前的猜想是正確的。

3 fuxi

3.1 fuxi項目簡介

OpenStack fuxi是一個比較新的項目,最初是從magnum項目分離出來,于2016年2月26號被OpenStack社區接受成為社區項目,目前主要由華為主導開發,其目標是使Docker容器可以使用Cinder volume和Manila share作為持久化存儲卷。

3.2 環境準備

OpenStack環境仍然使用之前的DevStack環境,fuxi安裝過程如下。

首先安裝依賴的包,這些包其實DevStack基本都已經安裝完成了。

  1. sudo apt-get update 
  2. sudo apt-get install python-dev git libffi-dev libssl-dev gcc 
  3. sudo apt-get install open-iscsi 
  4. sudo apt-get install sysfsutils 

下載fuxi源碼并安裝:

  1. git clone https://github.com/openstack/fuxi.git 
  2. cd fuxi 
  3. sudo pip install -r requirements.txt 
  4. sudo python setup.py install 
  5. ln -s /lib/udev/scsi_id /usr/local/bin # for root 

使用generate_config_file_samples.sh生成配置文件模板,并拷貝到/etc/fuxi目錄下。

  1. ./tools/generate_config_file_samples.sh 
  2. sudo cp etc/fuxi.conf.sample /etc/fuxi/fuxi.conf 

修復配置文件,最終配置文件如下:

  1. root@devstack:~# cat /etc/fuxi/fuxi.conf  | grep -v '^#' | grep -v '^$' 
  2. [DEFAULT
  3. my_ip = 10.0.2.15 
  4. volume_providers = cinder 
  5. [cinder] 
  6. region_name = RegionOne 
  7. volume_connector = osbrick 
  8. fstype = ext4 
  9. auth_url = http://10.0.2.15/identity/v3 
  10. project_name = admin 
  11. project_domain_name = Default 
  12. username = admin 
  13. user_domain_name = Default 
  14. password = nomoresecret 
  15. [keystone] 
  16. [manila] 
  17. volume_connector = osbrick 
  18. auth_type = password 
  19. [nova] 

注意auth_url必須包含版本,如/v3。

啟動服務:

  1. fuxi-server --config-file /etc/fuxi/fuxi.conf 

3.3 功能驗證

使用Docker創建一個volume:

  1. $ docker volume create -d fuxi --name int32bit-test-fuxi 
  2. int32bit-test-fuxi 
  3. $ docker volume ls | grep int32bit-test-fuxi 
  4. fuxi                int32bit-test-fuxi 

掛載volume到Docker容器中:

  1. $ docker run -ti --rm -v int32bit-test-fuxi:/int32bit-test-fuxi busybox 
  2. / # cd /int32bit-test-fuxi/ 
  3. /int32bit-test-fuxi # ls 
  4. a           b           c           lost+found 

我們可以驗證volume其實是映射到本地路徑的:

  1. $ lsblk -Sf 
  2. NAME HCTL       TYPE VENDOR   MODEL             REV TRAN   NAME FSTYPE LABEL UUID                                 MOUNTPOINT 
  3. sda  2:0:0:0    disk ATA      VBOX HARDDISK    1.0  sata   sda 
  4. sdb  11:0:0:1   disk IET      VIRTUAL-DISK     0001 iscsi  sdb  ext4         d04b16a1-3392-41df-999f-e6c36b5d0cd6 /fuxi/data/cinder/int32bit-test-fuxi 
  5. sr0  1:0:0:0    rom  VBOX     CD-ROM           1.0  ata    sr0 

由此可見,fuxi首先把Volume attach到本地,并mount到指定路徑中,然后mount到Docker容器中,又和我們的猜想一致,接下來我們從源碼角度分析。

3.4 Docker使用fuxi掛載volume源碼分析

fuxi掛載是通過fuxi/volumeprovider/cinder.py模塊的Cinder類實現的,該類實現了provider.Provider接口,而該接口就是對應前面介紹的Docker volume plugin接口。我們主要研究其mount方法:

  1. t(self, docker_volume_name): 
  2.     cinder_volume, state = self._get_docker_volume(docker_volume_name) 
  3.     LOG.info("Get docker volume %(d_v)s %(vol)s with state %(st)s"
  4.              {'d_v': docker_volume_name, 'vol': cinder_volume, 
  5.               'st': state}) 
  6.  
  7.     connector = self._get_connector() 
  8.     if state == NOT_ATTACH: 
  9.         connector.connect_volume(cinder_volume) 
  10.     elif state == ATTACH_TO_OTHER: 
  11.         if cinder_volume.multiattach: 
  12.             connector.connect_volume(cinder_volume) 
  13.         else
  14.             msg = _("Volume {0} {1} is not shareable").format( 
  15.                 docker_volume_name, cinder_volume) 
  16.             raise exceptions.FuxiException(msg) 
  17.     elif state != ATTACH_TO_THIS: 
  18.         msg = _("Volume %(vol_name)s %(c_vol)s is not in correct state, " 
  19.                 "current state is %(state)s"
  20.         LOG.error(msg, {'vol_name': docker_volume_name, 
  21.                         'c_vol': cinder_volume, 
  22.                         'state': state}) 
  23.         raise exceptions.NotMatchedState() 

以上主要通過Cinder API獲取volume信息,檢查其attach情況:

  • 如果volume沒有attach,則直接attach。
  • 如果volume已經attach(in-use)到其它主機,則檢查其是否支持multiattach,如果支持多掛載,則直接掛載,否則拋出異常,掛載失敗。
  • 如果volume已經attach到當前主機,則說明已經掛載到本地了,但這不是我們所期望的,因此直接拋出異常。

假設前面都沒有問題,順利把volume attach到本地,則我們可以獲取映射到本地的虛擬設備名,接下來的代碼就是檢查該路徑是否就緒:

  1. link_path = connector.get_device_path(cinder_volume) 
  2.     if not os.path.exists(link_path): 
  3.         LOG.warning("Could not find device link file, " 
  4.                     "so rebuild it"
  5.         connector.disconnect_volume(cinder_volume) 
  6.         connector.connect_volume(cinder_volume) 
  7.  
  8.     devpath = os.path.realpath(link_path) 
  9.     if not devpath or not os.path.exists(devpath): 
  10.         msg = _("Can't find volume device path"
  11.         LOG.error(msg) 
  12.         raise exceptions.FuxiException(msg) 

如果前面順利獲取的volume到設備名,比如/dev/sdd,則最后的工作就是mount到本地文件系統了:

  1. mountpoint = self._get_mountpoint(docker_volume_name) 
  2.   self._create_mountpoint(mountpoint) 
  3.   fstype = cinder_volume.metadata.get('fstype', cinder_conf.fstype) 
  4.   mount.do_mount(devpath, mountpoint, fstype) 
  5.   return mountpoint 

其中mountpoint是掛載的目標目錄,其路徑為volume_dir + volume_type + volume_name,其中volume_dir通過配置文件配置,默認為/fuxi/data,volume_type這里為cinder,假設volume name為int32bit-test-volume,則掛載路徑為/fuxi/data/cinder/int32bit-test-volume。

create_mountpoint就是創建掛載目錄:

  1. (self, mountpoint): 
  2.     """Create mount point directory for Docker volume. 
  3.     :param mountpoint: The path of Docker volume. 
  4.     ""
  5.     try: 
  6.         if not os.path.exists(mountpoint) or not os.path.isdir(mountpoint): 
  7.             utils.execute('mkdir''-p''-m=755', mountpoint, 
  8.                           run_as_root=True
  9.             LOG.info("Create mountpoint %s successfully", mountpoint) 
  10.     except processutils.ProcessExecutionError as e: 
  11.         LOG.error("Error happened when create volume " 
  12.                   "directory. Error: %s", e) 

最后調用mount.do_mount,mount是fuxi實現的一個通用的mount庫,代碼位于fuxi/common/mount.py。

  1. (devpath, mountpoint, fstype): 
  2.     """Execute device mount operation. 
  3.  
  4.     :param devpath: The path of mount device. 
  5.     :param mountpoint: The path of mount point. 
  6.     :param fstype: The file system type. 
  7.     ""
  8.     try: 
  9.         if check_already_mounted(devpath, mountpoint): 
  10.             return 
  11.  
  12.         mounter = Mounter() 
  13.         mounter.mount(devpath, mountpoint, fstype) 
  14.     except exceptions.MountException: 
  15.         try: 
  16.             mounter.make_filesystem(devpath, fstype) 
  17.             mounter.mount(devpath, mountpoint, fstype) 
  18.         except exceptions.FuxiException as e: 
  19.             with excutils.save_and_reraise_exception(): 
  20.                 LOG.error(str(e)) 

該方法直接調用Mounter的mount方法,如果mount失敗,則重新創建格式化文件系統后再次掛載(第一次掛載時沒有安裝文件系統,因此mount必然失敗)。mount方法如下:

  1. (self, devpath, mountpoint, fstype=None): 
  2.     try: 
  3.         if fstype: 
  4.             utils.execute('mount''-t', fstype, devpath, mountpoint, 
  5.                           run_as_root=True
  6.         else
  7.             utils.execute('mount', devpath, mountpoint, 
  8.                           run_as_root=True
  9.     except processutils.ProcessExecutionError as e: 
  10.         msg = _("Unexpected error while mount block device. " 
  11.                 "Devpath: {0}, " 
  12.                 "Mountpoint: {1} " 
  13.                 "Error: {2}").format(devpath, mountpoint, e) 
  14.         raise exceptions.MountException(msg) 

由此我們通過研究源碼,再次驗證了我們之前的猜想是正確的。

4 REX-Ray

REX-Ray是一個EMC團隊領導的開源項目,為Docker、Mesos及其他容器運行環境提供持續的存儲訪問。其設計旨在囊括通用存儲、虛擬化和云平臺,提供高級的存儲功能。換句話說,REX-Ray進一步封裝,提供一個統一的為Docker提供volume的工具,整合了各種不同的provide,如Ceph、Cinder、EBS等。但遺憾的是,目前Docker掛載Cinder卷,Docker必須安裝在Nova虛擬機中,虛擬機還必須能夠和OpenStack管理網打通,參考Cinder: failed to attach volume while using cinder driver,因此實際使用場景有限,本文不再詳細介紹。

【本文是51CTO專欄作者“付廣平”的原創文章,如需轉載請通過51CTO獲得聯系】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2025-01-16 14:03:35

Redis

2017-04-17 15:48:15

Cinder備份實踐

2021-10-04 21:11:18

Redis混合持久化

2024-04-11 11:04:05

Redis

2020-07-16 08:39:18

服務狀態排錯

2019-10-16 16:33:41

Docker架構語言

2015-05-12 10:38:56

openstack k開源分析

2017-03-16 10:02:50

2020-02-18 16:14:33

RedisRDBAOF

2022-01-20 10:56:53

Webpack5持久化緩存

2023-01-18 08:32:13

2022-07-11 15:35:42

云計算銀行本文主要從銀行實際應

2009-09-29 16:46:01

創建Hibernate

2022-02-16 09:01:13

iOSS開發XCode

2015-02-06 09:39:16

OpenStack j云主機創建

2019-12-27 13:50:04

JavaAPI代碼

2018-04-09 12:25:11

2022-09-28 08:00:43

MinioS3接口

2023-08-17 16:17:00

Docker前端

2021-08-09 11:15:28

MybatisJavaSpring
點贊
收藏

51CTO技術棧公眾號

国产欧美婷婷中文| 精品捆绑美女sm三区| 日韩福利二区| av老司机久久| 99国产成+人+综合+亚洲欧美| 亚洲精品色婷婷福利天堂| 一级做a免费视频| 爱情岛论坛亚洲品质自拍视频网站| 99riav久久精品riav| 国产欧美一区二区三区在线| 久久网一区二区| 波多野结衣在线播放一区| 日韩免费高清av| 99草草国产熟女视频在线| 91亚洲天堂| 国产亚洲欧美一级| 成人精品水蜜桃| 狠狠躁夜夜躁人人爽视频| 黑丝一区二区| 色婷婷综合成人av| 熟妇人妻久久中文字幕| 电影中文字幕一区二区| 色狠狠桃花综合| 国产欧美日韩网站| 国产最新在线| 麻豆成全视频免费观看在线看| 亚洲美女少妇无套啪啪呻吟| 精品国产一区二区三区久久狼5月| 性囗交免费视频观看| 国产一区二区三区| 欧美日韩日日夜夜| 日本www高清视频| 欧美aa在线观看| 亚洲一区二区三区激情| 国产高清精品软男同| 不卡在线视频| 久久精品一区二区三区不卡| 精品欧美一区二区三区久久久 | 91福利入口| 中文字字幕在线中文乱码| 国产农村妇女精品一二区| 欧美黑人视频一区| 九九视频免费看| 亚洲区综合中文字幕日日| 色偷偷9999www| 99在线视频免费| 国产精品探花在线观看| 日韩精品视频三区| 北岛玲一区二区| 国偷自产视频一区二区久| 精品国产制服丝袜高跟| 国偷自产av一区二区三区麻豆| 四虎永久精品在线| 欧美日本在线观看| 在线观看免费av网址| 欧洲亚洲精品| 555夜色666亚洲国产免| 欧美性受xxxxxx黑人xyx性爽| 欧美激情啪啪| 8v天堂国产在线一区二区| 天天干天天色天天干| 成人污版视频| 欧美v亚洲v综合ⅴ国产v| 国偷自产av一区二区三区麻豆| 777久久精品| 亚洲成人精品av| 欧美一区二区三区成人精品| 国产91一区| 最近2019年手机中文字幕| 免费精品在线视频| 亚洲小说区图片区| 欧美一区二区.| 小泽玛利亚一区二区三区视频| 日本中文在线一区| 95av在线视频| 秋霞网一区二区| 99re成人精品视频| 日产精品一线二线三线芒果| 一区二区三区视频在线观看视频| 中文字幕亚洲电影| 国产a级黄色大片| 激情aⅴ欧美一区二区欲海潮| 色综合中文字幕国产| 色播五月综合网| 99精品国产一区二区三区2021| 亚洲精品一区二区三区影院| 无码人妻精品一区二区中文| 婷婷激情图片久久| 韩国一区二区电影| 欧美另类高清videos的特点| 韩国理伦片一区二区三区在线播放 | 日韩精品免费一线在线观看| 免费看91的网站| 欧美在线网址| 国产成人精品国内自产拍免费看| 在线观看毛片av| 成人av电影免费观看| 欧美在线3区| 亚洲丝袜一区| 欧美怡红院视频| 人妻换人妻a片爽麻豆| 欧美丝袜一区| 午夜精品福利电影| 一本色道久久综合熟妇| 99re热这里只有精品视频| 亚洲成人一区二区三区| 国产乱码在线| 欧美另类z0zxhd电影| 香蕉视频黄色在线观看| 久久久久久久久国产一区| 欧美性受xxxx黑人猛交| 国产99久一区二区三区a片| 久久人人爽爽爽人久久久| 成年丰满熟妇午夜免费视频| 日韩制服诱惑| 日韩精品免费在线视频观看| 欧美精品色哟哟| 男人操女人的视频在线观看欧美| 国产伦精品一区二区三区在线 | 538国产精品一区二区免费视频| 国产精品特级毛片一区二区三区| xfplay精品久久| 免费在线黄网站| 日日夜夜精品| 在线播放国产一区中文字幕剧情欧美| 日韩精品手机在线| 国产91丝袜在线播放0| 综合视频免费看| 韩日精品一区| 一区国产精品视频| 日韩视频在线观看一区| 成人h动漫精品一区二| 日本精品免费视频| 99精品视频在线免费播放| 在线看福利67194| 国产一区二区视频网站| 99麻豆久久久国产精品免费| 欧美日韩午夜爽爽| 国产精品日本一区二区三区在线| 日韩中文字幕视频在线| 91丨九色丨丰满| 国产精品人妖ts系列视频| 久久久精品麻豆| 国产欧美一区| 国产精品国产福利国产秒拍 | 佐佐木明希电影| 91福利在线尤物| 精品日韩av一区二区| 黄色片在线观看网站| 国产一区日韩二区欧美三区| 99亚洲精品视频| 国产日韩在线观看视频| 久久亚洲欧美日韩精品专区| 国产乱码精品一区二区三区精东| 日韩一区欧美一区| 日本一区二区三区在线免费观看| 中文字幕乱码亚洲无线精品一区 | 国产亚洲一卡2卡3卡4卡新区 | 久久久999精品免费| 91久久精品无码一区二区| 国产精品欧美一级免费| 午夜福利123| 亚洲国产二区| 免费中文日韩| 久久亚洲资源中文字| 久久精品国产96久久久香蕉| 国产黄色片网站| 午夜精品一区二区三区电影天堂| 成年人网站免费看| 蜜臀久久久久久久| 黄色成人在线免费观看| 日韩精品福利一区二区三区| 国产精品久久二区| 在线中文字幕电影| 日韩国产高清视频在线| 日本视频www色| 亚洲色图在线播放| 人妻av一区二区| 日韩电影免费一区| 视色,视色影院,视色影库,视色网| 91亚洲无吗| 国产91免费看片| 成人免费高清| 亚洲精品久久视频| 91福利免费视频| 亚洲www啪成人一区二区麻豆| 91网站免费视频| 国产一区二区在线观看免费| 女人天堂av手机在线| 久久国产精品亚洲人一区二区三区 | 免费看又黄又无码的网站| 国产一区二区三区四区二区| 亚洲综合国产精品| av2014天堂网| 九一精品国产| 92看片淫黄大片看国产片| cao在线视频| 中文字幕精品—区二区| 亚洲欧美激情国产综合久久久| 欧美日韩亚洲视频一区| 91制片厂在线| 91免费在线看| 日批视频在线看| 丝袜美腿亚洲综合| 国产在线观看欧美| 三上亚洲一区二区| 免费国产一区二区| 99精品在免费线中文字幕网站一区| 国产精品美女www爽爽爽视频| 成人性生交大片免费看网站| 日韩在线视频一区| 青青青草网站免费视频在线观看| 欧美一级电影网站| 中文字幕视频二区| 色婷婷久久久久swag精品| 久久久久久国产精品视频| 国产精品乱码妇女bbbb| theav精尽人亡av| 国产成人av福利| www.色欧美| 免费欧美在线视频| 国产精品免费成人| 99精品福利视频| avav在线播放| 99久久久久| 亚洲v欧美v另类v综合v日韩v| 国产毛片久久久| 成人高清在线观看| 精品麻豆剧传媒av国产九九九| 国产精品美女主播在线观看纯欲| 亚洲国产福利| 黄色成人在线网站| 国产亚洲二区| 99热这里有精品| 国产精自产拍久久久久久| 日本成人三级电影| 全亚洲最色的网站在线观看| 精精国产xxxx视频在线野外| 欧美激情一区二区三区在线视频观看| 黄色动漫在线观看| 色偷偷av一区二区三区| av在线天堂播放| 亚洲最新av在线网站| 欧美中文在线| 亚洲色图第三页| 青青草视频免费在线观看| 亚洲精品国产精品国自产观看浪潮| 亚洲国产精品久久人人爱潘金莲| 欧美精品v国产精品v日韩精品| 一级黄色大片免费| 欧美日韩精品一区二区三区蜜桃| 中文文字幕一区二区三三| 91国模大尺度私拍在线视频| 亚洲国产精品无码久久久| 日韩欧美中文字幕在线观看 | 欧洲色大大久久| 亚洲性猛交富婆| 欧美日韩一区成人| 国产精品久久久午夜夜伦鲁鲁| 欧美精品第1页| 亚洲成人中文字幕在线| 亚洲国产成人精品女人久久久 | 91麻豆精品国产91久久久平台| 亚洲黄色一区二区三区| 91久久电影| 欧美精品在欧美一区二区| 亚洲第一网站| 成人性做爰aaa片免费看不忠| 麻豆国产欧美一区二区三区| 亚洲女人天堂色在线7777| 在线视频欧美亚洲| 日韩一级精品视频在线观看| 欧美熟妇另类久久久久久不卡 | 91久久精品国产91久久| 日韩精品视频在线看| 精品久久精品久久| 欧美色蜜桃97| 欧美另类videosbestsex日本| 日韩视频一区| 杨幂毛片午夜性生毛片| 国产suv精品一区二区883| 国产精品一级黄片| 国产精品情趣视频| 久久午夜无码鲁丝片午夜精品| 欧美性猛交xxxx黑人| 国产又粗又猛又爽| 亚洲精品二三区| 幼a在线观看| 久久久人成影片一区二区三区| 欧美黄色网页| 亚洲已满18点击进入在线看片 | 国产成人精品免费看| 特大黑人巨人吊xxxx| √…a在线天堂一区| 日韩av一二三区| 欧美日韩免费高清一区色橹橹| 狠狠人妻久久久久久综合麻豆| 在线看日韩欧美| av今日在线| 91精品免费视频| 色棕色天天综合网| 免费看毛片的网址| 久久av资源网| 免费看污黄网站在线观看| 尤物在线观看一区| 特级西西444www大胆免费看| 亚洲成人激情在线| 国产cdts系列另类在线观看| 91av视频在线免费观看| 91精品国产色综合久久不卡粉嫩| 久久综合九色欧美狠狠| 欧美日韩综合| 日韩va在线观看| 日本一区二区久久| 日韩久久中文字幕| 亚洲成人亚洲激情| av黄色在线| 国产中文欧美精品| 欧美精品第一区| 老太脱裤让老头玩ⅹxxxx| 国产精品一区二区黑丝| 亚洲色图日韩精品| 色哟哟国产精品| 天堂网www中文在线| 久久久久久久久久久久久久久久久久av | 国产美女精品视频| 一区二区三区视频免费观看| av女优在线播放| 处破女av一区二区| 成人免费毛片东京热| 欧美精品第一页| 久久免费视频6| 国产主播精品| 色播五月激情五月| 中文字幕欧美区| а中文在线天堂| 一区二区亚洲精品国产| 欧美成人影院| 青青草国产精品| 久久男女视频| 99久久久无码国产精品性| 欧美色视频日本高清在线观看| 天天操天天操天天操| 69av视频在线播放| 日日天天久久| www.浪潮av.com| 久久久久久久免费视频了| 亚洲成熟少妇视频在线观看| 亚洲一级黄色av| 外国电影一区二区| 手机看片福利永久国产日韩| 日本美女视频一区二区| 久久久久久久久福利| 精品视频1区2区| 老司机精品视频在线观看6| 91在线免费网站| 国产综合色产| 亚洲av无码专区在线播放中文| 亚洲电影第三页| 婷婷五月综合激情| 日韩av理论片| 欧美丰满日韩| 激情av中文字幕| 欧美日韩国产丝袜另类| 免费在线黄色网址| 国产精品久久电影观看| 亚洲91中文字幕无线码三区| 一卡二卡三卡四卡五卡| 亚洲成人午夜电影| 免费一级在线观看| 国产精品专区h在线观看| 欧美a级片网站| yjizz视频| 91国在线观看| 羞羞网站在线免费观看| 激情久久av| 麻豆91小视频| 欧美日韩中文视频| 亚洲性视频网址| 网站一区二区| www.国产区| 亚洲黄色性网站| 精品乱码一区二区三四区视频 | 噜噜噜狠狠夜夜躁精品仙踪林| 日本韩国欧美在线观看| 欧美经典三级视频一区二区三区| 国产免费黄色片| 欧美在线一区二区视频| 偷偷www综合久久久久久久| 亚洲精品无码一区二区| 在线免费观看日本欧美| 在线三级电影| 视频一区二区三区在线观看| 国产精品系列在线播放| 狠狠人妻久久久久久综合| 久久中文字幕一区| 国产一区网站| 高清中文字幕mv的电影| 欧美日韩另类一区| 9i看片成人免费高清|