Openstack Neutron : LBaaS v2
目录 |
- LBaaS v2 - 负载均衡概念 - 实现 - HAproxy - Octavia |
LBaaS v2
Neutron 包含负载均衡服务,即LBaaS。负载均衡器可以将用户的访问流量通过算法均摊到多台主机实例上,实现以 Scale-out的方式扩容应用的性能。Neutron LBaaS 包含以下核心的概念:
- 服务器池 Pool:服务器池内包含了多个服务器成员,同一个池内的服务器至少包含一种统一的对外服务。
- 服务器成员 Member:服务器成员,包含服务器的IP和端口。
- 监听器 Listener:监听器将持续监听指定的端口上的连接请求。一个负载均衡器中允许存在多个监听器,同时通过共享服务器池,多个监听器也可以关联到同一个服务器池。
- 健康监控 Health monitor:检查服务器池中成员的状态,以及服务器的加入、离开。
之所以称之为 lbaas v2,是因为Neutron的负载均衡的模型有过一次如上图的进化,在v2的版本中,neutron 对负载均衡的架构有了一次非常大的调整,v2版本变得更符合行业标准,且驱动和功能扩展变得更为简单,除此之外新版本还允许一个负载均衡器下添加多组 Listener 监听服务,以及加入了TLS。Lbaas v2无法和lbaas v1同时运行,开启lbaas v2需要停止lbaas v1。
改进后的LBaaS v2经过了更为全面的测试,并且加入了更多的HTTP层代理的特性。并开始支持Active-Standby部署模式,后续版本中将进一部支持Active-Active。新版可以说是负载均衡架构和功能的一次飞跃。
负载均衡概念
服务器池 Pool
服务器池即后端一组提供服务的实例,每个成员都是一个IP地址+4层的端口。例如,常见的提供web服务的实例,在服务器池中表示为:192.168.1.1:80。提供的服务不同则端口号也不相同。池内的服务器都统一对外提供某一种服务。例如:
服务器 1:192.168.1.1:80
服务器 2:192.168.1.3:80
服务器 3:192.168.1.4:80
负载均衡器通过 VIP 统一对前端提供服务,用户向虚拟IP发起连接请求,监听器监听到对应端口的请求后,通过负载均衡算法将请求转发到后端服务池中的一个成员上。然后成员对用户请求的资源进行响应,这样整个过程对于用户来说是透明的。包括后端服务器的增加、减少以应对用户规模的增缩,都不会对已经建立的连接产生影响。
监听器 Listener
监听器即一个不断在端口上检查连接请求的进程,一旦发现客户端的连接请求,则会按照你设定的规则将连接请求转发给后端的服务器池。一个监听器关联一个端口,如:HTTP(80)、HTTPS(443),当使用HTTPS,则需要上传用于https 加密和解密的证书到监听器中。
L7 转发策略 l7 policy
l7策略转发流程
LBaaS v2 支持L7的转发策略,每个监听器上都可以配置多条转发策略(L7 Policy)。策略由由规则(rule)和操作组成,类似 if…then…的条件语句,当有流量匹配了 rule 的条件时,就按照策略中的操作转发。否则就继续向下匹配。规则可以匹配HTTP请求中的特殊字段或URL,这给业务带来了极大的灵活性。
rule 支持的匹配项包括:
- Hostname,L7 rule 支持匹配HTTP/1.1 请求中的host字段
- path,HTTP URI 中路径的部分
- file_type,请求的文件类型
- header,HTTP 头中其他字段
- cookie,cookie的值
需要注意的是,同一个policy下的rule是“与”的关系,即策略下的所有rule都匹配的情况下,才会按照策略的操作转发。其中任何一条不匹配都会跳过该策略向下匹配。
匹配的算法包括:
- regex,正则表达式,非的意思
- starts_with,字符串开头
- ends_with,字符串结尾
- contains,字符串中包含的值
- equal_to,等于
L7 policy 的操作支持:
- block,请求将直接被拒绝;
- redirect_to_url,重定向用户的url;
- redirect_to_pool,重定向到后端特定的主机池内。
例如:可以在监听器上添加两条rule,一条匹配HTTP请求中 file_type 包含:jgp、png、gif、zip、txt 的请求转发给 image pool。另一条一条匹配URI中 path 以“*/login”开头的请求转发给APP pool。
这样就简单的实现了网站上静态内容(图片)与动态内容(用户登录)的分流处理,这能在不改变应用架构的情况下,减轻web服务的负载。对于云原生应用来说,这样的功能非常重要。
L7策略配置示例如下:
- neutron --policy policy1 lbaas-create-l7policy --name "policy1" --description "My Description" --listener "listener1" --action redirect_to_pool --pool "pool1" --position 1 (创建L7策略,命名为“policy1”描述为“lb策略”,并关联 “listener 1”,策略的动作是将匹配的流量转发到“pool1”)
- neutron lbaas-create-l7rule rule1 --rule-type path --compare-type starts_with --value "/api" --policy policy (在“policy 1”下添加一条规则,匹配所有URL中以 “/api”开头的请求)
可见到 LBaaS v2可根据业务需求制定出非常灵活的7层转发策略。
负载均衡算法 Algorithms
本身Neutron支持的负载均衡算法包括:轮询、最少连接、源IP。
- 轮询 Round robin,是最普遍的算法,每当有一个新的请求来临,负载均衡器都会按顺序选择服务器池中的一台设备来响应。有点类似音乐播放软件的列表循环。这种模式下服务器池中的每一个服务器都能均匀地分配到相同的访问请求数,而不会管服务器繁忙程度、服务器配置的高低。比较适用于服务器池内的服务器配置相同、用户访问习惯相同的业务。加权轮询是改进的负载均衡算法,当后端服务器池中设备配置高低不一时,可根据服务器处理能力的高低分配服务器的权值,权值高的服务器会被分配更多的用户请求。
- 最少连接算法 Least connections,负载均衡器收到新的请求时,都会从当前服务器池中挑选一个当前并发连接数最少的服务器来负责。最少连接算法考虑的服务器的实时负载情况,尽量保证了任务分配的平均,防止单个服务器超出负载,但是当后端服务器池中存在高处理能力的服务器时,这个处理能力高的设备始终无法获得更多的工作负载,存在性能的浪费。最少连接算法有优化后的加权最小连接算法
- IP hash,负载均衡器在收到主机的连接请求后,会根据数据包的源IP地址字段的hash值,同时按照轮询的方式为客户端分配主机,当负载均衡器再次收到同一IP的请求时,则会按照之前的记录为客户端分配上次建立连接的主机。这样保证了当同一个IP的用户,多次独立的访问都能由同一台服务器来处理,适用于服务器需要临时记录或保存客户信息的应用中。
健康监测 Monitor
健康检测的机制是指是负载均衡器通过定期的心跳信号检测服务器池中的服务器运行状态,从而排除掉后端故障的主机,保证服务整体正常。
Neutron支持的健康检测方式包括 ICMP、TCP、HTTP几种。
- ICMP是最简单的,通过ping 和echo的方式,看根据服务器是否响应。只要服务器操作系统TCP/IP协议栈运行正常,网卡不出问题,服务器到负载均衡之间的网络正常,ICMP的方式都起到良好的作用,但以上情况都不能代表服务器上面运行的应用是正常的。
- TCP是4层的检测方式,相比ICMP、TCP会请求主机的特定端口,看特定的端口能否正常响应。
- HTTP的方式则更进一筹,会通过get特定的页面,根据HTTP的返回代码来判断应用是否正常。
健康监测的指标越精确,越能反映服务的实际响应情况,如果是web服务,最好是使用HTTP的方式,这样检测结果更可信。
会话保持 Session persistence
会话保持功能常用于有状态的服务中,比如服务器通过session来维护用户连接的状态,因为session保存在服务器本地,如果不断地通过网络来在服务器池中同步session的话,会消耗服务器的带宽和处理能力,所以这时会选择使用负载均衡器的会话保持功能。它能保证同一个用户的请求会被发送到同一台服务器。
Lbaas v2支持的会话保持的类型为:
- 源IP:源IP即IP hash 算法,根据IP地址来识别客户。负载均衡器在收到请求后会计算数据包头源IP地址的hash值,并按照轮询的方式给该客户端分配一个服务器,同时将两者的对应关系记录到表中,当再次收到同一源IP发来的请求时,则查找到之前的服务器进行转发。但是当客户端通过NAT、或代理的方式上网时,源IP的方式就可能导致多个客户端被分配到同一个主机。顺便一提,去年在公司用12306在高峰期抢车票时,刚打开网站就被提示“您的操作频率过快”,即很有可能12306后端也是判断同一个IP提交的访问请求过多,从而误把新接入用户当作了已访问过的用户。
- HTTP_cookie:该模式下会根据浏览器中缓存的cookie来识别用户,cookie里面一般都缓存了计算机信息和浏览器的信息以及用户认证的信息。Lbaas v2中负载均衡器会在服务器第一次返回给客户端的回应中插入“SRV”的cookie值,标识了回复的服务器。当再次收到客户端发起的HTTP请求时,lbaas v2会找出 cookie中的"SRV"字段,并剥离掉后转发给之前回复的服务器。HTTP_cookie 的问题在于,有可能一些用户会禁用掉浏览器上的cookies,这种情况下基于cookies的会话保持就将失效了。
- App_cookie:该模式下需要在负载均衡器中预先定义各个后端中设置的cookie,并将对应关系存储到表中,当收到客户端的请求时,检查请求中是否有预先定义的cookie,如果有,则转发到对应的服务器。
虽然当今互联网应用中通过token来实现用户的识别和鉴权已经比较常见了,但负载均衡的会话保持能够很好弥补通过 seesion 识别用户的应用的不足。但是基于cookie的会话保持无法支持服务器直接返回的部署模式,即服务器返回给用户的流量不经过负载均衡器,而是直接上行转发出去。所以在某些大流量的应用中,负载均衡器可能成为性能的瓶颈。
非对称流量中,服务器直接返回到客户端,上行流量不经过负载均衡器,LBaaS v2 暂时还不支持这种部署模式。
实现
Neutron中 LBaaS v2有两种实现方式,
一是:使用HAproxy作为负载均衡器,在网络节点上运行LBaaS agent,agent会完成节点上的Haproxy 的创建和配置工作。这也是目前较为成熟的使用方式。
二是:使用Octavia 作为负载均衡器,Octavia是在LBaaS v2中加入到openstack中的,官方对它的定位不是要代替HAproxy在neutron中的地位,而是作为一个可选开源的LB服务提供者,类似LVS+F5等。Octavia的架构是全新设计的,而且在一开始就立志成为运营级的负载均衡解决方案。只是目前Octavia还是远谈不上成熟,官方推荐只在Devstack中使用。
HAproxy + keepalive
比较常用的开源负载均衡器有LVS、Nginx、HAproxy,其中LVS只能做到四层的负载均衡,即只能依据IP+端口的方式进行转发,不支持L7的转发策略,Nginx不仅能做Web服务器,同时也能作为负载均衡器使用;HAproxy 和Nginx都能基于L7策略进行转发。LVS也经常和HAproxy、Nginx混用,在大流量的集群中,先由LVS将流量分摊到不同的Nginx/HAproxy集群,再由Nginx/HAproxy做L7转发。除此之外Neutron也支持Ctrix、F5、Radware等公司的插件,从而通过专用的负载均衡硬件来实现。
LBaaS v2的经典实现方式就是在网络节点上部署HAproxy+Keepalive 实现负载均衡服务。 其中HAproxy提供L7的负载均衡,Keepalive用于实现高可用方案。
HAproxy
HAproxy能够为服务器池提供7层的负载均衡功能,即能根据HTTP请求头中的内容来执行负载均衡算法。而且作为开源软件,被广泛使用。
1.启用lbaas v2首先需要修改neutron的配置文件,加入插件: /etc/neutron/neutron.conf service_plugins = [existing service plugins],neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2 2.在lbaas的配置文件中添加lbaas v2: /etc/neutron/neutron_lbaas.conf service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default 3.选择2层设备的驱动: /etc/neutron/lbaas_agent.ini [DEFAULT] interface_driver = openvswitch 根据实际,选择 ovs 或者 linux bridge,需要与节点上的2层设备类型匹配。 4.开启数据库迁移 neutron-db-manage --subproject neutron-lbaas upgrade head 5.启动 lbaas v2 agent。 neutron-lbaasv2-agent \ --config-file /etc/neutron/neutron.conf \ --config-file /etc/neutron/lbaas_agent.ini
随后即可以创建负载均衡器:
1.创建负载平衡器,指定负载平衡的名称和关联的子网名。需指定与虚拟机所在的子网。 neutron lbaas-loadbalancer-create --name my-lb private-subnet 2.为新负载平衡器创建侦听器。 neutron lbaas-listener-create \ //添加监听器 --loadbalancer my-lb \ //关联之前创建的负载均衡器 --protocol HTTP \ //选择监听器协议,TCP\HTTP\HTTPS --protocol-port 80 \ //选择监听器对外监听的端口(即向用户开放的端口) --name webservice-listener \ //设置监听器名称 3.创建 LBaaS 服务器池。 neutron lbaas-pool-create \ --lb-algorithm ROUND_ROBIN \ //选择负载均衡算法,支持上文中提到的轮询、最少连接、IP hash等 --listener LISTENER_1_NAME \ //关联监听器 --protocol HTTP \ //服务器池使用的协议 --name LB_POOL_1 //服务器名称 4.将服务器实例添加到创建的 LBaaS 池中。 neutron lbaas-member-create \ --subnet <subnet-id> --address <server 1 IP> \ //将后端服务器添加到地址池中 --protocol-port 80 <pool name> //后端服务器上服务所使用的端口,可以与前端的端口不一致 neutron lbaas-member-create \ --subnet <subnet-id> --address <server 2 IP> \ --protocol-port 80 <pool name> 5.设置Health monitor指标。 neutron lbaas-healthmonitor-create \ --delay DELAY_IN_SECONDS //设置心跳检测发送到服务器成员的周期,单位为秒。需避免过于频繁的心跳检测,以及检测不及时的情况出现,达到平衡。对可用性要求高可以设置为3~5秒, --type [HTTP | TCP] //选择心跳检测的协议,如果TCP则只检测服务器上端口是否开启,HTTP则支持检测web服务的状态。当选择HTTP时,可以指定http的方法,默认是 get 一个特定的页面。同时还能指定服务器正常响应对应的HTTP状态码,如返回200时,代表web服务正常,200以外的值,如404、408等则代表异常。可通过 expected_codes 设置。url_path 则用来指定health monitor 请求的页面。 --max-retries NUMBER \ //设置在改变服务器可用状态之前,等待服务器的应答的次数。假设为n,如果是n次未响应,则切换为inactive,之后如果n次正常响应,则切换为active。推荐为 3 --timeout TIMEOUT_IN_SECONDS //设置超时的时长,当超过该时长服务器都没有回应,则认为服务器此次心跳监测为故障。 --pool LBAAS_POOL //将健康监测配置关联到服务器池。
一个服务器从出现故障,到负载均衡器发现并标记为不可用,不再为其分配流量,这其中需要的时间为:Time = delay *(max-retries -1) + timeout (*忽略从服务器发生故障到下一次健康监测中间的延时),在这个时间段内,负载均衡器都会为服务器分配流量。 6.分配浮动IP,为负载均衡器分配浮动IP与为云主机分配浮动IP是一样的,都是在fip的命名空间中为指定一个公网地址到内网地址的映射。这样外部的用户就可以通过公网地址直接访问到服务器池内的主机。如果作为内部使用的负载均衡器,则不需要分配浮动ip。 neutron floatingip-associate FLOATINGIP_ID LOAD_BALANCER_PORT_ID
最后不要忘记设置防火墙和安全组,允许外部流量访问负载均衡器的VIP和开启的listener端口。
Keepalive
HAproxy的 Active/Standby 部署模式就是通过keepalive 来实现的。keepalive的核心是vrrp,openstack的HA中大量使用了vrrp协议来提供高可用,包括之前L3中提到的路由器的高可用。负载均衡器的vip将会配置在vrrp的 vip上,对外提供服务。同时vrrp会通过心跳检测负载均衡主备设备运行的状态,并实现vip的切换。
Octavia中还有一个假主备模式,即负载均衡在实际中为单节点部署,不过Octavia Controller内的Health manager会频繁检测负载均衡节点的运行状态,一旦发现负载均衡器故障,则从备用的负载均衡器中选一个代替故障的设备,并套用原来的配置。
Octavia
Octavia项目是在 Liberty 版本中随着LBaaS v2一同发布,其amphorea模块是实现负载均衡功能的模块,支持部署在虚拟机、容器、裸机上,为云上的租户提供负载均衡服务。
上图是Octavia的架构,neutron原生集成了Octavia的驱动,可以直接通过Neutron的接口来完成Octavia的管理。同时Octavia也支持独立工作,其拥有独立的数据库,租户的配置信息不仅会保存在Neutron的数据库中,也会保存在Octavia的独立数据库中。(同时按照网上的部署经验,octavia和neutron的数据库同步是一个较大的问题)
Octavia 0.8版本中的amphorae 镜像是一台运行了HAproxy的ubuntu虚拟机,已经支持RH Linux、Centos、Fedora。未来还将支持以容器和裸金属的方式部署。
除此之外是Octavia的核心Controller,它包含4个组件:
- API Controller:运行Octavia 的API,并接受外部的调用申请,然后通过消息总线传送给worker。
- Controller Worker:负责执行API的各种操作,包括对nova、neutron接口的调用,以实现amphorae虚拟机的生命周期管理、创建端口、创建外部网络等资源,除此之外还有SSL证书、工作流等等功能管理。都由worker来一一实现。
- Health manager:用于监控amphorae的运行状态,并执行amphorae的故障切换。
- Housekeeping manager:用于删除无用的数据库记录,管理备用池和安全证书等。
用户在openstack环境中创建负载均衡服务时,创建amphorea虚拟机、端口、安全组等操作,这些都是由Octavia Controller自动完成,用户不可见,用户能见到的只有部署完成之后的Octavia的配置项和对应的网络端口。
service_provider = LOADBALANCERV2:Octavia:neutron_lbaas.drivers.octavia.driver.OctaviaDriver:default
Octavia的创建和配置命令与创建HAproxy的命令是完全一样的,配置好插件后 Octavia API Controller 将执行neutron指令,并完成amphorae的创建和配置等工作。
可见到Octavia项目目标是搭建一个完善的本地负载均衡管理平台,目前它是以虚拟机的方式提供服务,将来计划能够对云主机、容器、甚至裸机部署负载均衡服务,并支持Active、Active部署方式。
更多内容可以参考以下文章
https://docs.openstack.org/octavia/latest/reference/introduction.html
http://lingxiankong.github.io/blog/2016/03/30/octavia/
http://502245466.blog.51cto.com/7559397/1303506
Load Balancing as a Service : Liberty and Beyond
负载均衡本身的技术并不复杂,也发展得较为成熟,但如今负载均衡在各种云上扮演着非常重要的角色,各个云上与部署解决方案中都能看到它的身影。究其原因是其给租户的应用带来的弹性和可用性。云的租户可以在前端用户完全无感知的情况下,按负载增删后台服务器的数量,并实现服务的高可用,这非常符合云“按需使用”“分布式高可用服务”的理念。所以当服务的弹性伸缩和高可用性成为云计算的基本属性时,负载均衡器就开始在云上扮演不可替代的角色,可以说,不支持负载均衡的云不能称之为云。而传统的硬件负载均衡器无论是在可靠性、扩展性、可编程性、成本等方面都无法满足云供应商的需求。
Otavia的加入也可以说是openstack社区很清楚地看到了这一趋势,并立志将负载均衡单独拿出neutron作为一个重要项目来对待。从Octavia支持的部署模式就能看出这一项目的野心。或许它未来将成为一个跨虚拟机、容器、裸机的统一负载均衡服务。