Keepalived + LVS-DR Nginx 双主高可用

Posted by Sunday on 2018-08-09

LVS/DR模式

LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。LVS目前有三种IP负载均衡技术(VS/NAT、VS/TUN和VS/DR)、十种调度算法(rr | wrr | lc | wlc | lblc | lblcr |dh | sh | sed | nq)。
LVS在Unix-like系统中是作为一个前端(Director)存在的,又称为调度器,它本身不提供任何的服务,只是将通过互联网进来的请求接受后再转发给后台运行的真正的服务器(RealServer)进行处理,然后响应给客户端。

LVS集群采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。为此,在设计时需要考虑系统的透明性、可伸缩性、高可用性和易管理性。

LVS有两个重要的组件:一个是IPVS,一个是IPVSADM。ipvs是LVS的核心组件,它本身只是一个框架,类似于iptables,工作于内核空间中。ipvsadm 是用来定义LVS的转发规则的,工作于用户空间中。

LVS三种转发类型

LVS-NAT模式

称为网络地址转换,实现起来比较简单,所有的RealServer集群节点和前端调度器Director都要在同一个子网中,这种模型可以实现端口映射,RealServer的操作系统可以是任意操作系统,前端的Director既要处理客户端发起的请求,又要处理后台RealServer的响应信息,将RealServer响应的信息再转发给客户端,前端Director很容易成为整个集群系统性能的瓶颈。通常情况下RealServer的IP地址(以下简成RIP)为私有地址,便于RealServer集群节点之间进行通信通常情况下前端的Director有两个IP地址,一个为VIP,是虚拟的IP地址,客户端向此IP地址发起请求。一个是DIP,是真正的Director的IP地址,RIP的网关要指向Director的DIP。

LVS-DR模式

DR:直接路由(direct routing)模式,此种模式通过MAC地址转发工作,所有的RealServer集群节点和前端调度器Director都要在同一个物理网络中,此种模式不支持端口映射,此种模式的性能要优于LVS-NAT,RIP可以使用公网的IP,RIP的网关不能指向DIP。

优点:
相对LVS/NAT模式,DR模式不需要把返回的数据通过负载均衡转发,想要他发挥优势,那么就要相应的数据包的数量和长度远远大于请求数据包,幸运的是,大部分WEB服务都具备这样的特点,响应和请求并不对称,因此常用的WEB服务,都可以使用这种模式。

这种方式,负载均衡器不再是系统的瓶颈。如果你的负载均衡器只拥有100M的全双工网卡和带宽的话,通过集群的横向扩展也可以让整个系统达到1G的流量。

来自LVS官方站点的测试结果也告诉我们,LVS-DR可以容纳100台以上的实际应用服务器,对一般的服务而已,这样的表现足够了。

不足:
DR模式下不能跨网段转发数据,如果必须要跨网段进行负载,那么就必须使用LVS/TUN模式。

LVS-TUN模式

称为隧道模型RealServer服务器与前端的Director可以在不同的网络中,此种模型也不支持端口映射,RealServer只能使用哪些支持IP隧道的操作系统,前端的Director只处理客户端的请求,然后将请求转发给RealServer,由后台的RealServer直接响应客户端,不再经过Director,RIP一定不能是私有IP,在DR、TUN模式中,数据包是直接返回给用户的,所以,在Director Server上以及集群的每个节点上都需要设置这个地址。此IP在Real Server上一般绑定在回环地址上,例如lo:0,同样,在Director Server上,虚拟IP绑定在真实的网络接口设备上,例如eth0:0。

环境

准备四台服务器或虚拟机:

Web Nginx:192.168.10.111/192.168.10.112
Keepalived:192.168.10.101/192.168.10.102
Keepalived VIP:192.168.10.91/192.168.10.92
OS:CentOS 7.4

条件

安装keepalived。
时间同步。
设置SELinux和防火墙。
互相之间/etc/hosts文件添加对方主机名(可选)。
确认网络接口支持多播(组播)新网卡默认支持。

keepalived配置

ka101配置
vim /usr/local/keepalived/etc/keepalived/keepalived.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
[root@node1 ~]# cat /etc/keepalived/keepalived.conf 
global_defs {
notification_email {
root@localhost
}
notification_email_from ka@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 60
vrrp_mcast_group4 224.0.0.111
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 198
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass sunday
}
virtual_ipaddress {
192.168.10.91
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 199
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass sunday
}
virtual_ipaddress {
192.168.10.92
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

ka102配置

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
global_defs {
notification_email {
root@localhost
}
notification_email_from ka@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 60
vrrp_mcast_group4 224.0.0.111
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 198
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass sunday
}
virtual_ipaddress {
192.168.10.91
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
vrrp_instance VI_2 {
state MASTER
interface eth0
virtual_router_id 199
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass sunday
}
virtual_ipaddress {
192.168.10.92
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

notify 邮件通知脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
contact='root@localhost'

notify() {
local mailsubject="$(hostname) to be $1, vip floating"
local mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $contact
}

case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac

启动keepalived服务

1
2
systemctl start keepalived
systemctl enable keepalived

进行测试…

查看组播状态

1
2
3
4
5
6
7
[root@node1 ~]# tcpdump -nn -i eth0 host 224.0.0.111
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:30:08.594351 IP 192.168.10.102 > 224.0.0.111: VRRPv2, Advertisement, vrid 199, prio 100, authtype simple, intvl 1s, length 20
15:30:08.609724 IP 192.168.10.101 > 224.0.0.111: VRRPv2, Advertisement, vrid 198, prio 100, authtype simple, intvl 1s, length 20
15:30:09.597621 IP 192.168.10.102 > 224.0.0.111: VRRPv2, Advertisement, vrid 199, prio 100, authtype simple, intvl 1s, length 20
15:30:09.612917 IP 192.168.10.101 > 224.0.0.111: VRRPv2, Advertisement, vrid 198, prio 100, authtype simple, intvl 1s, length 20

配置LVS

分别安装lvs。CentOS7已经集成了LVS的核心,所以只需要安装LVS的管理工具就可以了

1
yum -y install ipvsadm

停止两台keepalived服务

1
systemctl stop keepalived

分别在ka101/ka102配置文件最后添加Virtual Server配置

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
52
53
54
55
56
57
58
59
60
61
62
virtual_server 192.168.10.91 80 {
delay_loop 3
lb_algo rr
lb_kind DR
protocol TCP
# sorry_server 127.0.0.1 80
real_server 192.168.10.111 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
real_server 192.168.10.112 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}
virtual_server 192.168.10.92 80 {
delay_loop 3
lb_algo rr
lb_kind DR
protocol TCP
# sorry_server 127.0.0.1 80
real_server 192.168.10.111 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
real_server 192.168.10.112 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}

配置RS(Real Server)Web服务

1
2
yum install epel-release -y
yum install nginx -y

分别在两台nginx web执行如下命令

1
2
3
4
5
echo web111 > /usr/share/nginx/html/index.html 
systemctl restart nginx

echo web222> /usr/share/nginx/html/index.html
systemctl restart nginx

添加RS脚本

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
vim lvs_rs.sh

#!/bin/bash
vip1=192.168.10.91
vip2=192.168.10.92
dev1=lo:1
dev2=lo:2
case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $dev1 $vip1 netmask 255.255.255.255 broadcast $vip1 up
ifconfig $dev2 $vip2 netmask 255.255.255.255 broadcast $vip2 up
echo "VS Server is Ready!"
;;
stop)
ifconfig $dev1 down
ifconfig $dev2 down
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "VS Server is Cancel!"
;;
*)
echo "Usage `basename $0` start|stop"
exit 1
;;
esac

分别启动脚本

1
2
chmod +x lvs_rs.sh 
./lvs_rs.sh start

测试

在另一台服务器测试是否能够访问

1
2
3
4
5
6
7
8
9
10
11
root@Demo21:~# for i in `seq 5`;do curl 192.168.10.91 192.168.10.92;done
web111
web333
web333
web111
web111
web333
web333
web111
web111
web333

停止ka101 keepalived,192.168.10.91会漂移到ka102上
恢复ka101 keepalived,192.168.10.91会漂移到ka101上

https://renwole.com/archives/1120