LoadBalancerv2的原理分析
OpenStack 是直接采用各种开源可用的负载均衡项目来完成负载均衡的任务,默认使用 HAProxy。LBaaSv2 本质来说,其实也是根据用户提出的负载均衡要求,生成符合的HAProxy配置文件并启动 HAProxy,然后由 HAProxy 进行负载均衡。
High Availability Proxy(HAProxy)?
HAProxy 是个著名的开源的软件 TCP(四层)/HTTP(七层) 负载均衡器和代理(proxy)软件,可以运行在 Linux,Solaris 和 FreeBSD 等系统上。目前,它已经被许多大公司采用,包括GitHub, Imgur, Instagram, and Twitter 等。它类似 Nginx 的,采用了单进程和事件驱动模型;它使用的内存量低而且稳定,能够处理大量并发请求。
在这里我简单罗列HAProxy配置。详细内容查看:
http://www.cnblogs.com/wanstack/p/8392332.html
haproxy 配置中分成五部分内容,分别如下:
global:参数是进程级的,通常是和操作系统相关。这些参数一般只设置一次,如果配置无误,就不需要再次进行修改。
defaults:配置默认参数,这些参数可以被用到frontend,backend,Listen组件。
frontend:接收请求的前端虚拟节点,Frontend可以更加规则直接指定具体使用后端的backend。
backend:后端服务集群的配置,是真实服务器,一个Backend对应一个或者多个实体服务器。
Listen Fronted和backend的组合体。
neutron的LoadBalancerv2配置文件在 /etc/haproxy/haproxy.cfg中
###########全局配置######### global log /dev/log local0 #[日志输出配置,所有日志都记录在本机,通过local0输出] log /dev/log local1 notice #定义haproxy 日志级别[error warringinfo debug] chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin stats timeout 30s user haproxy group haproxy #可以由配置项 user_group 指定,默认为 nogroup daemon #以后台形式运行harpoxy # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS ssl-default-bind-options no-sslv3 ########默认配置############ defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http
我们事先创建了qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2,我们看看它的配置文件
root@netagent:~# ip netns list qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2
该负载均衡是1个LoadBalance对应1个listener,1个pool。
在/var/lib/neutron/lbaas/v2/0f66315f-0ccf-43cb-abca-2bb6f51e8fb2/haproxy.conf 中
# Configuration for loadbalance1 global daemon user nobody group haproxy log /dev/log local0 log /dev/log local1 notice stats socket /var/lib/neutron/lbaas/v2/0f66315f-0ccf-43cb-abca-2bb6f51e8fb2/haproxy_stats.sock mode 0666 level user defaults log global retries 3 option redispatch timeout connect 5000 timeout client 50000 timeout server 50000 frontend 62ac018e-f6fc-4d60-80df-13b1e4cdc6f6 option tcplog maxconn 100 option forwardfor bind 2.2.2.20:80 mode http default_backend 8d28b2c3-9c44-46e5-b2eb-7bd9b8d5faf6 backend 8d28b2c3-9c44-46e5-b2eb-7bd9b8d5faf6 mode http balance roundrobin timeout check 1 option httpchk GET /index.html http-check expect rstatus 201|200|202 server d56fc582-33cd-4fc7-b95f-16534c8a4860 2.2.2.5:80 weight 1 check inter 1s fall 5 server cc2230bf-f3b8-4beb-8584-71b0f3a0ba5c 2.2.2.4:80 weight 1 check inter 1s fall 5 server b490cadb-cff1-4e7a-92c7-a134c0f8b321 2.2.2.6:80 weight 1 check inter 1s fall 5
LBaasv2 可以看做 OpenStack Neutron 对各种物理负载均衡器的虚拟化。它的概念可以和 HAProxy 中的概念进行类比:
HAProxy 的概念 | LBaasv2 的概念 | 说明 |
---|---|---|
Driver | LBaas v2也是采取 driver 模型来支持多种物理的负载均衡器。LBaasv2 默认实现了 HAProxy driver,同时,它也支持多个其他 Vendor driver。厂商驱动 | |
Frontend | Listener | LBaasv2采用Listener方式将流量转移到不同的pool中的member。 |
Backend | Pool | 代表Listener所监听的负载后端的虚拟机池。 |
Backend server | Member | Member 对应的是 pool 里面处理网络请求的一个 OpenStack Nova 虚机 |
Health check | Health monitor | 它用来监测 pool 里面 member 的状态,支持 HTTP, TCP, 和 ping 等多种检测方法。在 Nuetron 中这是可选的,如果没有 Health monitor,pool 会一直认为所有的 member 都是 ACTIVE 状态,这样所有的 member 会一直出现在 VIP 的分发列表中,哪怕 member 对应的实例不能响应网络请求。这在实际应用中会造成负载均衡的响应异常。 |
LoadBalancerv2的使用场景?
由上图可知道,一个LoadBalancerv2可以对应多个Pool,我们另外又建立一个pool如下所示:
在/var/lib/neutron/lbaas/v2/0f66315f-0ccf-43cb-abca-2bb6f51e8fb2/haproxy.conf 中
# Configuration for loadbalance1 global daemon user nobody group haproxy #可以由配置项 user_group 指定,默认为 nogroup log /dev/log local0 log /dev/log local1 notice stats socket /var/lib/neutron/lbaas/v2/0f66315f-0ccf-43cb-abca-2bb6f51e8fb2/haproxy_stats.sock mode 0666 level user defaults #不用管 log global retries 3 option redispatch timeout connect 5000 timeout client 50000 timeout server 50000 frontend 62ac018e-f6fc-4d60-80df-13b1e4cdc6f6 option tcplog maxconn 100 option forwardfor # 当 mode 为 ”http“时,设置 forwardfor,使得通过 X-Forward-For 头来保存原始的源 IP 地址 bind 2.2.2.20:80 #监听Listener的vip:port mode http #监听Protocol default_backend 8d28b2c3-9c44-46e5-b2eb-7bd9b8d5faf6 #对应的监听池 frontend bf144f31-cdbb-4426-b90b-4bdbc67501f1 option tcplog maxconn 100 option forwardfor bind 2.2.2.20:100 mode http default_backend 8b50ed30-5290-421c-9d31-fb3751a26be2 backend 8b50ed30-5290-421c-9d31-fb3751a26be2 mode http balance roundrobin server bef852d0-9164-46ee-ace5-92462e8d89ef 2.2.2.14:100 weight 1 server 8aeb5cc2-7301-4931-ac3b-e0d0ca891e88 2.2.2.15:100 weight 1 server 250a919f-dfc1-41b6-8378-2b4015f1acd0 2.2.2.16:100 weight 1 backend 8d28b2c3-9c44-46e5-b2eb-7bd9b8d5faf6 mode http balance roundrobin timeout check 1 option httpchk GET /index.html http-check expect rstatus 201|200|202 server cc2230bf-f3b8-4beb-8584-71b0f3a0ba5c 2.2.2.4:80 weight 1 check inter 1s fall 5 # member1 的配置,包括 ip,port(member 提供服务的端口,此时没有指定check port,因此也是健康检查的 TCP端口),weight;check 指定做健康检查;
# inter 指定两次连续检查之间的间隔,默认2s (1s);fall 指定 Max Retries 或者连续几次检查失败即认为member 是 DOWN 的次数 (5) server d56fc582-33cd-4fc7-b95f-16534c8a4860 2.2.2.5:80 weight 1 check inter 1s fall 5 server b490cadb-cff1-4e7a-92c7-a134c0f8b321 2.2.2.6:80 weight 1 check inter 1s fall 5
访问wget -O - http://2.2.2.2:80 和wget -O - http://2.2.2.2:100都成功。
以上是vip与pool的members同在一个subnet下,下面我们验证一下vip与pool的members不在同一个subnet。
我们创建一个新的Loadbalance和一个listener,vip地址为7.7.7.7,然后创建一个pool,注意一个虚拟机可以加入多个pool,所以我们还把上面的虚拟机加入这个新建的pool中。然后通过路由器subnet7.7.7.0/24和subnet2.2.2.0/24连通。也就是说vip7.7.7.7能与member2.2.2.4,2.2.2.5,2.2.2.6是联通的。
配置如下/var/lib/neutron/lbaas/v2/5081116f-8928-40d7-8aaa-e30c336ca713/haproxy.conf
# Configuration for loadbalance3 global daemon user nobody group haproxy log /dev/log local0 log /dev/log local1 notice stats socket /var/lib/neutron/lbaas/v2/5081116f-8928-40d7-8aaa-e30c336ca713/haproxy_stats.sock mode 0666 level user defaults log global retries 3 option redispatch timeout connect 5000 timeout client 50000 timeout server 50000 frontend 84800dd3-0507-4628-b54b-a23226bec4f8 option tcplog maxconn 100 option forwardfor bind 7.7.7.7:80 mode http default_backend 3583deda-e9ca-40bb-ba23-0fec204c099f backend 3583deda-e9ca-40bb-ba23-0fec204c099f mode http balance roundrobin server 48b36860-8e4d-476e-9196-ad052c317f44 2.2.2.5:80 weight 1 server f8732b2a-bfaa-4e5f-b8bb-f88c9fed899b 2.2.2.4:80 weight 1 server 004f7950-4031-4de3-98b2-ca30e39c4e4e 2.2.2.6:80 weight 1
也就是说只要vip与member可通信即可,不一定要在同一个subnet中。
另外,如果要从外网访问的话,则还需要创建一个 floating ip 并且把它关联到 lb 的vip 上。 haproxy 所在的namespace 其实只有一个IP地址,分别接收外部连接以及和成员之间的连接。
LoadBalancerv2的多agent模式?
LoadBalancerv2服务可以独立部署在服务器上,包括2个服务,neutron-openvswitch-agent 和neutron-lbassv2-agent。假设有2个节点都部署了LoadBalancerv2服务,当neutron-server发出创建请求时,会在这两个节点选择一个创建对应得namespace空间。
LoadBalancerv2的流程分析?
我们以qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2为例子来分析这个过程。
ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 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 9: tap83f82fcf-d1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1 link/ether fa:16:3e:d1:c8:b1 brd ff:ff:ff:ff:ff:ff inet 2.2.2.20/24 brd 2.2.2.255 scope global tap83f82fcf-d1 #vip的地址 valid_lft forever preferred_lft forever inet6 fe80::f816:3eff:fed1:c8b1/64 scope link valid_lft forever preferred_lft forever
该接口tap83f82fcf-d1挂在ovs上,并被打上它所在network的vlan_id的:
Bridge br-int fail_mode: secure Port patch-tun Interface patch-tun type: patch options: {peer=patch-int} Port br-int Interface br-int type: internal Port "tap83f82fcf-d1" tag: 1 Interface "tap83f82fcf-d1" type: internal
对于LoadBalancerv2创建过程(在v2中指Create a load balancer和Create listener完成,我们发现当只是完成Create a load balancer时候,并没有出现namespace,当Create listener完成时才会有namespace出现)我们对等如下操作:
ovs-vsctl --if-exists del-port tap83f82fcf-d1 --add-port br-int tap83f82fcf-d1 --set Interface tap83f82fcf-d1 type=internal --set Interface tap83f82fcf-d1 external-ids:iface-id=83f82fcf-d141-4774-87a0-ace79196bc88 --set Interface tap83f82fcf-d1 external-ids:iface-status=active --set Interface tap83f82fcf-d1 external-ids:attached-mac=fa:16:3e:d1:c8:b1 #iface-id 和 attached-mac可以在数据库中查到 ip link set tap83f82fcf-d1 address fa:16:3e:d1:c8:b1 ip netns add qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 sysctl -w net.ipv4.conf.all.promote_secondaries=1 ip link set tap83f82fcf-d1 netns qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip link set lo up ip link set tap83f82fcf-d1 netns qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip link set tap83f82fcf-d1 up ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip addr show tap83f82fcf-d1 permanent scope global ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip -4 addr add 2.2.2.20/24 brd 255.255.255.0 scope global dev tap83f82fcf-d1 ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 ip route list dev tap83f82fcf-d1 scope link ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 route add default gw 2.2.2.1 ip netns exec qlbaas-0f66315f-0ccf-43cb-abca-2bb6f51e8fb2 arping -U -I tap83f82fcf-d1 -c 3 2.2.2.20
LoadBalancerv2的源码解读?
LoadBalancerv2的代码结构如下:
1.Create a load balancer
2.Create a listener
3.Create a pool
4.Add member
5.Create a health monitor