Linux网络设备veth pair和netns

我在对面的角落 2020-11-07 20:56:06
linux 网络 网络设备 设备 veth


Linux网络设备veth pair和netns

虚拟网络拓扑的实现当然离不开虚拟网络设备的参与,今天我们就来介绍一下Linux上的网络设备veth pair和netns。

Veth Pair 虚拟网络接口

veth pari是成对出现的一种虚拟网络设备接口,一端连着网络协议栈,一端彼此相连。如下图所示:

virtual-device-veth-1

由于它的这个特性,常常被用于构建虚拟网络拓扑。例如连接两个不同的网络命名空间(Network Namespace),连接docker容器等,其中一个很常见的案例就是OpenStack Neutron底层用它来构建非常复杂的网络拓扑。

配置veth pair

  1. 创建一对veth pair

    ip link add veth0 type veth peer name veth1
  2. 分别给这两个虚拟网卡启动并设置IP

    ip link set veth0 up
    ip addr add 10.0.0.1/24 dev veth0
    ip link set veth1 up
    ip addr add 10.0.0.2/24 dev veth1
  3. 此时的网络配置情况如下图

    veth-pair

验证网络

  1. 确认网卡是否正确启动

    # 查看网卡
    ifconfig
    # 输出
    veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 10.0.0.1 netmask 255.255.255.0 broadcast 0.0.0.0
    inet6 fe80::4880:cff:fe37:b9de prefixlen 64 scopeid 0x20<link>
    ether 4a:80:0c:37:b9:de txqueuelen 1000 (Ethernet)
    RX packets 7 bytes 578 (578.0 B)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 7 bytes 578 (578.0 B)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
    veth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 10.0.0.2 netmask 255.255.255.0 broadcast 0.0.0.0
    inet6 fe80::c094:68ff:feed:451d prefixlen 64 scopeid 0x20<link>
    ether c2:94:68:ed:45:1d txqueuelen 1000 (Ethernet)
    RX packets 7 bytes 578 (578.0 B)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 7 bytes 578 (578.0 B)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  2. 测试Veth Pair 的连通性

    # 在宿主机器上ping veth0
    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_seq=1 ttl=64 time=0.051 ms
    64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms
    64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.038 ms
    64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.044 ms
    ^C
    --- 10.0.0.1 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 2999ms
    rtt min/avg/max/mdev = 0.038/0.043/0.051/0.005 ms
    # 在宿主机器上ping veth1
    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_seq=1 ttl=64 time=0.056 ms
    64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.043 ms
    64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.039 ms
    64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.039 ms
    ^C
    --- 10.0.0.2 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 2999ms
    rtt min/avg/max/mdev = 0.039/0.044/0.056/0.008 ms

    进行完上面的测试你或许心里会想:“什么鬼?都在同一台机器上当然可以通信啊。”
    别着急,我们下面开始学习另一项技术,Network Namespace,想办法把它放在不同的地方。

Network Namespce 网络命名空间

Linux 3.8内核中包括了6种命名空间:

命名空间 描述
Mount(mnt) 隔离挂载点
Process ID(process) 隔离进程ID
Network(net) 隔离网络设备、协议栈、端口等
InterProcess Communication(ipc) 隔离进程间通信
UTS 隔离Hostname和NIS域名
User ID(user) 隔离用户和group ID

其中网络命名空间就是我们今天要学习的内容。

配置网络命名空间

  1. 创建两个网络命名空间

    ip netns add ns0
    ip netns add ns1
  2. 将虚拟网卡veth0和veth1分别移动到ns0和ns1网络命名空间中

    ip link set veth0 netns ns0
    ip link set veth1 netns ns1
  3. 此时的网络配置情况如下图,在宿主机器上是看不到veth0和veth1的了

    netns0

验证网络

  1. 测试网络连通性

    # 在宿主机器上ping veth0
    ping 10.0.0.1
    # 输出
    PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
    From 10.0.0.1 icmp_seq=1 Destination Host Unreachable
    From 10.0.0.1 icmp_seq=2 Destination Host Unreachable
    From 10.0.0.1 icmp_seq=3 Destination Host Unreachable
    From 10.0.0.1 icmp_seq=4 Destination Host Unreachable
    # 在宿主机器上ping veth1
    ping 10.0.0.2
    # 输出
    PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
    From 10.0.0.2 icmp_seq=1 Destination Host Unreachable
    From 10.0.0.2 icmp_seq=2 Destination Host Unreachable
    From 10.0.0.2 icmp_seq=3 Destination Host Unreachable
    From 10.0.0.2 icmp_seq=4 Destination Host Unreachable
    # 在ns0中ping自己
    ip netns exec ns0 ping 10.0.0.1
    # 输出
    connect: 网络不可达
    # 在ns0中ping veth1
    ip netns exec ns0 ping 10.0.0.2
    # 输出
    connect: 网络不可达

    却发现无论如何也ping不通,这是为什么呢?让我们来看一下网络命名空间ns0ns1中的网络信息吧。

  2. 查询网络命名空间的网络信息

    # 在ns0中查看ip
    ip netns exec ns0 ip a
    # 输出
    1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    11: veth0@if10: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 4a:80:0c:37:b9:de brd ff:ff:ff:ff:ff:ff link-netnsid 1
    # 在ns1中查看ip
    ip netns exec ns1 ip a
    # 输出
    1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    10: veth1@if11: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether c2:94:68:ed:45:1d brd ff:ff:ff:ff:ff:ff link-netnsid 0

可以看到不仅本地环回和veth的状态都是DOWN,就连veth的IP信息也没有了,这是因为在不同的网络命名空间中移动虚拟网络接口时会重置虚拟网络接口的状态。

这里使用了ip a命令来查看网卡,因为ifconfig命令不会显示状态为down的网卡

修改veth pair配置

给网络命名空间中的veth配置IP并启动相关网卡

# 配置ns0
ip netns exec ns0 ip addr add 10.0.0.1/24 dev veth0
ip netns exec ns0 ip link set lo up
ip netns exec ns0 ip link set veth0 up
# 配置ns1
ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth1
ip netns exec ns1 ip link set lo up
ip netns exec ns1 ip link set veth1 up

再次验证网络

# 在ns0中ping自己
ip netns exec ns0 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_seq=1 ttl=64 time=0.033 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.065 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.067 ms
^C
--- 10.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.033/0.058/0.069/0.016 ms
# 在ns0中ping veth1
ip netns exec ns0 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_seq=1 ttl=64 time=0.105 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.046 ms
^C
--- 10.0.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.046/0.061/0.105/0.026 ms
# 在宿主机器上ping veth1
ping 10.0.0.1
# 输出
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
^C
--- 10.0.0.1 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
# 在宿主机器上ping veth1
ping 10.0.0.2
# 输出
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
^C
--- 10.0.0.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 999ms

可以看到在宿主机器无法连通任何一个网络命名空间,证明了网络命名空间的隔离特性。

同时两个网络命名空间是可以通信的,证明了veth pair的连通特性。

看到这里或许你会有这样一个想法,我能否把一个veth设置到netns中,另一个veth保留在宿主机器上呢?

答案是可以的,我们接下来将完成这样的想法。

修改网络配置

  1. 将veth0移回宿主机器上,并配置网卡信息

    因为veth0在宿主机器上是看不到的,当然也无法操作,因此需要从ns0中操作,默认情况下根网络命令空间的PID是1
    # 将veth0移回宿主机器上
    ip netns exec ns0 ip link set veth0 netns 1
    # 删除ns0
    ip netns del ns0
    # 启动veth0并配置ip
    ip link set veth0 up
    ip addr add 10.0.0.1/24 dev veth0
  2. 此时的网络配置情况如下图

netns1

测试网络连通性

# 在宿主机器上ping veth0
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_seq=1 ttl=64 time=0.053 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.034 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.038 ms
^C
--- 10.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.034/0.041/0.053/0.007 ms
# 在宿主机器上ping veth1
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_seq=1 ttl=64 time=0.068 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.045 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.040 ms
^C
--- 10.0.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.040/0.050/0.068/0.011 ms
# 在ns1中ping veth0
ip netns exec ns1 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_seq=1 ttl=64 time=0.071 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.045 ms
^C
--- 10.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.045/0.054/0.071/0.011 ms

使用veth pair我们成功的将宿主机器和网络命名空间的隔离性打破,建立了一个可以互联的网络。这样的场景相当于用一根网线把两个网络设备连接到了一起,而veth pair就是这根”网线“。这种方式也被广泛应用到了docker网络中,后面我们也会讲到如何随心所欲的玩转docker网络。

接下来我们将探讨学习Linux Bridge虚拟网桥。

本文首发 Linux网络设备veth pair和netns 未经允许,不可转载。
版权声明
本文为[我在对面的角落]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000037758230

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云