Docker 技術原理淺析

Docker 技術原理淺析

1.簡介

簡單介紹Docker使用的核心技術

  • 利用Linux的Namespace功能,實現資源的隔離
  • 利用Linux的cgroups功能,實現資源的限制
  • 利用AUFS棧式疊加的文件系統(聯合掛載),實現docker的分層結構和增量更新等能力

以下一切都基於操作系統資源分配的最小單位:進程 進行討論

2.NameSpace

Linux Namespace是Linux提供的一種內核級別的環境隔離方法,可以實現不同資源的隔離。

Linux提供的不同Namespace有六種:

  • Mount Namespace:用於隔離文件系統的掛載點
  • UTS Namespace:用於隔離hostname主機名和DomianName域名
  • IPC Namespace:用於隔離進程間通信
  • PID Namespace:用於隔離進程ID
  • NetWork Namespace:用於隔離網絡
  • User Namespace:用於隔離用戶和用戶組 UID/GID

每種Namespace都有一個默認值代表不同的命名空間,通過這些默認值,我們在創建新進程時設置新進程應該在哪些資源上與宿主機器進行隔離,比如Linux Namespace 主要的三個API:

  • clone 創建一個新進程,需要傳入一個namespace的默認值,用於指定namespace
  • setns 允許進程重新加入一個已經存在的namesapce
  • unshare 將調用進程移動到新的namesapce

正是這三個namespace的API,使得docker可以在進程級別有實現’獨立環境‘的能力,這樣docker容器內部的任意進程都對宿主機器的進程一無所知。

Docker容器與容器,容器與宿主機之間的通信是如何實現的?

使用iptables進行數據包轉發,讓docker容器可以優雅的爲宿主機器或其他容器提供服務。

具體實現:

docker默認提供的網絡模式是網橋模式

在這種模式下,除了分配隔離的網絡命名空間外,docker還會爲所有容器設置ip地址

當docker服務器在主機上啓動之後,會創建新的虛擬網橋docker0,隨後在該主機上啓動的全部服務都默認與該網橋相連

在默認的情況下,每一個容器在創建時,都會創建一對虛擬網卡,兩個虛擬網卡組成了數據通道,其中一個網卡放在創建的容器中,另一個放到虛擬網橋docker0中

這樣的話,docker0會爲每一個容器分配一個新的ip地址並且將docker0的ip地址設置爲默認的網關,網橋docker0通過iptables中的配置與宿主機上的網卡相連,所有符合條件的請求都會通過iptables轉發到docker0然後分發給對應的容器

“當有docker服務需要暴露給宿主機時,就會爲容器分配一個ip地址,同時向iptables追加一條心規則”

Docker如何實現文件系統的隔離?

掛載點,在新的進程中創建隔離的掛載點命名空間需要在clone函數中傳入CLONE_NENNS,這樣子進程就能得到父進程掛載點的拷貝,如果不傳入這個參數,子進程對文件系統的讀寫都會同步回父進程以及整個主機的文件系統,爲了保證當前容器進程沒有辦法訪問宿主機上的目錄,還需要通過libcontainer提供的pivot_port或change root函數改變進程能夠訪問的文件目錄的根節點

change root:Linux中,默認文件路徑都是以/開頭,chroot的使用能夠改變當前系統根目錄結構,通過改變系統的根目錄,我們能夠限制用戶的權利,在新的目錄下並不能夠訪問舊系統根目錄的文件,這樣就是實現了和原系統隔離的目錄結構

3.CGroups

雖然Namespace爲我們新創建的進程隔離了文件系統,網絡,但是其並不能夠爲我們提供物理資源上的隔離,比如CPU和內存,而control groups,簡稱cgroups,能夠隔離宿主機上的物理資源,比如cpu,內存,磁盤IO和網絡帶寬。

每一組CGroup都是一組被相同標準和參數限制的進程,不同的CGroup之間是有層級關係的,也就是說他們之間可以從父類繼承一些用於限制資源使用的標準和參數

Linux的CGroup能夠爲一組進程分配資源,比如cpu,內存,網絡帶寬等

在CGroup中,所有的任務就是一個系統的一個進程,而CGroup就是一組按照某種標準劃分的進程,在CGroup這種機制中,所有的資源控制都是以CGroup爲單位實現的,每一個進程都可以隨時加入一個CGroup,也可以隨時退出一個CGroup

那麼,CGroups又是如何實現的呢?

Linux使用文件系統來實現CGroups,比如想創建的一個新的CGroup,只需要在想要分配或者限制資源的子系統下創建一個文件夾,然後這個文件夾下就會自動出現很多內容,每一個cgroups下面都有一個tasks文件,其中存儲着屬於cgroup的所有進程的pid,

作爲負責 cpu 的子系統,cpu.cfs_quota_us 文件中的內容能夠對 CPU 的使用作出限制,如果當前文件的內容爲 50000,那麼當前控制組中的全部進程的 CPU 佔用率不能超過 50%

當我們使用 Docker 關閉掉正在運行的容器時,Docker 的子控制組對應的文件夾也會被 Docker 進程移除,Docker 在使用 CGroup 時其實也只是做了一些創建文件夾改變文件內容的文件操作,不過 CGroup 的使用也確實解決了我們限制子容器資源佔用的問題,系統管理員能夠爲多個容器合理的分配資源並且不會出現多個容器互相搶佔資源的問題。

4.UnionFS

棧式的文件疊加系統,解決鏡像文件問題

Docker 中的每一個鏡像都是由一系列只讀的層組成的,Dockerfile 中的每一個命令都會在已有的只讀層上創建一個新的層

當鏡像被 docker run 命令創建時就會在鏡像的最上層添加一個可寫的層,也就是容器層,所有對於運行時容器的修改其實都是對這個容器讀寫層的修改。

容器和鏡像的區別就在於,所有的鏡像都是隻讀的,而每一個容器其實等於鏡像加上一個可讀寫的層,也就是同一個鏡像可以對應多個容器。

UnionFS 其實是一種爲 Linux 操作系統設計的用於把多個文件系統『聯合』到同一個掛載點的文件系統服務。而 AUFS 即 Advanced UnionFS 其實就是 UnionFS 的升級版,它能夠提供更優秀的性能和效率。

AUFS 作爲聯合文件系統,它能夠將不同文件夾中的層聯合(Union)到了同一個文件夾中,這些文件夾在 AUFS 中稱作分支,整個『聯合』的過程被稱爲*聯合掛載(Union Mount)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章