在 Linux中,Namespace 和 Cgroups 是如何實現資源隔離?
Linux 內核提供了多種機制來實現系統資源的隔離和管理,這篇文章,我們來詳細分析兩種關鍵的技術:Namespace 和 Cgroups。
一、Namespace 詳解
Namespace(命名空間,也稱名稱空間)是 Linux 內核用于隔離系統資源,使得不同的進程組可以擁有各自獨立的資源視圖。Namespace 的核心思想是通過將系統資源劃分為不同的命名空間,進而實現資源的隔離。
Namespace通常包含以下幾種類型:
- PID Namespace
- Mount Namespace
- UTS Namespace
- IPC Namespace
- Network Namespace
- User Namespace
1. PID Namespace
PID Namespace 用于隔離進程 ID 空間。每個 PID Namespace 都有自己獨立的進程 ID 號,父 Namespace 可以查看和管理子 Namespace 中的進程,但反之則不行。這種機制使得在容器中運行的進程可以擁有從 1 開始的 PID。
# 創建新的 PID Namespace 并運行一個 Bash 進程
unshare -p -f --mount-proc bash
2. Mount Namespace
Mount Namespace 用于隔離掛載點。不同的 Mount Namespace 可以擁有各自獨立的文件系統視圖。這樣一來,在一個 Namespace 中對文件系統的修改不會影響到其他 Namespace。
# 創建新的 Mount Namespace 并運行一個 Bash 進程
unshare -m bash
3. UTS Namespace
UTS (UNIX Time-Sharing) Namespace 用于隔離主機名和域名。不同的 UTS Namespace 可以擁有不同的主機名和域名,這對于容器化應用非常有用。
# 創建新的 UTS Namespace 并運行一個 Bash 進程
unshare -u bash
hostname new_hostname
4. IPC Namespace
IPC (Inter-Process Communication) Namespace 用于隔離進程間通信資源,如消息隊列、信號量和共享內存。不同的 IPC Namespace 之間的通信資源是隔離的。
# 創建新的 IPC Namespace 并運行一個 Bash 進程
unshare -i bash
5. Network Namespace
Network Namespace 用于隔離網絡資源,如網絡接口、路由表、防火墻規則等。每個 Network Namespace 可以擁有獨立的網絡設備和配置。
# 創建新的 Network Namespace 并運行一個 Bash 進程
ip netns add mynamespace
ip netns exec mynamespace bash
6. User Namespace
User Namespace 用于隔離用戶和用戶組 ID。它允許在不同的 Namespace 中使用相同的用戶 ID,但這些 ID 在不同的 Namespace 中是獨立的。這樣一來,即使在容器中運行的進程以 root 身份運行,也不會擁有對宿主系統的 root 權限。
# 創建新的 User Namespace 并運行一個 Bash 進程
unshare -U bash
7. 無法被 Namespace
盡管 Linux的 Namespace機制提供了對多種系統資源的隔離,但并不是所有的系統資源都能被 Namespace隔離,以下是一些不能被 Namespace隔離的資源及其原因:
- 內核模塊: 內核模塊(Kernel Modules)在整個系統中是全局共享的。加載或卸載一個內核模塊會影響到所有Namespace中的進程。
- 內核參數: 通過sysctl命令設置的內核參數(如/proc/sys下的參數)是全局的,無法在不同的Namespace中進行獨立設置。
- 硬件資源:硬件資源是物理存在的,無法通過軟件機制進行隔離。
- CPU:盡管Cgroups可以對CPU資源進行分配和限制,但CPU本身是一個物理資源,無法在不同的Namespace中進行隔離。
- 內存:Cgroups可以對內存資源進行分配和限制,但物理內存本身無法在不同的Namespace中進行隔離。
- 磁盤:磁盤設備是物理存在的,無法在不同的Namespace中進行隔離。盡管可以通過Cgroups對磁盤I/O進行限制,但磁盤設備本身是共享的。
- 時間:系統時間(如系統時鐘和硬件時鐘)在整個系統中是共享的,無法在不同的Namespace中進行獨立設置。
- 安全機制:一些系統級的安全機制無法在不同的Namespace中進行隔離。
- SELinux:SELinux(Security-Enhanced Linux)是一種安全模塊,它的策略在整個系統中是全局的,無法在不同的Namespace中進行獨立設置。
- AppArmor:類似于SELinux,AppArmor也是一種安全機制,它的配置和策略在整個系統中是全局的。
- 系統日志:系統日志(如/var/log下的日志文件)在整個系統中是共享的,無法在不同的Namespace中進行獨立管理。
- 特殊設備文件:一些特殊的設備文件(如/dev下的某些設備文件)在不同的Namespace中是共享的,無法進行隔離。例如,/dev/null、/dev/zero等設備文件在整個系統中是全局的。
二、Cgroups 詳解
1. 什么是Cgroups?
Cgroups (Control Groups,控制組)是 Linux 內核的一個特性,用于限制、記錄和隔離一組進程的資源使用(CPU、內存、磁盤 I/O、網絡等)。
Cgroups 通過將進程分組,然后對這些組應用資源限制來工作,核心組件包括:
- Subsystem: 資源控制的具體實現,如 CPU、內存等。
- Hierarchy: Subsystem 的組織結構,類似于文件系統的層級結構。
- Cgroup: Hierarchy 中的一個節點,代表一組進程。
2. Cgroups 的子系統
Cgroups 支持多種子系統,每種子系統負責不同的資源控制:
- cpu: 控制 CPU 資源的分配。
- cpuacct: 提供 CPU 資源使用的統計信息。
- memory: 控制內存資源的分配和使用。
- blkio: 控制塊設備的 I/O 操作。
- net_cls: 控制網絡資源的分類。
- devices: 控制設備的訪問權限。
- freezer: 暫停和恢復進程。
3. 創建和管理 Cgroups
通過命令行工具 cgcreate、cgset 和 cgexec 可以方便地創建和管理 Cgroups。
# 創建一個新的 Cgroup
cgcreate -g cpu,memory:/mygroup
# 設置 CPU 使用限制
cgset -r cpu.shares=512 mygroup
# 設置內存使用限制
cgset -r memory.limit_in_bytes=256M mygroup
# 將一個進程加入到 Cgroup
cgexec -g cpu,memory:mygroup /bin/bash
4. Cgroups v2
Cgroups v2 是 Cgroups 的第二個版本,提供了更為統一和簡化的接口。Cgroups v2 的主要特點包括:
- 統一的層級結構,所有子系統共享同一個層級。
- 更為簡化的配置接口,減少了配置的復雜性。
- 提高了資源控制的精度和靈活性。
# 掛載 Cgroups v2
mount -t cgroup2 none /sys/fs/cgroup
# 創建一個新的 Cgroup
mkdir /sys/fs/cgroup/mygroup
# 設置 CPU 使用限制
echo 50000 > /sys/fs/cgroup/mygroup/cpu.max
# 設置內存使用限制
echo 256M > /sys/fs/cgroup/mygroup/memory.max
# 將一個進程加入到 Cgroup
echo $$ > /sys/fs/cgroup/mygroup/cgroup.procs
三、Namespace 和 Cgroups 的結合
Namespace 和 Cgroups 的結合使用是容器技術的基礎,Namespace 提供了進程級別的隔離,而 Cgroups 則用于資源的分配和限制,通過這兩種機制,可以創建高效且安全的容器化環境。
容器的創建
以下是一個簡單的示例,展示如何使用 Namespace 和 Cgroups 創建一個容器:
# 創建新的 Namespace
unshare -p -f -m -u -i -n --mount-proc bash
# 設置主機名
hostname container
# 掛載新的文件系統
mount -t tmpfs none /tmp
# 創建新的 Cgroup
cgcreate -g cpu,memory:/container
# 設置 CPU 和內存限制
cgset -r cpu.shares=512 container
cgset -r memory.limit_in_bytes=256M container
# 將當前進程加入到 Cgroup
cgclassify -g cpu,memory:container $$
在上述示例中,我們首先創建了一個新的 Namespace,然后設置了主機名并掛載了新的文件系統。接著,我們創建了一個新的 Cgroup,并設置了 CPU 和內存限制。最后,我們將當前進程加入到 Cgroup。
四、總結
Namespace 和 Cgroups 是 Linux 內核提供的兩種關鍵機制,用于實現系統資源的隔離和管理。Namespace 提供了進程級別的隔離,使得不同的進程組可以擁有各自獨立的資源視圖,而 Cgroups 則用于資源的分配和限制,通過將進程分組,然后對這些組應用資源限制來工作。結合使用這兩種機制,可以創建高效且安全的容器化環境。