理解uts namespace
uts(UNIX Time-Sharing System) namespace可隔離hostname和NIS Domain name資源,使得一個宿主機可擁有多個主機名或Domain Name。換句話說,可讓不同namespace中的進程看到不同的主機名。
例如,使用unshare命令(較新版本Linux內核還支持nscreate命令)創建一個新的uts namespace:
#?-u或--uts表示創建一個uts?namespace
#?這個namespace中運行/bin/bash程序
$?hostname
longshuai-vm??????#?當前root?namespace的主機名為longshuai-vm
$?sudo?unshare?-u?/bin/bash
root@longshuai-vm:/home/longshuai#???#?進入了新的namespace中的shell#?其主機名初始時也是longshuai-vm,#?其拷貝自上級namespace資源
上面指定運行的是/bin/bash程序,這會進入交互式模式,當執行exit時,bash退出,回到當前的namespace中。也可以指定在namespace中運行其他程序,例如unshare -u sleep 3
表示在uts namespace中睡眠3秒后退出并回到當前namespace。
因為是uts namespace,所以可在此namespace中修改主機名:
#?修改該namespace的主機名為ns1
#?修改后會立即生效,但不會顯示在當前Shell提示符下
#?需重新加載Shell環境
root@longshuai-vm:/home/longshuai#?hostname?ns1
root@longshuai-vm:/home/longshuai#?hostname
ns1
root@longshuai-vm:/home/longshuai#?exec?$SHELL
root@ns1:/home/longshuai#
namespace中修改的主機名不會直接修改主機名配置文件(如/etc/hostname),而是修改內核屬性/proc/sys/kernel/hostname:
root@ns1:/home/longshuai#?cat?/proc/sys/kernel/hostname
ns1
root@ns1:/home/longshuai#?cat?/etc/hostname?
longshuai-vm
創建了新的namespace并在其中運行/bin/bash進程后,再去關注一下進程關系:
#?ns1中的bash進程PID
root@ns1:/home/longshuai#?echo?$$
14279#?bash進程(PID=14279)和grep進程運行在ns1?namespace中,
#?其父進程sudo(PID=14278)運行在ns1的上級namespace即root?namespace中
root@ns1:/home/longshuai#?pstree?-p?|?grep?$$|-sshd(10848)---bash(10850)---sudo(14278)---bash(14279)-+-grep(14506)#?運行在ns1中當前bash進程(PID=14279)的namespace
root@ns1:/home/longshuai#?ls?-l?/proc/14279/ns
lrwxrwxrwx?...?cgroup?->?'cgroup:[4026531835]'
lrwxrwxrwx?...?ipc?->?'ipc:[4026531839]'
lrwxrwxrwx?...?mnt?->?'mnt:[4026531840]'
lrwxrwxrwx?...?net?->?'net:[4026531992]'
lrwxrwxrwx?...?pid?->?'pid:[4026531836]'
lrwxrwxrwx?...?pid_for_children?->?'pid:[4026531836]'
lrwxrwxrwx?...?user?->?'user:[4026531837]'
lrwxrwxrwx?...?uts?->?'uts:[4026532588]'??#?注意這一行,和sudo進程的uts?inode不同#?父進程sudo(PID=14278)不在ns1中,它的namespace信息
root@ns1:/home/longshuai#?ls?-l?/proc/14278/ns
lrwxrwxrwx?...?cgroup?->?'cgroup:[4026531835]'
lrwxrwxrwx?...?ipc?->?'ipc:[4026531839]'
lrwxrwxrwx?...?mnt?->?'mnt:[4026531840]'
lrwxrwxrwx?...?net?->?'net:[4026531992]'
lrwxrwxrwx?...?pid?->?'pid:[4026531836]'
lrwxrwxrwx?...?pid_for_children?->?'pid:[4026531836]'
lrwxrwxrwx?...?user?->?'user:[4026531837]'
lrwxrwxrwx?...?uts?->?'uts:[4026531838]'???#?注意這一行,和PID=1的uts?inode相同
回到創建uts namespace時敲下的unshare命令:
sudo?unshare?-u?/bin/bash
從進程關系...---sudo(14278)---bash(14279)
可知兩個進程PID是連續的,說明unshare程序對應的進程被/bin/bash程序通過execve()替換了。
詳細的過程如下:「sudo進程運行在當前namespace中,它將fork一個新進程來運行unshare程序,unshare程序加載完成后,將創建一個新的uts namespace,unshare進程自身將加入到這個uts namespace中,unshare進程內部再exec加載/bin/bash,于是unshare進程被替換為/bin/bash進程,/bin/bash進程也將運行在uts namespace中」。
當namespace中的/bin/bash進程退出,該namespace中將沒有任何進程,該namespace將自動銷毀。注意,在默認情況下,namespace中必須要有至少一個進程,否則將被自動被銷毀。但也有一些手段可以讓namespace持久化,即使已經沒有任何進程在其中運行。
如果在ns1中再創建一個namespace ns2,這個ns2初始時將共享ns1的其他資源并拷貝ns1的主機名資源,其初始主機名也為ns1。
$?sudo?unshare?-u?/bin/bash????#?在root?namespace環境下創建一個namespace
root@longshuai-vm:/home/longshuai#?hostname?ns1?#?修改主機名為ns1
root@longshuai-vm:/home/longshuai#?hostname
ns1#?在ns1中創建一個namespace
############?注意沒有sudo
root@longshuai-vm:/home/longshuai#?unshare?-u?/bin/bash?
root@ns1:/home/longshuai#?hostname????#?初始主機名拷貝自上級namespace的主機名ns1
ns1
root@ns1:/home/longshuai#?hostname?ns2
root@ns1:/home/longshuai#?hostname??#?修改主機名為ns2
ns2
root@ns1:/home/longshuai#?exit
exitroot@longshuai-vm:/home/longshuai#?hostname??#?ns2修改主機名不影響ns1
ns1
root@longshuai-vm:/home/longshuai#?exit
exit[~]->$?hostname??????#?ns1修改主機名不影響root?namespace
longshuai-vm
注意,即使root namespace當前用戶為longshuai,但因為使用了sudo創建ns1,進入ns1后其用戶名為root,所以在ns1中執行unshare命令創建新的namespace不需要再使用sudo。
$?echo?$USER??????#?當前root?namespace的用戶為longshuai
longshuai$?sudo?unshare?-u?/bin/bash
root@longshuai-vm:/home/longshuai#?echo?$USER??#?ns中的用戶名變為root
root
root@longshuai-vm:/home/longshuai#?id;echo?$HOME;echo?~
uid=0(root)?gid=0(root)?groups=0(root)
/root
/root