初識
Namespace是Linux 容器中用來實現(xiàn)"隔離"的技術手段。Namespace 技術實際上修改了應用進程看待整個計算機"視圖",即容器的"視線"被操作系統(tǒng)做了限制,只能"看到"某些指定的內容。但對于宿主機來說,這些被"隔離"了的進程跟其他進程并沒有太大區(qū)別。
安裝docker
詳見http://www.itdecent.cn/p/19bebef87579
1、創(chuàng)建一個容器
[root@docker1 ~]# docker run -it --name ten centos:7 /bin/bash
這條指令翻譯成人類的語言就是:請幫我啟動一個容器,在容器里執(zhí)行 /bin/bash,并且給我分配一個命令行終端跟這個容器交互。
這樣,這臺centos7.4機器就變成了一個宿主機,而一個運行著 /bin/bash 的容器,就跑在了這個宿主機里面。
2、在容器里執(zhí)行 ps 指令,會發(fā)現(xiàn)一些有趣的事情:/bin/bash,就是這個容器內部的第 1 號進程(PID=1),而這個容器里一共只有兩個進程在運行。這就意味著,前面執(zhí)行的 /bin/bash,以及我們剛剛執(zhí)行的 ps,已經被 Docker 隔離在了一個跟宿主機完全不同的世界當中。
[root@51d6d6e2afbe /]# ps -ef

在宿主機中
[root@docker1 ~]# docker inspect ten |grep Pid
"Pid": 14452,
"PidMode": "",
"PidsLimit": null,
[root@docker1 ~]# pstree -pl |grep 14452
|-containerd(2274)-+-containerd-shim(14435)-+-bash(14452)
可以看出我們剛剛運行的容器的pid并不是1,由此可見容器的進程和宿主機的進程是被隔離開的
3、如果把宿主機上的14452進程殺掉
[root@docker1 ~]# kill -9 14452
[root@docker1 ~]# docker ps

剛才創(chuàng)建的主機變成了停止的狀態(tài)
深入
Namespace其實只是 Linux 創(chuàng)建新進程的一個可選參數(shù)。
在 Linux 系統(tǒng)中創(chuàng)建線程的系統(tǒng)調用是 clone(),比如:
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
這個系統(tǒng)調用就會為我們創(chuàng)建一個新的進程,并且返回它的進程號 pid。
當用 clone() 系統(tǒng)調用創(chuàng)建一個新進程時,就可以在參數(shù)中指定 CLONE_NEWPID 參數(shù),比如:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
這時,新創(chuàng)建的這個進程將會"看到"一個全新的進程空間,在這空間里,它的 PID 是 1。之所以說"看到",是因為這只是一個"障眼法",在宿主機真實的進程空間里,這個進程的 PID 還是真實的數(shù)值,比如 100。
多次執(zhí)行上面的 clone() 調用,就會創(chuàng)建多個 PID Namespace,而每個 Namespace 里的應用進程,都會認為自己是當前容器里的第 1 號進程,它們既看不到宿主機里真正的進程空間,也看不到其他 PID Namespace 里的具體情況。
而除了剛用到的 PID Namespace,Linux 操作系統(tǒng)還提供了 Mount、UTS、IPC、Network 和 User 這些 Namespace,用來對各種不同的進程上下文進行"障眼法"操作。
比如,Mount Namespace,用于讓被隔離進程只看到當前 Namespace 里的掛載點信息;Network Namespace,用于讓被隔離進程看到當前 Namespace 里的網絡設備和配置。
這就是 Linux 容器最基本的實現(xiàn)原理了。
所以,Docker 容器這個聽起來玄而又玄的概念,實際上是在創(chuàng)建容器進程時,指定了這個進程所需要啟用的一組 Namespace 參數(shù)。這樣,容器就只能"看"到當前 Namespace 所限定的資源、文件、設備、狀態(tài),或者配置。而對于宿主機以及其他不相關的程序,它就完全看不到了。
所以說,容器,其實是一種特殊的進程而已。