在展开学习命名空间发现,大多数教程都基于C语言讲解,其实也很合理,毕竟Linux的历史由来就这样,但是为了更加简便,这里采用golang来进行讲解。
说来惭愧,Linux namespace是我在接触了docker之后才了解的概念,由于之前使用dotnet开发,也没接触这方面的东西,(C#中也有个命名空间的概念😂),显然这里是不一样的。
Linux namespace是现代容器实现最基础的基础了,主要可以用于系统资源的隔离,比如不同的进程间实现不同资源的独立。
对应容器来说这是一个很关键的点,比如,进程A要卸载一个目录,此时不应该影响B,而B要改变一个网络也不应该影响C。这就可以通过namespace来隔离。
注意,这有个知识点还要强调下,namespace并不限制物理资源的访问,比如CPU内存之类的。 要对资源访问实行限制,是通过另一种技术叫cgroups如果后面有机会的话再介绍好了
小试牛刀
以下命令默认在centos 7下测试,其他Linux发行版应该也ok
root@vm41: unshare -h
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)
--propagation <slave|shared|private|unchanged>
modify mount propagation in mount namespace
-s, --setgroups allow|deny control the setgroups syscall in user namespaces
-h, --help display this help and exit
-V, --version output version information and exit
For more details see unshare(1).
看到帮助是说unshare命令可以从父进程中脱离,用另外一个命名空间运行一个程序。
那就用这个命令来测试UTS命名空间最合适不过了,UTS命名空间可以提供独立的主机名和域名等系统标志,具体是不是不同。
可以在任意的UTS命名下的/bin/sh 进程运行hostname my-new-hostname
测试出来。并可以得知hostname的改变仅限于此进程。在此进程之外并没有变化。
root@vm41: sudo su //切换用户
root@vm41: hostname //当前主机名,看到是vm41
vm41
root@vm41: unshare -u /bin/sh //用新的UTS命名空间创建一个sh进程
sh-4.2#
sh-4.2# hostname my-new-hostname //设置新的主机名
sh-4.2# hostname //查看此时主机名已经改变
my-new-hostname
sh-4.2# exit //退出新的的UTS命名空间
exit
root@vm41: hostname //确认原主机名并未受影响
vm41
主要是考虑到创建命名空间需要root权限,所以一开始就切换了su,当然我本来就是root用户,这里是通过hostname来测试。
可以看到,原命名空间hostname是vm41,然后用unshare命令创建的进程改变了hostname为my-new-hostname,这是一个新的,独立的UTS命名空间。
因此在这里修改了主机名,它并不会影响到原来的UTS命名空间上,为什么呢,因为这里执行exit后,回来原命名空间可以看到hostname的值并没有改动。
7种namespace类型
上面的🌰已经简要地演示了UTS命名空间的魔力,实际上还有很多,在写这篇文章的时候就已经有7种命名空间。
分别是
- Mount - 用于独立文件系统和挂载点
- UTS -用于独立hostname和domainname
- IPC - 用于独立进程之间的通信资源nterprocess communication (IPC)
- PID - 用于独立PID号空间
- Network -用于间隔网络接口interfaces
- User - 用于间隔UID/GID空间
- Cgroup - 用于间隔cgroup root目录
可以确定的是,不同的容器实现都是基于以上的命名空间进行处理,不一而足,理论归理论,实现归实现,本文暂不会全部解释,但是可以留着以后再慢慢解释。
后续
最后,本文只是用unshare
命令来引出命名空间的概念,后面还有很多实用的讲解和理论。