使用golang理解Linux namespace(一)- 基础

Linux namespace是何物

在展开学习命名空间发现,大多数教程都基于C语言讲解,其实也很合理,毕竟Linux的历史由来就这样,但是为了更加简便,这里采用golang来进行讲解。

说来惭愧,Linux namespace是我在接触了docker之后才了解的概念,由于之前使用dotnet开发,也没接触这方面的东西,(C#中也有个命名空间的概念😂),显然这里是不一样的。

Linux namespace是现代容器实现最基础的基础了,主要可以用于系统资源的隔离,比如不同的进程间实现不同资源的独立。

对应容器来说这是一个很关键的点,比如,进程A要卸载一个目录,此时不应该影响B,而B要改变一个网络也不应该影响C。这就可以通过namespace来隔离。

注意,这有个知识点还要强调下,namespace并不限制物理资源的访问,比如CPU内存之类的。 要对资源访问实行限制,是通过另一种技术叫cgroups如果后面有机会的话再介绍好了

小试牛刀

以下命令默认在centos 7下测试,其他Linux发行版应该也ok

 [email protected]: 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的改变仅限于此进程。在此进程之外并没有变化。


[email protected]: sudo su //切换用户
[email protected]: hostname //当前主机名,看到是vm41
vm41
[email protected]: 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
[email protected]: 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命令来引出命名空间的概念,后面还有很多实用的讲解和理论。

参考:https://medium.com/@teddyking/linux-namespaces-850489d3ccf