容器Namespace - 1
Namespace是怎么回事?Linux namespace,可以理解为将全局的操作系统资源,逻辑上划分成功能独立的单元。如进程号PID,这些个单元有各自独立的PID空间,还比如网络栈,这些个独立的单元有各自独立的路由表,网络接口。linux实现了mount、UTS、IPC、network、pid、user这六种namespace。下面先用unshare来测试实验梳理一...
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
可以得出几点:
- test这个普通用户,在linux系统里是没有权限执行与mount有关的命令的,因此执行unshare这个命令也不能带-m参数。当然,如果是宿主机的管理员root执行unshare,是没有这个限制的。
- 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上是怎么回事。
更多推荐
所有评论(0)