Keepalived实现Nginx高可用

一、介绍

Keepalived 是一款开源的、基于 VRRP 协议的Linux软件,通过虚拟IP地址(VIP)的漂移和健康检查来实现服务器故障时的自动切换。

原理

检测keepalived 进程是否存活,如果检测不到,就代表对方宕机,会把虚拟IP地址(VIP)抢占过来。

如果需要检测 nginx 的话,可以写个脚本,检测 nginx 的状态。

二、环境准备

两台机器环境初始化,安装 keepalivednginx

当然也可以从官网下载源码包,编译安装。最新版 2.3.4

规划

主机名 ip地址 用途
nginx-01 192.168.10.101
nginx-02 192.168.10.102
192.168.10.100 虚拟ip地址

安装,版本比较旧 1.3.5

1
yum install -y keepalived nginx

修改默认 html

1
2
3
4
5
6
7
8
9
10
11
12
cat > /usr/share/nginx/html/index.html <<EOF
<html>
<head>
<title>
192.168.10.101
</title>
</head>
<body>
This is nginx-01 192.168.10.101
</body>
</html>
EOF
1
2
3
4
5
6
7
8
9
10
11
12
cat > /usr/share/nginx/html/index.html <<EOF
<html>
<head>
<title>
192.168.10.102
</title>
</head>
<body>
This is nginx-02 192.168.10.102
</body>
</html>
EOF

三、验证

默认的配置文件是 /etc/keepalived/keepalived.conf

注意事项,一定要注意配置是否正确,该一致时一致,不一样的地方不要配置成一样。

3.1 检测 keepalived 的进程

  1. nginx-01 上修改配置文件
1
vim /etc/keepalived/keepalived.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
! Configuration File for keepalived
global_defs {
router_id LB101
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
}
  • router_id 唯一标识一个节点
  • vrrp_instance 实例名称
  • state 节点的角色
  • interface 网卡名称
  • priority 优先级,0-255,越大越优先
  • advert_int 检测间隔
  • authentication 同一组应该保持一致
  • virtual_ipaddress 虚拟ip
  1. nginx-02 上修改配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
! Configuration File for keepalived
global_defs {
router_id LB102
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.10.100
}
}
  1. 启动后验证
1
systemctl enable --now keepalived

外部机器一直ping虚拟ip

1
ping -t 192.168.10.100

关闭 nginx-01

1
shutdown -h now

3.2 检测 nginx 进程

  1. nginx-01 的配置
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
global_defs {
router_id Node1
}

# 脚本:每 2 秒检查一次 Nginx 活着没
vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
}

vrrp_instance VI_1 {
state MASTER # 【核心】我是老大
interface ens33 # 【注意】改这里!你的网卡名,用 ip addr 看
virtual_router_id 51 # 组号,老大老二必须一样
priority 100 # 【核心】权重,老大要高
advert_int 1

authentication {
auth_type PASS
auth_pass 1111
}

virtual_ipaddress {
192.168.10.100 # 【核心】这就是那个漂移的 VIP
}

track_script {
check_nginx # 引用上面的检查脚本
}
}
  • killall 通常用来杀死进程
    • -0 询问操作系统是否存在此进程,
      • 存在返回 0
      • 不存在返回 1,此时就开始降权,停止发送 VRRP 报文。
  1. nginx-02 的配置
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
global_defs {
router_id Node2
}

vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
}

vrrp_instance VI_1 {
state BACKUP # 【核心】我是备胎
interface ens33 # 【注意】改这里!
virtual_router_id 51 # 必须和老大一样
priority 90 # 【核心】权重,备胎要低
advert_int 1

authentication {
auth_type PASS
auth_pass 1111
}

virtual_ipaddress {
192.168.10.100 # 同样的 VIP
}

track_script {
check_nginx
}
}
  1. 启动并验证
1
systemctl restart keepalived

nginx-01 关闭 nginx

1
systemctl stop nginx

3.3 排错

  1. 查看日志,排错时用到
1
tail -f /var/log/messages
  1. 如果出现脑裂现象(两个节点都抢占IP地址)

可能原因

VRRP是一种三层之上、四层之下的协议,虽然不需要暴露端口,但仍需要master持续发送组播包,来证明自己存活。

解决方案,放行防火墙

1
2
3
# Firewalld 的正确放行姿势(允许 vrrp 协议)
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens33 --protocol vrrp -j ACCEPT
firewall-cmd --reload

四、抢占模式和非抢占模式

主服务器回归后,是否抢占回来虚拟IP。

默认情况会抢占回来,但有时候不希望IP一直漂移。需要设置非抢占模式。

  • master
1
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
global_defs {
router_id Node1
}

# 脚本:每 2 秒检查一次 Nginx 活着没
vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
}

vrrp_instance VI_1 {
# state MASTER # 【核心】我是老大
state BACKUP # 【核心】我是备胎
nopreempt # 非抢占模式
interface ens33 # 【注意】改这里!你的网卡名,用 ip addr 看
virtual_router_id 51 # 组号,老大老二必须一样
priority 100 # 【核心】权重,老大要高
advert_int 1

authentication {
auth_type PASS
auth_pass 1111
}

virtual_ipaddress {
192.168.10.100 # 【核心】这就是那个漂移的 VIP
}

track_script {
check_nginx # 引用上面的检查脚本
}
}
  • slave
1
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
global_defs {
router_id Node2
}

vrrp_script check_nginx {
script "/usr/bin/killall -0 nginx"
interval 2
weight -20
}

vrrp_instance VI_1 {
state BACKUP # 【核心】我是备胎
nopreempt
interface ens33 # 【注意】改这里!
virtual_router_id 51 # 必须和老大一样
priority 90 # 【核心】权重,备胎要低
advert_int 1

authentication {
auth_type PASS
auth_pass 1111
}

virtual_ipaddress {
192.168.10.100 # 同样的 VIP
}

track_script {
check_nginx
}
}