iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0

透過對 namespace 的討論,我們知道了所謂的「隔離」,其實就是建立各種不同種類的命名空間給我們要新執行的那個 process,如此一來這個 process 及其後續建立出來的 processes 就只能看到這些新命名空間中的資訊,看不到 parent namespace,也看不到其他 namespace 裡的資料。

container 就是用了這樣 namespace 的技術去達成隔離的,更直接地說,這些在 container 中的 processes 是「被騙」了,他們的的視圖被這些命名空間們給限制住了,所以看不到其他人,以至於覺得這個世界只有我,殊不知,從 Host 的視角來說,根本是裸體的、一覽無遺的,還記得我們在 Day 03 做的實驗嗎?在 container 中的 process 中其實在 Host 中都看得到,也有自己的 PID,我們來多做幾個試試看:

$ docker run -it alpine ash
/ # sleep 2000 &
/ # ps -eaf
PID   USER     TIME  COMMAND
    1 root      0:00 ash
    7 root      0:00 sleep 2000
    8 root      0:00 ps -eaf

用另外一個 terminal 查看一下 Host 中的情況:

$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
ffb4953e6750   alpine    "ash"     6 minutes ago   Up 6 minutes             fervent_albattani

$ docker container inspect --format='{{ json .State }}' ffb4953e6750 | jq
{
  "Status": "running",
  "Running": true,
  "Paused": false,
  "Restarting": false,
  "OOMKilled": false,
  "Dead": false,
  "Pid": 58127,
  "ExitCode": 0,
  "Error": "",
  "StartedAt": "2022-09-29T14:13:05.026420935Z",
  "FinishedAt": "0001-01-01T00:00:00Z"
}

$ ps -eaf
...略
root       58127   58107  0 14:13 pts/0    00:00:00 ash
root       58155   58127  0 14:13 pts/0    00:00:00 sleep 2000

在 Host 中是可以看得到在 container 中的 ash 以及 sleep 2000 的。我們之前說過,container 其實就只是 Host 中的 process 而已,但他比較特殊,特殊在哪裡呢?就是在這裡,container 中的 processes 被騙了,以為全世界只有他們,但其實並不是,是不是很可憐呢?(喂)


在繼續下去之前,先帶大家看一個目錄 /proc/58127/ns:

$ sudo ls -al /proc/58127/ns
total 0
dr-x--x--x 2 root root 0 Sep 29 14:13 .
dr-xr-xr-x 9 root root 0 Sep 29 14:13 ..
lrwxrwxrwx 1 root root 0 Sep 29 14:21 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 ipc -> 'ipc:[4026532278]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 mnt -> 'mnt:[4026532276]'
lrwxrwxrwx 1 root root 0 Sep 29 14:13 net -> 'net:[4026532280]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 pid -> 'pid:[4026532279]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 pid_for_children -> 'pid:[4026532279]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 time -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Sep 29 14:21 uts -> 'uts:[4026532277]'

/proc/[PID]/ns 這個目錄裡儲存了這個 process 所在的各種 namespaces 的 file descriptor,在 Linux 的世界裡,所有的東西都是一個 file,file descriptor 則是一個用來辨識某一個 open file 的唯一編號。

這時候如果我們在 container 中用 lsns 查看 namespace,會看到以下結果:

# alpine 中沒有 lsns 指令,安裝一下:
/ # apk add util-linux
...略
/ # lsns
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time        3   1 root ash
4026531835 cgroup      3   1 root ash
4026531837 user        3   1 root ash
4026532276 mnt         3   1 root ash
4026532277 uts         3   1 root ash
4026532278 ipc         3   1 root ash
4026532279 pid         3   1 root ash
4026532280 net         3   1 root ash

是不是跟 /proc/58127/ns 裡的檔案結果一致呢?

這個 container 中還有另外一個 process 是 sleep 2000,透過在 Host 用 ps 指令查看,我們可以知道他的 PID 是 58155,那我們也來看一下 /proc/58155/ns 的內容:

# 回到 Host
$ sudo ls -al /proc/58155/ns
total 0
dr-x--x--x 2 root root 0 Sep 29 14:29 .
dr-xr-xr-x 9 root root 0 Sep 29 14:14 ..
lrwxrwxrwx 1 root root 0 Sep 29 14:41 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 ipc -> 'ipc:[4026532278]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 mnt -> 'mnt:[4026532276]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 net -> 'net:[4026532280]'
lrwxrwxrwx 1 root root 0 Sep 29 14:29 pid -> 'pid:[4026532279]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 pid_for_children -> 'pid:[4026532279]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 time -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Sep 29 14:41 uts -> 'uts:[4026532277]'

是不是跟 /proc/58127/ns 裡頭的都一模一樣呢,也就是在 container 裡的兩個 processes,他們所在的各種 namespaces 都是一樣的。

讓我們在 Host 隨意啟動一個 process,並且去觀察一下他的 ns 是什麼:

$ sleep 3000 &
[1] 58326

$ sudo ls -al /proc/58326/ns
total 0
dr-x--x--x 2 ubuntu ubuntu 0 Sep 29 14:43 .
dr-xr-xr-x 9 ubuntu ubuntu 0 Sep 29 14:43 ..
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 mnt -> 'mnt:[4026531841]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 net -> 'net:[4026531840]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 time -> 'time:[4026531834]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 user -> 'user:[4026531837]'
lrwxrwxrwx 1 ubuntu ubuntu 0 Sep 29 14:43 uts -> 'uts:[4026531838]'

$ sudo lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid     122     1 root /sbin/init
4026532279 pid       2 58127 root ash

可以看到跟 container 裡的 processes 的 namespaces 都不一樣。透過在 Host 執行 lsns,也可以查看到目前有兩個 PID namespaces,4026531836 恰好是 PID 58326 這個 process 的 PID namespace,而 4026532279 則會是 container 中的那兩個 processes 的 PID namespace。


親眼「看到」這些 namespaces 是不是很有趣呢?有沒有一種 container 愈來愈不神秘的感覺?


上一篇
Day 13: Mount Namespace 的坑
下一篇
Day 15: docker exec 是怎麼辦到的呢?
系列文
那些關於 docker 你知道與不知道的事32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言