1.介紹
聯合檔案系統,overlayFs依賴并建立在其它的檔案系統之上(例如ext4fs和xfs等等),并不直接參與磁盤空間結構的劃分,僅僅将原來底層檔案系統中不同的目錄進行“合并”.
2.指令
mount -t overlay overlay -o lowerdir=lower1:lower2:lower3,upperdir=upper,workdir=work merged
1)lowerdir=xxx:指定使用者需要挂載的lower層目錄(支援多lower,最大支援500層);
2)upperdir=xxx:指定使用者需要挂載的upper層目錄;
3)workdir=xxx:指定檔案系統的工作基礎目錄,挂載後内容會被清空,且在使用過程中其内容使用者不可見;
4) merged: 最後merge到哪個目錄

- 對使用者來說,他隻知道有一個merge目錄,merge下的檔案來自哪個lower,哪個upper,他都不知道.
- merge規則:如果存在同名檔案,那麼upper>lower[n]>lower[n+1].如果存在同名目錄,那麼取并集.
- 讀寫規則:
- 對merge檔案的操作:如果操作的檔案原屬于upper目錄,那麼會直接造成對源檔案的修改;如果操作的檔案原屬于lower目錄,那麼會複制一份到upper目錄.從此原lower中的檔案與merge目錄沒有任何關系,有關系的是upper下的同名檔案.
- 對原檔案的操作:對原檔案的操作,均會影響merged檔案的内容,因為他們本身就是映射的.
3.實際操作:
建立一些目錄以及檔案.
[[email protected] testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
├── u
│ └── u1
└── work
執行mount操作
[[email protected] testAufs]# mount -t overlay overlay -o lowerdir=l1:l2,upperdir=u,workdir=work result
檢視目前結構
[[email protected] testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ └── u1
└── work
└── work
由此可見: l1,l2,u目錄下的檔案全部merge到了 result目錄.下面做一些測試
3.1.修改原檔案,看是否merge後的檔案也會改.
[[email protected] testOverlay]# echo "old l1">l1/l1-1
[[email protected] testOverlay]# cat l1/l1-1
old l1
[[email protected] testOverlay]# cat result/l1-1
old l1
可見,檔案已經改了
3.2.修改result中的檔案.修改原本屬于upper的檔案
[[email protected] testOverlay]# echo "upper txt">result/u1
You have new mail in /var/spool/mail/root
[[email protected] testOverlay]# cat result/u1
upper txt
[[email protected] testOverlay]# cat u/u1
upper txt
[[email protected] testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ └── u1
└── work
└── work
3.3.修改result下原本屬于lower層的檔案.
[[email protected] testOverlay]# echo "result/lower txt">result/l2-1
[[email protected] testOverlay]# cat result/l2-1
result/lower txt
[[email protected] testOverlay]# cat l2/l2-1
[[email protected] testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ ├── l2-1
│ └── u1
└── work
└── work
注意這裡:
result/l2-1 内容變了,但是原本目錄下 l2/l2-1沒變,因為是隻讀層, upper層下多了l2-1檔案.此時資料是更改的内容.此時upper下的同名檔案隐藏掉lower下的檔案.你再修改lower下的檔案,result的内容也不會變了.
3.4.動态添加一個檔案
3.4.1 添加到 lower,在upper無同名./添加到upper,lower無同名
[[email protected] l1]# touch l1-add
[[email protected] testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ ├── l1-2
│ └── l1-add
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l1-add
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ ├── l2-1
│ └── u1
└── work
└── work
######添加到upper,lower無同名#########
[[email protected] testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ ├── l1-2
│ └── l1-add
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l1-add
│ ├── l2-1
│ ├── l2-2
│ └── u4
├── u
│ ├── l1-2
│ ├── l2-1
│ └── u4
└── work
└── work
多會合并的
4.2 添加lower,且upper有同名/ 添加upper,且lower有同名/添加upper,在lower有同名,都不行
###添加lower,在upper有同名####肯定無效
[[email protected] testOverlay]# touch l1/u4
You have new mail in /var/spool/mail/root
[[email protected] testOverlay]# echo "11">l1/u4
[[email protected] testOverlay]# cat result/
l1-1 l1-2 l1-add l2-1 l2-2 u4
[[email protected] testOverlay]# cat result/u4
###添加lower,在lower有同名#### 無效
[[email protected] testOverlay]# echo "l1 add">l1/l2-2
[[email protected] testOverlay]# cat result/l
l1-1 l1-2 l1-add l2-1 l2-2
[[email protected] testOverlay]# cat result/l
l1-1 l1-2 l1-add l2-1 l2-2
[[email protected] testOverlay]# cat result/l
l1-1 l1-2 l1-add l2-1 l2-2
[[email protected] testOverlay]# cat result/l2-2
###添加upper,在lower有同名#### 無效
3.5.删除呢??
删除需要考慮到幾種場景.
a删除的檔案是upper層,且lower層沒有同名檔案,很好辦.直接删除就行了
b删除lower檔案,并且upper沒有同名檔案名.
有點難搞,要保證lower原檔案不能删除,又要保證使用者見不到該檔案. overlayFs使用了障眼法.Whiteout檔案.Whiteout檔案在使用者删除檔案時建立,用于屏蔽底層的同名檔案,同時該檔案在merge層是不可見的
類似一個黑名單
當使用者在merge層通過ls指令(将通過readddir系統調用)檢查父目錄的目錄項時,overlayfs會自動過過濾掉和whiteout檔案自身以及和它同名的lower層檔案和目錄,達到了隐藏檔案的目的,讓使用者以為檔案已經被删除了
c要删除的檔案是upper層覆寫lower層的檔案,要删除的目錄是上下層合并的目錄
要把upper層的删除,并且屏蔽掉lower層檔案
3.6.建立一個檔案或目錄
3.7.rename檔案/目錄
4.docker怎麼使用的
[[email protected] data]# mount|grep overlay
overlay on /var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/AYCIYBZZOU2SBB7HAWWC53G5MV:/var/lib/docker/overlay2/l/7AC2GBWZ3VYQGR2IW6FVGTJELH,upperdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/diff,workdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/work)
overlay on /data/dockerTest/testAufs/merged type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=result)
overlay on /data/dockerTest/testOverlay/result type overlay (rw,relatime,lowerdir=l1:l2,upperdir=u,workdir=work)
overlay on /data/dockerTest/testOverlay/m type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=work)
後面三個是我們測試時用的
第一個是目前docker啟動的容器用的
可以看到:
1.lower是/var/lib/docker/overlay2/l/ 檔案夾下的某幾個檔案
隻讀層,這些檔案一起構成了某個鏡像.例如 Ubuntu+java+tomcat+nginx+webApp構成了整個應用的鏡像
Dockerfile 中的每個原語執行後,都會生成一個對應的鏡像層.即使原語本身并沒有明顯地修改檔案的操作(比如,ENV 原語),它對應的層也會存在。隻不過在外界看來,這個層是空的
2.upper是upperdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/diff 檔案
這個是讀寫層.容器就是一個讀寫層,我們在容器裡增删改操作會都是寫在這裡.
一旦我們容器運作時,送出成為一個鏡像.那麼 會把該讀寫層,變為隻讀層!!主要:容器是可寫,鏡像是隻讀!
3.merge檔案是/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged 這不就是作業系統嗎??
[[email protected]llchain-tool-02 merged]# ll /var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged
total 48
drwxr-xr-x 2 root root 12288 Oct 13 07:47 bin
drwxr-xr-x 1 root root 4096 Nov 25 12:49 dev
drwxr-xr-x 1 root root 4096 Nov 25 12:49 etc
drwxr-xr-x 2 nfsnobody nfsnobody 4096 Oct 13 07:47 home
drwxr-xr-x 2 root root 4096 Nov 25 12:49 proc
drwx------ 2 root root 4096 Oct 13 07:47 root
drwxr-xr-x 2 root root 4096 Nov 25 12:49 sys
drwxrwxrwt 2 root root 4096 Oct 13 07:47 tmp
drwxr-xr-x 3 root root 4096 Oct 13 07:47 usr
drwxr-xr-x 4 root root 4096 Oct 13 07:47 var
容器建立成功後,會添加一個upper層,運作時的修改都是在針對 upper層操作.如果要修改lower層呢??那麼需要寫時複制了,就是把lower層複制到upper層,然後你就可以修改了.
如果容器退出,那麼upper層會删除掉,之前的lower層不會變,你再用同樣的鏡像去生成一個容器,還是使用同樣的lower層.
5.volume原理
剛剛我們分析了docker的存儲層的原理.在此總結下:docker的鏡像是又多個隻讀層疊加的.容器是這些隻讀層+讀寫層.如果運作的時候,對檔案作出了修改,那麼會使用cow機制,将lower層資料拷貝到upper層.當删除容器後,讀寫層也會删除.
1.啟動一個容器,使用volume
docker run -it --name volume-test -h CONTAINER -v /data/testvolume busybox /bin/sh
2.檢視容器中的資料.啥都沒有
/data/testvolume # ls /data/testvolume/
/data/testvolume #
3.檢視
[[email protected] data]# docker inspect volume-test|grep volume
"Name": "/volume-test",
"Type": "volume",
"Source": "/var/lib/docker/volumes/c40fae3cefad3ffb1eac6fa584a131551ff7c3e5723b15a153a9ca9332316af3/_data",
"Destination": "/data/testvolume",
"/data/testvolume": {}
說明/data/testvolume 映射在了/var/lib/docker/volumes/c40fae3cefad3ffb1eac6fa584a131551ff7c3e5723b15a153a9ca9332316af3/_data
注意,這裡是docker volumes目錄,說明volume已經繞過了overlayfs.我們在_data下新增一個檔案
[[email protected] ~]# cd /var/lib/docker/volumes/e124d9f2cf43d41f6c2882bac080db974636c6cbbcd01f28aaf3ffe553b4514b/_data
[[email protected] _data]# touch testhh
檢視容器
/data/testvolume # ls /data/testvolume/
testhh
沒有問題
我們在容器裡建立
/data/testvolume # touch /data/testvolume/testhh2
在主控端的目錄上
[[email protected] _data]# ls /var/lib/docker/volumes/e124d9f2cf43d41f6c2882bac080db974636c6cbbcd01f28aaf3ffe553b4514b/_data
testhh testhh2
我們再看下mount
[[email protected] data]# mount|grep overlay
overlay on /data/dockerTest/testAufs/merged type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=result)
overlay on /data/dockerTest/testOverlay/result type overlay (rw,relatime,lowerdir=l1:l2,upperdir=u,workdir=work)
overlay on /data/dockerTest/testOverlay/m type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=work)
overlay on /var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/ZOOVPE6ITB5JBEWQW3AIQBLXTE:/var/lib/docker/overlay2/l/7AC2GBWZ3VYQGR2IW6FVGTJELH,upperdir=/var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/diff,workdir=/var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/work)
确實沒有使用overlayfs
參考:https://blog.csdn.net/luckyapple1028/article/details/78075358 這個文章寫得很好
https://zhuanlan.zhihu.com/p/41958018