[云原生网络] linux网络虚拟化

644 阅读10分钟

前言,云原生网络的基础就是在主机层面的网络虚拟化而来,将原有的网络空间通过虚拟化隔离出单独的网络空间。在宿主机中的每个容器获得一个单独的网络空间,对网络资源的隔离就是云原生网络的基础。所以本文主要是对云原生的基石linux 网络虚拟化相关的知识相关笔记

network namespace

linux 的network namespace技术可以自定义一个独立的网络栈,简单到只有loopback设备,复杂到具备系统完整的网络能力,linux namespace的作用就是隔离内核资源,想要使用namespace里的资源,首先要进入到,namespace中,而且还无法跨namespace访问资源

  • ip netns
ip netns add netns1
ip netns list 
ip netns exec netns1 sh 
ip netns delete netns1

当ip命令创建一个network namespace之后,系统会在/var/run/netns路径下生成一个挂载点,挂载点的作用一是对namespace管理二是namespace没有进程运行也能存在

  • 配置namespace 创建的namespace中会附带创建一个本地回环地址lo,状态还是down的,所以访问当前namespace的本地回环地址是不通的 想要与外界通信的话,需要在namespace里再创建一对veth pair,并将其一端放于当前namespace,一端放于想要互通的namespace
ip link add veth0 type veth peer name veth1
ip link set veth1 netns netns1

到目前为止,在netns1 namespace内部,仍然不能与外界通信,因为这两个块网卡还处于down状态,还需要手动为网卡绑定IP

ip netns exec netns1 ifconfig veth1 10.1.1.1/24 up
ifconfig veth0 10.1.1.1.2/24 up

此外,不同的namespace直接的路由表和防火墙规则等也是隔离的,所以netns1的路由表和防火墙没法和主机共享路由表和防火墙

veth pair

veth pair是虚拟以太网卡(Virtual Ethernet)的缩写,veth设备总是成对的,所以成为veth pair,一端发送的数据会在另一端接收,非常像linux的双向管道,使用可以参照network namespace

linux bridge

网桥是二层设备,两个端口Denbighshire有一条独立的交换信道,不共享一条背板总线。linux bridge就是linux系统中的网桥,但是linux bridge的行为更像是一台网络虚拟交换机

  • 创建bridge
ip link add name br0 type bridge 
ip linl set br0 up 
brctl addbr br0

刚刚创建的bridge是一个独立的网络设备,只有一个端口连接协议栈,其它端口什么都没连,这里加上一堆veth设备,并配置IP

ip link add veth0 type veth peer name veth1
ip addr add 1.2.3.1/24 dev veth0 
ip addr add 1.2.3.2/24 dev veth1
ip link set veth0 up 
ip link set veth0 up 

将veth0连接到br0

ip link set dev veth0 master br0
brctl addif br0 veth0

查看当前网桥上连接了哪些设备

bridge link
brctl show

br0和veth0相连之后发生了如下变化

br0和veth0直接连接起来了,并且是双向通道,协议站和veth0直接变成了单项通道,协议栈能发送数据给veth0,但veth0收到的数据不会转发给协议栈,直接转发给bridge了

从上面分析可以看出,给veth0分配IP没有意义,因为就算协议栈传数据包给veth0,回程报文也回不来,所以直接把veth0的IP地址让给,linux bridge

ip addr del 1.2.3.101/24 dev veth0
ip addr add 1.2.3.101/24 dev br0 
ping -c 1 -I br0 1.2.3.102

这样就可以ping通veth1了但是还是ping不通网关,因为网桥上只有veth1 和 veth2 ,不知道网关的地址

所以把物理网卡也加到bridge上

tun/tap

tun/tap设备,从linux文件系统角度看,是用户可以用文件句柄操作的字符设备,从网络虚拟化角度看,是虚拟网卡,一端连接网络协议栈,一端连接用户态程序。tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备。tun/tap设备可以讲TCP/ip协议栈处理好的网络包发送给任何一个使用tun/tap驱动的进程,由进程冲洗处理后发到物理链路中。

iptables

iptables底层实现是,netfilter,它提供了一整套hook函数的管理机制,使得数据包过滤,包处理(设置标志位、修改TTL等)、地址伪装、网络地址转换、透明代理等功能 因为iptables 相对复杂,篇幅所限不很难讲解透彻,感兴趣的可以自行了解,要点在iptables 的四表五链

ipip

linux原生支持下列5种L3隧道,

  • ipip:IPv4 in IPv4 ,在IPv4报文的基础上再封装一个IPv4报文
  • GRE:通用路由封装(Generic Routing Encapsulation),定义了在任意的一种网络协议上封装其它任意一种网络层协议的机制,v4和v6都支持
  • sitL和ipip类似,不同的是用IPv4报文封装IPv6
  • ISATAP:站内自动隧道寻址协议与sit类似,也用于IPv6的隧道封装
  • VTI:虚拟隧道接口,思科提出的一种IPSec隧道技术

Linux L3隧道底层实现原理都基于tun设备

VXLan

Macvlan

macvlan接口可以看作是物理以太网接口的虚拟子接口,macvlan允许用户在主机的一个网络接口上配置多个虚拟的网络接口,每个macvlan接口都有自己区别于父接口的Mac地址,并且可以像普通的网络接口一样分配IP地址,,一块物理网卡上可以绑定多个IP地址,每个IP地址都有自己的MAC地址

bridge模式:区别于linux网桥,不需要学习mac地址,性能要优于 linux bridge. 相同父接口的两块macvlan虚拟网卡可以直接通信,不需要把流量通过父接口发送到外部网络。

vepa模式:默认模式,所有从macvlan接口发出的流量都会从父接口发出,经由交换机处理

private模式,类似vepa模式,但是增强了隔离,完全阻止了,同一父接口的macvlan之间的通信,

passthru:模式,直通模式,macvlan每个父接口只能绑定一个macvlan

在容器网络中,访问跨节点的容器,物理网卡(父接口)相当于一个交换机,对应进出其子Macvlan网卡的数据包,只转发,不处理,所以使用本机Macvlan网卡的IP,无法和本届物理网卡IP通信。

只为虚拟机或容器提供访问外部物理网络的连接

IPvlan

和macvlan类似,IPvlan也是从一个主机接口虚拟出多个虚拟网络接口,区别在于IPvlan所有的虚拟接口都是相同的MAC地址,但是IP地址却不同,所有的IPvlan共享mac地址,所以需要注意DHCP使用的场景,DHCP分配IP地址的时候一般回用MAC地址所谓机器表示,所以在使用MACVlan的情况下,客户端动态获取PI的时候需要配置唯一的clientID,

IPvlan有L2和L3两种模式,一个父接口只能选择其中一种模式

  • L2模式:和macvlan的bridge模式工作原理相似,父接口作为交换机转发子接口的数据,同一个网络的子接口可以通过父接口转发数据,如果想发送到其它网络,则报文回通过父接口的路由转发出去
  • L3模式,有点像路由器的功能。IPvlan在各个虚拟网络和主机网络之间进行不同网络报文的路由转发工作。只要父接口相同,即使虚拟机/容器不在同一个网络内,也可以互通

路由

很多的网络问题都和路由有关,所以需要能看懂路由表,已经如何添加修改 在命令行中输入route -n 或者netstat -rn打印本机路由表输出如下

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.22.19.254    0.0.0.0         UG    0      0        0 eth0
10.22.19.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
10.96.0.0       0.0.0.0         255.240.0.0     U     0      0        0 boc0
169.254.169.254 10.22.19.1      255.255.255.255 UGH   0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

字段解释

  • Destination :目的网段,最长匹配0.0.0.0

  • Gateway: 网关 0.0.0.0 表示无网关,即与本机IP同一网段,不需要经过网关(同一局域网的两台主机通信不需要经过网关)

  • GenMask: 子网掩码

  • Flags

    U - Up表示有效 G - Gateway表示连接路由,若无这个字段表示直连目的地址 H - Host表示目标是具体主机,而不是网段 R 恢复动态路由产生的表项 D 由路由的后台程序动态地安装 M 由路由的后台程序修改

    ! 拒绝路由址 H-Host表示目标是具体主机不是网段。

  • Metric: 路由距离,到达指定网络所需要的中转数,大型局域网和广域网所必须的

  • Ref: 路由项的引用次数(不在linux内核中使用)

  • Use:此路由项被路由软件查找的次数

  • Iface:网卡名

路由类型

主机路由:路由表中执行单个IP地址或者主机名的路由记录,Flag值为H

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        10.139.128.1    255.255.255.0   UG    0      0        0 eth0

网络路由: 主机可到达的网络

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        10.139.128.1    255.255.255.0   UG    0      0        0 eth0

默认路由: 目标主机的IP或者网络不在路由表中,数据包就被发往默认网关

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    0      0        0 eth0

路由命令

-A:设置地址类型 -C:打印 Linux 内核的路由缓存 -v:显示详细信息 -n:不执行 DNS 反向查找,直接显示数字形式的 IP 地址 -e:netstat 格式显示路由表 -net:到一个网络的路由表 -host:到一个主机的路由表

参数:

add:增加路由记录 del:删除路由记录 target:目的网络或目的主机 gw:设置默认网关 mss:设置TCP的最大区块长度(MSS),单位MB window:指定通过路由表的TCP连接的TCP窗口大小 dev:路由记录所表示的网络接口

  • 1、添加主机路由,添加主机路由时,需要指定网络 ID 和主机 ID,此时需要设置 netmask 255.255.255.255
[root@VM_139_74_centos ~]# route add -net 10.0.0.10 netmask 255.255.255.255 gw 10.139.128.1 dev eth0
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.10       10.139.128.1    255.255.255.255 UGH   0      0        0 eth0
  • 2 添加网络路由,添加网络路由时,只需指定网络 ID,通过 netmask 设置掩码长度:
[root@VM_139_74_centos ~]# route add -net 10.0.0.0 netmask 255.255.255.0 gw 10.139.128.1 dev eth0
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        10.139.128.1    255.255.255.0   UG    0      0        0 eth0
  • 3 添加同一个局域网的主机,不指定 gw 选项时,添加的路由记录不使用网关
[root@VM_139_74_centos ~]# route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
  • 4 屏蔽路由
[root@VM_139_74_centos ~]# route add -net 224.0.0.0 netmask 240.0.0.0 reject
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
224.0.0.0       -               240.0.0.0       !     0      -        0 -
  • 5删除可用
route del -net 224.0.0.0 netmask 240.0.0.0
  • 6 删除屏蔽路由
route del -net 224.0.0.0 netmask 240.0.0.0 reject
  • 7 删除和添加设置默认网关,添加或删除默认网关时,Linux 会自动检查网关的可用性:
[root@VM_139_74_centos ~]# route add default gw 192.168.1.1
SIOCADDRT: Network is unreachable
[root@VM_139_74_centos ~]# route del default gw 192.168.1.1
SIOCDELRT: No such process