前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >openflow group实现vip主主模式

openflow group实现vip主主模式

作者头像
惠伟
发布2021-02-24 11:25:33
1.2K0
发布2021-02-24 11:25:33
举报
文章被收录于专栏:虚拟化笔记虚拟化笔记

需求

租户创建vpc,租户创建虚拟机,租户创建数据库实现,返回访问的vip,vip主主模式,vip流量尽量负载均衡,同一session保持到固定的LB节点,而且虚拟机迁移时到vip不断流,迁移这个session还保持在同一个LB节点,要求租户流程隔离,LB运行于物理机,LB节点可扩展,后面是k8s pod,数据库实例运行于k8s pod中。

设计

第0步,部署完后,调用neutron-server api添加dpvs节点信息,neutron-server存数据库,然后广播所有ovs-agent,ovs-agent创建到dpvs的vxlan tunnel。

第1步,web调用k8s api创建mysql实现

第2步,k8s给web返回mysql所有ip和port

第3步,web调用neutron-server api创建vip

第4步,neutron-server给web返回vip ip,并且广播所有ovs-agent给此vip添加流表,web给用户展示vip ip和mysql实现vip port

第5步,web把vip_ip,vip_port,vpc_vxlan, k8s_ip,k8s_port提交给所有dpvs节点,dpvs进行配置

删除过程,web先通知dpvs删除,再通知neutron和k8s删除。

新的dpvs节点上线,web给neutron-server api添加dpvs节点,然后同步所有vip和k8s信息给dpvs

openstack第一要实现LB节点故障探测并且快速切换,第二要实现vip流量负载到LB节点之间,考虑过neutron-server实现,server和agent之间rpc太慢,故障切换时间不可保证,用neutron-openvswitch-agent实现,agent信息有限只能根据vpc/vip/vm实现流量负载均衡,而且没有好的故障探测机制,即使探测到故障再修改流表切换LB节点时间也太久。最后决定用ovs实现,ovs是转发面,越靠近转发面故障切换越快,并且实现了bfd功能,而且用group table能达到报文级别负载均衡。LB改造dpvs实现vxlan收发,并用vni隔离租户流量,不同租户vip有可能一样,不同租户虚拟机ip有可能一样,计算节点和dpvs节点full mesh建立vxlan tunnel,tunnel上运行bfd协议。ovs实现给虚拟机访问vip arp代答,ovs group table实现访问vip的流量走不同tunnel,group type用select,hash算法保证同一session的流量固定发往同一个dpvs节点。

ovs group负载均衡

代码语言:javascript
复制
Open vSwitch 2.4 and later by default hashes the source and destination Ethernet address, 
VLAN ID, Ethernet type, IPv4/v6 source and destination address and protocol, and for TCP and SCTP only, 
the source and destination ports.
The hash is "symmetric", meaning that exchanging source and destination addresses does not change the bucket selection.

详见ovs代码pick_default_select_group,bfd把port down后会自动切换到其它bucket出去

ovs bfd

代码语言:javascript
复制
ovs-vsctl set interface vxlan-0ad08026 bfd:enable=true
Port "vxlan-0ad08026"
Interface "vxlan-0ad08026"
type: vxlan
options: {df_default="true", egress_pkt_mark="0", in_key=flow, local_ip="10.208.128.20", out_key=flow, remote_ip="10.208.128.38"}
bfd_status: {diagnostic="No Diagnostic", flap_count="1", forwarding="true", remote_diagnostic="No Diagnostic", remote_state=up, state=up}

需要和dpvs配合运行bfd,bfd远远好于发icmp包探测这样的monitor。

openstack改造

  • 流表设计如下:

在br-tun table 20中增加一条priority更大的流表,让dst mac是vip的查group table,区别就是action从strip_vlan,set_tunnel:0x29,output:1177变为trip_vlan,set_tunnel:0x29,group:41,原来从一个tunnel口出去,现在到group,group中有好几个tunnel口,根据hash结果选一个tunnel口出去。

代码语言:javascript
复制
#原来的流
cookie=0xb37f4b0e192fa003, duration=26723512.305s, table=20, n_packets=1377429016, n_bytes=239779004594, idle_age=0, hard_age=65534, priority=2,dl_vlan=67,dl_dst=fa:16:3e:df:0a:dd actions=strip_vlan,set_tunnel:0x29,output:1177
#group流
cookie=0xb37f4b0e192fa003, duration=26723512.305s, table=20, n_packets=1377429016, n_bytes=239779004594, idle_age=0, hard_age=65534, priority=3,dl_vlan=67,dl_dst=fa:16:3e:df:0a:dd actions=strip_vlan,set_tunnel:0x29,group:41

group id是vip所在vxlan id,一个vpc对应一个group,一个dpvs节点对应group中一个bucket。

代码语言:javascript
复制
 ovs-ofctl -O OpenFlow13 add-group br-tun group_id=41,type=select,bucket=watch_port:vxlan-0ad08026,output:vxlan-0ad08026,bucket=watch_port:vxlan-0ad08038,output:vxlan-0ad08038
  • neutron-server:

增加api用于创建和删除dpvs节点,存储数据库,然后广播所有ovs-agent。vip利用port的api,device_owner标志为NEUTRON_VIP_PORT,这种类型的port广播所有ovs-agent。

  • neutron-ovs-agent:

ovs-agent启动时从neutron-server pull所有dpvs节点然后建立tunnel,再主动从server pull所有vip port,下流表。

当用户创建/删除vip时,server向所有agent广播创建/删除vip port,agent创建/删除流表。创建时br-tun table 20加一条流表,如果group不存则增加group。删除时br-tun table 20删除这条流表,如果是这个vpc的最后一个group则删除group。

当用户创建/删除dpvs时,server向所有agent广播创建/删除dpvs,agent创建/删除流表。创建时添加vxlan port,然后遍历group表在每个表中添加一个bucket,删除时遍历group表删除dpvs节点对应的bucket。

代码实现

python代码写得烂,请大家不要见笑。

https://github.com/huiweics/neutron/tree/openflow_group_ecmp_lb​github.com

效果和性能

最终采用的hash配置是selection_method=hash,fields\(ip_src,ip_dst,ip_proto\)。

测试环境就两个dpvs节点6和7。

测试脚本

代码语言:javascript
复制
i="1"
while [ $i -lt 10 ]
do
ovs-vsctl add-port br-int vxlan_net0_ip"$i"  -- set Interface vxlan_net0_ip"$i"  type=internal
ovs-vsctl set port vxlan_net0_ip"$i" tag=30
i=$[$i+1]
done
i="1"
while [ $i -lt 10 ]
do
openstack port create --network vxlan_net0 --mac-address fa:16:3e:ec:85:0"$i" --fixed-ip subnet=vxlan_subnet0,ip-address=192.168.200."$i"0 vxlan_net0_ip"$i"
i=$[$i+1]
done
i="1"
while [ $i -lt 10 ]
do
ip netns add vxlan_net0_ip"$i"
ip link set dev vxlan_net0_ip"$i" netns vxlan_net0_ip"$i"
ip netns exec vxlan_net0_ip"$i" ip link set dev vxlan_net0_ip"$i" address fa:16:3e:ec:85:0"$i"
ip netns exec vxlan_net0_ip"$i" ip addr add dev vxlan_net0_ip"$i" 192.168.200."$i"0/24
ip netns exec vxlan_net0_ip"$i" ip link set dev vxlan_net0_ip"$i" up
i=$[$i+1]
done
i="1"
while [ $i -lt 10 ]
do
ip netns exec vxlan_net0_ip"$i" curl http://192.168.200.5:3306/
i=$[$i+1]
done
i="1"
while [ $i -lt 10 ]
do
ip netns exec vxlan_net0_ip"$i" nc -nzv -u 192.168.200.5 3307
i=$[$i+1]
done
i="1"
while [ $i -lt 10 ]
do
ip netns exec vxlan_net0_ip"$i" curl http://192.168.200.6:3306/
i=$[$i+1]
done
i="1"
while [ $i -lt 10 ]
do
ip netns exec vxlan_net0_ip"$i" nc -nzv -u 192.168.200.6 3307
i=$[$i+1]
done

只ip proto变化,12/18才散列开。只dst_ip从192.168.200.5变华为192.168.200.5,9/18散列开。6出现15次,7出现21次,考虑到ip的相似性,hash结果还不错。

性能方面,首包送用户态,进行hash计算,然后给datapath安装流表,后续只在datapath转发,只要datapath安装的流表不老化就不再需要重新hash计算,对长连接大量数据传送性能没有影响,对短的连接影响比较大,短连接在任何场景都需要重新安装流表,相比较于安装流表,hash计算影响也比较小。

故障时间方面,如果ovs和dpvs之间的tunnel bfd检测到down了,那么ovs会把报文转发到另一个dpvs节。udp不受影响,直接到了另一个dpvs节点,就是不知道dpvs节点能不能转发到同一个rs。tcp如果处于等syn+ack状态,重传一次syn包就行了,最多64s,由net.ipv4.tcp_syn_retries控制。tcp如果连接已经建立好了,重传数据,时间会很久,由net.ipv4.tcp_retries1和net.ipv4.tcp_retries2控制。这是内核机制,总的来说用户态可以通过socket调用设置timeout参数,设置小一点能快速恢复故障。

后续

  • 怎么创建vip port

openstack port create --device-owner "network:network_vip" --network 79fe1480-adc2-4633-b31c-c1236ac9b757 vip_port

vip_port不支持多个ip,不能没有ip(--no-fixed-ip),创建后不支持修改device-owner。network 只能有一个segment。

  • ovs-agent down了,network被删除,ovs-agent重启后怎么删除这个network的group? group没有cookier机制。

重启先用OFPGroupDescStatsRequest获取所有group table,有的不再重复下,多的clean_stale_flow时删除。group不相同的增加或者删除bucket。

  • dpvs节点添加或者删除

增加api用于创建和删除dpvs节点,存储数据库,然后广播所有ovs-agent,dpvs的ip不再作为ovs-agent的配置项。

当用户创建/删除dpvs时,server向所有agent广播创建/删除dpvs,agent创建/删除流表。创建时添加vxlan port,然后遍历group表在每个表中添加一个bucket,删除时遍历group表删除dpvs节点对应的bucket,然后删除vxlan口。

  • of_interface

cfg.StrOpt('of_interface', default='native',choices=['ovs-ofctl', 'native'])

默认是native,先实现native方式给ovs下流表,后面再实现ovs-ofctl给ovs下发流表

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求
  • 设计
  • ovs group负载均衡
  • ovs bfd
  • openstack改造
  • 代码实现
  • 效果和性能
  • 后续
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档