NameSpace
NameSpace介绍
在操作系统中命名空间命名空间提供的是系统资源的隔离,其中系统资源包括了:进程、网络、文件系统等等
-
实际上linux系统实现命名空间主要目的之一就是为了实现轻量级虚拟化服务,也就是我们说的容器,在同一个命名空间下的进程可以感知彼此的变化,而对其他命名空间的进程一无所知,这样就可以让容器中的进程产生一个错觉,仿佛它自己置身于一个独立的系统环境当中,以此达到独立和隔离的目的。
Linux的namespace(名字空间)的作用就是“隔离内核资源”。
在Linux的世界里,
文件系统挂载点、
主机名、
POSIX进程间通信消息队列、
进程PID数字空间、
IP地址、
user ID数字空间等全局系统资源被namespace分割,装到一个个抽象的独立空间里。
而隔离上述系统资源的namespace分别是Mount namespace、UTS namespace、IPC namespace、PID namespace、network namespace和user namespace。
对进程来说,要想使用namespace里面的资源,首先要“进入”(具体操作方法,下文会介绍)到这个namespace,而且还无法跨namespace访问资源。
Linux的namespace给里面的进程造成了两个错觉:
(1)它是系统里唯一的进程。
(2)它独享系统的所有资源。
默认情况下,Linux进程处在和宿主机相同的namespace,即初始的根namespace里,默认享有全局系统资源
namespace分类
namespace针对不同资源有不同的隔离方案和实现.
| 资源 | 描述 | 实现思路 |
|---|---|---|
| 进程 | 隔离进程ID | Linux通过命名空间管理进程号,同一个进程,在不同的命名空间进程号不同. 进程命名空间是一个父子结构,子空间对于父空间可见 |
| 网络 | 隔离网络设备、协议栈、端口等 | 通过网络命名空间,实现网络隔离 docker采用虚拟网络设备,将不同命名空间的网络设备连接到一起 |
| IPC | 隔离进程间通信 | 进程间交互方法 PID命名空间和IPC命名空间可以组合起来用, 同一个IPC名字空间内的进程可以彼此看见,允许进行交互,不同空间进程无法交互 |
| 磁盘 | 隔离挂载点 | 隔离文件目录 进程运行时可以将挂载点与系统分离,使用这个功能时,我们可以达到 chroot 的功能,而在安全性方面比 chroot 更高 |
| UTS | 隔离Hostname和NIS域名 | 让容器拥有独立的主机名和域名,从而让容器看起来像个独立的主机 目的是独立出主机名和网络信息服务(NIS) |
| 用户 | 隔离用户和group ID | 每个容器内上的用户跟宿主主机上不在一个命名空间 同进程 ID 一样,用户 ID 和组 ID 在命名空间内外是不一样的,并且在不同命名空间内可以存在相同的 ID |
NameSpace隔离原理
NameSpace怎么实现隔离的?
它是Linux内核级别支持的.
Linux内核自2.4.19版本接纳第一个namespace:Mount namespace(用于隔离文件系统挂载点)起,到3.8版本的user namespace(用于隔离用户权限),总共实现了上文提到的6种不同类型的namespace。
尽管Linux的namespace隔离技术很早便存在于内核中,而且它就是为Linux的容器技术而设计的,但它一直鲜为人知。直到Docker引领的容器技术革命爆发,它才进入普罗大众的视线——Docker 容器作为一项轻量级的虚拟化技术,它的隔离能力来自Linux内核的namespace技术
Network Namespace
它在Linux内核2.6版本引入,作用是隔离Linux系统的设备,以及IP地址、端口、协议栈/路由表、防火墙规则等网络资源。因此,每个网络namespace里都有自己的网络设备(如IP地址、路由表、端口范围、/proc/net目录等)。从网络的角度看,network namespace使得容器非常有用,一个直观的例子就是:由于每个容器都有自己的(虚拟)网络设备,并且容器里的进程可以放心地绑定在端口上而不必担心冲突,这就使得在一个主机上同时运行多个监听80端口的Web服务器变为可能
以下是网络命名空间如何实现这些隔离的简单概述:
-
网络设备隔离:每个网络命名空间都可以有自己的网络设备(网卡)。同一网络设备不能同时出现在多个命名空间中,但可以通过veth(Virtual Ethernet)设备对或者macvlan等技术,在不同的网络命名空间之间建立网络连接。当网络设备移动到另一网络命名空间时,对于原命名空间,该设备就像是被移除了一样。
-
协议栈隔离:网络协议栈是操作系统实现网络协议(如TCP/IP)的一部分,它处理如何发送和接收数据包。Linux的每个网络命名空间都有自己的网络协议栈,它们是彼此独立的。这意味着,网络配置(如IP地址、路由规则、防火墙规则等)在一个命名空间中的改变不会影响其他命名空间。
-
端口隔离:在网络命名空间中,端口是隔离的。每个网络命名空间都有自己的端口范围和端口分配。例如,不同的网络命名空间都可以使用相同的端口号(如80),而不会发生冲突,因为它们在不同的命名空间中。
这样,网络命名空间使得我们可以创建多个隔离的网络环境,每个网络环境都可以有自己的网络设备、IP地址、路由规则和其他网络配置。这在创建容器等隔离环境时非常有用。
-
在 Linux 中,网络命名空间可以被认为是隔离的拥有单独网络栈(网卡、路由转发表、iptables)的环境。网络命名空间经常用来隔离网络设备和服务,只有拥有同样网络命名空间的设备,才能看到彼此。几乎所有物理存在的都可以进行虚拟虚拟局域网,虚拟MAC地址,虚拟交换机,虚拟网络层,虚拟链路层等等各个维度的,具体支持的类型可以在 ip netns的bash shell中查看
man ip-link-
网络设备: 如网卡
-
路由转发表
-
iptables
-
邻接表
-
netfilter表
-
网络套接字
-
网络procfs条目
-
网络sysfs条目
-
其他网络资源
-
-
从逻辑上说,网络命名空间是网络栈的副本,拥有自己的网络设备、路由选择表、邻接表、Netfilter表、网络套接字、网络procfs条目、网络sysfs条目和其他网络资源。
-
从系统实现角度来看,当通过clone()系统调用创建新进程时,传递标志CLONE_NEWNET将在新进程中创建一个全新的网络命名空间。
-
从用户交互API角度来看,我们只需使用工具ip(package is iproute2)来创建一个新的持久网络命名空间。

网络命名空间管理
创建
ip netns add netns01
这个命令
ip netns add netns01用于在Linux系统中添加一个新的网络命名空间,具体解释如下:
ip: 这是Linux系统的一个常用命令,用于显示或操作路由、设备、策略路由和隧道。
netns: 是ip命令的子命令,用于管理网络命名空间。网络命名空间(Network Namespace)是Linux内核的一个功能,用于隔离网络环境,例如隔离网络设备、IP地址、路由表等。
add: 是netns的子命令,用于添加一个新的网络命名空间。
netns01: 这是新建网络命名空间的名称。创建的网络命名空间在文件系统中以文件的形式存在,位于
/var/run/netns/目录下。# ll /var/run/netns/ total 0 -r--r--r--. 1 root root 0 Jul 28 23:33 netns01使用说明和注意事项:
在运行
ip netns add命令之前,你需要确保ip命令有足够的权限(需要root权限)来创建新的网络命名空间。网络命名空间创建后,可以使用
ip netns exec netns01 command命令在新的网络命名空间中执行命令。例如,ip netns exec netns01 ip link set lo up可以在新的网络命名空间中启用lo(loopback)设备。当不再需要网络命名空间时,可以使用
ip netns del netns01命令来删除它。注意,创建的网络命名空间是隔离的,新的网络命名空间并不会自动拥有任何网络设备,包括
lo(loopback)设备,这些设备需要在新的网络命名空间中手动创建和启用。在操作网络命名空间时需要小心,不正确的操作可能会导致网络问题,例如错误地删除或修改网络设备、IP地址或路由规则等。在生产环境下操作时,应遵循最佳实践,并在可能的情况下进行充分的测试。
查看
网络命名空间
ip netns ls
ip netns identify 和 ip netns ls
ip netns identify和ip netns ls这两个命令在功能和用途上有很大的不同。
ip netns identify:此命令用于查找并打印与给定进程相关联的所有网络命名空间的名称。例如,ip netns identify 1234将列出与进程ID为1234相关的所有网络命名空间的名称。
ip netns ls:此命令列出系统上存在的所有网络命名空间的名称。这并不涉及任何特定的进程,而是给出了系统当前的所有网络命名空间。
删除
ip netns del
ip netns del netns01
ip netns ls
上面这条命令实际上并没有删除netns1这个network namespace,它只是移除了这个network namespace对应的挂载点。只要里面还有进程运行着,network namespace便会一直存在。
进入
进入空间及执行命令
ip netns add netns01
ip netns exec netns01 bash
ip netns exec netns01 bash命令是在创建的网络命名空间netns01内执行bash shell的命令。在这个命令中:
执行完bash之后其实就是启动了一个bash shell,后续的操作都是在这个shell空间中进行了,但是注意没有提示,你需要先退出才能退回到os的shell
ip netns exec是命令的前缀,用于在指定的网络命名空间执行后面的命令。
netns01是网络命名空间的名称。
bash是要执行的命令。它启动了一个bash shell,该shell会在netns01命名空间中运行。这意味着在这个bash shell中执行的所有命令,都会在netns01命名空间中运行。除了bash,
ip netns exec后面可以接任何命令,例如:
ip netns exec netns01 ip addr:在netns01网络命名空间中查看网络接口的IP地址。
ip netns exec netns01 ping 8.8.8.8:在netns01网络命名空间中ping一个IP地址。注意事项:
在使用
ip netns exec命令时,你需要root权限。
ip netns exec会改变命令的网络命名空间上下文,但不会改变其他的命名空间上下文,例如PID命名空间、用户命名空间等。如果你需要在完全隔离的环境中运行命令,你可能需要使用其他工具,例如unshare或docker。你需要确保你在正确的网络命名空间中运行命令。在错误的网络命名空间中运行命令可能会导致网络问题或者数据丢失。如果你不确定,你可以使用
ip netns identify命令来查看当前的网络命名空间。
ip netns exec命令在运行命令时会更改网络命名空间。如果你在一个脚本中使用ip netns exec,你需要确保这个脚本不会在改变命名空间后的命令失败时继续执行,否则后续的命令可能会在错误的网络命名空间中运行。
空间内指令
在进入命名空间的bash shell上下文后,你就有一个空间内的shell环境了
查看网卡
# 在网络命名空间中查看网络命名空间中的网卡信息
ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# 可以看到目前处于DOWN状态
# 在Linux主机系统中查看
ip netns exec netns01 ip link list
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
当你执行
ip netns exec netns01 bash并进入到网络命名空间的 bash shell 之后,你可以执行的操作就和在任何 Linux shell 中一样广泛。然而,因为你现在在一个特定的网络命名空间内,所以所有的网络相关的操作都将局限于这个网络命名空间。以下是一些可能的操作:
网络配置:使用
ip、ifconfig、route、netstat等命令查看和更改网络配置。例如,你可以使用ip addr来查看网络接口的 IP 配置。注意事项:因为你在特定的网络命名空间中,所以你看到的将仅仅是在这个命名空间内的网络配置。网络通信:使用
ping、traceroute、nc、telnet、ssh等命令来测试网络连接或者进行网络通信。注意事项:你只能够连接到在同一命名空间内,或者是可以路由到的网络实体。网络服务:你可以启动或停止在特定网络命名空间内运行的网络服务,如 HTTP 服务器、FTP 服务器等。注意事项:这些服务只能在此网络命名空间内访问,除非进行了特殊配置。
系统命令:你可以执行像
ls、cat、vi、top这样的系统命令,它们和网络无关。注意事项:这些命令的执行不受网络命名空间的影响。
退出空间
# 退出已进入的网络命名空间
exit
配置虚拟网卡
如果没有网卡那是无法通信的,所以容器也需要配置网卡,虚拟网卡.
对容器来说需要创建一对网卡.因为一个网卡是容器的一个是物理机的,容器需要连接到物理机的网卡才能对外通信
创建
ip link add veth01 type veth peer name veth10
ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
10: veth10@veth01: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 06:6e:31:5e:f3:19 brd ff:ff:ff:ff:ff:ff
11: veth01@veth10: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 9a:77:14:b4:99:dd brd ff:ff:ff:ff:ff:ff
# 可以直接指定空间
netns <netns>:这个选项允许你直接将新创建的veth对的一端移动到指定的网络命名空间。例如,
ip link add veth0 type veth peer name veth1 netns mynetns
将会创建一个veth对veth0和veth1,其中veth1会被放入到名为mynetns的网络命名空间。
迁移
ip link set veth01 netns netns01
从空间1移动到空2
# 进入源(netns01)网络命名空间执行
ip link set veth10 netns netns02
# 宿主机执行 netns01移动到netns02
ip netns exec netns01 ip link set veth10 netns netns02
# 创建到目标空间
ip link add veth01 type veth peer name veth10 netns netns01
# 查看本地
ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:c6:03:83 brd ff:ff:ff:ff:ff:ff
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT qlen 1000
link/ether 52:54:00:04:70:ac brd ff:ff:ff:ff:ff:ff
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000
link/ether 52:54:00:04:70:ac brd ff:ff:ff:ff:ff:ff
5: veth01@if12: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether f2:53:c0:3b:ef:f2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
# 查看目标空间
ip netns exec netns01 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
12: veth10@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 5a:50:9d:01:dc:cc brd ff:ff:ff:ff:ff:ff link-netnsid 0
移出
# 在netns01命名空间执行删除
ip link delete veth01
或者执行
ip link delete veth10
# 都是成对删除, 删除任何一个,另一个也会被删除
# 或者宿主机bash执行
ip netns exec netns01 ip link delete veth10
# 查看
ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
删除
ip link delete veth10
# 自动成对删除
配置地址
配置地址
ip addr add 172.16.193.233/24 dev veth10
查看地址
ip addr show
此时状态是DOWN,需要up启动状态
启动
ip link set veth10 up ip addr show
启动lo回环网卡
ip link set lo up
此时还是不通的,为什么?
因为这个成对的网卡,另外一个还没有地址
宿主机执行
6: veth01@if7: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether e6:1e:9b:28:c5:6a brd ff:ff:ff:ff:ff:ff link-netnsid 1
配置成对地址
宿主机分配IP
ip addr add 172.16.193.234/24 dev veth01 # 宿主机不需要执行up,当你执行其中一个虚拟网卡up的时候 另一个网卡也是up的 # 执行up之后直接退出了, 且重启之后netns都消失了 client_loop: send disconnect: Broken pipe
ping验证
宿主机ping网络空间虚拟网卡
ping 172.16.193.233
配置路由条目
ip netns exec netns01 ip route add default via 172.16.193.233
网络空间虚拟网卡ping宿主机
ip netns exec netns01 ping -c 4 172.16.193.133
配置路由
通过查看虚拟网卡的路由表
ip netns exec netns01 route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.50.0 0.0.0.0 255.255.255.0 U 0 0 0 veth1
我们看到它智能到达50网段的出口,没有外网出口,即它无法访问外网
ip netns exec netns01 ping -c 1 www.baidu.com
通过ping可以看到是不通.
那我们就要思考怎么才能联通外网呢,只能利用成对的虚拟网卡,因为那个网卡是在宿主机上,是可以出外网的
所以我们可以在命名空间的虚拟网卡配置下路由,让他联通成对虚拟网卡
ip netns exec netns01 ip route add default via 192.168.50.3 ip netns exec netns01 route -n --- Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.50.3 0.0.0.0 UG 0 0 0 veth1 192.168.50.0 0.0.0.0 255.255.255.0 U 0 0 0 veth1 [root@centos133 ~]#
配置了这个路由还不行,还是没法转发出去
配置脚本
ip netns add netns01
ip link add veth0 type veth peer name veth1
ip link set veth1 netns netns01
ip netns exec netns01 ip addr add 192.168.30.2/24 dev veth1
ip netns exec netns01 ip link set veth1 up
ip netns exec netns01 ip link set lo up
ip addr add 192.168.30.3/24 dev veth0
ip link set veth0 up
ip netns exec netns01 ip route add default via 192.168.30.3
# ping 虚拟机
ping -c 1 172.16.193.133
# ping 虚拟机 veth0
ping -c 1 192.168.30.3
# 在宿主机上ping netns01 中的veth1
ping -c 1 192.168.50.76
# 增加ipv4转发,主要是能访问外网主机
vim /etc/sysctl.conf
net.ipv4.ip_forward=1



















