keepalived选举机制和切换机制
本文档主要讲述了keepalived的选举机制VRRP(虚拟路由冗余协议),描述了keepalived在不同场景
下该如何去选择和配置合适的主从切换模式。并辅助使用docker来验证其选举特性
keepalived的选举机制:
keepalived中优先级高的节点为MASTER。MASTER其中一个职责就是响应VIP的arp包,将VIP和mac地址映射关系告诉局域网内其他主机,同时,它还会以多播的形式(默认目的地址224.0.0.18)向局域网中发送VRRP通告,告知自己的优先级。网络中的所有BACKUP节点只负责处理MASTER发出的多播包,当发现MASTER的优先级没自己高,或者没收到MASTER的VRRP通告时,BACKUP将自己切换到MASTER状态,然后做MASTER该做的事:响应arp包和发送VRRP通告
-
当一个激活了VRRP的接口Up之后,如果接口的VRRP优先级为255,那么其VRRP状态将直接从
Initialize切换到Master,而如果接口的VRRP优先级不为255,则首先切换到Backup状态,然后再
视竞争结果决定是否能够切换到Master状态。 -
如果在同一个广播域的同一个VRRP组内出现了两台Master路由器,那么它们收到对方发送的VRRP通
告报文之后,将比较自己与对方的优先级,优先级的值更大的设备胜出,继续保持Master状态,而
竞争失败的路由器则切换到Backup状态。如果这两台Master路由器的优先级相等,那么接口IP地址
更大的路由器接口将会保持Master状态,而另一台设备则切换到Backup状态。 -
一个网络在稳定运行时,同一个VRRP组内不会同时出现两台Master路由器。
下面给出几套及简单的配置,对应于不同场景下主从切换的模式。
1. 非抢占模式
这种模式主要是针对主机崩溃,集群已经重新选出新的主机,并且原来的主机重新上线后并不争夺主
机的情况。这种模式适合那些倾向于认为崩溃的主机即便上线还是会出现崩溃的场景。
这种模式的核心思想是将所有节点的优先级(priority)值设为相同,当两个节点的优先级相同时,
以节点发送VRRP通告的IP作为比较对象,IP较大者为MASTER。
因此这种模式下,当主机崩溃时,所有从机中IP地址最大的那个节点一定会成为主机,并且原来的主机
上线后不会再次触发选举,原来的主机也就成为了从机。
IP | priority | 主备模式 |
---|---|---|
172.17.0.2 | 100 | BACKUP |
172.17.0.3 | 100 | BACKUP |
172.17.0.4 | 100 | BACKUP |
现在有三个节点,均为BACKUP,优先值都为100。Server-1,Server-2,Server-3的ip逐渐增大,
但是由于Server-1最先启动,所以他是一开始的主机。
# Server-1的容器启动
docker run -itd --name Server-1 --privileged=true --hostname Server-1 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-1 /bin/bash -c "
echo 'I am Server -1' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
mcast_src_ip 172.17.0.2
virtual_router_id 203
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
# Server-2的容器启动
docker run -itd --name Server-2 --privileged=true --hostname Server-2 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-2 /bin/bash -c "
echo 'I am Server -2' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
mcast_src_ip 172.17.0.3
virtual_router_id 203
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
# Server-3的容器启动
docker run -itd --name Server-3 --privileged=true --hostname Server-3 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-3 /bin/bash -c "
echo 'I am Server -3' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
mcast_src_ip 172.17.0.4
virtual_router_id 203
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
使用 curl 172.17.0.100 命令查看当前的主机。
此时发现停止Server-1后Server-3就会成为新的主机,这是因为虽然所有节点优先级一样,但
Server-3的ip最大所以会获得成为主机的权利。同时即便Server-1重新上线,也不会重新选举主机。
2. 抢占模式
这种模式主要是针对主机崩溃,集群已经重新选出新的主机,并且原来的主机重新上线后重新争夺主
机、成为主机的情况。这种情况比较适合需要崩溃的主机重新上线做主机的情况。
也就是说本模式是某主机节点在崩溃后,集群新选出了主机。但是崩溃的节点恢复后,又触发了选举,最终原
节点再次成为主机的过程。
IP | priority | 主备模式 |
---|---|---|
172.17.0.2 | 200 | MASTER |
172.17.0.3 | 100 | BACKUP |
172.17.0.4 | 100 | BACKUP |
现在有三个节点,Server-1,Server-2,Server-3的ip逐渐增大
- Server-1 的优先值为 200 类型为Master
- Server-2 的优先值为 100 类型为Backup
- Server-3 的优先值为 100 类型为Backup
很显然Server-1是一开始的主机。
# Server-1的容器启动
docker run -itd --name Server-1 --privileged=true --hostname Server-1 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-1 /bin/bash -c "
echo 'I am Server -1' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_instance VI_1 {
state Master
interface eth0
mcast_src_ip 172.17.0.2
virtual_router_id 203
priority 200
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
# Server-2的容器启动
docker run -itd --name Server-2 --privileged=true --hostname Server-2 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-2 /bin/bash -c "
echo 'I am Server -2' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
mcast_src_ip 172.17.0.3
virtual_router_id 203
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
# Server-3的容器启动
docker run -itd --name Server-3 --privileged=true --hostname Server-3 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-3 /bin/bash -c "
echo 'I am Server -3' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
mcast_src_ip 172.17.0.4
virtual_router_id 203
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
使用 curl 172.17.0.100 命令查看当前的主机。
这种情况下,当停止了Server-1时,由于Server-3的ip大小胜过Server-2,因此Server-接替了主
机位置。但是当Server-1再次上线后,可以发现几秒后Server-1再次成为了主机。
3. 灵活型切换模式
keepalived配置中可以设定按时自动执行用户脚本,当用户脚本执行完毕后可以在规则内对节点的
优先值进行更新,这个值只会更新一次。主要通过偏移量weight来实现:
- 当weight > 0 时,vrrp_script script脚本执行返回0(成功)时优先级为priority + weight,
否则为priority。当BACKUP发现自己的优先级大于MASTER通告的优先级时,进行主从切换。 - 当weight < 0 时,vrrp_script script脚本执行返回非0(失败)时优先级为priority + weight,
否则为priority。当BACKUP发现自己的优先级大于MASTER通告的优先级时,进行主从切换。 - 当两个节点的优先级相同时,以节点发送VRRP通告的IP作为比较对象,IP较大者为MASTER。
VIP漂移是比较灵活的配置方式,可以根据下面的实例进行参考。
Server-2初始优先值80,Server-1初始优先级100。但是由于Server-2的weight值为30,当脚本
检测成功并返回0的时候,Server-1的优先级为80+30=110,比Server-1高,因此会取代Server-1
成为新的主节点。
IP | priority | 主备模式 |
---|---|---|
172.17.0.2 | 100 | MASTER |
172.17.0.3 | 80 | BACKUP |
# Server-1的容器启动
docker run -itd --name Server-1 --privileged=true --hostname Server-1 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-1 /bin/bash -c "
echo 'I am Server -1' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id server1
script_user root
enable_script_security
}
vrrp_instance VI_1 {
state MASTER
interface eth0
mcast_src_ip 172.17.0.2
virtual_router_id 203
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
# Server-2的容器启动
docker run -itd --name Server-2 --privileged=true --hostname Server-2 xzsww123/cluster-node:v1.0 /usr/sbin/init
docker exec -it Server-2 /bin/bash -c "
echo 'I am Server -2' > /var/www/html/index.html &&
systemctl restart httpd &&
yum install -y keepalived &&
echo 'exit 0' > /etc/keepalived/chk_my.sh &&
chmod 744 /etc/keepalived/chk_my.sh &&
echo '
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id vip-0
}
vrrp_script chk_my_service {
script \"/etc/keepalived/chk_my.sh\"
interval 10
weight 5
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
mcast_src_ip 172.17.0.3
virtual_router_id 203
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass MrUse
}
virtual_ipaddress {
172.17.0.100
}
track_script {
chk_my_service
}
}
' > /etc/keepalived/keepalived.conf &&
systemctl daemon-reload &&
systemctl start keepalived.service &&
systemctl enable keepalived.service &&
systemctl status keepalived.service
"
参考文档
[1] keepalived的vip选举机制与VRRP协议
[2] VRRP——Master选举
[3] 解决Keepalived脚本启动时warning、Unsafe
[4] Keepalived监测脚本一直不执行
[5] nginx+keepalived基本服务器宕机的主从切换配置