1. 编译安装
# 安装依赖包yum install -y gcc openssl-devel libnl3-devel net-snmp-devel# 解压tar xvf keepalived-2.2.2.tar.gz -C /usr/local/src# 编译安装cd /usr/local/src/keepalived-2.2.2/./configure --prefix=/opt/app/keepalivedmake && make install# 查看版本/opt/app/keepalived/sbin/keepalived -v# 安装完会自动生成 service 文件cat /lib/systemd/system/keepalived.service[Unit]Description=LVS and VRRP High Availability MonitorAfter=network-online.target syslog.targetWants=network-online.target[Service]Type=forkingPIDFile=/run/keepalived.pidKillMode=processEnvironmentFile=-/usr/local/keepalived/etc/sysconfig/keepalivedExecStart=/usr/local/keepalived/sbin/keepalived $KEEPALIVED_OPTIONSExecReload=/bin/kill -HUP $MAINPID[Install]WantedBy=multi-user.target
2. 启动 Keepalived
默认 Keepalived 会去 /etc/keepalived/ 路径下去寻找配置文件,因此安装完成后需要自己创建 /etc/keepalived/ 目录,并将配置文件放入该目录下,否则会报错。也可以在keepalived.service文件中使用-f选项指定配置文件的位置。
# 方式一:创建目录和配置文件。
[root@C7-01 ~]# mkdir /etc/keepalived
[root@C7-02 ~]# cp /opt/app/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
# 方式二:修改 service 文件,指定配置文件位置。
[root@C7-01 ~]# vim /lib/systemd/system/keepalived.service
ExecStart=/opt/app/keepalived/sbin/keepalived -f /opt/app/keepalived/etc/keepalived/keepalived.conf $KEEPALIVED_OPTIONS
# 启动 keepalived 服务
systemctl enable --now keepalived
3. 配置文件
Keepalived 的配置文件大概分为三部分组成:
- global_defs :全局配置
- vrrp_instance
:虚拟路由配置 - virtual_server
:虚拟IP与后端真实服务IP的对应关系配置 3.1 常用配置项说明
```bash ! Configuration File for keepalived
全局配置
global_defs { notification_email { wuvikr@aliyun.com # keepalived 发生故障切换时发送邮件的目标邮箱 root@localhost } notification_email_from wuvikr@aliyun.com # 发邮件的地址 script_user root # 脚本执行用户 smtp_server 192.168.200.1 # SMTP邮件服务器地址 smtp_connect_timeout 30 # 邮件服务器超时时间 router_id C7-01.wuvikr.top # keepalived 主机唯一标识,建议使用当前主机名 vrrp_skip_check_adv_addr # 如果收到的通告报文和上一个报文是同一个路由,则跳过检查,默认为检查所有报文
vrrp_strict # 开启vrrp严格模式,一般不建议使用
vrrp_garp_interval 0 # gratuitous ARP messages 报文发送延迟,0表示不延迟 vrrp_gna_interval 0 # unsolicited NA messages (不请自来)消息发送延迟 vrrp_mcast_group4 224.0.0.18 # 指定组播IP地址范围:224.0.0.0到239.255.255.255,默认值:224.0.0.18 }
VIP 虚拟路由实例配置
vrrp_instance VI_1 { state MASTER # 当前节点在此虚拟路由器上的初始状态,状态为MASTER或者BACKUP interface eth0 # 绑定当前虚拟路由器使用的物理接口,可以不和VIP在同一个网卡 virtual_router_id 11 # 每个虚拟路由器惟一标识,范围:0-255,同属一个虚拟路由器的多个 keepalived 节点此值必须相同 priority 100 # 当前物理节点在此虚拟路由器的优先级,范围:1-254 advert_int 1 # vrrp通告的时间间隔,默认1s nopreempt # 非抢占式,使用此项必须将各 keepalived 服务器 state 都配置为 BACKUP才行 authentication { # 认证机制 auth_type PASS # 认证类型,可以是AH或PASS,AH为IPSEC认证(不推荐),PASS为简单密码(建议使用) auth_pass 111111 # 预共享密钥,即相互认证密码 } virtual_ipaddress { # 虚拟路由IP 172.16.200.251 # 指定VIP,不指定网卡,默认eth0,注意:不指定/prefix,默认为32 172.16.200.252/24 dev eth1 # 指定VIP的MASK和网卡 192.168.200.102/24 dev eth2 label eth2:1 # 指定VIP的label }
# 使用单播配置,按需求和上面的组播二选一即可
unicast_src_ip 172.16.200.10 # 本机IP
unicast_peer{
172.16.200.20 # 指向其他Keepalived主机IP
}
}
LVS 负载均衡调度器配置
virtual_server 172.16.200.251 3306 { # VS主机IP地址及其端口 delay_loop 6 # 检查后端服务器的时间间隔 lb_algo rr # 定义调度方法,rr|wrr|lc|wlc|lblc|sh|mh|dh|fo|ovf|lblcr|sed|nq lb_kind NAT # LVS类型,注意要大写, NAT|DR|TUN persistence_timeout 50 # 持久连接时长 protocol TCP # 指定服务协议,一般默认为TCP,TCP|UDP|SCTP sorry_server # 所有的RS都故障时,备用服务器地址
# 后端真实服务器配置
real_server 172.16.200.251 3306 { # RS的IP和PORT
weight 1 # 调度权重
notify_up # RS上线通知脚本
notify_down # RS下线通知脚本
HTTP_GET|SSL_GET {
url {
path /health.html # 定义要监控的URL
status_code 200 # 判断上述检测机制为健康状态的响应码,一般为 200
}
connect_timeout 2 # 客户端请求的超时时长, 相当于haproxy的timeout server
nb_get_retry 3 # 重试次数
delay_before_retry 1 # 重试之前的延迟时长
connect_ip 172.16.200.25 # 向当前RS哪个IP地址发起健康状态检测请求
connect_port 80/443 # 向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> # 向当前RS发出健康状态检测请求时使用的源地址
bind_port <PORT> # 向当前RS发出健康状态检测请求时使用的源端口
}
TCP_CHECK {
connect_ip 172.16.200.25 # 向当前RS的哪个IP地址发起健康状态检测请求
connect_port 3306 # 向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> # 发出健康状态检测请求时使用的源地址
bind_port <PORT> # 发出健康状态检测请求时使用的源端口
connect_timeout <INTEGER> # 客户端请求的超时时长, 等于haproxy的timeout server
nb_get_retry 3 # 重新连接次数
delay_before_retry 3 # 重新连接间隔时间
}
}
}
<a name="ufUmr"></a>
## 3.2 子配置文件
keepalived 支持子配置文件,在主配置文件末尾,使用`include`指令,则可以从指定目录中加载配置文件。
```bash
include /etc/keepalived/conf.d/*.conf
3.3 开启 Keepalived 日志
Keepalived 日志默认输出到系统日志 /var/log/messages 文件中,可以修改配置使其输出到一个独立的 log 文件中。
# 修改参数文件
[root@C7-01 ~]# vim /opt/app/keepalived/etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -S 6"
# 修改系统日志文件
[root@C7-01 ~]# vim /etc/rsyslog.conf
local6.* /var/log/keepalived.log
# 重启服务
[root@C7-01 ~]# systemctl restart keepalived.service rsyslog.service
# 查看日志
[root@C7-01 ~]# tail /var/log/keepalived.log
May 12 16:22:13 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:13 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:13 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:13 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:18 posptest Keepalived_vrrp[23723]: (VI_1) Sending/queueing gratuitous ARPs on eth0 for 172.16.200.251
May 12 16:22:18 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:18 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:18 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:18 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
May 12 16:22:18 posptest Keepalived_vrrp[23723]: Sending gratuitous ARP on eth0 for 172.16.200.251
4. LVS 高可用
Keepalived 可以通过 virtual_server 自动将 VIP 配置成 LVS 来进行请求的调度。
这里以 MySQL 为例,实现通过VIP:172.16.200.251将请求调度到后端的 RS 服务器172.16.200.203、172.16.200.211上。由于选择使用 LVS 的 DR 模型,因此需要先在本地 lo 网卡绑定 VIP,使用下面的脚本实现:
[root@c7-01 ~]# cat /etc/init.d/lvs_dr_rs.sh
#!/bin/bash
echo_colors() {
echo -e "\e[1;$1m$2\e[0m"
}
trap "echo_colors 36 'Thank you for using, goodbye !'" EXIT
vip=172.16.200.251
mask=255.255.255.255
#prefix=32
dev=lo:1
case $1 in
start)
# 禁用本地ARP请求,绑定回环地址。
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
# 在回环地址上绑定VIP,设置掩码,与Director服务器自身IP保持通信
/sbin/ifconfig ${dev} ${vip} netmask ${mask} up
route add -host ${vip} dev ${dev}
#ip addr add ${vip}/${prefix} dev $dev label ${dev}
#ip route add ${vip} via 0.0.0.0 scope link src ${vip} dev ${dev}
echo_colors 32 "LVS-DR Real Server starts successfully.\n"
;;
stop)
/sbin/ifconfig $dev down
/sbin/route del $vip
#ip addr del ${vip}/${prefix} dev ${dev}
#ip route del $vip
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_colors 31 "LVS-DR Real Server stopped.\n"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
将上面的脚本加上执行权限并设置开机自动执行,最后执行上面的脚本:
# 添加执行权限
[root@c7-01 ~]# chmod +x /etc/init.d/lvs_dr_rs.sh
# 开机自启
[root@c7-01 ~]# echo "/etc/init.d/lvs_dr_rs.sh start" >> /etc/rc.d/rc.local
# 执行脚本
[root@c7-01 ~]# /etc/init.d/lvs_dr_rs.sh start
使用的 Keepalived 配置文件如下:
global_defs {
script_user root # 脚本执行用户
router_id C7-01.wuvikr.top # keepalived 主机唯一标识,建议使用当前主机名
vrrp_skip_check_adv_addr # 如果收到的通告报文和上一个报文是同一个路由,则跳过检查,默认为检查所有报文
vrrp_mcast_group4 224.0.0.18 # 指定组播IP地址范围:224.0.0.0到239.255.255.255,默认值:224.0.0.18
}
vrrp_instance VIP{
state BACKUP # 当前节点在此虚拟路由器上的初始状态,状态为MASTER或者BACKUP
interface eth0 # 绑定当前虚拟路由器使用的物理接口,可以不和VIP在同一个网卡
virtual_router_id 111 # 每个虚拟路由器惟一标识,范围:0-255,同属一个虚拟路由器的多个 keepalived 节点此值必须相同
priority 120 # 当前物理节点在此虚拟路由器的优先级,范围:1-254
advert_int 1 # vrrp通告的时间间隔,默认1s
nopreempt # 非抢占式
authentication { # 认证机制
auth_type PASS # 认证类型,可以是AH或PASS,AH为IPSEC认证(不推荐),PASS为简单密码(建议使用)
auth_pass 111111 # 预共享密钥,即相互认证密码
}
virtual_ipaddress { # 虚拟路由IP
172.16.200.251 # 指定VIP,不指定网卡,默认eth0,注意:不指定/prefix,默认为32
}
}
virtual_server 172.16.200.251 3306 { # 虚拟路由 IP 和 PORT
delay_loop 3 # 检查后端服务器的时间间隔
lb_algo rr # 定义调度方法,rr|wrr|lc|wlc|lblc|sh|mh|dh|fo|ovf|lblcr|sed|nq
lb_kind DR # LVS类型,注意要大写, NAT|DR|TUN
protocol TCP # 指定服务协议,一般默认为TCP,TCP|UDP|SCTP
real_server 172.16.200.203 3306 { # RS的IP和PORT
weight 1 # 调度权重
TCP_CHECK {
nb_get_retry 3 # 重新连接次数
delay_before_retry 3 # 重新连接间隔时间
connect_port 3306 # 向当前RS的哪个PORT发起健康状态检测请求
connect_timeout 3 # 客户端请求的超时时长, 等于haproxy的timeout server
}
}
real_server 172.16.200.211 3306 {
weight 1
TCP_CHECK {
nb_get_retry 3
delay_before_retry 3
connect_port 3306
connect_timeout 3
}
}
}
从 Keepalived 配置文件唯一的区别仅是 priority 值不一样,配置完成后重启 Keepalived 服务,并查看 IP :
[root@c7-01 ~]# systemctl restart keepalived.service
[root@c7-01 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 172.16.200.251/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:30:49:3c:12:00 brd ff:ff:ff:ff:ff:ff
inet 172.16.200.203/24 brd 172.16.200.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 172.16.200.251/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::d629:4b7f:837e:df98/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
[root@c7-02 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 172.16.200.251/32 scope global lo:1
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:9a:af:7c:4b:00 brd ff:ff:ff:ff:ff:ff
inet 172.16.200.211/24 brd 172.16.200.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::d629:4b7f:837e:df98/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
使用另一台 Client 访问一下VIP:172.16.200.251查看一下效果:
[root@c7-03 ~]# while true; do mysql -utest -p'Test#123.com' -h172.16.200.252 -N -s -e "select @@server_id" 2> /dev/null ; sleep 0.5 ;done
203
211
203
211
5. VRRP Script 实现应用高可用
Keepalived 利用 VRRP Script 技术,可以调用外部的辅助脚本进行资源监控,并根据监控的结果进行动态调整,从而实现其它应用的高可用性功能。
5.1 VRRP Script 配置
5.1.1 定义脚本
vrrp_script:自定义资源监控脚本,vrrp 实例根据脚本返回值来绝对是否进行后续操作,属于公共定义,可被多个实例同时调用,定义在 vrrp 实例之外的独立配置块。
注意:定义部分需要在调用部分的前面,否则会报错。一般放在global_defs设置块之后。
vrrp_script <SCRIPT_NAME> { # 定义一个检测脚本
script <STRING>|<QUOTED-STRING> # script 也可以是一个简单 shell 命令,返回值为非0时则触发下面 OPTIONS 执行
interval <INTEGER> # 检测间隔时间,单位为秒,默认1秒
timeout <INTEGER> # 超时时间
weight <INTEGER:-254..254> # 默认为0,如果设置此值为负数,当上面脚本返回值为非0时,会将此值与本节点权重相加可以降低本节点权重,即表示fall. 如果是正数,当脚本返回值为0,会将此值与本节点权重相加可以提高本节点权重,即表示 rise.通常使用负值
fall <INTEGER> # 脚本几次失败转换为失败,建议设为2以上
rise <INTEGER> # 脚本连续监测成功后,把服务器从失败标记为成功的次数
user USERNAME [GROUPNAME] # 执行监测脚本的用户或组
init_fail # 设置默认标记为失败状态,监测成功之后再转换为成功状态
}
调用脚本
track_script:调用事先定义的 vrrp_script 的脚本去监控资源,定义在VRRP实例之内。
track_script {
SCRIPT_1
SCRIPT_2
}
范例: Nginx 反向代理的高可用
在两个 Nginx 节点都配置相同的反向代理服务。
[root@Nginx01 ~]# vim /etc/nginx/nginx.conf
http {
upstream websrvs {
server 10.0.0.7:80 weight=1;
server 10.0.0.17:80 weight=1;
}
server {
listen 80;
server_name example.test.com
location /{
proxy_pass http://websrvs/;
}
}
}
Keepalived 配置:
global_defs {
script_user root # 脚本执行用户
router_id C7-01.wuvikr.top # keepalived 主机唯一标识,建议使用当前主机名
vrrp_skip_check_adv_addr # 如果收到的通告报文和上一个报文是同一个路由,则跳过检查,默认为检查所有报文
vrrp_mcast_group4 224.0.0.18 # 指定组播IP地址范围:224.0.0.0到239.255.255.255,默认值:224.0.0.18
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
#script "/usr/bin/killall -0 nginx"
interval 1
weight -30
fall 3
rise 5
timeout 2
}
vrrp_instance VIP_Nginx {
state MASTER
interface eth0
virtual_router_id 66
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
10.0.0.10/24 dev eth0 label eth0:1
}
track_interface {
eth0
}
track_script {
check_nginx
}
}
/etc/keepalived/check_nginx.sh 脚本内容如下:
[root@Keepalived01 ~]# cat /etc/keepalived/check_nginx.sh
#!/bin/bash
/usr/bin/killall -0 nginx || systemctl restart nginx
添加执行权限:
chmod +x /etc/keepalived/check_nginx.sh
