原文地址: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. 20145213《Java程序设计》实验三敏捷开发与XP实践

    20145213<Java程序设计>实验三敏捷开发与XP实践 实验要求 1.XP基础 2.XP核心实践 3.相关工具 实验内容 1.敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法 ...

  2. 20145213《Java程序设计》第一周学习总结

    20145213<Java程序设计>第一周学习总结 教材学习内容总结 期待了一个寒假,终于见识到了神秘的娄老师和他的Java课.虽说算不上金风玉露一相逢,没有胜却人间无数也是情理之中,但娄 ...

  3. jquery $(document).ready() 与window.onload的异同

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的.   1.执行时间     ...

  4. IOS 去掉导航栏(UINavigationBar)下方的横线

    这是导航栏的问题,将下边的代码放在  viewWillAppear  方法中就可以实现效果: - (void)viewWillAppear:(BOOL)animated{ // Called when ...

  5. [Android Pro] AOSP download

    Ubuntu14.04系统下载Android源码,直接上步骤: 清华大学 TUNA 镜像源 https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/ https: ...

  6. October 3rd 2016 Week 41st Monday

    Better to light one candle than to curse the darkness. 与其诅咒黑暗,不如燃起蜡烛. Sitting in the darkness and wa ...

  7. 关于jQuery新的事件绑定机制on()的使用技巧

    关于jQuery新的事件绑定机制on()的使用技巧 http://www.jb51.net/article/36064.htm 本篇文章介绍了,关于jQuery新的事件绑定机制on()的使用技巧.需要 ...

  8. ArrayList 和 LinkedList 的区别

    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.2.对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动 ...

  9. hdu1212(大数取模)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1212 题意:给出两个数a, b,求a%b: 思路:(c+d)%e=c%e+d%e,(c*d)%e=(c ...

  10. Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)(set容器里count函数以及加强for循环)

    题目链接:http://codeforces.com/contest/722/problem/D 1 #include <bits/stdc++.h> #include <iostr ...