Posted Dev / Linux24 minutes read (About 3564 words) visits
Linux Network Name Space
Intro
A namespace wraps a global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource. Changes to the global resource are visible to other processes that are members of the namespace, but are invisible to other processes. One use of namespaces is to implement containers. This page provides pointers to information on the various namespace types, describes the associated /proc files, and summarizes the APIs for working with namespaces.
以上为 Linux Manpage 中对命名空间的描述。综上所述,命名空间是实现资源隔离的强大工具,对于实现容器化、增强系统安全性和提高资源管理效率至关重要。
Namespace Types
The following table shows the namespace types available on Linux. The second column of the table shows the flag value that is used to specify the namespace type in various APIs. The third column identifies the manual page that provides details on the namespace type. The last column is a summary of the resources that are isolated by the namespace type.
Namespace
Isolates
Description
Cgroup
Cgroup root directory
Control Group 允许独立控制资源使用(CPU、内存等),实现资源限制与优先级分配
IPC
System V IPC, POSIX message queues
隔离进程间通信资源,确保命名空间间通信独立,避免相互干扰
Network
Network devices, stacks, ports, etc.
提供独立的网络环境配置能力,包括 IP 地址、网络设备和端口隔离
Mount
Mount points
支持独立的文件系统挂载配置,每个命名空间可拥有独特的文件系统视图
PID
Process IDs
实现进程 ID 的独立管理,命名空间内的 PID 与外界隔离,可重用 PID 值
Time
Boot and monotonic clocks
允许独立设置系统时间和单调时钟,适合需要独立时钟管理的场景
User
User and group IDs
使用户和组 ID 在命名空间内可重定义,增强安全隔离和权限管理灵活性
UTS
Hostname and NIS domain name
允许设置独立的主机名和 NIS 域名,模拟独立的系统实例标识
Network Namespace
Linux 网络命名空间(Network Namespace)是 Linux 内核的一部分,用于隔离网络堆栈,允许每个命名空间有自己独立的网络配置,如网络接口、IP 地址、路由表、防火墙规则(iptables)等。这些隔离的环境使得在容器、虚拟机或独立的进程中能够拥有完全独立的网络配置。
在 Linux 系统中,当没有特别指定网络命名空间时,默认操作的是所谓的 root network namespace。这是系统启动时自动创建的第一个网络命名空间。
Query network configuration information
下面将介绍部分查询网络配置信息的命令
ip link: 显示和操作网络设备。
arp: 显示和操作 ARP 缓存表。
route: 显示或操作网络路由表。
ip link
ip link 命令用于显示和操作网络设备。它可以用来添加、删除或修改网络接口的状态。
查看网络接口的状态 ip link show
启用一个网络接口 ip link set eth0 up
禁用一个网络接口 ip link set eth0 down
1 2 3 4 5 6 7 8
ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 00:15:5d:05:8f:2c brd ff:ff:ff:ff:ff:ff 3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000 link/ether 38:f3:ab:8c:2f:1e brd ff:ff:ff:ff:ff:ff ...
ip netns help Usage: ip netns list # list all network namespaces ip netns add NAME # create a new network namespace ip netns attach NAME PID # attach a process to a network namespace ip netns set NAME NETNSID # set the namespace ID of a network namespace ip [-all] netns delete [NAME] # delete a network namespace ip netns identify [PID] # identify a network namespace ip netns pids NAME # list the PIDs of processes in a network namespace ip [-all] netns exec [NAME] cmd ... # ⭐ execute a command in a network namespace ip netns monitor ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]
1 2 3
# 创建网络命名空间 ip netns add ns1 ip netns add ns2
create and config veth pair and
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# 创建虚拟网卡 ip link add veth_ns1 type veth peer name veth_ns2 ip link set veth_ns1 netns ns1 ip link set veth_ns2 netns ns2 # 检测network namespace中的网卡 ip --all netns exec ip link
netns: ns2 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 9: veth_ns2@if10: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 36:b6:79:b6:f3:13 brd ff:ff:ff:ff:ff:ff link-netns ns1
netns: ns1 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 10: veth_ns1@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether ae:a0:29:4d:6c:7e brd ff:ff:ff:ff:ff:ff link-netns ns2
在 Linux 系统中的网络接口上添加 IP 地址,使用ip addr add [ADDRESS]/PREFIXLENGTH dev INTERFACE,并激活设备
1 2 3 4 5 6 7 8
# 为网络接口添加 IP 地址 ip netns exec ns1 ip addr add 192.168.20.1/24 dev veth_ns1 ip netns exec ns2 ip addr add 192.168.20.2/21 dev veth_ns2 # 激活设备,使其可以接收和发送数据包 ip -n ns1 link set veth_ns1 up ip -n ns1 link set lo up ip -n ns2 link set veth_ns2 up ip -n ns2 link set lo up
config route table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
ip netns exec ns1 ip route add default via 192.168.20.1 dev veth_ns1 ip netns exec ns2 ip route add default via 192.168.20.2 dev veth_ns2 ip --all netns exec route -n
netns: ns2 Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.20.2 0.0.0.0 UG 0 0 0 veth_ns2 192.168.16.0 0.0.0.0 255.255.248.0 U 0 0 0 veth_ns2
netns: ns1 Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.20.1 0.0.0.0 UG 0 0 0 veth_ns1 192.168.20.0 0.0.0.0 255.255.255.0 U 0 0 0 veth_ns1
ping between two network namespace
完成上述步骤后,就可以在两个网络命名空间之间进行通信了。
1 2 3 4 5 6 7 8 9 10
ip netns exec ns1 ping 192.168.20.2 -c 4 PING 192.168.20.2 (192.168.20.2) 56(84) bytes of data. 64 bytes from 192.168.20.2: icmp_seq=1 ttl=64 time=0.027 ms 64 bytes from 192.168.20.2: icmp_seq=2 ttl=64 time=0.043 ms 64 bytes from 192.168.20.2: icmp_seq=3 ttl=64 time=0.062 ms 64 bytes from 192.168.20.2: icmp_seq=4 ttl=64 time=0.043 ms
--- 192.168.20.2 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3117ms rtt min/avg/max/mdev = 0.027/0.043/0.062/0.012 ms
Linux 网桥不仅能够简化命名空间间的连接配置,还能提供一种无缝的网络通信方式,使得处于不同命名空间的虚拟设备能够像连接到同一个物理网络一样进行数据交换。通过使用 Linux 网桥,我们可以构建一个更加灵活和可扩展的虚拟网络环境
以下是使用 bridge 实现 network namespace 之间通信的步骤:
使用 ip netns add 创建 namespace&bridge
创建 veth 对,与 bridge 建立连接
为 veth 设备分配 IP 地址并激活它们。
使用 ping 测试
create network namespace and bridge
1 2 3 4 5 6
# create network namespace ip netns add h1 ip netns add h2 ip netns add h3 # create bridge brctl addbr s1
brctl 命令来自于 bridge-utils
create veth pair and connect to bridge
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# create veth pair ip link add veth1 type veth peer name br1 ip link add veth2 type veth peer name br2 ip link add veth3 type veth peer name br3 # add interface to namespace ip link set veth1 netns h1 ip link set veth2 netns h2 ip link set veth3 netns h3 # add interface to bridge(s1) brctl addif s1 br1 brctl addif s1 br2 brctl addif s1 br3 # check brctl show bridge name bridge id STP enabled interfaces s1 8000.82fcceb79d4c no br1 br2 br3
Config veth pair and bridge
配置 Ip 地址,设置状态为 up
1 2 3 4 5 6 7 8 9 10 11
ip -n h1 addr add local 192.168.1.1/24 dev veth1 ip -n h2 addr add local 192.168.1.2/24 dev veth2 ip -n h3 addr add local 192.168.1.3/24 dev veth3
ip link set s1 up ip link set br1 up ip link set br2 up ip link set br3 up ip -n h1 link set veth1 up ip -n h2 link set veth2 up ip -n h3 link set veth3 up
连接到桥上的 veth 接口通常不会配置 IP 地址,原因如下: 桥接设备(例如 br0)的作用是转发数据包,它相当于一个二层交换机,工作在链路层。数据包在桥上的转发不依赖于 IP 地址,而是基于 MAC 地址。