原文地址:https://segmentfault.com/a/1190000004059167

介绍

在专业的网络世界中,经常使用到Virtual Routing and Forwarding(VRF),比如Cisco,Alcatel-Lucent, Juniper 等。对于L2 switch,自从上世纪90年代就开始使用VLAN,一个物理交换机上可以使用多个广播域,如今大多数交换机都支持4K vlan。

这个概念被引入到L3,如今很多网络设备支持VRF。这意味着,单个物理设备上可运行多个虚拟路由(L3 转发实例)。

在linux中,VRF被叫做“network namespace”,当然了linux中还包括其他namespace,不过本文不讨论。

每个network namespace拥有其对应的路由表(routing table)& 其对应的iptables,并且运行程序运行其中。 为什么有人使用它?比如一个运行在linux上的 Firewall,将firewall的所有服务端口分配给一个network namespace,这样,默认的network namespace 和 Firewall network namespace就运行着不同的路由表。像SSH这样的application运行在默认的network namespace,但是不在Firewall network namespace。

下面展示了其基本用法。

Basic network namespace commands

基本命令为“ip”,有些用户使用它来代替废弃的 ifconfig,route,netstat... 必须为root用户来使用它,这样才能更改network stack的配置。下面是ip命令和其他命令的映射:

ifconfig                                            --> ip addr or just ip a
ifconfig <interface> up/down --> ip link set dev <interface> up/down
ifconfig <interface> <ip> netmask <netmask> --> ip addr add <ip>/<masklen> dev <interface>
netstat -rn --> ip route or just ip r
route add -net <net> netmask <netmask> gw <gateway> --> ip r add <net>/<netmasklen> via <gateway>

Check your Linux for namespace support

使用前,先检查系统是否支持。

Creating a network namespace

# add a new namespace
ip netnas add <network namespace name>
#Example:
ip netns add nstest

Listing all existing network namespaces in the system

# list all namespaces
ip netns list
#will show the namespace from above nstest

Deleting a network namespace

ip netns delete <network namespace name>

Executing a command in a network namespace

下面展示了使程序运行在network namespace中的“黑魔法”。

# execute a command in a namespace
ip netns exec <network namespace name> <command>
#Example using the namespace from above:
ip netns exec nstest ip addr

展示了在此network namespace中的所有的ip interface

lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

一个脏技巧是在network namespace中运行shell:

ip netns exec <network namespace name> bash

现在,你已经“trapped”入namespace中了,exit退出。

Exploring the network namespace

当我们已经创建了network namespace,第一个task是bring up其中的lo interface。应该注意到的是,在创建了network namespace后,lo interface的状态是down。如果忽略了这个,可能会发生一些奇怪的事。

# set the link of lo in the namespace to up
ip netns exec nstest ip link set dev lo up
# list all interfaces and the state in the namespace
ip netns exec nstest ip link

现在lo interface状态为up,现在,是时候将network namespace链接到外部空间。

Adding interfaces to a network namespace (这里需要用到veth pair)

什么是veth pair
Veth pair 是一对虚拟网卡,从一张veth网卡发出的数据包可以直接到达它的peer veth,两者之间存在着虚拟链路。Veth 网卡和常规的以太网区别仅在于xmit接口:将数据发送到其peer,触发peer的Rx 过程。
Veth 的原理示意图如下:


将一个物理interface分配给network namespace是不可能的,而是使用 virtual interface来实现。所以,我们先创建一个virtual interface,同样使用 ip command:

ip link add veth-a type veth peer name veth-b

上述命令创建了两个virtual interface,分别为veth-a & veth-b,他们之间通过一个virtual cable链接。ip link命令显示了在默认namespace下这两个interface的信息。

ip link
veth-b: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 72:01:ad:c5:67:84 brd ff:ff:ff:ff:ff:ff
veth-a: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 8e:8b:bd:b1:88:e5 brd ff:ff:ff:ff:ff:ff

下面我们将其中的一个interface添加入之前我们创建的namespace nstest:

ip link set veth-b netns nstest

现在veth-b不在默认的namespace下了,而出现在了nstest 中,使用如下命令验证:

# list all interfaces in the namespace nstest
ip netns exec nstest ip link lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
veth-b: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 72:01:ad:c5:67:84 brd ff:ff:ff:ff:ff:ff

现在,在network namespace nstest中,就拥有了两个interface。

Assign ip addresses to the veth interfaces

现在是时候为这个veth interface分配ip并且使他的状态为up。

# default namespace
ip addr add 10.0.0.1/24 dev veth-a
ip link set dev veth-a up
#
# namespace nstest
ip netns exec nstest ip addr add 10.0.0.2/24 dev veth-b
ip netns exec nstest ip link set dev veth-b up

可通过“ip link”查看interface状态是否为up,使用“ip addr”查看interface的ip 地址,使用“ip route”查看其路由。

现在可以在default namespace中,通过veth-a来ping通 位于 nstest中的veth-b。

ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_req=1 ttl=64 time=0.054 ms
64 bytes from 10.0.0.2: icmp_req=2 ttl=64 time=0.034 ms
64 bytes from 10.0.0.2: icmp_req=3 ttl=64 time=0.039 ms
64 bytes from 10.0.0.2: icmp_req=4 ttl=64 time=0.036 ms

以及在nstest network namespace中,通过veth-b来ping通 veth-a:

ip netns exec nstest ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=64 time=0.064 ms
64 bytes from 10.0.0.1: icmp_req=2 ttl=64 time=0.036 ms
64 bytes from 10.0.0.1: icmp_req=3 ttl=64 time=0.039 ms

Demo

下面一起来实现一个demo,最终实现如下的case:

首先,先建立对应的namespace:

$ sudo ip netns add server
$ sudo ip netns add gateway
$ sudo ip netns add client
$ ip netns list
client
gateway
server

然后,启用gateway namespace中的ip forward功能,注意,操作全是在root权限下执行:

$ ip netns exec gateway sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

下面我们来创建两对veth,用来连接不同的namespace:

$ ip link add svr-veth type veth peer name svrgw-veth
$ ip link add cli-veth type veth peer name cligw-veth
$ ip link show | grep veth
3: svrgw-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
4: svr-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
5: cligw-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
6: cli-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

将veth对的两端加入对应的namespace中,这样在默认的default namespace中就看不到他们了:

$ ip link set svr-veth netns server
$ ip link set svrgw-veth netns gateway
$ ip link set cligw-veth netns gateway
$ ip link set cli-veth netns client
$ ip link show | grep veth

在指定的namespace上可以看到对应的interface:

$ ip netns exec server ip link show | grep veth
4: svr-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

为各个veth分配ip:

$ ip netns exec server ip addr add 192.168.100.1/24 broadcast + dev ser-veth
$ ip netns exec gateway ip addr add 192.168.100.254/24 broadcast + dev sergw-veth
$ ip netns exec gateway ip addr add 10.0.100.254/24 broadcast + dev cligw-veth
$ ip netns exec client ip addr add 10.0.100.1/24 broadcast + dev cli-veth

在各个veth对中,通过ping来检查连通性:

$ ip netns exec gateway ping 192.168.100.1 -I 192.168.100.254
PING 192.168.100.1 (192.168.100.1) from 192.168.100.254 : 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_req=1 ttl=64 time=0.044 ms
64 bytes from 192.168.100.1: icmp_req=2 ttl=64 time=0.036 ms
64 bytes from 192.168.100.1: icmp_req=3 ttl=64 time=0.040 ms
^C
--- 192.168.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.036/0.040/0.044/0.003 ms $ ip netns exec gateway ping 10.0.100.1 -I 10.0.100.254
PING 10.0.100.1 (10.0.100.1) from 10.0.100.254 : 56(84) bytes of data.
64 bytes from 10.0.100.1: icmp_req=1 ttl=64 time=0.107 ms
64 bytes from 10.0.100.1: icmp_req=2 ttl=64 time=0.037 ms
64 bytes from 10.0.100.1: icmp_req=3 ttl=64 time=0.037 ms
^C
--- 10.0.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.037/0.060/0.107/0.033 ms

接下来设定路由,将各namespace中的默认路由指向对应的veth ip:

$ sudo ip netns exec client ip route add default via 10.0.100.254 dev cli-veth
$ sudo ip netns exec client netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.0.100.254 0.0.0.0 UG 0 0 0 cli-veth
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 cli-veth
$ ip netns exec server ip route add default via 192.168.100.254 dev ser-veth
$ ip netns exec server netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.100.254 0.0.0.0 UG 0 0 0 svr-veth
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 svr-veth

最后我们尝试从client namespace 到 server namespace的网络连通性,通过ping命令来测试:

 
$ ip netns exec client ping 192.168.100.1 -I 10.0.100.1
PING 192.168.100.1 (192.168.100.1) from 10.0.100.1 : 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_req=1 ttl=63 time=0.106 ms
64 bytes from 192.168.100.1: icmp_req=2 ttl=63 time=0.076 ms
64 bytes from 192.168.100.1: icmp_req=3 ttl=63 time=0.050 ms
^C
--- 192.168.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.050/0.077/0.106/0.024 ms

Dokcer网络: https://segmentfault.com/a/1190000005794036

【转】linux network namespace 学习的更多相关文章

  1. Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  2. Netruon 理解(12):使用 Linux bridge 将 Linux network namespace 连接外网

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  3. 【转】理解Docker容器网络之Linux Network Namespace

    原文:理解Docker容器网络之Linux Network Namespace 由于2016年年中调换工作的原因,对容器网络的研究中断过一段时间.随着当前项目对Kubernetes应用的深入,我感觉之 ...

  4. 一文搞懂 Linux network namespace

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 本文通过 IP ...

  5. Linux Network Namespace

    Linux Network Namespaces Linux kernel在2.6.29中加入了namespaces,用于支持网络的隔离,我们看一下namespace是如何使用的 创建与配置 创建一个 ...

  6. Linux network namespace源码分析

    一.network namespace的创建 在对iproute2的源码进行分析后,我们可以知道,当我们调用命令`ip netns add ns1`时,本质上就是调用`unshare(CLONE_NE ...

  7. linux network name space

    linux network namespace概念类似于网络中的 VRF (virtual routing and forwarding).但是,你不知道VRF的概念也没关系,下面我们通过一个简单的介 ...

  8. docker--linux network namespace

    docker container的namespace使用 的是一种虚拟网络设备 veth-pair.顾名思义,veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出 ...

  9. linux 网络虚拟化: network namespace 简介

    linux 网络虚拟化: network namespace 简介 network namespace 是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自的网络栈信息.不管是虚拟机还是 ...

随机推荐

  1. nginx配置负载

    一.系统优化 1.修改/etc/sysctl.conf,优化tcp连接数 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 120 ...

  2. Spring自动装配与扫描注解

    1 javabean的自动装配 自动注入,减少xml文件的配置信息. <?xml version="1.0" encoding="UTF-8"?> ...

  3. October 13th 2016 Week 42nd Thursday

    If the world seems cold to you, kindle fires to warm it. 若世界以寒相待,请点燃火堆以温暖相报. Kindle fires to warm th ...

  4. Warp divergence

    Threads are executed in warps of 32, with all threads in the warp executing the same instruction at ...

  5. hdu1798(几何面积计算)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1798 题意:给出两个圆的圆心坐标与半径,求他们相交部分的大小 思路:有三种情况: 1. 两圆相离,ar ...

  6. sys.sysprocesses视图的使用小结

    Sys.SysProcesses 系统表是一个很重要的系统视图,主要用来定位与解决Sql Server的阻塞和死锁包含正在 SQL Server 实例上运行的进程的相关信息.这些进程可以是客户端进程或 ...

  7. Delphi线程的终止

    当线程对象的Execute()执行完毕,我们就认为此线程终止了.这时候,它会调用Delphi的一个标准例程EndThread(),这个例程再调用API函数ExitThread().由ExitThrea ...

  8. 深入理解JavaScript定时机制和定时器注意问题

    容易欺骗别人感情的JavaScript定时器 JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不 ...

  9. 攻城狮在路上(叁)Linux(十九)--- 磁盘分区

    磁盘分区使用fdisk命令,该命令仅root有使用权限. 磁盘分区的一般步骤: 1.首先用df命令查看设备名 df -h; 2.fdisk /dev/sda; <== 按m显示help d:删除 ...

  10. Solr入门之(3)常用概念说明(持续补充):

    由于solr底层使用lucene,所以很多概念与lucene相同,下面是几个常用的概念: * Document:一个要进行索引的单元,相当于数据库的一行纪录,任何想要被索引的数据,都必须转化为Docu ...