Keepalived
是一个用 C 语言编写的路由软件,它通过维护 VIP(Virtual IP)
实现为 Linux 系统提供简单而健壮的负载均衡和高可用性设施。
介绍

说明:
- 图中的 VIP 由 keepalive 维护
- 使用场景
- 双活主备
- 冷备(注意是否切换成功)
-
主 priority
> 备 priority
&& 主 priority + 主 vrrp_script.weight
< 备 priority + 备 vrrp_script.weight
- 备的 notify_master 脚本中有启动服务的命令,备中服务最初处于关闭状态
重要概念
- 虚拟 IP 地址(VIP 或 VIPA)是指与实际物理网口不对应的 IP 地址。对 vip 的使用包括网络地址转换(特别是一对多 NAT)、容错和移动性
- A virtual IP address (VIP or VIPA) is an IP address that doesn’t correspond to an actual physical network interface. Uses for VIPs include network address translation (especially, one-to-many NAT), fault-tolerance, and mobility.
LVS(Linux virtual server)
Linux 虚拟服务器,是一个虚拟的服务器集群系统。工作原理:用户请求 LVS VIP,LVS 根据转发方式和算法,将请求转发给后端服务器,后端服务器接收到请求,返回给用户。
ARP(Address Resolution Protocol)
协议属于 TCP/IP 协议族里面一种用户将 IP 地址解析为 MAC 地址的协议。该协议是用户局域网内解析 IP 地址对应的物理地址。
- 虚拟路由冗余协议
VRRP(Virtual Router Redundancy Protocol)
通过把几台路由设备联合组成一台虚拟的路由设备,将虚拟路由设备的 IP 地址作为用户的默认网关实现与外部网络通信。
安装部署
环境说明
VMware Fusion pro,自定义网络已经打开混杂模式(VMware Fusion
-> 偏好设置
-> 网络
-> 勾选 允许通过鉴定才能进入混杂模式
):
- host1: 172.20.0.21
- host2: 172.20.0.22
- vip: 172.20.0.20
所有机器均配置 ip_nonlocal_bind
绑定(实现没有 vip 时,可以启动 haproxy 等服务):
echo net.ipv4.ip_nonlocal_bind=1 >> /etc/sysctl.conf
sysctl -p
CentOS 安装
为 host1
、host2
安装软件
yum install -y nginx keepalived
sed -i "s#Welcome to CentOS#Welcome to CentOS`ip a | grep "172.20" | awk '{print $2}'`#g" /usr/share/nginx/html/index.html
通过 ip 地址区分访问的是哪个 nginx
systemctl start nginx.service
systemctl enable nginx.service
systemctl start keepalived.service
systemctl enable keepalived.service
配置 nginx
- nginx 存活检测脚本
/usr/local/bin/check_nginx_alive.sh
#!/bin/bash
nginx_count=`ps -C nginx --no-header |wc -l`
if [ $nginx_count -eq 0 ]; then
echo 'nginx server is died'
exit 1
fi
exit 0
或使用 systemctl is-active nginx
命令检测。
chmod +x /usr/local/bin/check_nginx_alive.sh
配置 host1 keepalive
host1 为 MASTER
,priority 优先级为 100
-
如果 rise 次脚本执行都是成功的(返回 0),则增加 weight 数量的优先级
-
如果是 fall 次脚本执行都是失败的(返回 1),则减少|weight|数量的优先级
-
/etc/keepalived/keepalived.conf
- 配置文件示例
/etc/keepalived/keepalived.conf.sample
或 /usr/share/.../keepalived.conf.vrrp.localcheck
(不同版本略有不同)
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
# vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx_alive {
script "/usr/local/bin/check_nginx_alive.sh"
interval 3
rise 2
fall 3
weight -15
}
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 {
172.20.0.20 dev ens33
}
track_script {
check_nginx_alive
}
# notify_master xxx
# notify_backup xxx
# notify_f.. xxx
}
virtual_server 172.20.0.20 80 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
# preempt
real_server 172.20.0.21 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
systemctl restart keepalived
配置 host2 keepalive
host2 为 BACKUP
,priority 优先级为 90(比 host1 底)
- /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
# vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx_alive {
script "/usr/local/bin/check_nginx_alive.sh"
interval 3
weight -15
}
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 {
172.20.0.20 dev ens33
}
track_script {
check_nginx_alive
}
}
virtual_server 172.20.0.20 80 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 172.20.0.22 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
systemctl restart keepalived
检测
$ ip a show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:33:42:98 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.21/24 brd 172.20.0.255 scope global ens33
valid_lft forever preferred_lft forever
inet 172.20.0.20/32 scope global ens33
valid_lft forever preferred_lft forever
systemctl stop nginx
可以观察到 vip 漂移到 host2,并且 访问 http://172.20.0.20 可以看到为 host2 的 nginx
systemctl start nginx
可以观察到 vip 漂移到 host1,并且 访问 http://172.20.0.20 可以看到为 host1 的 nginx
运维
问题是排查命令
tcpdump proto 112
tcpdump -i ens33 vrrp -n
arp -n
ip -br a
查看 ip 地址
haproxy 存活检测脚本
vrrp_script check_haproxy {
script "/usr/local/bin/check_keepalive.sh"
interval 1
weight -15
fall 3
rise 2
timeout 2
}
/usr/local/bin/check_haproxy_alive.sh
#!/bin/bash
# This will return 0 when it successfully talks to the haproxy daemon via the socket
# Failures return 1
echo "show info" | socat unix-connect:/var/lib/haproxy/stats stdio > /dev/null
chmod a+x /usr/local/bin/check_haproxy_alive.sh
/usr/local/bin/check_haproxy_alive2.sh
另一种实现方式?
#!/bin/bash
/usr/bin/killall -0 haproxy || systemctl restart haproxy
nginx
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh"
interval 2 # 指定脚本执行的间隔,单位是秒,默认为1s
weight -20 # 调整优先级。默认为2。如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少
fall 3 # 执行失败多少次才认为失败
rise 2 # 执行成功多少次才认为是成功
user root # 加上用户名,使用root用户登录的话
}
#!/bin/bash
A=`ps -ef | grep nginx | grep -v grep | wc -l`
if [ $A -eq 0 ];then
nginx
sleep 2
if [ `ps -ef | grep nginx | grep -v grep | wc -l` -eq 0 ];then
# killall keepalived
ps -ef|grep keepalived|grep -v grep|awk '{print $2}'|xargs kill -9
fi
fi
Tracking files
- Keepalived 支持根据文件内容来决定优先级,如运行的应用程序能向该文件(
/var/run/my_app/vrrp_track_file
)写入值
- 若
echo 5 > /var/run/my_app/vrrp_track_file
,则 prio 249 = 244 + 5
vrrp_track_file track_app_file {
file /var/run/my_app/vrrp_track_file
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 244
advert_int 1
authentication {
auth_type PASS
auth_pass 12345
}
virtual_ipaddress {
192.168.122.200/24
}
track_file {
track_app_file weight 1
}
}
Track interface
- 对于有多个接口的服务器,根据接口的状态调整 Keepalived 实例的优先级
- 若接口 ens5 是 up 的状态,prio 249 = 244 + 5
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 244
advert_int 1
authentication {
auth_type PASS
auth_pass 12345
}
virtual_ipaddress {
192.168.122.200/24
}
track_interface {
ens9 weight 5
}
}
F&Q
脚本开头加 #!bin/bash
Disabling track script xxx since not found/accessible
脚本需要写绝对路径
Keepalived_vrrp[]: WARNING - default user ‘keepalived_script’ for script execution does not exist
keepalived.conf
中添加:
global_defs {
script_user root
}
scripts are being executed but script_security not enabled
keepalived.conf
中添加:
global_defs {
enable_script_security
}
vip ping 不通
删除如下配置中的 vrrp_strict
,严格遵守 VRRP 协议,不允许状况:
- 没有 VIP 地址
- 单播
- 在 VRRP 版本 2 中使用 IPv6 地址
global_defs {
vrrp_strict
}