1. Nginx负载均衡配合Keepalived服务的案例实战
1.1 在lb01和lb02上配置Nginx负载均衡
结合前面介绍的Nginx负载均衡的环境,根据下图调整好主负载均衡器lb01、备用负载均很器lb02服务器上Nginx负载均衡环境,两台服务器的安装基础环境一致。
这里使用的Nginx负载均衡的配置如下:
[root@lb01 ~]# cd /application/nginx/conf/
[root@lb01 conf]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream www_pools { ---这里定义Web服务器池,包含了106和108两个Web节点
server 192.168.9.106:80 weight=1;
server 192.168.9.108:80 weight=1;
}
server { ---这里定义代理的负载均衡域名虚拟主机
listen 192.168.9.210:80; ---请注意这里的配置,指定IP监听了
server_name www.etiantian.org;
location / {
proxy_pass http://www_pools; ---访问www.etiantian.org,请求发送给www_pools里面的节点
proxy_set_header Host $host;
}
}
}
提示:此配置仅代理了www.etiantian.org域名。
1.2 在lb01和lb02上配置Keepalived服务
此处使用单实例为例进行配置说明。lb01上Keepalived服务单实例主节点的配置如下:
[root@lb01 keepalived]# cat keepalived.conf
global_defs {
router_id lb01
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.9.210/24 dev eth0 label eth0:3
}
}
提示:VIP为192.168.9.210,即工作时需要把Nginx负载均衡代理的www.etiantian.org解析到这个VIP。
lb02上Keepalived服务单实例备节点的配置如下:
[root@lb02 keepalived]# cat keepalived.conf
global_defs {
router_id lb02
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.9.210/24 dev eth0 label eth0:3
}
}
1.3 用户访问准备及模拟实际访问
准备工作如下:
1)在客户端hosts文件里把www.etiantian.org域名解析到VIP 192.168.9.210上,正式场景需通过DNS解析。
192.168.9.210 www.etiantian.org
2)两台服务器也要配好Nginx负载均衡服务,并且确保后面代理的Web节点可以测试访问。
[root@lb01 conf]# tail -1 /etc/hosts
192.168.9.210 www.etiantian.org
[root@lb01 keepalived]# netstat -lntup|grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 28553/nginx: master
[root@lb01 keepalived]# ip addr|grep 192.168.9.210
inet 192.168.9.210/24 scope global secondary eth0:3
下面模拟实际的访问。
1)通过在客户端浏览器输入“www.etiantian.org”测试访问,按Ctrl+F5组合键刷新几次,正常应该可以出现如下图所示的两种访问结果。
2)此时停止lb01服务器或者停掉Keepalived服务,观察业务是否正常:
[root@lb01 conf]# systemctl stop keepalived
[root@lb01 conf]# ip addr|grep 192.168.9.210
提示:严格来讲应该关掉服务器来模拟效果才是最佳的。
3)观察lb02备节点是否接管VIP 192.168.9.210。
[root@lb02 keepalived]# ip addr|grep 192.168.9.210
inet 192.168.9.210/24 scope global secondary eth0:3
再次在客户端浏览器输入“www.etiantian.org”测试访问,按Ctrl+F5组合键刷新几次,正常应该可以出现和切换lb02前相同的访问结果。
4)开启lb01的Keepalived服务。
[root@lb01 conf]# systemctl start keepalived
[root@lb01 conf]# ip addr|grep 192.168.9.210
inet 192.168.9.210/24 scope global secondary eth0:3
可以看到,VIP很快就接管回来了,此时浏览器访问结果依然正常。
2. 解决服务监听的网卡上不存在IP地址的问题
如果配置使用“listen 192.168.9.210:80;”的方式指定IP监听服务,而本地的网卡上没有192.168.9.210这个IP,Nginx就会报错:
[root@lb01 conf]# nginx
nginx: [emerg] bind() to 192.168.9.210:80 failed (99: Cannot assign requested address)
如果要实施双主(即主备)同时提供不同的服务,配置文件里指定了IP监听,备节点则会因为网卡实际不存在VIP报错。
出现上面问题的原因就是在物理网卡上没有与配置文件里监听的IP相应的IP,我们要让Nginx服务在网卡上没有指定监听的IP时也能启动,不报错,解决办法是在/etc/sysctl.conf中加入如下内核参数配置:
net.ipv4.ip_nonlocal_bind = 1
---此项表示启动Nginx而忽略配置中监听的IP是否存在,它同样适合Haproxy。
最后执行sysctl -p使上述修改生效。
3. 解决高可用服务只是针对物理服务器的问题
默认情况下,Keepalived软件仅仅在对方机器宕机或者Keepalived停掉的时候才会接管业务。但在实际工作中,有业务服务停止而Keepalived服务还在工作的情况,这就会导致用户访问的VIP无法找到对应的服务,那么,如何解决业务宕机就可以将IP漂移到备节点接管提供服务呢?
方法一:可以写守护进程脚本来处理。当Nginx业务出现问题时就停掉本地的Keepalived服务,实现IP漂移到对端接管提供服务。实际工作中部署及开发的示例脚本如下:
[root@lb01 conf]# cd /server/scripts/
[root@lb01 scripts]# vim check_nginx.sh
#!/bin/bash
while true
do
if [ 'netstat -lntup|grep nginx|wc -l' != 1 ];then
systemctl stop keepalived
break
fi
sleep 5
done
此脚本的基本思想是若没有80端口存在,就停掉Keepalived服务实现释放本地的VIP。
在后台执行上述脚本并检查:
[root@lb01 scripts]# sh /server/scripts/check_nginx.sh &
[1] 29858
[root@lb01 scripts]# ps -ef|grep check
root 29858 19844 0 16:49 pts/0 00:00:00 sh /server/scripts/check_nginx.sh
确认Nginx以及Keepalived服务是正常的。
[root@lb01 scripts]# lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 29398 root 6u IPv4 168351 0t0 TCP www.etiantian.org:http (LISTEN)
nginx 29399 nginx 6u IPv4 168351 0t0 TCP www.etiantian.org:http (LISTEN)
[root@lb01 scripts]# ps -ef|grep keep|grep -v grep
root 29656 1 0 15:29 ? 00:00:00 /usr/sbin/keepalived -D
root 29657 29656 0 15:29 ? 00:00:00 /usr/sbin/keepalived -D
root 29658 29656 0 15:29 ? 00:00:00 /usr/sbin/keepalived -D
然后模拟Nginx服务停掉,看IP是否发生切换。
[root@lb01 scripts]# nginx -s stop
[root@lb01 scripts]# systemctl status keepalived
---keepalived已停
[root@lb01 scripts]# netstat -lntup|grep nginx
此时,备节点已接管:
[root@lb02 conf]# ip addr|grep 192.168.9.210
inet 192.168.9.210/24 scope global secondary eth0:3
方法二:可以使用Keepalived的配置文件参数触发写好的监测服务脚本。
首先要开发监测服务脚本,注意这个脚本与上一个脚本的区别。
[root@lb01 scripts]# vim chk_nginx_proxy.sh
#!/bin/bash
if [ 'netstat -lntup|grep nginx|wc -l' != 1 ];then
systemctl stop keepalived
fi
[root@lb01 scripts]# chmod +x chk_nginx_proxy.sh
[root@lb01 scripts]# ls -l chk_nginx_proxy.sh
-rwxr-xr-x 1 root root 94 Apr 3 17:21 chk_nginx_proxy.sh
此时,Keepalived服务的完整配置如下:
[root@lb01 keepalived]# cat keepalived.conf
global_defs {
router_id lb01
script_user root ---指定检查脚本的用户
enable_script_security
}
vrrp_script chk_nginx_proxy { ---定义VRRP脚本,检测HTTP端口
script "/server/scripts/chk_nginx_proxy.sh" ---执行脚本,当Nginx服务出现问题时,就停掉Keepalived服务
interval 2 ---间隔2秒
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.9.210/24 dev eth0 label eth0:3
}
}
下面测试接管结果。
[root@lb01 keepalived]# lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 31922 root 6u IPv4 237693 0t0 TCP www.etiantian.org:http (LISTEN)
nginx 31923 nginx 6u IPv4 237693 0t0 TCP www.etiantian.org:http (LISTEN)
[root@lb01 keepalived]# ps -ef|grep keep
root 31914 1 0 11:40 ? 00:00:00 /usr/sbin/keepalived -D
root 31915 31914 0 11:40 ? 00:00:00 /usr/sbin/keepalived -D
root 31916 31914 0 11:40 ? 00:00:00 /usr/sbin/keepalived -D
root 31945 31806 0 11:40 pts/0 00:00:00 grep --color=auto keep
[root@lb01 keepalived]# ip addr|grep 192.168.9.210
inet 192.168.9.210/24 scope global secondary eth0:3
[root@lb01 keepalived]# nginx -s stop
[root@lb01 keepalived]# ip addr|grep 192.168.9.210
[root@lb01 keepalived]# ps -ef|grep keep
root 31945 31806 0 11:40 pts/0 00:00:00 grep --color=auto keep
当停掉Nginx的时候,Keepalived 2秒钟内会被自动停掉,IP被释放,由对端接管,这样就实现了即使服务宕机也进行IP漂移、业务切换,如果此时把Nginx和Keepalived同时启动,IP又会被接管回来。
lb01的日志是Keepalived停掉的消息。
4. 解决多组Keepalived服务器在一个局域网内冲突的问题
当在同一个局域网内部署了多组Keepalived服务器而又未使用专门的心跳线通信时,可能会发生高可用接管的严重故障问题。前面已经讲解过Keepalived高可用功能是通过VRRP协议实现的,VRRP协议默认通过IP多播的形式实现高可用服务对之间的通信,如果同一个局域网内存在多组Keepalived服务器对,就会造成IP多播地址冲突问题,导致接管错乱,不同组的Keepalived都会使用默认的224.0.0.18作为多播地址。此时的解决办法是在同组的Keepalived服务器所有的配置文件里指定各自独一无二的多播地址,配置如下:
global_defs {
router_id LVS_19
vrrp_mcast_group4 224.0.0.19 ---这个就是指定多播地址的配置
}
提示:
1)不同实例的通信认证密码也最好不同,以确保接管正常。
2)另一款高可用软件Hearbeat,如果采用多播方式实现主备通信,同样会有多播地址冲突问题。
5. 配置指定文件接收Keepalived服务日志
默认情况下,Keepalived服务日志会输出到系统日志/var/log/messages,和其他日志信息混合在一起,查看起来很不方便,可以将其调整成由独立的文件记录Keepalived服务日志。操作步骤如下:
1)编辑配置文件/etc/sysconfig/keepalived,将“KEEPALIVED_OPTIONS="-D"”修改为“KEEPALIVED_OPTIONS="-D -d -S 0"”,快速修改方法如下:
[root@lb01 keepalived]# sed -i '14 s#KEEPALIVED_OPTIONS="-D"#KEEPALIVED_OPTIONS="-D -d -S 0"#g' /etc/sysconfig/keepalived
[root@lb01 keepalived]# sed -n '14p' /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -d -S 0"
说明:可以查看/etc/sysconfig/keepalived里注释获得上述参数的说明
--dump-conf -d 导出备份配置数据
--log-detail -D 详细日志
--log-facility -S 设置本地的syslog设备,编号0-7(default=LOG_DAEMON)
-S 0 表示指定为local0设备
2)修改rsyslog的配置文件vi /etc/rsyslog.conf,在结尾处加入如下两行内容:
#keepalived
local0.* /var/log/keepalived.log
上述配置表示来自local0设备的所有日志信息都记录到了/var/log/keepalived.log文件中。
然后在如下信息的第一列结尾加入“;local0.none”,注意有分号。
*.info;mail.none;authpriv.none;cron.none;local0.none /var/log/messages
上述配置表示来自local0设备的所有日志信息不再记录于/var/log/messages里。
3)配置完成后,重启rsyslog服务。
[root@lb01 keepalived]# systemctl restart rsyslog.service
4)测试Keepalived日志记录结果。在重启Keepalived服务后,就会把日志信息输出到rsyslog定义的/var/log/keepalived.log文件中:
[root@lb01 keepalived]# systemctl restart keepalived
[root@lb01 keepalived]# tail /var/log/keepalived.log
Apr 4 12:15:52 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:52 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:52 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:52 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:57 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:57 lb01 Keepalived_vrrp[32113]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth0 for 192.168.9.210
Apr 4 12:15:57 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:57 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:57 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
Apr 4 12:15:57 lb01 Keepalived_vrrp[32113]: Sending gratuitous ARP on eth0 for 192.168.9.210
如果要求更高,还可以在/var/log/messages上设置对/var/log/keepalived.log进行轮询,以防单个日志文件变得太大。
6. 开发监测Keepalived“裂脑”的脚本
检测思路:在备节点上执行脚本,如果可以ping通主节点并且备节点有VIP就报警,让工作人员检查是否裂脑。
1)在lb02备节点开发脚本并执行。
[root@lb02 scripts]# cat check_split_brain.sh
#!/bin/bash
lb01_vip=192.168.9.210
lb01_ip=192.168.9.81
while true
do
ping -c 2 -W 3 $lb01_ip &>/dev/null
if [ $? -eq 0 -a `ip addr|grep "$lb01_vip"|wc -l` -eq 1 ]
then
echo "ha is split brain.warning."
else
echo "ha is ok."
fi
sleep 5
done
[root@lb02 scripts]# sh check_split_brain.sh
ha is ok.
ha is ok.
正常情况下,主节点活着,VIP 192.168.9.210在主节点,因此不会报警,提示“ha is ok.”。
2)停止Keepalived服务看lb02脚本执行情况。lb01上:
[root@lb01 keepalived]# systemctl stop keepalived
[root@lb01 keepalived]# ip addr|grep 192.168.9.210
在lb02上观察即可,此前脚本已经执行。
[root@lb02 scripts]# sh check_split_brain.sh
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
3)关掉lb01服务器,然后再观察lb02脚本的输出。
[root@lb02 scripts]# sh check_split_brain.sh
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is ok.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is ok.
ha is ok.
裂脑报警恢复了。
4)可以将此脚本整合到Nagios或Zabbix监控服务里,进行监控报警。