聊聊容器化的原理
容器化
無論LXC還是Docker,底層主要的核心技術是Cgroups、Namespace。Cgroups是Linux內核提供的一種用來限定進程資源使用的技術,可以限制和隔離進程所使用的物理資源,比如CPU、內存、磁盤和網絡I/O。相對于物理資源隔離,Namespace則是用來隔離進程ID、網絡等系統資源的,類似Java中的類加載器(classloader)。即使是同樣的PID、同樣的IP,不同的Namespace之間也是相互獨立的,毫無影響。比如父容器通過調用clone()函數創建兩個子進程,ID分別為100、101,這兩個子進程擁有自己的Namespace,映射到子進程后,分別對應PID為1的init進程,雖然在兩個Namespace里PID都為1,但是有了Namespace的隔離,兩者互不影響,如圖所示。
圖片
有了隔離,子容器之間可以相對獨立、互不打擾地工作。每個容器都是為了處理特定工作的,比如有的容器負責提供數據庫服務,有的容器負責提供緩存服務,有的容器負責應用系統的運行。如何決定容器創建后做什么工作呢?答案是通過Dockerfile。
我們把Dockerfile比作人體的DNA,它記錄了容器運行的子進程,進而決定了容器的核心功能。通過Dockerfile我們可以構建鏡像,隨時拉起多個容器,實現應用的高速擴展。業務應用的鏡像本質上都很相似,假設應用A的Dockerfile為DockerfileA,應用B的Dockerfile為DockerfileB,它們都依賴于操作系統、JDK、Tomcat、日志采集器等,只有應用的War包不一樣。如果每個鏡像都重復維護多個共性的部分,帶來的資源損耗和維護成本都是巨大的。
Docker采用分層技術來解決這個問題,每個容器都有自己獨立的容器層,不同的容器共享一個鏡像層,這樣容器之間就可以共享基礎資源。我們保存一個基礎鏡像(通常稱作base鏡像)到磁盤后,它就可以被其他鏡像共享了,如圖所示。
圖片
Dockerfile底層用的核心文件共享技術就是UFS。UFS是一種輕量級、高性能、分層的文件系統。UFS把文件系統的每次修改作為一個個層進行疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下。如果一次同時加載多個文件系統,UFS會把各層文件疊加起來,最終文件系統會包含所有底層文件和目錄,從外部視角來看,用戶看到的是一個文件系統。鏡像就是利用UFS的特性,通過分層來進行繼承、疊加,通常我們會先制作一個基礎鏡像,通過基礎鏡像衍生出各種具體的應用鏡像。UFS是Docker鏡像的基礎。
這段內容涉及到了幾個核心的虛擬化和容器化技術,讓我們來解釋一下
Cgroups(Control Groups)
Cgroups 是 Linux 內核提供的一種資源管理機制,用于限制和隔離進程對系統資源的使用,如 CPU、內存、磁盤和網絡帶寬等。它允許系統管理員為不同的進程組分配資源,并限制每個組能夠使用的資源量。
Cgroups(Control Groups)是 Linux 內核提供的一種資源管理機制,其原理主要涉及以下幾個方面
資源隔離
Cgroups 允許管理員將系統中的進程劃分為不同的組,并為每個組分配特定的資源限制。這樣可以確保每個組內的進程只能使用分配給它們的資源,而不會影響其他組的進程。
資源控制
Cgroups 允許管理員為每個組設置資源限制,包括 CPU、內存、磁盤和網絡帶寬等。這些限制可以是硬限制(無法超出)或軟限制(可以超出一段時間),從而實現對系統資源的精確控制和管理。
層次結構
Cgroups 支持層次結構,允許管理員創建多層次的組織結構。這種層次結構可以使得資源的管理更加靈活,可以根據需要對不同層次的組進行不同程度的資源分配和限制。
控制接口
Cgroups 提供了一組控制接口,允許管理員動態地管理和調整組的資源限制。這些接口可以通過文件系統的方式進行訪問和操作,使得資源管理變得簡單和靈活。
我們來總結一下,Cgroups 的原理是通過為進程分組和設置資源限制,實現對系統資源的隔離和控制,從而確保系統能夠有效地利用資源,提高系統的性能和穩定性。
安全問題
Cgroups 本身并不會引入安全問題,因為它是 Linux 內核提供的一種資源管理機制,旨在幫助管理員對系統資源進行更好地管理和控制。然而,在實際使用過程中,存在一些安全隱患需要注意
資源競爭
如果不合理地配置了 Cgroups,會導致資源競爭問題,即某些組或進程占用了過多的資源,導致其他組或進程無法正常運行。因此,需要合理設置資源限制,避免資源過度分配。
權限問題
Cgroups 的配置和管理涉及到系統的權限管理,如果權限設置不當,會導致未授權的用戶獲取到對系統資源的控制權限,從而造成安全隱患。因此,需要嚴格管理和控制對 Cgroups 的訪問權限。
DoS 攻擊
如果攻擊者能夠繞過 Cgroups 的限制,惡意占用系統資源,會導致系統資源耗盡,從而影響系統的正常運行。因此,需要及時監控和響應異常行為,防止 DoS(拒絕服務)攻擊。
我們來總結一下,Cgroups 本身并不會引入安全問題,但在使用過程中需要注意合理配置和管理,避免出現資源競爭、權限問題和 DoS 攻擊等安全隱患。同時,及時更新系統和內核版本,以修復已知的安全漏洞,提高系統的安全性。
Namespace(命名空間)
Namespace 是 Linux 內核提供的一種隔離機制,用于隔離進程的全局資源,如進程 ID(PID)、網絡、文件系統、用戶等。不同的 Namespace 提供了一種虛擬化的環境,使得在同一主機上運行的進程之間彼此隔離,互不干擾。
Namespace 是 Linux 內核提供的一種隔離機制,用于將系統資源劃分為多個獨立的、互相隔離的環境。它允許在同一主機上運行的進程看到不同的系統資源,從而實現資源的隔離和虛擬化。Linux 內核提供了多種類型的 Namespace,包括 PID(進程 ID)、Network(網絡)、Mount(文件系統掛載點)、IPC(進程間通信)、UTS(主機名和域名)等。以下是 Namespace 的一些主要類型及其作用
PID Namespace
每個 PID Namespace 都有自己的進程 ID 空間,進程在其中的 ID 對于其他 Namespace 是不可見的。這使得在不同的 PID Namespace 中運行的進程之間相互隔離,各自擁有自己的進程樹,從而可以更好地管理和控制進程。
Network Namespace
每個 Network Namespace 都有自己的網絡棧,包括網絡設備、IP 地址、路由表、網絡連接等。這使得在不同的 Network Namespace 中運行的進程之間擁有獨立的網絡環境,可以實現網絡的隔離和虛擬化。
Mount Namespace
每個 Mount Namespace 都有自己的文件系統掛載點,使得在不同的 Mount Namespace 中可以擁有不同的文件系統視圖。這樣可以實現文件系統的隔離,使得不同的進程可以擁有不同的文件系統環境。
IPC Namespace
IPC Namespace 提供了進程間通信機制的隔離,使得在不同的 IPC Namespace 中的進程無法直接通信,從而增強了系統的安全性和隔離性。
UTS Namespace
UTS Namespace 提供了主機名和域名的隔離,使得在不同的 UTS Namespace 中可以擁有不同的主機名和域名,從而實現了系統標識信息的隔離。
這些 Namespace 可以被用來創建容器,實現容器之間的隔離和虛擬化。通過將不同類型的 Namespace 組合在一起,可以實現更加靈活和強大的容器隔離環境,為容器提供了更加安全和可靠的運行環境。
安全問題
Namespace 本身并不具有安全問題,它是 Linux 內核提供的一種資源隔離機制,用于創建隔離的運行環境。然而,在實際使用中,如果配置不當或者存在漏洞,會導致安全問題的產生。以下是一些導致安全問題的情況
提權漏洞
如果容器中運行的進程具有提權漏洞,會導致攻擊者獲得 root 權限,并從容器中逃逸到宿主主機。
容器逃逸
如果容器本身存在漏洞,攻擊者會利用這些漏洞從容器中逃逸,獲取宿主主機上的敏感信息或者控制宿主主機。
命名空間隔離不完整
如果命名空間隔離不完整或者存在漏洞,會導致容器之間的信息泄露或者相互影響。
共享命名空間
如果容器共享了某些命名空間,會導致容器之間的信息共享,增加了攻擊面。
為了確保容器環境的安全性,需要采取一系列安全措施,包括但不限于
- 及時更新容器鏡像和基礎操作系統,修復已知漏洞。
- 限制容器的權限,使用最小特權原則。
- 啟用安全策略,如 SELinux、AppArmor 等,限制容器的系統調用。
- 實施網絡隔離和安全組策略,限制容器之間的通信。
- 使用安全審計工具對容器環境進行監控和審計,及時發現異常行為。
- 使用容器運行時的安全特性,如 Docker 的安全掃描、容器簽名等。
我們來總結一下,雖然 Namespace 本身不會引起安全問題,但是在實際使用中需要注意配置和管理,以確保容器環境的安全性。
Dockerfile
Dockerfile 是一個文本文件,用于定義 Docker 鏡像的內容和構建步驟。通過 Dockerfile,可以指定基礎鏡像、容器中運行的命令、文件和目錄的添加、環境變量的設置等。使用 Dockerfile 可以輕松地創建自定義的 Docker 鏡像,方便地部署和管理應用程序。
分層文件系統(Union File System,UFS)
分層文件系統是一種文件系統技術,允許將多個文件系統掛載到同一個虛擬文件系統中,形成一個層次結構。在 Docker 中,每個容器都有自己的容器層,不同的容器可以共享相同的基礎鏡像層。這種分層機制可以節省磁盤空間,并提高鏡像的重用性和部署效率。
分層文件系統(Union File System,UFS)是一種文件系統技術,通過將多個文件系統層疊加掛載到同一個虛擬文件系統中,形成一個層次結構。在 Docker 中,分層文件系統的概念被廣泛應用于容器鏡像的構建和管理中。
分層文件系統的主要原理是利用文件系統的層疊加特性,每個文件系統層可以包含文件和目錄,并且可以被其他文件系統層疊加在其上。在 Docker 中,每個容器都由多個文件系統層組成,包括只讀的基礎鏡像層和讀寫的容器層。這些層次結構的組合使得容器可以像構建積木一樣,根據需要組裝不同的鏡像,而無需重復存儲相同的文件。
具體來說,分層文件系統的工作原理如下
基礎鏡像層(Base Image Layer)
基礎鏡像層包含了容器的基礎文件系統,通常包括操作系統的核心文件和系統工具。這一層是只讀的,所有容器都共享同一個基礎鏡像層。基礎鏡像層通常由 Docker Hub 或私有倉庫提供,并由開發者維護和更新。
容器層(Container Layer)
每個容器都有自己的容器層,用于存儲容器的特定文件和目錄,包括應用程序、配置文件、日志等。容器層是可寫的,并且可以根據容器的運行狀態進行修改。當容器啟動時,容器層會疊加在基礎鏡像層之上,構成容器的完整文件系統。
寫時復制(Copy-on-Write)
當容器對文件系統進行寫操作時,分層文件系統采用寫時復制(Copy-on-Write)策略。這意味著在寫操作發生時,文件系統會在容器層上創建一個新的文件副本,而不是直接修改基礎鏡像層中的文件。這樣可以確保每個容器都擁有自己獨立的文件系統,同時最大程度地節省存儲空間。
鏡像的組裝和重用
由于分層文件系統的特性,Docker 鏡像可以通過疊加不同的文件系統層來構建。這使得鏡像可以像積木一樣靈活組裝,從而實現鏡像的復用和共享。如果多個鏡像共享相同的基礎鏡像層,它們之間只需存儲不同的容器層,大大減少了存儲空間的消耗。
我們來總結一下,分層文件系統是 Docker 中非常重要的一個概念,它通過利用文件系統的層疊加特性,實現了鏡像的高效構建、部署和管理。通過寫時復制和鏡像的重用,分層文件系統可以節省存儲空間,并提高容器的性能和效率。
安全問題
分層文件系統在 Docker 中雖然帶來了諸多優勢,但也存在一些安全考慮
容器逃逸(Container Escape)
盡管容器之間是通過分層文件系統進行隔離的,但在某些情況下,惡意用戶通過利用操作系統或 Docker 引擎的漏洞,從容器中逃逸出來,獲取主機系統的權限。這種容器逃逸攻擊導致主機系統被入侵或受到破壞。
鏡像污染(Image Poisoning)
如果基礎鏡像層或其他共享層中存在漏洞或惡意代碼,那么所有依賴這些鏡像構建的容器都受到影響。攻擊者可以通過修改或篡改鏡像的文件來植入惡意軟件或后門,從而危害容器內的應用程序和數據安全。
不安全的基礎鏡像
如果使用了不安全或未經驗證的基礎鏡像,那么容器構建的整個分層文件系統都受到威脅。建議使用官方或可信賴的基礎鏡像,并及時更新鏡像以修補已知的漏洞和安全問題。
文件系統權限
在容器內部,文件系統的權限通常是由容器運行時的配置和用戶設置決定的。如果文件系統權限配置不當,導致容器中的敏感文件被非授權用戶訪問或修改,從而造成數據泄露或損壞。
為了減輕這些安全風險,建議采取以下措施
- 使用官方或可信賴的基礎鏡像,并定期更新以獲取最新的安全補丁和修復程序。
- 實施安全最佳實踐,如使用容器運行時的安全配置、限制容器的特權訪問、禁止不必要的系統調用等。
- 配置容器的訪問控制策略,限制容器之間的通信和資源訪問,確保容器只能訪問其需要的最小權限資源。
- 監控容器的運行狀態和行為,及時發現和應對的安全威脅和攻擊行為。
我們來總結一下,雖然分層文件系統為容器化應用提供了便利和效率,但在實際應用中仍需注意安全風險,并采取相應的措施加以防范和應對。
這些技術共同構成了容器化技術的核心,使得容器能夠實現資源隔離、輕量級和快速部署的特性。
作用關系圖
使用Plantuml畫三者的作用關系圖,如下
@startuml
left to right direction
skinparam packageStyle rectangle
skinparam padding 10
skinparam defaultFontName Helvetica
package "Host" {
package "Namespace" {
[Process 1] as Process1
[Process 2] as Process2
[Process 3] as Process3
}
package "Cgroup" {
[Cgroup 1] as Cgroup1
[Cgroup 2] as Cgroup2
[Cgroup 3] as Cgroup3
}
package "UnionFS" {
[Layer 1] as Layer1
[Layer 2] as Layer2
[Layer 3] as Layer3
}
Process1 --> Cgroup1
Process2 --> Cgroup2
Process3 --> Cgroup3
Cgroup1 --> Layer1
Cgroup2 --> Layer2
Cgroup3 --> Layer3
}
@enduml
圖片
這個圖展示了在主機上的三種關鍵技術之間的關系:Namespace(命名空間)、Cgroup(控制組)和分層文件系統(UnionFS)。
- Namespace用于隔離進程的全局資源,如進程ID(PID)、網絡、文件系統等。在圖中,每個進程(Process)都被分配到自己的Namespace中,以確保它們之間的隔離。
- Cgroup用于控制和限制進程對系統資源的使用,如CPU、內存等。每個進程都被分配到相應的Cgroup中,以限制其對資源的訪問。
- 分層文件系統(UnionFS)允許將多個文件系統掛載到同一個虛擬文件系統中,形成一個層次結構。每個Cgroup都與一個或多個分層文件系統的層相關聯,這些層包含了進程所需的文件系統內容。
總之,Namespace提供了隔離的執行環境,Cgroup控制了資源使用,而分層文件系統則提供了文件系統的層次結構,使得容器可以共享和重用文件系統的內容。





























