一,namespace是什么?
namespace 是 Linux 內核用來隔離內核資源的方式。
它是對全局系統資源的封裝隔離,
處於不同 namespace 的進程擁有獨立的全局系統資源,
改變一個 namespace 中的系統資源只會影響當前 namespace 里的進程,
對其他 namespace 中的進程沒有影響
每個namespace下的資源對於其他namespace下的資源是透明的,不可見的。
從操作系統角度看,可以出現多個相同pid的進程,
由於它們屬於不同的namespace,所以進程之間並不沖突。
從用戶角度看,只能看到屬於用戶自己namespace下的資源,
例如:ps命令只能列出自己namespace下的進程。
說明:劉宏締的架構森林是一個專注架構的博客,地址:https://www.cnblogs.com/architectforest
對應的源碼可以訪問這里獲取: https://github.com/liuhongdi/
說明:作者:劉宏締 郵箱: 371125307@qq.com
二,namespace的用途?
當前linux內核中提供了7類namespace,分別用於:
Cgroup :Cgroup 根目錄
IPC :System V IPC/POSIX 消息隊列
Network :網絡設備/協議棧/端口
Mount :掛載點
PID :進程ID
User :用戶和group ID
UTS :Hostname和NIS域名
三,查看一個進程所屬的namespace
1,得到一個nginx進程的id
[root@blog ~]# ps auxfww | grep nginx: root 491 0.0 0.0 71028 3368 ? Ss May18 0:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx nginx 492 0.0 0.0 102496 7036 ? S May18 0:00 \_ nginx: worker process nginx 493 0.0 0.0 102764 7496 ? S May18 0:00 \_ nginx: worker process nginx 494 0.0 0.0 102496 5856 ? S May18 0:00 \_ nginx: worker process …
我們選擇492這個進程
2,查看492這個進程的namespace
[root@blog ~]# ls /proc/492/ns/ cgroup ipc mnt net pid pid_for_children user uts
3,這些namespace文件的類型是符號鏈接
[root@blog ns]# ll /proc/492/ns/ total 0 lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 ipc -> 'ipc:[4026531839]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 mnt -> 'mnt:[4026532277]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 net -> 'net:[4026531992]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 pid -> 'pid:[4026531836]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 pid_for_children -> 'pid:[4026531836]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 user -> 'user:[4026531837]' lrwxrwxrwx 1 nginx nginx 0 Jun 15 13:32 uts -> 'uts:[4026531838]’
鏈接文件的內容的格式為 xxx:[inode number]。
xxx 是 namespace 的類型,
inode number 用來標識一個 namespace,
四,查看一個進程的mnt namespace信息
1,mnt namespace的掛載點信息,記錄在下面的3個文件中
[root@blog ns]# ll /proc/492/mount* -r--r--r-- 1 nginx nginx 0 Jun 13 23:23 /proc/492/mountinfo -r--r--r-- 1 nginx nginx 0 Jun 13 23:23 /proc/492/mounts -r-------- 1 nginx nginx 0 Jun 13 23:23 /proc/492/mountstats
mnt namespace的作用:隔離mount point,
每個mnt namespace內的文件結構可以單獨進行修改,互不影響
2,我們做一個試驗驗證mnt namespace:
先創建兩個目錄,下面各創建一個文件:
[root@localhost ~]# mkdir /root/hosta [root@localhost ~]# touch /root/hosta/a.txt [root@localhost ~]# mkdir /root/hostb [root@localhost ~]# touch /root/hostb/b.txt
查看當前的mnt目錄:
[root@localhost ~]# ls /mnt hgfs
新開啟兩個終端:
在終端a中進行如下操作:
創建新的mount namespace和uts namespace,並運行bash
[root@localhost ~]# unshare --mount --uts bash
修改主機名為hosta
[root@localhost ~]# hostname hosta && exec bash
查看當前進程中mnt和uts兩個namespace的inode number
#$$:當前的進程id
[root@hosta ~]# readlink /proc/$$/ns/{mnt,uts} mnt:[4026532774] uts:[4026532775]
掛載hosta目錄到mnt下
[root@hosta ~]# mount --bind hosta/ /mnt/ [root@hosta ~]# ls /mnt a.txt
3,回到最早的localhost終端中查看:
[root@localhost ~]# ls /mnt hgfs
/mnt目錄下的內容沒有變,說明localhost終端與 hosta終端的mount namespace是成功隔離的
在終端b中進行以下操作:
創建新的mount namespace和uts namespace,並運行bash
[root@localhost ~]# unshare --mount --uts bash
修改主機名為hostb
[root@localhost ~]# hostname hostb && exec bash
查看當前進程中mnt和uts兩個namespace的inode number
#$$:當前的進程id
[root@hostb ~]# readlink /proc/$$/ns/{mnt,uts} mnt:[4026532706] uts:[4026532707]
掛載hostb目錄到mnt下
[root@hostb ~]# mount --bind hostb/ /mnt/ [root@hostb ~]# ls /mnt b.txt
五,測試pid namespace
#—fork:以unshare的子進程來啟動bash
[root@localhost ~]# unshare --pid --uts --mount --fork bash
修改hostname,作為標識
[root@localhost ~]# hostname hosta && exec bash [root@hosta ~]# echo $$ 1
當前的進程id是1
#-p:顯示pid
#-l: 顯示長的行(不按COLUMNS這個環境變量去截取寬度)
[root@hosta ~]# pstree -pl systemd(1)─┬─ModemManager(871)─┬─{ModemManager}(911) │ └─{ModemManager}(924) ├─NetworkManager(867)─┬─dhclient(993) │ ├─{NetworkManager}(915) │ └─{NetworkManager}(925) …
用pstree可以看到:pid為1的進程是systemd
這是因為這里的proc是unshare給帶來的mount namespace的/proc
包括查看ns下的inode number也是如此,
[root@hosta ~]# readlink /proc/$$/ns/{pid,uts,mnt} pid:[4026531836] uts:[4026531838] mnt:[4026531840]
需要重新掛載/proc
[root@hosta liuhongdi]# mount --types proc proc /proc/ [root@hosta liuhongdi]# pstree -pl bash(1)───pstree(70)
說明:如果用unshare啟動bash時,加 --mount-proc 參數,則不需要重新掛載/proc
再次查看ns下的inode number,也可以正確顯示了
[root@hosta liuhongdi]# readlink /proc/$$/ns/{pid,uts,mnt} pid:[4026532779] uts:[4026532778] mnt:[4026532777]
六,查看linux的版本:
[root@node1 ~]# more /etc/redhat-release CentOS Linux release 8.1.1911 (Core) [root@node1 ~]# uname -r 4.18.0-147.el8.x86_64
