1. 程式人生 > 其它 >overlayfs儲存驅動的使用以及技術探究

overlayfs儲存驅動的使用以及技術探究

overlayfs儲存驅動的使用以及技術探究

1.overlayfs 基本概念

一種聯合檔案系統,設計簡單,速度更快。overlayfs在linux主機上只有兩層,一個目錄在下層,用來儲存映象(docker),另外一個目錄在上層,用來儲存容器資訊。在overlayfs中,底層的目錄叫做lowerdir,頂層的目錄稱之為upperdir,對外提供統一的檔案系統為merged。 當需要修改一個檔案時,使用CoW將檔案從只讀的Lower複製到可寫的Upper進行修改,結果也儲存在Upper層。在Docker中,底下的只讀層就是image,可寫層就是Container。

可以看到映象層和容器層可以儲存相同的檔案,容器層的檔案會覆蓋映象層的檔案

  • 在overlayfs中每個映象層都會在/var/lib/docker/overlay有對應的目錄,使用硬連結與底層資料進行關聯。

2. 優勢劣勢

  • 1.OverlayFS支援頁快取共享,多個容器訪問同一個檔案能共享一個頁快取,以此提高記憶體使用
  • 2.OverlayFS消耗inode,隨著映象和容器增加,inode會遇到瓶頸。Overlay2能解決這個問題。在Overlay下,為了解決inode問題,可以考慮將/var/lib/docker掛在單獨的檔案系統上,或者增加系統inode設定。

3. overlay中的讀寫

3.1 在容器中讀取檔案

  • (1)目標檔案不在容器層內,overlay會從映象層讀取檔案,此時,對容器效能的影響很小。
  • (2)目標檔案在容器層內,overlay直接從容器層讀取。
  • (3)目標檔案在容器層和映象層同時存在,overlay讀入容器層中的檔案,此時容器層的檔案會覆蓋映象層的檔案。

3.2 在容器中修改檔案

在容器中第一次修改檔案,此時檔案不在容器層中。overlay會把檔案從映象層複製到容器層,所有該檔案中的修改都儲存在容器層中。

注意:overlay工作檔案系統層(devicemapper工作再塊層面),因此複製檔案會複製整個檔案,因此在頻繁讀寫會很消耗資源

  • (1)只是在第一次修改檔案時,需要把檔案從映象層複製到容器層,後續操作都是在容器層中完成。
  • (2)overlayfs只有兩層,lowerdir和upperdir,因此在很深的目錄樹中,搜尋檔案會相對比較快

3.3 在容器中刪除檔案和目錄

在容器中刪除檔案時,overlay儲存驅動在容器層中新建一個without檔案,該檔案用語隱藏映象層中的目標檔案。在容器層刪除目錄時,overlay儲存驅動在容器層新建一個opaque目錄,該目錄用於隱藏映象層中的目標目錄。 需要明白的一點是,任何儲存驅動都不會刪除底層image中的目標檔案和目錄的。

3.4 overlayfs的原理測試

overlayfs掛載後系統檔案的page cache是全部共享的。

# mkdir low upper work
# ls
low  upper  work
# echo 'abs' > low/11.txt
# echo 'xuxuebiao' > upper/22.txt
# mkdir merged
# mount -t overlay overlay -olowerdir=./low,upperdir=./upper,workdir=./work ./merged
# ls
low  merged  upper  work
# cd merged/
# ls
11.txt  22.txt
# ll
total 8
-rw-r--r--. 1 root root  4 Mar 27 18:57 11.txt
-rw-r--r--. 1 root root 10 Mar 27 18:58 22.txt

# tree
.
├── low
│   └── 11.txt
├── merged
│   ├── 11.txt
│   └── 22.txt
├── upper
│   └── 22.txt
└── work
    └── work

5 directories, 4 files
可以看到,merged目錄中時low和upper目錄聯合的結果


分別修改檔案:
# cat 11.txt
abs
# cat 22.txt
xuxuebiao
# vim 11.txt
# cat 11.txt
Hello ,overlayfs!
# cat ../low/11.txt
abs
# cat ../upper/
11.txt   11.txt~  22.txt
# cat ../upper/11.txt
Hello ,overlayfs!
# cat ../upper/11.txt~
cat: ../upper/11.txt~: No such device or address
# cat ../upper/11.txt
11.txt   11.txt~
# cat ../upper/11.txt~
cat: ../upper/11.txt~: No such device or address

可以看到low目錄下的檔案沒有變化,但是upper裡面的檔案內容已經改變,並且有了一個11.txt~檔案


# ls -i ../upper/11.txt 11.txt
143902921 11.txt  143902921 ../upper/11.txt
可以看到upper和merged目錄中的兩個檔案11.txt的inode其實是一致的,其實是硬連結

# ls -i ../low/11.txt 11.txt
143902921 11.txt  143902918 ../low/11.txt
merged目錄檔案和low目錄檔案對比


刪除檔案測試:
# rm 11.txt
rm: remove regular file ‘11.txt’? y
# ls
ls: cannot access 11.txt: No such file or directory
ls: cannot access 11.txt~: No such file or directory
11.txt  11.txt~  22.txt

# cat ../upper/11.txt~
cat: ../upper/11.txt~: No such device or address
# ls -l ../upper/11.txt
c---------. 1 root root 0, 0 Mar 27 19:08 ../upper/11.txt

刪除檔案後發現檔案無法訪問,底層變成了一個大小為0,且沒有任何人有許可權的一個空檔案。
overlayfs用這種刪除標記的方式標識檔案被刪除,(如果upper中沒有該檔案的話,則底層low中的同名檔案又恢復出來顯示了,因此需要有這個空檔案來標識刪除,並且覆蓋底層的檔案)

4.overlayfs在docker中的使用

首先,overlayfs是在高版本的核心上才支援的儲存驅動,因此不管使用的官方核心,還是自己patch的核心,首先需要檢查overlayfs是否被載入

overlayfs

並且同樣重要的是,對於aufs和overlay的實現,用來讀取或執行共享庫的共享記憶體也在所有執行的容器之間共享,大大的減少了通用庫如’libc’的記憶體佔用。這是一個分層策略的巨大優勢,同時也是Docker的graphdriver是引擎中相當重要的一部分的原因之一。graphdriver的功能作用。

  • 1.檢查overlay是否被載入
檢視overlay是否被載入
$ lsmod | grep overlay
檢視核心是否支援overlay模組
$ modinfo overlayfs
載入核心模組
$ modprobe overlayfs
  • 2.docker啟動引數修改
檢測overlayfs釋放被識別,成功啟動後修改引數到預設的配置檔案中
$ docker daemon(dockerd) -s overlay(--storage-driver=overlay) 

修改配置檔案
$ cat /etc/sysconfig/docker.conf
DOCKER_OPTS="--storage-driver=overlay"

模擬配置:
other_args="-s overlay --graph=/export/lib/docker -H unix:///var/run/docker.sock --bip 10.0.0.1/24 -H 0.0.0.0:5256  --api-enable-cors=true"
  • 3.檢驗overlayfs是否成功啟動
$ sudo /etc/init.d/docker restart
成功啟動,檢視儲存資訊:
$ sudo docker info
Containers: 11
Images: 5
Server Version: 1.9.1
Storage Driver: overlay
 Backing Filesystem: extfs
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 2.6.32-431.el6.x86_64
Operating System: <unknown>
CPUs: 32
Total Memory: 126 GiB
Name: -----
ID: 2IER:NO5S:4NKX:ULDJ:THGQ:GBNR:NIN6:SCXG:SMFX:PG72:JAQF:GRZW

可用看到相關儲存驅動是overlay,檔案系統是extfs
  • 4.overlay在docker上面的使用

預設docker會將容器以及映象相關的檔案儲存在/var/lib/docker/overlay目錄下

sh-4.1# docker  images
REPOSITORY                        TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos6.8-sshd   latest              42c75e16533e        12 weeks ago        402 MB
sh-4.1# pwd  (這裡我們是配置了儲存路徑)
/export/lib/docker/overlay

sh-4.1# ll -t
total 28
drwx------ 4 root root 4096 Mar 31 10:37 8ab8690b0769d07cc0b546112cfc40068d99298ed7e1857272c98a522cede527
drwx------ 4 root root 4096 Mar 31 10:37 8ab8690b0769d07cc0b546112cfc40068d99298ed7e1857272c98a522cede527-init
drwx------ 3 root root 4096 Mar 31 10:35 42c75e16533e2ef46ffd22a21318d354b3f3e520709230e9848ebaca8f1f514e
drwx------ 3 root root 4096 Mar 31 10:35 b46ba152cc17054229bc0099e7fda8b34958d518ce687c0d378b4832c4d8c91e
drwx------ 3 root root 4096 Mar 31 10:35 9016bb11dc9b4a3ee23fbef484cf5b3c9b80491e87d67092febec45759baeb4f
drwx------ 3 root root 4096 Mar 31 10:35 ea80c789cb2b3bcc1d12b9b3226c8482a06f28e94a4a49f8e201b5e9cdbdf0cc
drwx------ 3 root root 4096 Mar 31 10:35 e444e2175366cd3507bc9278d9a68a7b7ca5759b364bfe960fc12a87f219e847

可用看到我們現在有一個image,id為42c75e16533e,overlay會把該映象的所有父映象儲存到本地(image的分層快取),該image共5層。
sh-4.1# docker  inspect 42c75e16533e | grep b46ba152cc1
    "Parent": "b46ba152cc17054229bc0099e7fda8b34958d518ce687c0d378b4832c4d8c91e",
sh-4.1# docker  inspect b46ba152cc1 | grep 9016bb11dc9b4a
    "Parent": "9016bb11dc9b4a3ee23fbef484cf5b3c9b80491e87d67092febec45759baeb4f",
sh-4.1# docker  inspect 9016bb11dc9b4a | grep ea80c789cb2
    "Parent": "ea80c789cb2b3bcc1d12b9b3226c8482a06f28e94a4a49f8e201b5e9cdbdf0cc",
sh-4.1# docker  inspect ea80c789cb2 | grep e444e2175366cd35
    "Parent": "e444e2175366cd3507bc9278d9a68a7b7ca5759b364bfe960fc12a87f219e847",
sh-4.1# docker  inspect e444e2175366cd35 | grep Parent
    "Parent": "",
sh-4.1#


由下面示例可以看到容器id 8ab8690b07,實際上是使用image 42c75e16533e 啟動起來的一個container,並給出了container 的LowerDir:`/export/lib/docker/overlay/42c75e16533e2ef46ffd22a21318d354b3f3e520709230e9848ebaca8f1f514e/root`

sh-4.1# docker inspect 8ab8690b07 | grep Parent
        "CgroupParent": "",
sh-4.1# docker inspect 8ab8690b07 | grep 42c75e1653
    "Image": "42c75e16533e2ef46ffd22a21318d354b3f3e520709230e9848ebaca8f1f514e",
            "LowerDir": "/export/lib/docker/overlay/42c75e16533e2ef46ffd22a21318d354b3f3e520709230e9848ebaca8f1f514e/root",
        "Image": "42c75e16533e",
sh-4.1#

檢視容器內部的儲存結構:
sh-4.1# ls 8ab8690b0769d07cc0b546112cfc40068d99298ed7e1857272c98a522cede527/
lower-id  merged/   upper/
容器的儲存裡面預設會存放三個檔案,lower-id紀錄的是image的id,也就是上面提到的LowerDir,其次存在merged和upper目錄,分別為容器層,和容器最終看到的merged層。overlayfs中的lower,upper,merged三者的關係看文首。