參考:深刻剖析Kubernetes 鏡像分層結構理論詳解1 深刻理解Docker容器和鏡像 Union File Systemlinux
上文簡單介紹了容器的隔離與限制,下文會更進一步去理解docker是如何保持一致性的。docker
Docker在鏡像的設計中引入了層(layer)的概念。也就是說,用戶製做鏡像的每一步操做,都會生成一個層,也就是一個增量rootfs(根文件系統)。bash
這裏涉及到2個概念:rootfs、image、layer和Union File System 。架構
什麼是rootfs?rootfs是內核啓動時所mount的第一個文件系統,內核代碼映像文件保存在根文件系統中,而系統引導啓動程序會在根文件系統掛載以後從中把一些基本的初始化腳本和服務等加載到內存中去運行。性能
docker架構下沿用了linux中的rootfs的思想,當 docker daemon 爲 docker 容器掛載 rootfs 時與傳統的linux內核極其相似,將其設置爲只讀模式,在rootfs掛載完成以後,和linux內核不同的是,docker daemon沒有將它切換爲讀寫模塊。測試
能夠這樣理解,對 Docker 項目來講,它最核心的原理實際上就是爲待建立的用戶進程:ui
容器鏡像的rootfs是容器只讀的文件系統,rootfs又是由多個只讀的image構成。因而,rootfs中每一個只讀的image均可以稱爲一層layer。spa
除了只讀的image以外,Docker Daemon在建立容器時會在容器的rootfs之上,再mount一層read-write filesystem,而這一層文件系統,也稱爲容器的一層layer,常被稱爲top layer。操作系統
Docker的設計理念中,top layer轉變爲image的行爲(Docker中稱爲commit操做),大大釋放了容器rootfs的靈活性。Docker的開發者徹底能夠基於某個鏡像建立容器作開發工做,而且不管在開發週期的哪一個時間點,均可以對容器進行commit,將全部top layer中的內容打包爲一個image,構成一個新的鏡像。Commit完畢以後,用戶徹底能夠基於新的鏡像,進行開發、分發、測試、部署等。不只docker commit的原理如此,基於Dockerfile的docker build,其追核心的思想,也是不斷將容器的top layer轉化爲image。
Docker的存儲驅動的實現是基於Union File System,簡稱UnionFS,他是一種爲Linux 、FreeBSD 和NetBSD 操做系統設計的,把其餘文件系統聯合到一個聯合掛載點的文件系統服務。它用到了一個重要的資源管理技術,叫寫時複製。寫時複製(copy-on-write),也叫隱式共享,是一種對可修改資源實現高效複製的資源管理技術。對於一個重複資源,若不修改,則無需馬上建立一個新的資源,該資源能夠被共享使用。當發生修改的時候,纔會建立新資源。這會大大減小對於未修改資源複製的消耗。
OverlayFS採用UFS模式,但相對於AUFS,其性能更高。在Docker中主要有overlay和overlay2兩種實現。Docker-CE默認採用overlay2。
OverlayFS中使用了兩個目錄,把一個目錄置放於另外一個之上,而且對外提供單個統一的視角。下層的目錄叫作lowerdir,上層的叫作upperdir。對外展現的統一視圖稱做merged。建立一個容器,overlay驅動聯合鏡像層和一個新目錄給容器。鏡像頂層是overlay中的只讀 lowerdir,容器的新目錄是 可讀寫 的upperdir。它們默認存儲於/var/lib/docker/overlay2/目錄下。例如:
[root@test-04 overlay2]# tree -L 2 . ├── 19435179b7c97d5363928de2e44c675528dac3c58c855e33396d907f023621cd │ ├── committed │ ├── diff │ └── link ├── 31dd5a960bc9d2b35771eaca22a598da3bfb089ac37120d14282eaaa20d83de2 │ ├── diff │ ├── link │ ├── lower │ └── work ├── 91ce67fbd28ed8938a39248405656dbbd9a5d66025cae63ee58d044e61c8907f │ ├── committed │ ├── diff │ └── link ├── 9c696d2632aa0894128ad9ab3141a8ed6cc8d6b012d5634b93527ef72b538106 │ ├── diff │ ├── link │ ├── lower │ └── work ├── 9c696d2632aa0894128ad9ab3141a8ed6cc8d6b012d5634b93527ef72b538106-init │ ├── committed │ ├── diff │ ├── link │ ├── lower │ └── work ├── 9f557c818388f90c28b782095bb37e8ad39c0d2d8888d0d4f96958d0ac941630 │ ├── committed │ ├── diff │ ├── link │ ├── lower │ └── work ├── backingFsBlockDev └── l ├── 44ISUTVEWAUB3GXP5K5ZTY66S4 -> ../9c696d2632aa0894128ad9ab3141a8ed6cc8d6b012d5634b93527ef72b538106/diff ├── 6WQVWTVP4BK4LSS6FEMXYI7UJL -> ../91ce67fbd28ed8938a39248405656dbbd9a5d66025cae63ee58d044e61c8907f/diff ├── FUB2EZA444WCH3SP5VKRH3SPES -> ../19435179b7c97d5363928de2e44c675528dac3c58c855e33396d907f023621cd/diff ├── IXUFBMAQP26LTFBD7APAIALQ2B -> ../31dd5a960bc9d2b35771eaca22a598da3bfb089ac37120d14282eaaa20d83de2/diff ├── OPVHT4CAHBKEYLSAQ7BCJ7RCGL -> ../9c696d2632aa0894128ad9ab3141a8ed6cc8d6b012d5634b93527ef72b538106-init/diff └── R4JCGPBIE4JRIOHLUFHILT5XJR -> ../9f557c818388f90c28b782095bb37e8ad39c0d2d8888d0d4f96958d0ac941630/diff
說明:
:
分隔;-init
以結尾的是頂層的lowerdir
的父目錄,目的是爲了初始化container配置信息;merged
:該目錄就是container的mount point,這就是暴露的lowerdir
和upperdir
的統一視圖。任何對容器的改變也影響這個目錄。在 rootfs 的基礎上,Docker 公司創新性地提出了使用多個增量 rootfs 聯合掛載一個完整 rootfs 的方案,這就是容器鏡像中「層」的概念。經過「分層鏡像」的設計,以 Docker 鏡像爲核心,來自不一樣公司、不一樣團隊的技術人員被緊密地聯繫在了一塊兒。並且,因爲容器鏡像的操做是增量式的,這樣每次鏡像拉取、推送的內容,比本來多個完整的操做系統的大小要小得多;而共享層的存在,可使得全部這些容器鏡像須要的總空間,也比每一個鏡像的總和要小。這樣就使得基於容器鏡像的團隊協做,要比基於動則幾個 GB 的虛擬機磁盤鏡像的協做要敏捷得多。
一旦這個鏡像被髮布,那麼你在全世界的任何一個地方下載這個鏡像,獲得的內容都徹底一致,能夠徹底復現這個鏡像製做者當初的完整環境。這,就是容器技術「強一致性」的重要體現。