技術(shù)實(shí)現(xiàn)
Docker 是使用 Linux 的 Namespace 技術(shù)實(shí)現(xiàn)各種資源隔離的撩扒。
Namespace 是 Linux 內(nèi)核的一項(xiàng)功能压彭,該功能對(duì)內(nèi)核資源進(jìn)行分區(qū)守伸,以使一組進(jìn)程看到一組資源滑肉,而另一組進(jìn)程看到另一組資源反肋。Namespace 的工作方式通過(guò)為一組資源和進(jìn)程設(shè)置相同的 Namespace 而起作用拖云,但是這些 Namespace 引用了不同的資源贷笛。資源可能存在于多個(gè) Namespace 中。這些資源可以是進(jìn)程 ID宙项、主機(jī)名乏苦、用戶 ID、文件名杉允、與網(wǎng)絡(luò)訪問(wèn)相關(guān)的名稱(chēng)和進(jìn)程間通信邑贴。
Namespace 類(lèi)型
在最新的 Linux 5.6 內(nèi)核中,提供了 8 種類(lèi)型的 Namespace叔磷,但最新版本的 Docker 只使用了其中的前 6 種類(lèi)型拢驾,如下表所示:
Namespace 名稱(chēng) | 簡(jiǎn)稱(chēng) | 作用 | 內(nèi)核版本 |
---|---|---|---|
Mount | mnt | 隔離掛載點(diǎn) | 2.4.19 |
Process ID | pid | 隔離進(jìn)程ID | 2.6.24 |
Network | net | 隔離網(wǎng)絡(luò)設(shè)備、端口號(hào)等 | 2.6.29 |
Interprocess Communication | ipc | 隔離信息量改基、消息隊(duì)列和共享內(nèi)存 | 2.6.19 |
UTS | uts | 隔離主機(jī)名和域名 | 2.6.19 |
User | user | 隔離用戶和用戶組 | 3.8 |
Control group | cgroup | 隔離 Cgroups 根目錄 | 4.6 |
Time | time | 隔離系統(tǒng)時(shí)間 | 5.6 |
Namespace 各類(lèi)型作用
通過(guò)使用
unshare
命令可以實(shí)現(xiàn)創(chuàng)建并訪問(wèn)不同類(lèi)型的 Namespace繁疤,模擬 Dokcer 資源隔離的效果。以下只針對(duì) Docker 使用的前 6 種類(lèi)型來(lái)分析它們各自的作用:
##### Mount Namespace:實(shí)現(xiàn)在不同的進(jìn)程中看到不同的掛載目錄
### 通過(guò)unshare命令創(chuàng)建一個(gè)bash進(jìn)程秕狰,作為窗口1
$ unshare --mount --fork /bin/bash
[root@centos7 ~]# mkdir /tmp/tmpfs
[root@centos7 ~]# mount -t tmpfs -o size=20m tmpfs /tmp/tmpfs
[root@centos7 ~]# df -h /tmp/tmpfs
Filesystem Size Used Avail Use% Mounted on
tmpfs 20M 0 20M 0% /tmp/tmpfs
### 打開(kāi)一個(gè)新的命令行窗口稠腊,作為窗口2驗(yàn)證
[root@centos7 ~]# df -h /tmp/tmpfs
df: /tmp/tmpfs: No such file or directory
--------------------------------------------------------------------------------------------------
##### PID Namespace:實(shí)現(xiàn)每個(gè)容器的主進(jìn)程為1號(hào)進(jìn)程,而容器內(nèi)的進(jìn)程在主機(jī)上卻擁有不同的PID
### 在當(dāng)前命令行窗口加入了新創(chuàng)建的 PID Namespace鸣哀,從而看不到主機(jī)上其他進(jìn)程信息
$ unshare --pid --fork --mount-proc /bin/bash
[root@centos7 ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 115544 2004 pts/0 S 10:57 0:00 bash
root 10 0.0 0.0 155444 1764 pts/0 R+ 10:59 0:00 ps aux
--------------------------------------------------------------------------------------------------
##### UTS Namespace:實(shí)現(xiàn)在容器內(nèi)的主機(jī)名稱(chēng)為任意自定義的主機(jī)名
### 在當(dāng)前命令行窗口加入了新創(chuàng)建的 UTS Namespace架忌,作為窗口1
$ unshare --uts --fork /bin/bash
[root@centos7 ~]# hostname -b utsdocker && hostname
utsdocker
### 打開(kāi)一個(gè)新的命令行窗口,作為窗口2驗(yàn)證
[root@centos7 ~]# hostname
centos7
--------------------------------------------------------------------------------------------------
##### IPC Namespace:實(shí)現(xiàn)在容器內(nèi)的不同空間下的進(jìn)程間不能通信
### 在當(dāng)前命令行窗口加入了新創(chuàng)建的 IPC Namespace我衬,作為窗口1
$ unshare --ipc --fork /bin/bash
## 創(chuàng)建系統(tǒng)間通信隊(duì)列
[root@centos7 centos]# ipcmk -Q
Message queue id: 0
## 查看系統(tǒng)間通信隊(duì)列列表
[root@centos7 ~]# ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0x73682a32 0 root 644 0 0
### 打開(kāi)一個(gè)新的命令行窗口叹放,作為窗口2驗(yàn)證
[root@centos7 ~]# ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
--------------------------------------------------------------------------------------------------
##### User Namespace:實(shí)現(xiàn)進(jìn)程在容器內(nèi)擁有root權(quán)限,而在主機(jī)上卻只是普通用戶
### unshare命令報(bào)錯(cuò)無(wú)效參數(shù)挠羔,需要修改系統(tǒng)允許創(chuàng)建 User Namespace 的數(shù)量
$ echo 65535 > /proc/sys/user/max_user_namespace
### 在當(dāng)前命令行窗口加入了新創(chuàng)建的 User Namespace
$ unshare --user -r /bin/bash
[root@centos7 ~]# id
uid=0(root) gid=0(root) groups=0(root),65534(nfsnobody) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
### 雖然已是root用戶井仰,但執(zhí)行重啟失敗,說(shuō)明并不能獲取到主機(jī)的root權(quán)限
[root@centos7 ~]# reboot
Failed to open /dev/initctl: Permission denied
Failed to talk to init daemon.
--------------------------------------------------------------------------------------------------
##### Net Namespace:實(shí)現(xiàn)每個(gè)進(jìn)程擁有自己獨(dú)立的IP地址破加、端口和網(wǎng)卡信息
### 在當(dāng)前命令行窗口加入了新創(chuàng)建的 Net Namespace俱恶,作為窗口1
$ unshare --net --fork /bin/bash
[root@centos7 ~]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
### 打開(kāi)一個(gè)新的命令行窗口,作為窗口2驗(yàn)證
[root@centos7 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 02:11:b0:14:01:0c brd ff:ff:ff:ff:ff:ff
inet 172.25.168.11/24 brd 172.25.168.255 scope global dynamic eth0
valid_lft 86063337sec preferred_lft 86063337sec
inet6 fe80::11:b0ff:fe14:10c/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:82:8d:a0:df brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:82ff:fe8d:a0df/64 scope link
valid_lft forever preferred_lft forever