IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Neutron DVR —Dive into Human Defined DVR

    hu, xueqing发表于 2016-04-21 09:51:50
    love 0

    本文旨在通过全部手动的方式,来完成DVR的手动部署。大体思路是,在一个DVR的环境里,手动创建虚拟机,手动创建各种Linux网络设备,手动添加各种流表,完成新建虚拟机和在DVR模式下的虚拟机的DHCP,二层,三层通信。

    目录

    • 拓扑结构和机器角色信息(上一篇:https://www.ustack.com/blog/neutron-dvr-dive/)
    •  Human Defined DVR之DHCP(上一篇:https://www.ustack.com/blog/neutron-dvr-dive/)
      手动创建虚拟机
      1、下载镜像
      2、 镜像格式转化(img->qcow2)
      3、 创建XML模板
      4、通过Libvirt启动虚拟机
      5、验证虚拟机是否正常发包
      配置虚拟机用到的网络设备
    • Human Defined DVR之虚拟机二层通信(上一篇:https://www.ustack.com/blog/neutron-dvr-dive/)
      Cirros和本地虚拟机的二层通信
      Cirros和其他计算节点上虚拟机的二层通信
    • Human Defined DVR之虚拟机三层通信
    • Human Defined DVR之FloatingIP的实现
                在QRouter ns里干点事
                 在FIP ns里干点事

     

    Human Defined DVR之虚拟机三层通信

    首先新创建个网络、子网,在用路由器把上面的子网和刚创建的子网连接,最后的逻辑拓扑是这样的:

    1111

    我们创建的Cirros虚拟机在下面的蓝色区域里,我们要和上面黄色区域里的虚拟机通信。

    首先,Cirros虚拟机的请求包转发到了br-tun上,我们分析下Cirros发送的报文,如下:

    fa:16:3e:ff:aa:66 > fa:16:3e:35:25:42, ethertype IPv4 (0x0800), length 98: 192.168.10.222 > 10.10.10.4: ICMP echo request, id 31745, seq 0, length 64

    三层通信时,虚拟机会把包发到自己的默认网关上(网关是192.168.10.1,目的IP是10.10.10.4,目的MAC是fa:16:3e:35:25:42)。

    由于本地的L3 agent是DVR模式,那么会把流量路由到本地的路由器上。路由器里的两个QR设备(一个是192.168.10.1,另一个是10.10.10.1)挂载在了br-int上,当Cirros虚拟机请求自己的网关192.168.10.1时,在br-int上192.168.10.1的QR设备收到了请求包(虚拟机发来的数据包的Tag是1,自己的Tag也是1),路由器一看,目的地址是10.10.10.4,自己本地正好有个10.10.10.1的网关设备,就把数据包发给了它,这个QR设备在br-int上的Tag是2,那么这个请求继续发到了br-tun上。

    接下来看看br-tun上的流表:

    首先,对于从br-int上来的数据包resubmit到table1

    ovs-ofctl add-flow br-tun table=0,priority=1,in_port=1,actions=resubmit(,1)

    接下来,在table1上匹配从10.10.10.1上来的,Tag是2,的数据包resubmit到table2,并且改成本地的HOST MAC

    ovs-ofctl add-flow br-tun table=1,priority=1,dl_vlan=2,dl_src=fa:16:3e:de:07:79,actions=mod_dl_src:fa:16:3f:02:d7:f2,resubmit(,2)

    PS:HOST MAC可以通过查看数据库查询:

    MariaDB [neutron]> select * from dvr_host_macs;
    +————+——————-+
    | host | mac_address |
    +————+——————-+
    | server-233 | fa:16:3f:02:d7:f2 |
    | server-68 | fa:16:3f:08:c7:a5 |
    | server-64 | fa:16:3f:c9:7c:3c |
    +————+——————-+

    让我们继续看看table2上干了啥。
    很简单,单播请求到table20,广播请求到table22

    ovs-ofctl add-flow br-tun,table=2,priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
    ovs-ofctl add-flow br-tun,table=2,priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)

    由于CIrros虚拟机并不知道对端虚拟机在哪里,于是发广播,通过如下规则完成本地VLAN和全局VXLAN的转换,并发给其他所有的计算节点

    ovs-ofctl add-flow br-tun table=22,dl_vlan=2,actions=strip_vlan,set_tunnel:0x1a,output:2,output:

    来到了对面的68节点

    从br-tun上收到了来自远端233的数据包,resubmit 到table4

    ovs-ofctl add-flow br-tun table=0,priority=1,in_port=3,actions=resubmit(,4)

    在table4上完成全局VXLAN和本地VLAN的转换

    ovs-ofctl add-flow br-tun table=9,priority=1,tun_id=0x1a,actions=mod_vlan_vid:2,resubmit(,9)

    因为从233上发来的数据的源MAC是HOST MAC,那么在br-tun上匹配这个MAC地址,转给patch port

    ovs-ofctl add-flow br-tun table=9,priority=1,dl_src=fa:16:3f:02:d7:f2,actions=output:1

    对端的路由器10.10.10.1挂载在了br-int上,并且Tag是2,那么这个设备收到了请求,一看目的地址10.10.10.4,那么直接转发给了目的虚拟机。

    至此。搞定。

    2222

    Human Defined DVR之FloatingIP的实现

    首先,我们在Neutron里创建一个外部网络,网段是2.2.2.0/24,创建floatingip,并给server-64上的一个虚拟机绑定这个公网IP,如下:

    [root@server-233 ~(keystone_admin)]# neutron net-create external_network –router:external=True
    Created a new network:
    +—————————+————————————–+
    | Field | Value |
    +—————————+————————————–+
    | admin_state_up | True |
    | id | ccf351c9-826c-4d93-9dd4-625302bf3051 |
    | mtu | 0 |
    | name | external_network |
    | provider:network_type | vxlan |
    | provider:physical_network | |
    | provider:segmentation_id | 22 |
    | router:external | True |
    | shared | False |
    | status | ACTIVE |
    | subnets | |
    | tenant_id | ef979882f1954a0fa4ce7daf244aa557 |
    +—————————+————————————–+
    [root@server-233 ~(keystone_admin)]# neutron subnet-create ccf351c9-826c-4d93-9dd4-625302bf3051 2.2.2.0/24
    Created a new subnet:
    +——————-+——————————————+
    | Field | Value |
    +——————-+——————————————+
    | allocation_pools | {“start”: “2.2.2.2”, “end”: “2.2.2.254”} |
    | cidr | 2.2.2.0/24 |
    | dns_nameservers | |
    | enable_dhcp | True |
    | gateway_ip | 2.2.2.1 |
    | host_routes | |
    | id | 285aebd1-cd44-4663-9e2d-5f948fc369dc |
    | ip_version | 4 |
    | ipv6_address_mode | |
    | ipv6_ra_mode | |
    | name | |
    | network_id | ccf351c9-826c-4d93-9dd4-625302bf3051 |
    | subnetpool_id | |
    | tenant_id | ef979882f1954a0fa4ce7daf244aa557 |
    +——————-+——————————————+
    [root@server-233 ~(keystone_admin)]# neutron floatingip-create ccf351c9-826c-4d93-9dd4-625302bf3051
    Created a new floatingip:
    +———————+————————————–+
    | Field | Value |
    +———————+————————————–+
    | fixed_ip_address | |
    | floating_ip_address | 2.2.2.4 |
    | floating_network_id | ccf351c9-826c-4d93-9dd4-625302bf3051 |
    | id | 8fc5a7b8-c5ab-4e8d-a9be-83ea8ffc34ef |
    | port_id | |
    | router_id | |
    | status | DOWN |
    | tenant_id | ef979882f1954a0fa4ce7daf244aa557 |
    +———————+————————————–+

    接下来我们要打通floatingip和server-64的管理网——10.0.44.64,打通的最后结果就是,在宿主机上可以ping通虚拟机的floatingip,在虚拟机里也能ping通宿主机的管理网地址。如图:

    3333333

    4444

    我们的目标,手动创建floatingip 2.2.2.100,把我们创建的Cirros虚拟机(内网IP:192.168.10.222/24)也能实现如上效果。

    在QRouter ns里干点事

    注:以下如没有特殊说明,均在Router namespace中执行
    首先,在qrouter namespace里的rfp设备上增加一个/32位的公网IP地址,如下:

    ip -4 addr add 2.2.2.100/32 scope global dev rfp-28e4ec01-f brd 2.2.2.100

    其次,在iptables的nat表中添加floatingip和fix ip的规则,如下:

    [root@server-233 ~(keystone_admin)]# iptables -t nat -A neutron-l3-agent-OUTPUT -d 2.2.2.100/32 -j DNAT –to-destination 192.168.10.222
    [root@server-233 ~(keystone_admin)]# iptables -t nat -A neutron-l3-agent-PREROUTING -d 2.2.2.100/32 -j DNAT –to-destination 192.168.10.222
    [root@server-233 ~(keystone_admin)]# iptables -t nat -A neutron-l3-agent-float-snat -s 192.168.10.222/32 -j SNAT –to-source 2.2.2.100

    添加高级路由

    ip -4 rule add from 192.168.10.222 priority 57482 table 16 type unicast

    其中,table 16里是这样的规则:

    [root@server-233 ~(keystone_admin)]# ip route show table 16
    default via 169.254.31.29 dev rfp-28e4ec01-f

    由于虚拟路由器的rfp设备和fip里的fpr设备是一对veth设备,那么会在fip namespace里收到包
    在FIP ns里干点事

    在FIP namespace里添加一条路由,如下:

    ip -4 route replace 2.2.2.100/32 via 169.254.31.28 dev fpr-28e4ec01-f

    最后,FIP namespace里的设备和路由信息是这样的:

    [root@server-233 ~(keystone_admin)]# ip route
    default via 2.2.2.1 dev fg-9f4709e2-8e
    2.2.2.0/24 dev fg-9f4709e2-8e proto kernel scope link src 2.2.2.6
    2.2.2.9 via 169.254.31.28 dev fpr-28e4ec01-f
    2.2.2.100 via 169.254.31.28 dev fpr-28e4ec01-f
    169.254.31.28/31 dev fpr-28e4ec01-f proto kernel scope link src 169.254.31.29
    [root@server-233 ~(keystone_admin)]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
    valid_lft forever preferred_lft forever
    2: fpr-28e4ec01-f@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 42:55:ae:6e:ab:34 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 169.254.31.29/31 scope global fpr-28e4ec01-f
    valid_lft forever preferred_lft forever
    inet6 fe80::4055:aeff:fe6e:ab34/64 scope link
    valid_lft forever preferred_lft forever
    62: fg-9f4709e2-8e: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether fa:16:3e:e1:15:10 brd ff:ff:ff:ff:ff:ff
    inet 2.2.2.6/24 brd 2.2.2.255 scope global fg-9f4709e2-8e
    valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fee1:1510/64 scope link
    valid_lft forever preferred_lft forever

    好了,下面就是见证奇迹的时刻!!
    LOOK!

    5555

    作者简介:

    苌智:
    个人简介:SDN 工程师,2015年1月加入 UnitedStack有云,专注于虚拟网络和 SDN 方向,OpenStack Neutron 社区活跃贡献者。



沪ICP备19023445号-2号
友情链接