linux 网络虚拟化: network namespace 简介

network namespace 是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自的网络栈信息。不管是虚拟机还是容器,运行的时候仿佛自己就在独立的网络中。这篇文章介绍 network namespace 的基本概念和用法,network namespace 是 linux 内核提供的功能,这篇文章借助 ip 命令来完成各种操作。ip 命令来自于 iproute2 安装包,一般系统会默认安装,如果没有的话,请读者自行安装。

NOTE:ip 命令因为需要修改系统的网络配置,默认需要 sudo 权限。这篇文章使用 root 用户执行,请不要在生产环境或者重要的系统中用 root 直接执行,以防产生错误。

ip 命令管理的功能很多, 和 network namespace 有关的操作都是在子命令 ip netns 下进行的,可以通过 ip netns help` 查看所有操作的帮助信息。

默认情况下,使用 ip netns 是没有网络 namespace 的,所以 ip netns ls 命令看不到任何输出。

创建 network namespace 也非常简单,直接使用 ip netns add 后面跟着要创建的 namespace 名称。如果相同名字的 namespace 已经存在,命令会报 Cannot create namespace 的错误。

ip netns 命令创建的 network namespace 会出现在 /var/run/netns/ 目录下,如果需要管理其他不是 ip netns 创建的 network namespace,只要在这个目录下创建一个指向对应 network namespace 文件的链接就行。

有了自己创建的 network namespace,我们还需要看看它里面有哪些东西。对于每个 network namespace 来说,它会有自己独立的网卡、路由表、ARP 表、iptables 等和网络相关的资源。ip 命令提供了 ip netns exec 子命令可以在对应的 network namespace 中执行命令,比如我们要看一下这个 network namespace 中有哪些网卡。更棒的是,要执行的可以是任何命令,不只是和网络相关的(当然,和网络无关命令执行的结果和在外部执行没有区别)。比如下面例子中,执行 bash 命令了之后,后面所有的命令都是在这个 network namespace 中执行的,好处是不用每次执行命令都要把 ip netns exec NAME 补全,缺点是你无法清楚知道自己当前所在的 shell,容易混淆。

更新:通过修改 bash 的前缀信息可以区分不同 shell,操作如下:

ip netns exec 后面跟着 namespace 的名字,比如这里的 net1,然后是要执行的命令,只要是合法的 shell 命令都能运行,比如上面的 ip addr 或者 bash

每个 namespace 在创建的时候会自动创建一个 lo 的 interface,它的作用和 linux 系统中默认看到的 lo 一样,都是为了实现 loopback 通信。如果希望 lo 能工作,不要忘记启用它:

默认情况下,network namespace 是不能和主机网络,或者其他 network namespace 通信的。

network namespace 之间通信

有了不同 network namespace 之后,也就有了网络的隔离,但是如果它们之间没有办法通信,也没有实际用处。要把两个网络连接起来,linux 提供了 veth pair 。可以把 veth pair 当做是双向的 pipe(管道),从一个方向发送的网络数据,可以直接被另外一端接收到;或者也可以想象成两个 namespace 直接通过一个特殊的虚拟网卡连接起来,可以直接通信。

使用上面提到的方法,我们再创建另外一个 network namespace,这里我们使用 net0 和 net1 两个名字。

我们可以使用 ip link add type veth 来创建一对 veth pair 出来,需要记住的是 veth pair 无法单独存在,删除其中一个,另一个也会自动消失。

小知识: 创建 veth pair 的时候可以自己指定它们的名字,比如 ip link add vethfoo type veth peer name vethbar 创建出来的两个名字就是 vethfoo 和 vethbar 。因为这里我们对名字没有特殊要求,所以就直接使用系统自动生成的名字。如果 pair 的一端接口处于 DOWN 状态,另一端能自动检测到这个信息,并把自己的状态设置为 NO-CARRIER

创建结束之后,我们能看到名字为 veth0 和 veth1 两个网络接口,名字后面的数字是系统自动生成的。接下来,要做的是把这对 veth pair 分别放到已经两个 namespace 里面,这个可以使用 ip link set DEV netns NAME 来实现:

最后,我们给这对 veth pair 配置上 ip 地址,并启用它们。

可以看到,最每个 namespace 中,在配置玩 ip 之后,还自动生成了对应的路由表信息,网络 10.0.1.0/24 数据报文都会通过 veth pair 进行传输。使用 ping 命令可以验证它们的连通性:

完成这些,我们创建的网络拓扑结构如下所示:

使用 bridge 连接不同的 namespace

虽然 veth pair 可以实现两个 network namespace 之间的通信,但是当多个 namespace 需要通信的时候,就无能为力了。
讲到多个网络设备通信,我们首先想到的交换机和路由器。因为这里要考虑的只是同个网络,所以只用到交换机的功能。linux 当然也提供了虚拟交换机的功能,我们还是用 ip 命令来完成所有的操作。

NOTE:和 bridge 有关的操作也可以使用命令 brctl,这个命令来自 bridge-utils 这个包,读者可以根据自己的发行版进行安装,使用方法请查阅 man 页面或者相关文档。

首先我们来创建需要的 bridge,简单起见名字就叫做 br0

下面只演示一个 namespace 的操作,其他 namespace 要做的事情和这个类似。创建 veth pair:

把其中一个 veth(veth1) 放到 net0 里面,设置它的 ip 地址并启用它:

最后,把另一个 veth(veth0)连接到创建的 bridge 上,并启用它:

可以通过 bridge 命令(也是 iproute2 包自带的命令)来查看 bridge 管理的 link 信息:

最后通过 ping 命令来测试网络的连通性:

下图是这部分网络的拓扑结构,如果对 docker 网络熟悉的话,其实这和 docker 默认的 bridge 网络模型非常相似。当然要实现每个 namespace 对外网的访问还需要额外的配置(设置默认网关,开启 ip_forward,为网络添加 NAT 规则等)。

参考资料

linux 网络虚拟化: network namespace 简介的更多相关文章

  1. linux网络虚拟化

    图解几个与Linux网络虚拟化相关的虚拟网卡-VETH/MACVLAN/MACVTAP/IPVLAN http://smilejay.com/2012/08/qemu-kvm-networking-m ...

  2. Docker核心实现技术(命名空间&控制组&联合文件系统&Linux网络虚拟化支持)

    作为一种容器虚拟化技术,Docker深度应用了操作系统的多项底层支持技术. 早期版本的Docker是基于已经成熟的Linux Container(LXC)技术实现的.自Docker 0.9版本起,Do ...

  3. Linux 网络 I/O 模型简介(图文)(转载)

    Linux 网络 I/O 模型简介(图文)(转载) 转载:http://blog.csdn.net/anxpp/article/details/51503329 1.介绍 Linux 的内核将所有外部 ...

  4. Linux ns 6. Network Namespace 详解

    文章目录 1. 简介 1.1 Docker Network 桥接模式配置 2. 代码解析 2.1 copy_net_ns() 2.2 pernet_list 2.2.1 loopback_net_op ...

  5. 【 Linux 网络虚拟化 】Openvswitch

    openvswitch:    openvswitch: 开放的虚拟交换机,虚拟交换就是利用虚拟平台,通过软件的方式形成交换机部件.跟传统的物理交换机相比,虚拟交换机同样具备众多优点:         ...

  6. 【 Linux 网络虚拟化 】Netns

    netns 可以创建一个完全隔离的新网络环境,这个环境包括一个独立的网卡空间,路由表,ARP表,ip地址表,iptables等.总之,与网络有关的组件都是独立的. 创建网络空间: # ip netns ...

  7. Linux 网络 I/O 模型简介(图文)

    1.介绍 Linux 的内核将所有外部设备都看做一个文件来操作(一切皆文件),对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符).而对一个sock ...

  8. 网络虚拟化技术(一): Linux网络虚拟化

    创建虚拟网络环境 使用命令 $ ip netns add net0 可以创建一个完全隔离的新网络环境,这个环境包括一个独立的网卡空间,路由表,ARP表,ip地址表,iptables,ebtables, ...

  9. Linux网络下载命令 wget 简介

    wget 是一个命令行的下载工具.对于我们这些 Linux 用户来说,几乎每天都在使用它.下面为大家介绍几个有用的 wget 小技巧,可以让你更加高效而灵活的使用 wget. $ wget -r -n ...

随机推荐

  1. leetCode53. 最大子序和

    示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6. 进阶: /** * @param {number[]} nu ...

  2. java8-函数编程

    在Function里面看到一个很奇怪的代码 static <T> Function<T, T> identity() { return t -> t; } 手动写了几个代 ...

  3. SQLALchemy中关于复杂关系表模型的映射处理

    映射在第五步,我们还是一步一步来哈 一. 关系介绍 举一个比较经典的关系,部门与员工(以下是我的需求情况,算是把该有的关系都涉及到了) 1.每个部门会有很多成员(这里排除一个成员属于多个部门的情况) ...

  4. mysql导入excel表格

    https://jingyan.baidu.com/album/fc07f9891cb56412ffe5199a.html?picindex=1

  5. 如何利用Git生成pitch和打pitch

    利用Git生成和应用patch  在程序员的日常开发与合作过程中,对于code的生成patch和打patch(应用patch)成为经常需要做的事情. 什么是patch?简单来讲,patch中存储的是你 ...

  6. 内核驱动程序中如何读写user space的文件,方便调试程序

    需要在Linux kernel--大多是在需要调试的驱动程序--中读写文件数据.但是在kernel中操作文件没有标准库可用,需要利用kernel的一些函数,这些函数主要有: filp_open() f ...

  7. 为什么移动构造要使用noexcept

    vector::push_back操作,保证了如果过程中出现异常,vector不会发生变化. push_back过程中,可能会因为已有内存空间不够,申请新的内存,同时把原内存中已有的元素,放到新申请的 ...

  8. maven项目(转)

    我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是自己悟性太低还是怎么滴,就是搞不清楚,现在弄清楚了,基本上入门了.写该篇博文,就是为了帮助那些和我一样对于maven迷迷糊糊的人. ...

  9. tcp,Socket,三次握手和四次挥手的图示

    tcp的图示: Socket的图示: Socket原理图示: “三次握手”图示介绍: 客户端向服务器发送一个SYN J 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1 客户端再 ...

  10. laravel view not found

    在windows开发的laravel项目,部署到Linux服务器找不到视图,代码格式可能是这样的 return view('news\list'); 原因是在Linux下不能识别反斜杠路径,解决办法是 ...