欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

linux中的网络命名空间的使用

程序员文章站 2024-03-24 23:18:34
...

背景

项目中使用了网络命名空间,用来隔离不同空间中的应用。

命名空间的使用,类似虚拟化技术,在同一台物理机上,创建的多个命名空间相互独立,各个空间的进程独立运行,互不干扰。

在此作一总结,学习加深理解。

linux命名空间

命名空间(Linux namespace)是linux内核针对实现容器虚拟化映入的一个特性。

我们创建的每个容器都有自己的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样,命名空间保证了容器之间互不影响。

命名空间和cgroups是软件集装箱化(Docker)的大部分新趋势的主要内核技术之一。 简单来说,cgroups是一种计量和限制机制,它们控制您可以使用多少系统资源(CPU,内存)。 另一方面,命名空间限制了您可以看到的内容。 由于命名空间进程有自己的系统资源视图。

系统中的所有进程是通过PID标识的,这意味着内核必须管理一个全局的PID列表。而且,所有调用者通过uname系统调用返回的系统相关信息(包括系统名称和有关内核的一些信息)都是相同的。用户ID的管理方式类似,即各个用户是通过一个全局唯一的UID号标识。

全局ID使得内核可以有选择地允许或拒绝某些特权。虽然UID为0的root用户基本上允许做任何事,但其他用户ID则会受到限制。例如UID为n 的用户,不允许杀死属于用户m的进程(m≠ n)。但这不能防止用户看到彼此,即用户n可以看到另一个用户m也在计算机上活动。只要用户只能操纵他们自己的进程,这就没什么问题,因为没有理由不允许用户看到其他用户的进程。

但有些情况下,当厂商需要向用户提供root权限时,理论上他需要向每个用户提供一台计算机。显然这代价太高,使用KVM或者VMWare提供的虚拟化环境是一种解决问题的方法,但资源分配做得不是非常好。

命名空间提供了一种不同的解决方案,只使用一个内核在一台物理计算机上运作,所有全局资源都通过命名空间抽象起来。这使得可以将一组进程放置到容器中,各个容器彼此隔离。隔离可以使容器的成员与其他容器毫无关系。但也可以通过允许容器进行一定的共享,来降低容器之间的分隔。例如,容器可以设置为使用自身的PID集合,但仍然与其他容器共享部分文件系统。

Linux内核提供了6种命名空间:

命名空间 描述 作用 备注
进程命名空间 隔离进程ID inux通过命名空间管理进程号,同一个进程,在不同的命名空间进程号不同 进程命名空间是一个父子结构,子空间对于父空间可见
网络命名空间 隔离网络设备、协议栈、端口等 通过网络命名空间,实现网络隔离 docker采用虚拟网络设备,将不同命名空间的网络设备连接到一起
IPC命名空间 隔离进程间通信 进程间交互方法 PID命名空间和IPC命名空间可以组合起来用,同一个IPC名字空间内的进程可以彼此看见,允许进行交互,不同空间进程无法交互
挂载命名空间 隔离挂载点 隔离文件目录 进程运行时可以将挂载点与系统分离,使用这个功能时,我们可以达到 chroot 的功能,而在安全性方面比 chroot 更高
UTS命名空间 隔离Hostname和NIS域名 让容器拥有独立的主机名和域名,从而让容器看起来像个独立的主机 要目的是独立出主机名和网络信息服务(NIS)
用户命名空间 隔离用户和group ID 每个容器内上的用户跟宿主主机上不在一个命名空间 同进程 ID 一样,用户 ID 和组 ID 在命名空间内外是不一样的,并且在不同命名空间内可以存在相同的 ID

下面主要介绍Linux网络命名空间。

网络命名空间

在 Linux 中,网络名字空间可以被认为是隔离的拥有单独网络栈(网卡、路由转发表、iptables)的环境。网络名字空间经常用来隔离网络设备和服务,只有拥有同样网络名字空间的设备,才能看到彼此。

从逻辑上说,网络命名空间是网络栈的副本,有自己的网络设备、路由选择表、邻接表、Netfilter表、网络套接字、网络procfs条目、网络sysfs条目和其他网络资源。

从系统的角度来看,当通过clone()系统调用创建新进程时,传递标志CLONE_NEWNET将在新进程中创建一个全新的网络命名空间。

从用户的角度来看,我们只需使用工具ip(package is iproute2)来创建一个新的持久网络命名空间。

iproute2 is usually shipped in a package called iproute or iproute2 and consists of several tools, of which the most important are ip and tc. ip controls IPv4 and IPv6 configuration and tc stands for traffic control. Both tools print detailed usage messages and are accompanied by a set of manpages.

创建netns

  • 查看是否存在命名空间:ip netns list

    • 若报错,需要更新系统内核,以及 ip 工具程序。
  • 添加命名空间:ip netns add ns1

添加网卡

  • 列出网卡: ip link list

  • 创建新的虚拟网卡:ip link add veth0 type veth peer name veth1

    • 同时创建veth0和veth1两个虚拟网卡
    • 这个时候这两个网卡还都属于“default”或“global”命名空间,和物理网卡一样。
  • 把其中一个网卡转移到命名空间ns1中:ip link set veth1 netns ns1

  • 验证:ip netns exec ns1 ip link list
  • 删除:ip netns exec ns1 ip link del veth1

  • 配置命名空间中的端口:

$ ip netns exec ns1 ip addr add 10.1.1.1/24 dev veth1
$ ip netns exec ns1 ip link set veth1 up
$ ip netns exec ns1 ip link set lo up
  • 配置主机上网卡ip:
$ ip addr add 10.1.1.2/24 dev veth0
$ ip link set veth0 up
  • 此时在ns1中ping自己10.1.1.1能通:
ip netns exec ns1 ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.058 ms
  • 但还不能ping通10.1.1.2,因为ns1中未设置路由。

设置命名空间路由

  • 设置默认路由
$ ip netns exec ns1 ip route add default via 10.1.1.1
$ ip netns exec ns1 ip route show
default via 10.1.1.1 dev veth1
  • 此时能够ping通主机:
$ip netns exec ns1 ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.086 ms

使能IP转发

但是到了这里依旧还不够,ns1命名空间中已经可以联通主机上的网络,但是依旧连不同主机以外的外部网络。这个时候必须在host主机上启动转发,并且在iptables中设置伪装。

Linux系统的IP转发的意思是,当Linux主机存在多个网卡的时候,允许一个网卡的数据包转发到另外一张网卡;在linux系统中默认禁止IP转发功能,可以打开如下文件查看,如果值为0说明禁止进行IP转发:

cat /proc/sys/net/ipv4/ip_forward

运行如下命令:

#使能ip转发

echo 1 > /proc/sys/net/ipv4/ip_forward

#刷新forward规则
iptables -F FORWARD
iptables -t nat -F

#刷新nat规则
iptables -t nat -L -n

#使能IP伪装
iptables -t nat -A POSTROUTING -s 10.1.1.0/255.255.255.0 -o eth8 -j MASQUERADE # eth8连接外网

#允许veth0和ens160之间的转发
iptables -A FORWARD -i eth8 -o veth0 -j ACCEPT
iptables -A FORWARD -o eth8 -i veth0 -j ACCEPT
  • 使能IP伪装这条语句,添加了一条规则到NAT表的POSTROUTING链中,对于源IP地址为10.1.1.0网段的数据包,用eth8网口的IP地址替换并发送。
  • iptables -A FORWARD这两条语句使能物理网口eth8和veth0之间的数据转发

总结

Linux网络命名空间提供了强大的虚拟化功能,使用得当能够达到事半功倍的效果。

本文简要介绍了Linux提供的6种命名空间,对命名空间的作用和使用场景作了详细的介绍。

着重对Linux网络命名空间进行了讲解,包括命名空间的创建、使用,与主机通信以及与外部网络的连接等。

对于一般的应用而言,掌握网络命名空间的创建、使用、ip命令等就能顺当使用命名空间了。