掌握這些 Docker 原理知識,出去吹牛逼不再擔憂了

在現代的開發流程中隨處可見 Docker 的身影,Docker 提供了環境隔離、應用打包等功能讓服務部署變得特別簡單,本文將會淺析 Docker 背後所使用的技術,閱讀完後,你能夠搞清楚以下問題:linux

  • 1. 容器與虛擬機之間的差異
  • 2.Docker 資源隔離的原理
  • 3.Docker 資源限制的原理
  • 4.Docker 分層結構的原理

容器 vs 虛擬機

虛擬機(VM)是計算機系統的仿真器,經過軟件模擬具備完整硬件系統功能的、運行在一個徹底隔離環境中的完整計算機系統,能提供物理計算機的功能。網絡

虛擬機經過在當前的真實操做系統上經過 Hypervisor 技術進行虛擬機運行環境與體系的創建並經過該技術進行資源控制,一個性能較好的物理機一般能夠承載多個虛擬機,每一個虛擬機都會有本身操做系統,如圖 1.1 所示。app

圖1.1
圖 1.1

從圖中能夠看出,虛擬機提供了物理機硬件級別的操做系統隔離,這讓不一樣虛擬機之間的隔離很完全,但也須要消耗更多資源,而有時不須要這麼完全的隔離,而更但願不消耗那麼多資源,此時就可使用容器技術。負載均衡

容器能夠提供操做系統級別的進程隔離,以 Docker 爲例,當咱們運行 Docker 容器時,此時容器自己只是操做系統中的一個進程,只是利用操做系統提供的各類功能實現了進程間網絡、空間、權限等隔離,讓多個 Docker 容器進程相互不知道彼此的存在,如圖 1.2 所示。運維

圖1.2
圖 1.2

虛擬機技術與容器技術的最大區別在於:多個虛擬機使用多個操做系統內核,而多個容器共享宿主機操做系統內核ssh

Docker 資源隔離:Linux Namespace

Linux Namespace(Linux 命名空間)是 Linux 內核(Kernel)提供的功能,它能夠隔離一系列的系統資源,如 PID(進程 ID,Process ID)、User ID、Network、文件系統等。編輯器

若是你熟悉 Linux,你可能會聯想到 linux 中的 chroot 命令,該命令容許將當前目錄修改爲根目錄(即根目錄 / 的掛載點切換了),至關於文件系統被隔離了,Namespace 也具備類似的功能,但更增強大。工具

目前 Linux 主要提供 6 中不一樣類型的 Namespace,以下表所示。性能

Namespace 類型 描述 系統調用 flags(標記)
Mount Namespace 隔離文件系統掛載點 CLONE_NEWS
UTS Namespace 隔離 HostName 與 DomianName CLONE_NEWUTS
IPC Namespace 隔離進程間通訊 CLONE_NEWIPC
PID Namespace 隔離進程 ID CLONE_NEWPID
Network Namespace 隔離網絡 CLONE_NEWNET
User Namespace 隔離用戶和用戶組 CLONE_NEWUSER

以一個具體的例子來解釋 Namespace 的做用,假設你有一臺性能很是好的計算機,你向用戶出售本身的計算機的資源,每一個用戶買到一個 ssh 實例,爲了不不一樣客戶之間相互干擾,你可能會對不一樣用戶進行權限限制,讓用戶只能訪問本身 ssh 實例下的資源。spa

但有些操做須要 root 權限,而咱們不能將 root 權限提供給用戶,此時就可使用 Namespae 了,經過 User Namespace 對 UID 進行隔離,具體而言,UID 爲 x 的用戶在該 Namespace 中具備 root 權限,但在真實物理機中,他依舊是 UID 爲 x 的用戶,這就解決了用戶間隔離的問題。

此外還能夠經過 PID Namespace 對 PID 進行隔離,從該 Namespace 中的用戶角度看,Namespace 中就像一臺新的 Linux,有本身的 init 進程(初始進程,PID 爲 1),其餘進程的 PID 在 init 進程 PID 上遞增,如圖 1.3 所示。

圖1.3
圖 1.3

圖中,進程 3 在父命名空就中 PID 爲 3,而在子命名空間中,其 PID 爲 1,用戶在該子命名空間中內看進程 3 就像 init 進程同樣。

Linux 提供了 3 個系統 API 方便咱們使用 Namespace:

  • clone () 建立新進程,根據系統調用 flags 來決定哪一種類型 Namespace 將會被建立,而該進程的子進程也會包含這些 Namespace。
  • setns () 將進程加入到已存在的 Namespace 中。
  • unshare () 將進程移出某個 Namespace

Docker 利用 Linux Namespace 功能實現多個 Docker 容器相互隔離,具備獨立環境的功能,Go 語言對 Namespce API 進行了相應的封裝,從 Docker 源碼中能夠看到相關的實現。

Docker 資源限制:Linux Cgroups

Docker 經過 Linux Namespace 幫進程隔離出本身單獨的空間 / 資源,那 Docker 如何限制進程對這些資源的使用呢?

Docker 容器本質依舊是一個進程,多個 Docker 容器運行時,若是其中一個 Docker 進程佔用大量 CPU 和內存就會致使其餘 Docker 進程響應緩慢,爲了不這種狀況,能夠經過 Linux Cgroups 技術對資源進行限制。

Linux Cgroups(Linux Contorl Groups,簡稱 Cgroups)能夠對一組進程及這些進程的子進程進行資源限制、控制和統計的能力,其中包括 CPU、內存、存儲、網絡、設備訪問權限等,經過 Cgroups 能夠很輕鬆的限制某個進程的資源佔用而且統計該進程的實時使用狀況。

Cgroups 由 3 個組件構成,分別是 cgroup(控制組)、subsystem(子系統)以及 hierarchy(層級樹),3 者相互協同做用。

  • cgroup 是對進程分組管理的一種機制,一個 cgroup 一般包含一組(多個)進程,Cgroups 中的資源控制都以 cgroup 爲單位實現。
  • subsystem 是一組(多個)資源控制的模塊,每一個 subsystem 會管理到某個 cgroup 上,對該 cgroup 中的進程作出相應的限制和控制。
  • hierarchy 會將一組(多個)cgroup 構建成一個樹狀結構,Cgropus 能夠利用該結構實現繼承等功能

3 者具體如何相互協同做用?

Cgroups 會將系統進程分組(cgroup)而後經過 hierachy 構建成獨立的樹,樹的節點就是 cgroup(進程組),每顆樹均可以與一個或多個 subsystem 關聯,subsystem 會對樹中對應的組進行操做。

有個幾個規則須要注意。

1. 一個 subsystem 只能附加到一個 hierarchy,而一個 hierarchy 能夠附加多個 subsystem 2. 一個進程能夠做爲多個 cgroup 的成員,但這些 cgroup 只能在不一樣的 hierarchy 中 3. 一個進程 fork 出子進程,此時子進程與父進程默認是在同一個 cgroup 中,能夠根據須要移動到其餘 cgroup

Docker 分層結構:Union File System

咱們都知道 Docker 鏡像是一種分層結構,每一層構建在其餘層之上,從而實現增量增長內容的功能,這是如何實現的?

要理解這個問題,首先須要理解 Union File System(簡稱,UnionFS),它是爲 Linux 系統設計的將其餘文件系統聯合到一個聯合掛載點的文件系統服務。UnionFS 使用 branch(分支)將不一樣文件系統的文件和目錄透明地疊加覆蓋,造成一個單一一致的文件系統,此外 UnionFS 使用寫時複製(Copy on Write,簡稱,CoW)技術來提升合併後文件系統的資源利用。(後續的文章會介紹 CoW 技術)

Docker 使用的第一種存儲驅動爲 AUFS(Advanced Multi-layered unification filesytem),AUFS 徹底重寫了早期的 UnionFS,目的是提升其性能與可靠性,此外還引入瞭如 branch 負載均衡等新功能。

與 UnionFS 相似,AUFS 能夠在基礎的文件系統上增量的增長新的文件系統,經過疊加覆蓋的形式最終造成一個文件系統。一般 AUFS 最上層是可讀可寫層,而其餘層只是只讀層,每一層都只是一個普通的文件系統。

Docker 鏡像分層、增量增長等功能正是經過利用 AUFS 的分層文件系統結構、增量增長等功能實現,這也致使了運行 Docker 容器若是沒有指定 volume(數據卷)或 bind mount,則 Docker 容器結束後,運行時產生的數據便丟失了。

Docker 存儲驅動除了 AUFS 外,還有 OverlayFS、Devicemapper、Btrfs、ZFS 等,本文很少討論。

總結

至此,咱們知道了 Docker 核心功能的基本原理,Docker 利用 Linux Namespace 進行網絡、用戶、進程等不一樣資源的隔離,使用 Linux Cgroups 技術對資源的使用進行限制與監控,經過 AUFS 等存儲驅動實現分層結構與增量更新等功能。

現實世界中的 Docker 還使用了不少其餘技術,但最核心且最基本的就是 Linux Namespace、Linux Cgrpus 與 AUFS。

Docker 在當前的開發流程中已成必備工具,容器帶來的優點解放了運維人員也避免了開發人員遇到開發環境與線上環境不一致時致使問題的狀況。目前容器編排技術(K8s)快速發展,Docker 容器技術在將來也將會進一步發展,它值得咱們花時間與精力去了解其本質。

相關文章
相關標籤/搜索