根據代碼看到,pause容器運行着一個非常簡單的進程,它不執行任何功能,一啟動就永遠把自己阻塞住了,
它的作用就是扮演PID1的角色,並在子進程稱為"孤兒進程"的時候,通過調用wait()收割這個子進程,這樣就不用擔心我們的Pod的PID namespace里會堆滿僵屍進程了,這也是為什么kubernetes不隨便找個容器,例如Nginx作為父容器,讓其他容器加入的原因
共享namespace的意思就是父進程先創建一個namespace,然后其他進程加入到該namespace就共享namespace了
一、從network namespace看pause容器
使用pause容器和共享namespace創建Pod
使用docker啟動pause進程,以便可以將其他容器添加到Pod中
docker run -d --name pause gcr.io/google_containers/pause-amd64:3.0
然后,在Pod中運行其他容器,分別是Nginx代理和ghost博客應用
Nginx代理的后端配置成http://127.0.0.1:2368,也就是ghost進程監聽的地址
##創建nginx配置文件 vim nginx.conf error_log stderr; events { worker_connections 1024; } http { access_log /dev/stdout combined; server { listen 80 default_server; server_name www.example.com; location / { proxy_pass http://127.0.0.1:2368 } } } ##啟動nginx容器 docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf -p 8080:80 --net=container:pause --ipc=container:pause --pid=container:pause nginx
為ghost博客應用程序創建另一個容器
docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghost
在這個例子中,我們將nginx容器和ghost容器 加入到pause容器的namespace,如果要訪問http://localhost:8080,就能看到ghost通過nginx代理運行,因為pause、nginx、ghost容器之間共享network namespace
注意:共享network namespace,一個pod中的nginx容器才能通過127.0.0.1:2368找到ghost,因為在一個network namespace內,才能通過localhost通信,相當於在一台機器里
二、從PID namespace看容器
在UNIX系統中,PID為1 的進程是init進程,即所有進程的父進程.init進程比較特殊,它維護一張進程表並且不斷的檢查其他進程的狀態.init進程其中一個作用就是當某個子進程由於父進程的錯誤退出而變成了"孤兒進程",就會被init進程"收養"並在該進程退出時回收系統資源
在容器中PID namespace對PID進行隔離,因此每個容器中都可以有獨立的init進程.當在主機發送SIGKILL或者SIGSTOP(也就是docker kill或者docker stop命令)強制終止容器的運行時,其實就是在終止容器內的init進程.一旦init進程被銷毀,同一PID namespace下的進程也隨之被銷毀
容器中,必須要有一個進程充當每個PID namespace的init進程,使用docker的話,ENTRYPOINT進程就是init進程,如果多個容器之間共享PID namespace,那么擁有PID namespace的那個進程要承擔init進程的角色,其他容器作為init進程的子進程添加到PID namespace中
舉例說明用戶容器和PID容器的關系
先啟動一個pause容器
docker run -idt --name pause gcr.io/google_containers/pause_amd64:3.0
在運行一個busybox容器,加入pause容器的namespace(Network PID IPC)
docker run -idt --name busybox --net=container:pause --pid=container:pause --ipc=container:pause busybox
上面這種加入的方式也是kubernetes啟動pod的原理
進入busybox容器查看里面的進程,發現PID=1的進程是/pause
docker exec -it busybox /bin/bash / # ps aux PID USER TIME COMMAND 1 root 0:00 /pause 5 root 0:00 sh 9 root 0:00 /bin/bash 13 root 0:00 ps aux
為什么不用別的容器做init進程,比如Nginx容器,如果由於子進程的父進程意外退出,那么子進程就成了"孤兒進程",Nginx容器沒辦法回收子進程退出后的資源