容器Namespace - 1

Namespace是怎麼回事?

       Linux namespace,可以理解爲將全局的操作系統資源,邏輯上劃分成功能獨立的單元。如進程號PID,這些個單元有各自獨立的PID空間,還比如網絡棧,這些個獨立的單元有各自獨立的路由表,網絡接口。linux實現了mount、UTS、IPC、network、pid、user這六種namespace。

 

下面先用unshare來測試實驗梳理一下linux namespace。

[root@centos ~]# unshare --help

Usage:

  unshare [options] <program> [<argument>...]

Run a program with some namespaces unshared from the parent.



Options:

 -m, --mount             unshare mounts namespace

 -u, --uts                unshare UTS namespace (hostname etc)

 -i, --ipc                 unshare System V IPC namespace

 -n, --net                unshare network namespace

 -p, --pid                unshare pid namespace

 -U, --user               unshare user namespace

 -f, --fork                fork before launching <program>

   --mount-proc[=<dir>]   mount proc filesystem first (implies --mount)

 -r, --map-root-user       map current user to root (implies --user)
[root@centos ~]# unshare -m --mount-proc -u -i -n -p -U -r -f  /bin/bash

unshare: unshare failed: Invalid argument    // 說明是哪個參數不支持



逐個減少參數後,反覆執行後,確認是-U這個參數的問題。

只指定-U參數

[root@centos ~]# unshare -U  /bin/bash

unshare: unshare failed: Invalid argument    // 問題確認, user namespace不支持嗎?

 

查詢了網上資料,確認了docker版本、內核都已經支持user ns的前提下,centos7默認沒有啓用user namespace。

 

執行下面的命令啓用user namespace,然後reboot

[root@centos ~]# grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"

資料來源:

https://github.com/procszoo/procszoo/wiki/How-to-enable-%22user%22-namespace-in-RHEL7-and-CentOS7%3F

Reboot後,執行下面的命令:

[root@centos ~]# unshare -m --mount-proc -u -i -n -p -U -r -f  /bin/bash

[root@centos ~]# ip link

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

在新的network namespace,只存在loop這個設備

[root@centos ~]# ip route

[root@centos ~]

在新的network namespace,路由表是空的

[root@centos ~]# ip link add  type veth    // 添加veth設備

[root@centos ~]# ip link

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

    link/ether 52:e9:ba:d6:23:4e brd ff:ff:ff:ff:ff:ff

3: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

    link/ether ba:6f:7a:dc:9f:4b brd ff:ff:ff:ff:ff:ff

在新的network namespace,創建了veth設備

 

[root@centos ~]# hostname onecloud

[root@centos ~]# hostname

onecloud

在宿主機上執行hostname

[root@centos ~]# hostname

centos

在新的UTS namespace,可以設置屬於自己的hostname, domain

 

[root@centos ~]#mkdir /tmp1 && mount -t tmpfs -o size=20m tmpfs /tmp1

[root@centos ~]# df -h | grep tmp1

tmpfs          20M     0   20M   0% /tmp1

在宿主機上執行

[root@centos ~]# df -h | grep tmp1

[root@centos ~]#

在新的mount namespace,執行mount動作後,宿主機被屏蔽了。這也是容器volume工作的基礎(volume相關的知識會另外講到)。

 

[root@centos ~]# ps -ef

UID        PID  PPID  C STIME TTY          TIME CMD

root         1     0  0 11:08 pts/3    00:00:00 /bin/bash

root        12     1  0 11:09 pts/3    00:00:00 ps -ef

在宿主機執行

[root@centos ~]# ps -ef

root     14069 14052  0 11:08 pts/3    00:00:00 unshare -m --mount-proc -u -i -n -p -U -r -f /bin/bash

root     14071 14069  0 11:08 pts/3    00:00:00 /bin/bash

root     14100   967  0 11:09 ?        00:00:00 sleep 60

root     14106 13000  0 11:10 pts/2    00:00:00 ps -ef

在新的pid namespace,bash是第一號進程

 

接下來,我們來看看有點模糊的user namespace

執行下面的命令:

[test@centos ~]$ id

uid=1000(test) gid=1000(test) groups=1000(test)

[test@centos ~]$ hostname test

hostname: you must be root to change the host name

[test@centos ~]$ unshare -m --mount-proc -u -i -n -p -U -r -f  /bin/bash

unshare: unshare failed: Operation not permitted

[test@centos ~]$ unshare -u -i -n -p -U -r -f  /bin/bash   //去掉了參數-m --mount-proc

[root@centos ~]# id

uid=0(root) gid=0(root) groups=0(root)

[root@centos ~]# hostname test

[root@centos ~]# mount -t tmpfs -o size=20m tmpfs /tmp1

mount: permission denied

[root@centos ~]# ip link add type veth

[root@centos ~]# ip link

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

    link/ether 3e:93:49:1a:0b:bc brd ff:ff:ff:ff:ff:ff

3: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

    link/ether 82:f2:8d:1e:18:e3 brd ff:ff:ff:ff:ff:ff

[root@centos ~]# useradd jacky

bash: /usr/sbin/useradd: Permission denied

 

可以得出幾點:

  1. test這個普通用戶,在linux系統裏是沒有權限執行與mount有關的命令的,因此執行unshare這個命令也不能帶-m參數。當然,如果是宿主機的管理員root執行unshare,是沒有這個限制的。
  2. user namespace的默認管理員root,是“map test user to root”而來,有權限設置主機名,管理網絡,沒有權限mount,也沒有權限管理用戶

 

那麼如果是管理員root的情況呢?

先準備一個centos 的rootfs

mkdir /opt/rootfs && cd /opt

docker export $(docker create centos) | tar -C ./rootfs -xf -

[root@centos opt]# unshare -m --mount-proc -u -i -n -p -U -r -f  /bin/bash

[root@centos opt]# chroot ./rootfs/

[root@centos /]# useradd peter     //創建新的用戶

[root@centos /]# passwd

Changing password for user root.   // 重新設置root管理員的密碼

New password:

BAD PASSWORD: The password is a palindrome

Retype new password:

passwd: all authentication tokens updated successfully.

我們用命令chroot將rootfs切換到了/opt/rootfs,因此ueradd、passwd命令的結果就不會影響宿主機系統的配置。如果不切換rootfs,那useradd、passwd改變的就是宿主機系統的配置,這將是很危險的

 

我們再從用戶態看看,linux系統的namespace是怎麼樣的形式:

[root@centos opt]# unshare -m --mount-proc -u -i -n -p -U -r -f  /bin/bash

[root@centos opt]# ps -ef

UID        PID  PPID  C STIME TTY          TIME CMD

root         1     0  0 14:08 pts/2    00:00:00 /bin/bash

root        12     1  0 14:08 pts/2    00:00:00 ps -ef

[root@centos opt]# ll /proc/1/ns/       // 1號進程創建了新的namespace

total 0

lrwxrwxrwx 1 root root 0 Apr 26 14:08 ipc -> ipc:[4026532455]

lrwxrwxrwx 1 root root 0 Apr 26 14:08 mnt -> mnt:[4026532452]

lrwxrwxrwx 1 root root 0 Apr 26 14:08 net -> net:[4026532458]

lrwxrwxrwx 1 root root 0 Apr 26 14:08 pid -> pid:[4026532456]

lrwxrwxrwx 1 root root 0 Apr 26 14:08 user -> user:[4026532450]

lrwxrwxrwx 1 root root 0 Apr 26 14:08 uts -> uts:[4026532454]

[root@centos opt]# exit

exit

[root@centos opt]# ll /proc/1/ns      // 宿主機1號進程的namespace

total 0

lrwxrwxrwx 1 root root 0 Apr 26 14:11 ipc -> ipc:[4026531839]

lrwxrwxrwx 1 root root 0 Apr 26 14:11 mnt -> mnt:[4026531840]

lrwxrwxrwx 1 root root 0 Apr 26 14:11 net -> net:[4026531962]

lrwxrwxrwx 1 root root 0 Apr 26 14:11 pid -> pid:[4026531836]

lrwxrwxrwx 1 root root 0 Apr 26 14:11 user -> user:[4026531837]

lrwxrwxrwx 1 root root 0 Apr 26 14:11 uts -> uts:[4026531838]

很顯然,這些個ns的id表示它們是屬於不同的namespace。

 

好了,通過上面的過程,我們基本上明白了namespace在linux上是怎麼回事。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章