linux(centos8):使用namespace做資源隔離


一,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 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM