Luckylau's Blog

LoadBalancerv2的原理分析

​ OpenStack 是直接采用各种开源可用的负载均衡项目来完成负载均衡的任务,默认使用 HAProxy。LBaaSv2 本质来说,其实也是根据用户提出的负载均衡要求,生成符合的HAProxy配置文件并启动 HAProxy,然后由 HAProxy 进行负载均衡。

更新时间 更新内容
2017-03-10 初始版本
2017-04-24 添加HAProxy详细说明链接

High Availability Proxy(HAProxy)?

​ HAProxy 是个著名的开源的软件 TCP(四层)/HTTP(七层) 负载均衡器和代理(proxy)软件,可以运行在 Linux,Solaris 和 FreeBSD 等系统上。目前,它已经被许多大公司采用,包括GitHub, Imgur, Instagram, and Twitter 等。它类似 Nginx 的,采用了单进程和事件驱动模型;它使用的内存量低而且稳定,能够处理大量并发请求。

在这里我简单罗列HAProxy配置。详细内容查看:

Neutron中的LoadBalancerv2的Haproxy

haproxy 配置中分成五部分内容,分别如下:
​ global:参数是进程级的,通常是和操作系统相关。这些参数一般只设置一次,如果配置无误,就不需要再次进行修改。
​ defaults:配置默认参数,这些参数可以被用到frontend,backend,Listen组件。
​ frontend:接收请求的前端虚拟节点,Frontend可以更加规则直接指定具体使用后端的backend。
​ backend:后端服务集群的配置,是真实服务器,一个Backend对应一个或者多个实体服务器。
​ Listen Fronted和backend的组合体。

neutron的LoadBalancerv2配置文件在 /etc/haproxy/haproxy.cfg中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
###########全局配置#########
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,我们看看它的配置文件

1
2
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 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 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 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 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为例子来分析这个过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
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的:

1
2
3
4
5
6
7
8
9
10
11
12
13
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出现)我们对等如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

参考:

http://blog.csdn.net/zhu_tianwei/article/details/41117323

Luckylau wechat
如果对您有价值,看官可以打赏的!