Linux中國

容器的四大基礎技術

在以前的文章中,我介紹過 容器鏡像 及其 運行時。在本文中,我研究了容器是如何在一些特殊的 Linux 技術基礎上實現的,這其中包括命名空間和控制組。

![容器技術的層次](/data/attachment/album/202109/17/085446w47ahozm1daudluh.png "layers of linux technologies")

圖1:對容器有貢獻的 Linux 技術(Nived Velayudhan, CC BY-SA 4.0

這些 Linux 技術構成了在系統上構建和運行容器進程的基礎:

  1. 命名空間
  2. 控制組(cgroups)
  3. Seccomp
  4. SELinux

命名空間

命名空間 namespace 為容器提供了一個隔離層,給容器提供了一個看起來是獨佔的 Linux 文件系統的視圖。這就限制了進程能訪問的內容,從而限制了它所能獲得的資源。

在創建容器時,Docker 或 Podman 和其他容器技術使用了 Linux 內核中的幾個命名空間:

[nivedv@homelab ~]$ docker container run alpine ping 8.8.8.8
[nivedv@homelab ~]$ sudo lsns -p 29413

        NS TYPE   NPROCS   PID USER COMMAND
4026531835 cgroup    299     1 root /usr/lib/systemd/systemd --switched...
4026531837 user      278     1 root /usr/lib/systemd/systemd --switched...
4026533105 mnt         1 29413 root ping 8.8.8.8
4026533106 uts         1 29413 root ping 8.8.8.8
4026533107 ipc         1 29413 root ping 8.8.8.8
4026533108 pid         1 29413 root ping 8.8.8.8
4026533110 net         1 29413 root ping 8.8.8.8

用戶

用戶(user)命名空間將用戶和組隔離在一個容器內。這是通過分配給容器與宿主系統有不同的 UID 和 GID 範圍來實現的。用戶命名空間使軟體能夠以 root 用戶的身份在容器內運行。如果入侵者攻擊容器,然後逃逸到宿主機上,他們就只能以受限的非 root 身份運行了。

掛載

掛載(mnt)命名空間允許容器有自己的文件系統層次結構視圖。你可以在 Linux 系統中的 /proc/<PID>/mounts 位置找到每個容器進程的掛載點。

UTS

Unix 分時系統 Unix Timeharing System (UTS)命名空間允許容器擁有一個唯一主機名和域名。當你運行一個容器時,即使使用 - name 標籤,也會使用一個隨機的 ID 作為主機名。你可以使用 unshare 命令 來了解一下這個工作原理。

nivedv@homelab ~]$ docker container run -it --name nived alpine sh
/ # hostname 
9c9a5edabdd6
/ # 
nivedv@homelab ~]$ sudo unshare -u sh
sh-5.0# hostname isolated.hostname 
sh-5.0# hostname
isolated.hostname
sh-5.0# 
sh-5.0# exit
exit
[nivedv@homelab ~]$ hostname
homelab.redhat.com

IPC

進程間通信 Inter-Process Communication (IPC)命名空間允許不同的容器進程之間,通過訪問共享內存或使用共享消息隊列來進行通信。

[root@demo /]# ipcmk -M 10M
Shared memory id: 0
[root@demo /]# ipcmk -M 20M
Shared memory id: 1
[root@demo /]# 
[root@demo /]# ipcs
------ Message Queues -----key        msqid      owner      perms      used-bytes   messages    
------ Shared Memory Segments -----key        shmid      owner      perms      bytes      nattch     status      
0xd1df416a 0          root       644        10485760   0                       
0xbd487a9d 1          root       644        20971520   0                       
------ Semaphore Arrays -----key        semid      owner      perms      nsems

PID

進程 ID Process ID (PID)命名空間確保運行在容器內的進程與外部隔離。當你在容器內運行 ps 命令時,由於這個命名空間隔離的存在,你只能看到在容器內運行的進程,而不是在宿主機上。

網路

網路(net)命名空間允許容器有自己網路介面、IP 地址、路由表、埠號等視圖。容器如何能夠與外部通信?你創建的所有容器都會被附加到一個特殊的虛擬網路介面上進行通信。

[nivedv@homelab ~]$ docker container run --rm -it alpine sh
/ # ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=119 time=21.643 ms
64 bytes from 8.8.8.8: seq=1 ttl=119 time=20.940 ms
^C
[root@homelab ~]# ip link show veth84ea6fc
veth84ea6fc@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
master docker0 state UP mode DEFAULT group default

控制組

控制組(cgroup)是組成一個容器的基本模塊。控制組會分配和限制容器所使用的資源,如 CPU、內存、網路 I/O 等。容器引擎會自動創建每種類型的控制組文件系統,並在容器運行時為每個容器設置配額。

[root@homelab ~]# lscgroup | grep docker
cpuset:/docker
net_cls,net_prio:/docker
cpu,cpuacct:/docker
hugetlb:/docker
devices:/docker
freezer:/docker
memory:/docker
perf_event:/docker
blkio:/docker
pids:/docker

容器運行時為每個容器設置了控制組值,所有信息都存儲在 /sys/fs/cgroup/*/docker。下面的命令將確保容器可以使用 50000 微秒的 CPU 時間片,並將內存的軟、硬限制分別設置為 500M 和 1G。

[root@homelab ~]# docker container run -d --name test-cgroups --cpus 0.5 --memory 1G --memory-reservation 500M httpd
[root@homelab ~]# lscgroup cpu,cpuacct:/docker memory:/docker
cpu,cpuacct:/docker/
cpu,cpuacct:/docker/c3503ac704dafea3522d3bb82c77faff840018e857a2a7f669065f05c8b2cc84
memory:/docker/
memory:/docker/c3503ac704dafea3522d3bb82c77faff840018e857a2a7f669065f05c8b2cc84
[root@homelab c....c84]# cat cpu.cfs_period_us 
100000
[root@homelab c....c84]# cat cpu.cfs_quota_us 
50000
[root@homelab c....c84]# cat memory.soft_limit_in_bytes 
524288000
[root@homelab c....c84]# cat memory.limit_in_bytes 
1073741824

SECCOMP

Seccomp 意思是「 安全計算 secure computing 」。它是一項 Linux 功能,用於限制應用程序進行的系統調用的集合。例如,Docker 的默認 seccomp 配置文件禁用了大約 44 個系統調用(總計超過 300 個)。

這裡的思路是讓容器只訪問所必須的資源。例如,如果你不需要容器改變主機上的時鐘時間,你可能不會使用 clock_adjtimeclock_settime 系統調用,屏蔽它們是合理的。同樣地,你不希望容器改變內核模塊,所以沒有必要讓它們使用 create_moduledelete_module 系統調用。

SELinux

SELinux 是「 安全增強的 Linux security-enhanced Linux 」的縮寫。如果你在你的宿主機上運行的是 Red Hat 發行版,那麼 SELinux 是默認啟用的。SELinux 可以讓你限制一個應用程序只能訪問它自己的文件,並阻止任何其他進程訪問。因此,如果一個應用程序被破壞了,它將限制該應用程序可以影響或控制的文件數量。通過為文件和進程設置上下文環境以及定義策略來實現,這些策略將限制一個進程可以訪問和更改的內容。

容器的 SELinux 策略是由 container-selinux 包定義的。默認情況下,容器以 container_t 標籤運行,允許在 /usr 目錄下讀取(r)和執行(x),並從 /etc 目錄下讀取大部分內容。標籤container_var_lib_t 是與容器有關的文件的通用標籤。

總結

容器是當今 IT 基礎設施的一個重要組成部分,也是一項相當有趣的技術。即使你的工作不直接涉及容器化,了解一些基本的容器概念和方法,也能讓你體會到它們如何幫助你的組織。容器是建立在開源的 Linux 技術之上的,這使它們變得更加美好。

本文基於 techbeatly 的文章,並經授權改編。

via: https://opensource.com/article/21/8/container-linux-technology

作者:Nived V 選題:lujun9972 譯者:wxy 校對:turbokernel

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國