极客时间运维进阶训练营第一周作业----docker学习之namespace
namespace,是linux底层的概念,由内核层实现,各个docker容器运行在同一个docker主进程并使用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间,于是就由namespace为同一台宿主机上的各个容器提供互相隔离的运行空间,即同一宿主机上的容器可以同时存在相同的文件系统、挂载点、主机名、进程树等,并且保护宿主机内核不受其他进程的干扰和影响。随着linux内核版本的迭代更新,支持的namespace类型也逐步增加。
各个类型的namespace的功能、 系统调用参数及所需要的内核版本如下:
隔离类型 |
功能 |
系统调用参数 |
内核版本 |
MNT Namespace(mount) |
提供磁盘挂载点和文件系统的隔离能力 |
CLONE_NEWNS |
Linux 2.4.19 |
IPC Namespace(Inter-Process Communication) |
提供进程间通信的隔离能力 |
CLONE_NEWIPC |
Linux 2.6.19 |
UTS Namespace(UNIX Timesharing System) |
提供主机名隔离能力 |
CLONE_NEWUTS |
Linux 2.6.19 |
PID Namespace(Process Identification) |
提供进程隔离能力 |
CLONE_NEWPID |
Linux 2.6.24 |
Net Namespace(network) |
提供网络隔离能力 |
CLONE_NEWNET |
Linux 2.6.29 |
User Namespace(user) |
提供用户隔离能力 |
CLONE_NEWUSER |
Linux 3.8 |
Time Namespace |
提供时间隔离能力 |
CLONE_NEWTIME |
Linux 5.6 |
Syslog Namespace |
提供syslog隔离能力 |
syslog namespace是由华为工程师RuiXiang(瑞翔)提出的,但没有合并到linux内核中,后systemd在2020年2月实现了一个名为 “journal namespace”的类似功能 |
|
Control group (cgroup) Namespace |
提供进程所属的控制组的身份隔离 |
Linux 4.6 |
接下来通过简单测试观察并总结一下各类型namespace的作用
(实验环境为Ubuntu 22.04.1 LTS操作系统,5.15.0-50-generic内核)
我在一台虚拟机上使用相同命令启动了两个容器,后面的操作均在这两个容器上完成。
root@docker1:/home/z9999# docker run -it -d httpd 7f34e157106ad9a47177a7813330934bccf46423df372b9ceda2614fe27fa14a root@docker1:/home/z9999# docker run -it -d httpd 3ed286e00c975cebc75c94f79c2f4bc41898c30c6c1ced8489eee5c21ded1893 root@docker1:/home/z9999# docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed286e00c97 httpd "httpd-foreground" 11 seconds ago Up 10 seconds 80/tcp condescending_kapitsa 7f34e157106a httpd "httpd-foreground" 13 seconds ago Up 12 seconds 80/tcp affectionate_shirley
MNT Namespace(mount):每个容器都有独立的根文件系统、独立的用户控件,以实现在容器里面启动服务并且使用容器的运行环境。并且在容器内不能访问其他容器或宿主机等当前容器未挂载的任何文件系统。
我分别将两个容器的container id写入了容器中/test文件,再使用cat命令查看一下
可以看到相同路径相同文件名但内容不一样,说明确实是两个隔离的文件系统
IPC Namespace(Inter-Process Communication):隔离进程间通信资源,同一个IPC namespace的进程可以共享内存等资源,但是不同的IPC namespace是隔离的
这里简单测试一下内存的隔离,分别在两个容器中使用env命令查看环境变量,其中有相同的变量不同的值,变量是存放在内存中的,当然也体现了IPC namespace隔离内存的作用
UTS Namespace(UNIX Timesharing System):UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息,用户系统标识,其中包含了hostname和域名,他使得每一个容器都拥有属于自己的hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器。
因为使用相同的命令相同的镜像运行了两个容器,所以内核名称和版本等信息都是一至的,但通过上面两个图可以看出两个容器和宿主机的主机名都是不同的。
PID Namespace(Process Identification):Linux系统中,有一个PID为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其他下属的子进程,就那么多个容器的进程通过PID namespace进行隔离(比如PID编号重复、容器内的主进程生成与子进程回收等)。
可以看到两个容器都有PID1和他们的子进程
Net Namespace(network):每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,docker使用network namespace启动一个venth X接口,这样你的容器将有它自己的桥接IP地址,通常是docker0,而docker0其实就是linux的虚拟网桥,网桥实在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。
使用ifconfig查看网卡信息,两个容器都有一个eth0,ip和mac地址却不同,由此可见是两个完全独立的网络设备
而且还可以在/var/run/docker/netns中看到
User Namespace(user):user namespace允许在同意宿主机上的各个容器空间内创建相同的用户名以及相同的UID和GID,只是会把用户的作用范围限制在每个容器内。
为了方便观察,这里我只显示了各个容器中用户的前三行,三个容器中都有相同的用户,且UID和GID也一样,并且这些用户都只能访问所属容器内的文件系统。
Control group (cgroup) Namespace:在一个容器中,如果不对其做任何资源限制,则宿主机会允许容器占用无线大的内存空间,有时候会因为代码BUG程序会一直申请内存,直到把宿主机内存占满,为了避免此类问题的出现,江苏主机有必要对容器进行资源分配限制,比如CPU、内存、网络带宽等。此外,还能对进程进行优先级设置,以及将进程挂起和回复等操作。
知识扩展:
unshare命令unshare - run program with some namespaces unshared from parent(使用与父程序不共享的名称空间运行程序),在下面这篇文章中详细解释了unshare的使用方法,还通过更具体的实验解释了各类型namespace功能
(85条消息) unshare命令详解及案例_张哲溪的博客-CSDN博客_unshare
MNT Namespace(mount):每个容器都有独立的根文件系统、独立的用户控件,以实现在容器里面启动服务并且使用容器的运行环境。