为什么构建容器需要 Namespace ?

简介: Namespace 是 Linux 内核的一项功能,该功能对内核资源进行分区,以使一组进程看到一组资源,而另一组进程看到另一组资源。Namespace 的工作方式通过为一组资源和进程设置相同的 Namespace 而起作用,但是这些 Namespace 引用了不同的资源。资源可能存在于多个 Namespace 中。这些资源可以是进程 ID、主机名、用户 ID、文件名、与网络访问相关的名称和进程间通信。

什么是 Namespace?


Namespace 是 Linux 内核的一项功能,该功能对内核资源进行分区,以使一组进程看到一组资源,而另一组进程看到另一组资源。Namespace 的工作方式通过为一组资源和进程设置相同的 Namespace 而起作用,但是这些 Namespace 引用了不同的资源。资源可能存在于多个 Namespace 中。这些资源可以是进程 ID、主机名、用户 ID、文件名、与网络访问相关的名称和进程间通信。


Namespace 是 Linux 内核的一个特性,该特性可以实现在同一主机系统中,对进程 ID、主机名、用户 ID、文件名、网络和进程间通信等资源的隔离。Docker 利用 Linux 内核的 Namespace 特性,实现了每个容器的资源相互隔离,从而保证容器内部只能访问到自己 Namespace 的资源。


最新的 Linux 5.6 内核中提供了 8 种类型的 Namespace:

20210520150211694.png

但是最新版本的 Docker 只使用了其中的前6 种,分别为Mount Namespace、PID Namespace、Net Namespace、IPC Namespace、UTS Namespace、User Namespace。

(1)Mount Namespace


Mount Namespace 是 Linux 内核实现的第一个 Namespace,从内核的 2.4.19 版本开始加入。它可以用来隔离不同的进程或进程组看到的挂载点。通俗地说,就是可以实现在不同的进程中看到不同的挂载目录。使用 Mount Namespace 可以实现容器内只能看到自己的挂载信息,在容器内的挂载操作不会影响主机的挂载目录。


使用 unshare 命令可以实现创建并访问不同类型的 Namespace。

 unshare --mount --fork /bin/bash

执行完上述命令后,这时我们已经在主机上创建了一个新的 Mount Namespace,并且当前命令行窗口加入了新创建的 Mount Namespace。下面我通过一个例子来验证下,在独立的 Mount Namespace 内创建挂载目录是不影响主机的挂载目录的。


首先在 /tmp 目录下创建一个目录。

mkdir /tmp/tmpfs

使用 mount 命令挂载一个 tmpfs 类型的目录

mount -t tmpfs -o size=20m tmpfs /tmp/tmpfs

 df 命令查看一下已经挂载的目录信息:

20210520152230390.png

打开一个命令行窗口,同样执行 df 命令查看主机的挂载信息

20210520161643438.png

通过上面输出可以看到主机上并没有挂载 /tmp/tmpfs,可见我们独立的 Mount Namespace 中执行 mount 操作并不会影响主机。


为了进一步验证我们的想法,我们继续在当前命令行窗口查看一下当前进程的 Namespace 信息,命令如下:

20210520162045962.png

主机上的 Namespace 信息

20210520162020514.png

通过对比两次命令的输出结果,我们可以看到,除了 Mount Namespace 的 ID 值不一样外,其他Namespace 的 ID 值均一致。


通过以上结果我们可以得出结论,使用 unshare 命令可以新建 Mount Namespace,并且在新建的 Mount Namespace 内 mount 是和外部完全隔离的。

(2)PID Namespace


PID Namespace 的作用是用来隔离进程。在不同的 PID Namespace 中,进程可以拥有相同的 PID 号,利用 PID Namespace 可以实现每个容器的主进程为 1 号进程,而容器内的进程在主机上却拥有不同的PID。例如一个进程在主机上 PID 为 122,使用 PID Namespace 可以实现该进程在容器内看到的 PID 为 1。


使用以下命令创建一个 bash 进程,并且新建一个 PID Namespace:

unshare --pid --fork --mount-proc /bin/bash

执行完上述命令后,我们在主机上创建了一个新的 PID Namespace,并且当前命令行窗口加入了新创建的 PID Namespace。在当前的命令行窗口使用 ps aux 命令查看一下进程信息:

2021052016281971.png

输出结果可以看到当前 Namespace 下 bash 为 1 号进程,而且我们也看不到主机上的其他进程信息。

(3)UTS Namespace


UTS Namespace 主要是用来隔离主机名的,它允许每个 UTS Namespace 拥有一个独立的主机名。例如我们的主机名称为 docker,使用 UTS Namespace 可以实现在容器内的主机名称为 testdocker 。


实例:

unshare --uts --fork /bin/bash

创建好 UTS Namespace 后,当前命令行窗口已经处于一个独立的 UTS Namespace 中,下面我们使用 hostname 命令(hostname 可以用来查看主机名称)设置一下主机名:

tmp]# hostname -b testdocker
[root@iZ2vceej7yes1abpm7yec2Z tmp]# 
[root@iZ2vceej7yes1abpm7yec2Z tmp]# hostname
testdocker

通过上面命令的输出,我们可以看到当前UTS Namespace 内的主机名已经被修改为 testdocker。然后我们新打开一个命令行窗口,使用相同的命令查看一下主机的 hostname:

~]$ hostname
iZ2vceej7yes1abpm7yec2Z

可以看到主机的名称并没有被修改。由此,可以验证 UTS Namespace 可以用来隔离主机名。

(4)IPC Namespace


IPC Namespace 主要是用来隔离进程间通信的。例如 PID Namespace 和 IPC Namespace 一起使用可以实现同一 IPC Namespace 内的进程彼此可以通信,不同 IPC Namespace 的进程却不能通信。

]# unshare --ipc --fork /bin/bash

下面我们需要借助两个命令来实现对 IPC Namespace 的验证。


ipcs -q 命令:用来查看系统间通信队列列表。


ipcmk -Q 命令:用来创建系统间通信队列。


我们首先使用 ipcs -q 命令查看一下当前 IPC Namespace 下的系统通信队列列表:

20210520164409370.png

使用 ipcmk -Q 命令创建一个系统通信队列, 并查看

20210520164613587.png

新打开一个命令行窗口,使用ipcs -q 命令查看一下主机的系统通信队列:

20210520164725356.png

(5)User Namespace


User Namespace 主要是用来隔离用户和用户组的。一个比较典型的应用场景就是在主机上以非 root 用户运行的进程可以在一个单独的 User Namespace 中映射成 root 用户。使用 User Namespace 可以实现进程在容器内拥有 root 权限,而在主机上却只是普通用户。

User Namesapce 的创建是可以不使用 root 权限的。创建一个 User Namespace,命令如下

]# unshare --user -r /bin/bash

CentOS7 默认允许创建的 User Namespace 为 0,如果执行上述命令失败( unshare 命令返回的错误为 unshare: unshare failed: Invalid argument ),需要使用以下命令修改系统允许创建的 User Namespace 数量,命令为:echo 65535 > /proc/sys/user/max_user_namespaces,然后再次尝试创建 User Namespace。

然后执行 id 命令查看一下当前的用户信息:

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

通过上面的输出可以看到我们在新的 User Namespace 内已经是 root 用户了。下面我们使用只有主机 root 用户才可以执行的 reboot 命令来验证一下,在当前命令行窗口执行 reboot 命令:

 reboot
Failed to open /dev/initctl: Permission denied
Failed to talk to init daemon.

可以看到,我们在新创建的 User Namespace 内虽然是 root 用户,但是并没有权限执行 reboot 命令。这说明在隔离的 User Namespace 中,并不能获取到主机的 root 权限,也就是说 User Namespace 实现了用户和用户组的隔离

(6)Net Namespace


Net Namespace 是用来隔离网络设备、IP 地址和端口等信息的。Net Namespace 可以让每个进程拥有自己独立的 IP 地址,端口和网卡信息。例如主机 IP 地址为 172.16.4.1 ,容器内可以设置独立的 IP 地址为 192.168.1.1。


ip a 命令查看一下主机上的网络信息

~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:16:3e:01:77:7c brd ff:ff:ff:ff:ff:ff
    inet 172.22.138.24/20 brd 172.22.143.255 scope global dynamic noprefixroute eth0
       valid_lft 298691843sec preferred_lft 298691843sec
    inet6 fe80::216:3eff:fe01:777c/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:de:28:7f:27 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:deff:fe28:7f27/64 scope link 
       valid_lft forever preferred_lft forever
143: vethfe73229@if142: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 3e:d8:f1:ec:2f:66 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::3cd8:f1ff:feec:2f66/64 scope link 
       valid_lft forever preferred_lft forever
145: vethf2ec15d@if144: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 2e:1c:45:97:db:09 brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::2c1c:45ff:fe97:db09/64 scope link 
       valid_lft forever preferred_lft forever
187: veth25c12d2@if186: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 06:0e:a6:3c:ee:f3 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::40e:a6ff:fe3c:eef3/64 scope link 
       valid_lft forever preferred_lft forever
193: veth78adf97@if192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 52:b7:11:4d:e2:1f brd ff:ff:ff:ff:ff:ff link-netnsid 4
    inet6 fe80::50b7:11ff:fe4d:e21f/64 scope link 
       valid_lft forever preferred_lft forever

使用以下命令创建一个 Net Namespace:

 unshare --net --fork /bin/bash

2021052017220435.png

可以看到,宿主机上有 lo、eth0、docker0 等网络设备,而我们新建的 Net Namespace 内则与主机上的网络设备不同。

为什么 Docker 需要 Namespace?


Linux 内核从 2002 年 2.4.19 版本开始加入了 Mount Namespace,而直到内核 3.8 版本加入了 User Namespace 才为容器提供了足够的支持功能。


当 Docker 新建一个容器时, 它会创建这六种 Namespace,然后将容器中的进程加入这些 Namespace 之中,使得 Docker 容器中的进程只能看到当前 Namespace 中的系统资源。


正是由于 Docker 使用了 Linux 的这些 Namespace 技术,才实现了 Docker 容器的隔离,可以说没有 Namespace,就没有 Docker 容器。


问题 :docker run --net=host 命令启动容器时,容器是否和主机共享同一个 Net Namespace?


解答:如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口

相关实践学习
基于Hologres+Flink搭建GitHub实时数据大屏
通过使用Flink、Hologres构建实时数仓,并通过Hologres对接BI分析工具(以DataV为例),实现海量数据实时分析.
实时计算 Flink 实战课程
如何使用实时计算 Flink 搞定数据处理难题?实时计算 Flink 极客训练营产品、技术专家齐上阵,从开源 Flink功能介绍到实时计算 Flink 优势详解,现场实操,5天即可上手! 欢迎开通实时计算 Flink 版: https://cn.aliyun.com/product/bigdata/sc Flink Forward Asia 介绍: Flink Forward 是由 Apache 官方授权,Apache Flink Community China 支持的会议,通过参会不仅可以了解到 Flink 社区的最新动态和发展计划,还可以了解到国内外一线大厂围绕 Flink 生态的生产实践经验,是 Flink 开发者和使用者不可错过的盛会。 去年经过品牌升级后的 Flink Forward Asia 吸引了超过2000人线下参与,一举成为国内最大的 Apache 顶级项目会议。结合2020年的特殊情况,Flink Forward Asia 2020 将在12月26日以线上峰会的形式与大家见面。
目录
相关文章
|
11月前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
阿里云与企业共筑容器供应链安全
171865 127
|
11月前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
随着云计算和DevOps的兴起,容器技术和自动化在软件开发中扮演着愈发重要的角色,但也带来了新的安全挑战。阿里云针对这些挑战,组织了一场关于云上安全的深度访谈,邀请了内部专家穆寰、匡大虎和黄竹刚,深入探讨了容器安全与软件供应链安全的关系,分析了当前的安全隐患及应对策略,并介绍了阿里云提供的安全解决方案,包括容器镜像服务ACR、容器服务ACK、网格服务ASM等,旨在帮助企业构建涵盖整个软件开发生命周期的安全防护体系。通过加强基础设施安全性、技术创新以及倡导协同安全理念,阿里云致力于与客户共同建设更加安全可靠的软件供应链环境。
150509 32
|
10月前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
对话|企业如何构建更完善的容器供应链安全防护体系
对话|企业如何构建更完善的容器供应链安全防护体系
|
10月前
|
人工智能 监控 安全
容器化AI模型的安全防护:构建可信的AI服务
在AI模型广泛应用的背景下,容器化AI模型的安全防护至关重要。主要安全威胁包括数据窃取、模型窃取、对抗样本攻击和模型后门攻击等。为应对这些威胁,需采取多层次防护措施:容器安全(如使用可信镜像、限制权限)、模型安全(如加密、水印)、数据安全(如加密、脱敏)和推理安全(如输入验证、异常检测)。此外,利用开源工具如Anchore Engine、Falco和ART等,可进一步加强防护。遵循安全开发生命周期、最小权限原则和深度防御等最佳实践,确保AI服务的安全性和可信度。
|
10月前
|
机器学习/深度学习 数据采集 人工智能
容器化机器学习流水线:构建可复用的AI工作流
本文介绍了如何构建容器化的机器学习流水线,以提高AI模型开发和部署的效率与可重复性。首先,我们探讨了机器学习流水线的概念及其优势,包括自动化任务、确保一致性、简化协作和实现CI/CD。接着,详细说明了使用Kubeflow Pipelines在Kubernetes上构建流水线的步骤,涵盖安装、定义流水线、构建组件镜像及上传运行。容器化流水线不仅提升了环境一致性和可移植性,还通过资源隔离和扩展性支持更大规模的数据处理。
|
11月前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
本期节目围绕软件供应链安全、容器安全的主要挑战以及阿里云如何帮助用户等维度展开了深入的讨论。
|
9月前
|
缓存 JavaScript 前端开发
Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具
Dockerfile 是容器化开发中的关键工具。理解并掌握其使用方式,不仅能提高开发效率,还能让你的应用具备更强的可移植性和灵活性。通过优化配置和合理安排构建步骤,可以打造更轻量、更高效的容器镜像。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
4月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
830 108

热门文章

最新文章