前言
由于网络部分出现了许多得新名词。将从整体到分部细致讲解。
基本结构
来源于网络得一张图
图片基本介绍
- A、B、C、D...P为端口
- qbrXXXX 属于linux网桥部分
- br-int、br-tun、br-ex 属于ovs网桥部分
- router是一个网络命名空间
- dhcp是另外一个网络命名空间
网络基本流程
如图所示,连成了一条线。重要得如何实现互联,接下来以表象论证这张图。
表象论证
最好将图放在一边,边看边对照图。
这里先介绍从虚拟机访问外网。端口A开始:
虚拟网卡【A】
表现出来就是虚拟机有张网卡A。
- 找到虚拟机ip
openstack server show
查询此虚拟机得子网ip为 10.1.1.5,以及所在节点,记住这个节点。
- 获取此ip对应得端口id
openstack port list --fixed-ip ip-address=10.1.1.5
通过子网ip查询到端口id为 b65c1085-a971-4333-82dc-57012e9be490
记住这个id
tap设备【B】
图中A与B互联,意味着A与B一定具有某种映射关系。
- 拿出虚拟机的所在节点,以及端口id。
- 去这个节点上,执行
brctl show
若没有此命令则安装:yum install -y bridge-utils
可以看到这个id对应的tap设备!
图中还有qbrXXX 以及qvbXXX。
qbr是linux网桥的名称,可以看到和端口id也是一对一的关系。
qvb是下面要讨论的端口【C】
veth pair 【C】
veth pair是什么?后面再介绍。
由图可知,端口B(qvbXXX)和端口C(tapXXX)在同一个linux网桥上。它们俩互通了。
veth pair 【D】
端口D在ovs网桥上。C和D的互联是veth pair的特性。
- 查询C和D之间的互联
在虚拟机所在节点执行,根据你自己的id变换参数:
ip a|grep qvob65c1085-a9
由图可以看出,qvoXXX在ovs网桥上,qvb在linux网桥上。它们之间的互联是veth pair的特性,它们就像一根导线的两端。
- 找到ovs上的D端口
我这里的ovs是安装在容器里的,所以需要进入容器中执行ovs命令。
进入容器:
docker exec -itu0 neutron_openvswitch_agent bash
ovs查询命令:
ovs-vsctl show
这里可以看到3种网桥: br-int、br-tun、br-ex。这里有个印象就好。
仔细的查看一下,可以看到qvoXXX在br-int网桥上。
至此D端口也找到了
【E】【F】
E、F端口通过ovs网桥自身连接。
ovs-vsctl show
可以看到两个patch类型的端口,用于连接br-int和br-tun。类似于veth pair。
【G】【H】
ovs-vsctl show
可以在br-tun网桥上看到vxlan类型的端口,并注明本地ip和remote ip,通过此类型端口,将不同的物理环境互联,对于上层好似就一个网桥。再者br-tun网桥还与br-int互联,这意味,对于再上一层的应用,似乎只有一个br-int。
【I】【J】
和【E】【F】相同。
【M】【N】【L】【K】
此时携带源ip为子网的流量到达M端口,而L端口得网段为外网网段,因此M网段的流量此时无法直接进入L端口。借助router(网络命名空间),使用iptables,将M端口流量的源ip转换为外网网段。此时流量可进入L端口从而访问外网。(M与N之间连通性非网络对实现,而是ovs tap设备实现。网络对的一个明显特征为 ip a 可以看到@符号连接两个端口)
找到虚拟机所在租户的路由id
本机为 894699dc-bc60-4b5e-b471-e95afa20f1d7
根据路由id找到网络命名空间
在所有节点上执行如下命令,找到对应id的qrouter
ip netns
本环境为:qrouter-894699dc-bc60-4b5e-b471-e95afa20f1d7
在此网络命名空间的节点上执行(如下命令意义为进入网络命名空间):
ip netns exec qrouter-894699dc-bc60-4b5e-b471-e95afa20f1d7 bash
此时已进入网络命名空间。
查看ip
ip a
可以看到qg和qr开头的网卡名称。qg为弹性ip地址组,qr为子网网关。此时在虚拟机所在节点上查询ovs网桥,可以在br-int看到与此同名的qg和qr端口。
由于是源地址转换,因此先路由再转换源ip(iptables规则)。
查看路由规则:
route -n
第一条可以看到外网的网关,通过qg网卡发送,规则正好匹配。
选好路由规则之后,进行更改源ip。
iptables -t nat -S
可以看到 neutron-l3-agent-float-snat(配置了弹性ip才会出现)、neutron-l3-agent-snat。因为neutron-l3-agent-float-snat优先级高于neutron-l3-agent-snat,如果没有配置弹性ip,则会将源ip改为该路由的外网ip;如果配置了弹性ip则会将源ip改为弹性ip。
总的来说,流量从qr出去绕了一圈(网络命名空间)改变了源ip又从qg进入,然后通过ovs patch进入br-ex。
br-ex如何与外网连接的呢?进入网络节点查看ovs网桥:
可以看到 br-ex与em3网卡互联。因此流量直接走em3出去。还记得你这张网卡是干嘛的吗?是那张不配置ip的物理网卡!
拓展介绍
从外网访问虚拟机
通过iptables的prerouting可以看出,在进入之前修改了目的弹性ip为子网ip,后经路由转发。另,网络命名空间可以通过arp发现子网ip与mac地址的对应关系。
额外的网络命名空间
lbaas,负载均衡
dhcp,dhcp服务。
虚拟机专用tunnel网络实现
通过前面说的br-tun 实现。如果没有单独划分网络,则使用管理网网段。若单独配置了tunnel网络,则br-tun里的网络使用tunnel网络。
br-tun 里定义了vxlan,并且指定了 local_ip、remote_ip。根据这两个ip以及路由信息,可以确定 br-tun 通过哪张网卡与外部通信。也是因此可以为tunnel配置专用网卡。
防火墙,安全组实现原理
都是通过iptables实现。
防火墙:qrouter网络命名空间中得iptables实现。
安全组:虚拟机所在得宿主机得iptables实现。
- 防火墙
在qrouter网络命名空间中执行
iptables -t filter -S
可以看到防火墙规则。
- 安全组
在虚拟机所在宿主机执行
iptables -t filter -S
可以看到对应端口id得安全组规则。
如何从外部访问到qg网卡的
已经知道了qrouter 利用nat表实现弹性ip与子网ip之间的映射,但是如何从外部访问到qg网卡的?
这里做了一个简单的模拟操作:
https://www.jianshu.com/p/44e73910c241
dhcp 简介
dnsmasq 实现。
kolla-ansible 的dnsmasq日志相对路径参考:neutron/dnsmasq.log(可通过dnsmasq.conf 找到日志路径)
日志中可以看到dhcp的详细过程。过程参考如下:
Apr 23 15:53:46 c100-1 dhcpd: DHCPDISCOVER from 08:00:27:b9:88:74 via eth2
Apr 23 15:53:46 c100-1 dhcpd: DHCPOFFER on 192.0.2.112 to 08:00:27:b9:88:74 via eth2
Apr 23 15:53:48 c100-1 dhcpd: DHCPREQUEST for 192.0.2.112 (192.0.2.131) from 08:00:27:b9:88:74 via eth2
Apr 23 15:53:48 c100-1 dhcpd: DHCPACK on 192.0.2.112 to 08:00:27:b9:88:74 via eth2
文档参考:
https://docs.openstack.org/neutron/stein/admin/intro-basic-networking.html#dhcp
dhcp也通过网络命名空间实现,名称由网络id决定。dhcp可以拥有多个,通过neutron.conf 中 dhcp_agents_per_network 决定。
另:centos7虚拟机中的 /var/log/messages 也记录了dhcp相关操作。
network qos 简介
network qos 可以理解为网络流量限制,官方名称:网络质量即服务
本环境通过openvswitch实现的qos。
- 带宽限制规则实现:
作用于虚拟机所在物理节点的ovs上的qvo端口。
文档参考:
http://docs.openvswitch.org/en/latest/faq/qos/
带宽限制 查询命令参考:
ovs-vsctl list interface qvof6c61a2f-95
如上图为设置的 带宽限制规则。
- dscp mark 规则实现:
作用于虚拟机所在物理节点的ovs上的qvo端口。
源码参考(update_dscp_marking方法):
https://github.com/openstack/neutron/blob/stable/queens/neutron/plugins/ml2/drivers/openvswitch/agent/extension_drivers/qos_driver.py
通过openflow控制dscp mark。
首先找到流表对应端口号,命令参考:
ovs-vsctl list interface qvof6c61a2f-95
根据端口号查看流表,命令参考:
ovs-ofctl dump-flows br-int |grep 353 |grep mod_nw_tos
上图标记的104就为dscp mark 乘 4 的结果,乘4是一种规范。
参考
https://docs.openstack.org/neutron/queens/admin/deploy-ovs.html