0%

LVS 小宇宙爆发! 当 Keepalived 遇上 LVS,实现集群高可用

关于 Keepalived 系列其他文章的传送门

  1. 《 实现高可用集群的神器 详解 Keepalived 》

  2. 《 LVS 小宇宙爆发! 当 Keepalived 遇上 LVS,实现集群高可用 》      您当前所在位置



IPVS_DR

实验介绍

众所周知,LVS 支持内核级调度,功能非常强大,但是 LVS 有一个致命的缺点,就是不支持对后端的 RS 做健康状态检测,RS 如果宕机了依然会把请求调度给故障的 RS,而且 Director 节点自己也存在单点故障的隐患,那 LVS 在生产环境中如何稳定的使用呢?

上篇文章已经介绍了 Keepalived 的使用方法和配置参数,《 实现高可用集群的神器 详解 Keepalived 》

所以本文将介绍在生产环境中 LVS 的正确使用方法:使用 Keepalived 实现 LVS 高可用

在 Keepalived 的加持下,可以实现对 Director 节点双活,并支持基于 4 层或 7 层对后端的 RS 节点做健康状态检测,能根据检测结果自动踢除故障的 RS,待 RS 健康后自动加回集群,让 LVS 的功能发挥到极致。

实验使用两个 VIP

VIP IP
VIP 1 192.168.50.200
VIP 2 192.168.50.201

和 4 台虚拟机

IP 功能 备注
192.168.50.11 Director 1 安装 Keepalived 实现双活
192.168.50.12 Direcotr 2 安装 Keepalived 实现双活
192.168.50.13 Realserver 1 使用 Nginx 承载网页文件
192.168.50.13 Realserver 1 使用 Nginx 承载网页文件

拓扑图
keepalived_lvs

一、配置两台 Realserver

安装配置 Nginx

在两台 Realserver 中都安装好 Nginx。

1
yum install epel-release nginx net-tools -y

创建测试页,生产环境中两台 Realserver 的网页应该相同,这里为了测试效果故意放置不同的内容。

1
2
3
4
#- 第一台 Director 中
echo "This Is Realserver 1" > /usr/share/nginx/html/index.html
#- 第二台 Director 中
echo "This Is Realserver 2" > /usr/share/nginx/html/index.html

启动服务。

1
2
systemctl start nginx
systemctl enable nginx

配置 IPVS

在两台 Realserver 中都创建配置 IPVS 的脚本文件。

如果想了解 LVS 的 DR 模型详细原理,可以先看看这篇 《 LVS 集群负载器的原理和配置 》

vim /root/realserver.sh

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
#!/bin/bash
#
#
vip1=192.168.50.200
vip2=192.168.50.201
mask='255.255.255.255'
vipni=lo

case $1 in
start)
# 关闭 ARP 应答和响应
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/$vipni/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/$vipni/arp_announce

# 清空防火墙规则
iptables -X
iptables -F

# 把 VIP1 配置在 lo:1 接口 防止和其他主机沟通 掩码32 只广播给自己
ifconfig $vipni:1 $vip1 netmask $mask broadcast $vip1 up
# 把 VIP2 配置在 lo:2 接口 防止和其他主机沟通 掩码32 只广播给自己
ifconfig $vipni:2 $vip2 netmask $mask broadcast $vip2 up

# 配置路由 只要是到 VIP 的报文,就走 vipni:1 网卡
route add -host $vip1 dev $vipni:1
# 配置路由 只要是到 VIP 的报文,就走 vipni:2 网卡
route add -host $vip2 dev $vipni:2
;;
stop)
# 关闭网卡
ifconfig $vipni:1 down
ifconfig $vipni:2 down

# 恢复 ARP 应答和响应
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/$vipni/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/$vipni/arp_announce

# 清空防火墙规则
iptables -X
iptables -F
;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

执行脚本,Realserver 就配置好了。

1
2
chmod +x /root/realserver.sh
/root/realserver.sh start

二、配置两台 Director

安装软件

两台 Director 中都安装好 nginxkeepalived

1
yum install epel-release nginx keepalived -y

使用 Nginx 作为 sorry server,创建 error server 的主页文件。

1
2
3
4
#- 第一台 Director 中
echo "All Realserver is Down! for Dictory 1" > /usr/share/nginx/html/index.html
#- 第二台 Director 中
echo "All Realserver is Down! for Dictory 2" > /usr/share/nginx/html/index.html

配置 Keepalived

在 Keepalived 配置文件中定义好 LVS 的规则,Keepalived 会自动创建 LVS 规则并检测健康状态。

配置 Director 1 中的 Keepalived。

vim /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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
! Configuration File for keepalived
// 全局配置
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.0.200
vrrp_iptables
}
// 192.168.50.200 虚拟路由器配置段
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 1
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 11112222
}
virtual_ipaddress {
192.168.50.200/24 brd 192.168.50.255 dev ens33 label ens33:1
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
// 192.168.50.201 虚拟路由器配置段
vrrp_instance VI_2 {
state BACKUP
interface ens33
virtual_router_id 2
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 22223333
}
virtual_ipaddress {
192.168.50.201/24 brd 192.168.50.255 dev ens33 label ens33:2
}
}
// 与第二台 Director 相比,只有以上配置有不同
///////////////////////////////////////////////////////////////////////////////////

// 定义第一个 VIP
virtual_server 192.168.50.200 80 {
protocol TCP
delay_loop 3
lb_algo wrr
lb_kind DR
sorry_server 127.0.0.1 80

real_server 192.168.50.13 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.50.14 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}
// 定义第二个 VIP
virtual_server 192.168.50.201 80 {
protocol TCP
delay_loop 3
lb_algo wrr
lb_kind DR
sorry_server 127.0.0.1 80

real_server 192.168.50.13 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.50.14 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}

配置 Director 2 中的 Keepalived。

vim /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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
! Configuration File for keepalived

global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node2
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.0.200
vrrp_iptables
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 1
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 11112222
}
virtual_ipaddress {
192.168.50.200/24 brd 192.168.50.255 dev ens33 label ens33:1
}
}

vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 2
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 22223333
}
virtual_ipaddress {
192.168.50.201/24 brd 192.168.50.255 dev ens33 label ens33:2
}
}

// 与第一台 Director 相比,只有以上配置有不同
///////////////////////////////////////////////////////////////////////////////////

// 定义第一个 VIP
virtual_server 192.168.50.200 80 {
protocol TCP
delay_loop 3
lb_algo wrr
lb_kind DR
sorry_server 127.0.0.1 80

real_server 192.168.50.13 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.50.14 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}
// 定义第二个 VIP
virtual_server 192.168.50.201 80 {
protocol TCP
delay_loop 3
lb_algo wrr
lb_kind DR
sorry_server 127.0.0.1 80

real_server 192.168.50.13 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.50.14 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}

启动服务

启动 Nginx 和 Keepalived 服务。

1
2
systemctl start nginx keepalived
systemctl enable nginx keepalived

添加 DNS 解析

把域名绑定到两个 VIP 上。

1
2
vip.monster.com.        A        192.168.50.200
vip.monster.com. A 192.168.50.201

三、测试效果

使用客户端连续访问域名进行测试,可以看到轮询的效果。

test_1
test_2

测试高可用

模拟 RS 宕机一台

在客户端循环每隔 1 秒访问一次集群,然后把 RS2 的 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
~]# while true; do curl vip.monster.com  && sleep 1; done
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
curl: (7) Failed connect to vip.monster.com:80; Connection refused
This Is Realserver 1
curl: (7) Failed connect to vip.monster.com:80; Connection refused
This Is Realserver 1
#- 这时停掉了 RS2 的 Nginx,可以看到后面的请求都调度到 RS1 上了
This Is Realserver 1
This Is Realserver 1
This Is Realserver 1
This Is Realserver 1
This Is Realserver 1
This Is Realserver 1
#- 这时恢复了 RS2 的 Nginx,又开始轮询
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2

模拟两台 RS 全部宕机

Keepalived 检测到两台 RS 全部宕机后,会将请求调度到之前准备的 Sorry server 上去。

1
2
3
4
5
6
7
8
9
10
11
12
13
~]# while true; do curl vip.monster.com  && sleep 1; done
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
curl: (7) Failed connect to vip.monster.com:80; Connection refused
curl: (7) Failed connect to vip.monster.com:80; Connection refused
curl: (7) Failed connect to vip.monster.com:80; Connection refused
All Realserver is Down! for Dictory 2
All Realserver is Down! for Dictory 2
All Realserver is Down! for Dictory 1
All Realserver is Down! for Dictory 2
All Realserver is Down! for Dictory 2

模拟 Dorector 宕机一台

先恢复 Nginx,然后依然在客户端循环每隔 1 秒访问一次集群,然后停止 Director 2 上的 Keepalived 服务模拟 Director 节点宕机一台。

1
2
3
4
5
6
7
8
9
10
11
12
13
~]# while true; do curl vip.monster.com  && sleep 1; done
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
#- 这时停掉了 DIrecot 2 上的 Keepalived,可以看到后面的请求都不受影响
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
This Is Realserver 1
This Is Realserver 2
从网络的角度看会更明显一些

先查看 VIP 的分布

Director 1

1
2
3
4
5
6
7
8
Director 1 ~]# ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.11 netmask 255.255.255.0 broadcast 192.168.50.255
...

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.200 netmask 255.255.255.0 broadcast 192.168.50.255
...

Director 2

1
2
3
4
5
6
7
8
Director 2 ~]# ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.12 netmask 255.255.255.0 broadcast 192.168.50.255
...

ens33:2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.201 netmask 255.255.255.0 broadcast 192.168.50.255
...

可以看出:

VIP1 192.168.50.200 在 Director 1 上
VIP2 192.168.50.201 在 Director 2 上

  • 双活状态

现在停止 Director 2 上的 Keepalived,再查看 VIP 的分布。

Director 2 上已经没有 VIP 了。

1
2
3
4
5
Director 2 ~]# ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.12 netmask 255.255.255.0 broadcast 192.168.50.255
...
...

两个 VIP 全部转移到 Director 1 上了。

1
2
3
4
5
6
7
8
9
10
11
12
Director 1 ~]# ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.11 netmask 255.255.255.0 broadcast 192.168.50.255
...

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.200 netmask 255.255.255.0 broadcast 192.168.50.255
ether 00:0c:29:cf:e7:f6 txqueuelen 1000 (Ethernet)

ens33:2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.50.201 netmask 255.255.255.0 broadcast 192.168.50.255
ether 00:0c:29:cf:e7:f6 txqueuelen 1000 (Ethernet)