keepalived+nginx之监测脚本无法停止keepalived服务
keepalived+nginx这样的负载均衡配置,很多环境都用到,搭建配置都很简单。
但是在最近的一次搭建过程中,出现了一种情况,就是nginx进程宕掉后,在监测脚本不能将进程拉起来的情况下,keepalived服务没有被终止,从而导致VIP一直漂在这台nginx已经宕掉的服务器上面,出现这样的情况,一般要么是配置错了,或者监测脚本错了,然而情况并非如此;
下面这个是keepalived+nginx的基本配置
环境信息 Ngx-Web1 虚拟IP:1.10 物理IP:1.1 Centos7.8 8080 Keepalived master keepalived-2.0.20 Nginx1.18.0 Ngx-Web2 物理IP:1.2 Centos7.8 8080 Keepalived backup keepalived-2.0.20 Nginx1.18.0
web1的keepalived配置
! Configuration File for Keepalived global_defs { router_id 1.1 ##指定本机物理主机IP } vrrp_script chk_nginx { script "/data/keepalived/nginx_check.sh" ## 检测 nginx服务状态 interval 2 ## 检测时间间隔 weight -20 ## 如果条件成立,权重-20 } vrrp_instance VI_1 { state MASTER ##指定这台主机keepalived为主节点 interface eth0 ##指定物理网卡接口 virtual_router_id 11 ## 虚拟路由的ID号,两个节点设置必须一样,建议用IP最后段 mcast_src_ip 1.1 ##指定本机物理主机IP priority 100 ## 节点优先级,值范围0-254,MASTER要比BACKUP高 nopreempt ## 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题 advert_int 1 ## 组播信息发送间隔,两个节点设置必须一样,默认 1s ## 设置验证信息,两个节点必须一致 authentication { auth_type PASS auth_pass 1111 } ## 将 track_script 块加入 instance 配置块 track_script { chk_nginx ## 执行 Nginx 监控的服务 } ## 虚拟 IP 池, 两个节点设置必须一样 virtual_ipaddress { 1.10 ## 虚拟ip,可以定义多个 } }
web2的keepalived配置
! Configuration File for Keepalived global_defs { router_id 1.2 ##指定本机物理主机IP } vrrp_script chk_nginx { script "/data/keepalived/nginx_check.sh" ## 检测 nginx服务状态 interval 2 ## 检测时间间隔 weight -20 ## 如果条件成立,权重-20 } vrrp_instance VI_1 { state MASTER ##指定这台主机keepalived为主节点 interface eth0 ##指定物理网卡接口 virtual_router_id 11 ## 虚拟路由的ID号,两个节点设置必须一样,建议用IP最后段 mcast_src_ip 1.2 ##指定本机物理主机IP priority 80 ## 节点优先级,值范围0-254,MASTER要比BACKUP高 nopreempt ## 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题 advert_int 1 ## 组播信息发送间隔,两个节点设置必须一样,默认 1s ## 设置验证信息,两个节点必须一致 authentication { auth_type PASS auth_pass 1111 } ## 将 track_script 块加入 instance 配置块 track_script { chk_nginx ## 执行 Nginx 监控的服务 } ## 虚拟 IP 池, 两个节点设置必须一样 virtual_ipaddress { 1.10 ## 虚拟ip,可以定义多个 } }
监测脚本/data/keepalived/nginx_check.sh,权限给777就可以了
#!/bin/bash C=`ps -C nginx --no-header |wc -l` if [ $C -eq 0 ] then su - nginx -c /data/nginx-1.18.0/sbin/nginx sleep 2 if [ `ps -C nginx --no-header |wc -l` -eq 0 ] then ps -C keepalived --no-header | awk '{print $1}' | xargs kill fi fi
正常情况下,上面的配置可以满足下面的负载条件:
测试用例1 节点nginx服务进程停止
测试方法 手工模拟停止nginx服务,检查nginx进程是否正常拉起
预计结果 Keepalived自动拉起nginx服务,业务访问VIP正常
实际结果 Keepalived自动拉起nginx服务,业务访问VIP正常
测试用例2 主节点宕机
测试方法 手工模拟将keepalived进程或是主机重启
预计结果 VIP自动漂移到备节点,业务访问VIP正常
实际结果 VIP自动漂移到备节点,业务访问VIP正常
测试用例3 主节点恢复
测试方法 恢复主节点keepalived与nginx服务
预计结果 备节点VIP回切主节点,业务访问VIP正常
实际结果 备节点VIP回切主节点,业务访问VIP正常
但是,经过测试,还是会出现一种情况:节点nginx服务进程停止,监测脚本无法拉起nginx的情况下,keepalived服务没有停止虚拟IP依然停留在nginx进程异常的节点上面,导致访问过来的请求出现报错。
一开始以为是脚本的问题、配置的问题,后来手动执行监测脚本,确实可以在nginx进程宕掉后,成功停止keepalived服务,然后虚拟IP漂到备节点上面,那就是脚本执行到一半就没有往下执行了,所以脚本确实是执行了,导致权重也没有减少,因此虚拟IP还是没有漂到备节点上面,配置、脚本都没有问题,百思不解之下,通过网上搜查,发现了另一个可行方案,监测脚本不变,但是web1的keepalived配置添加一个TCP监测项,监测nginx 的访问端口
! Configuration File for Keepalived global_defs { router_id 1.1 ##指定本机物理主机IP } vrrp_script chk_nginx { script "/data/keepalived/nginx_check.sh" ## 检测 nginx服务状态 interval 2 ## 检测时间间隔 weight -20 ## 如果条件成立,权重-20 } vrrp_instance VI_1 { state MASTER ##指定这台主机keepalived为主节点 interface eth0 ##指定物理网卡接口 virtual_router_id 11 ## 虚拟路由的ID号,两个节点设置必须一样,建议用IP最后段 mcast_src_ip 1.1 ##指定本机物理主机IP priority 100 ## 节点优先级,值范围0-254,MASTER要比BACKUP高 nopreempt ## 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题 advert_int 1 ## 组播信息发送间隔,两个节点设置必须一样,默认 1s ## 设置验证信息,两个节点必须一致 authentication { auth_type PASS auth_pass 1111 } ## 将 track_script 块加入 instance 配置块 track_script { chk_nginx ## 执行 Nginx 监控的服务 } ## 虚拟 IP 池, 两个节点设置必须一样 virtual_ipaddress { 1.10 ## 虚拟ip,可以定义多个 } } virtual_server 1.10 8080 { ## 虚拟ip和nginx访问端口 delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 5 protocol TCP real_server 1.1 8080 { ##本机物理主机IP和nginx访问端口 weight 1 notify_down /data/keepalived/sbin/nginx_check.sh ##监测本地nginx进程端口宕掉后,执行脚本,停止keepalived TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 8080 #监测的NGINX的访问的TCP端口 } } }
web2上面的keepalived配置跟web1一样,添加一个TCP监测
! Configuration File for Keepalived global_defs { router_id 1.2 ##指定本机物理主机IP } vrrp_script chk_nginx { script "/data/keepalived/nginx_check.sh" ## 检测 nginx服务状态 interval 2 ## 检测时间间隔 weight -20 ## 如果条件成立,权重-20 } vrrp_instance VI_1 { state MASTER ##指定这台主机keepalived为主节点 interface eth0 ##指定物理网卡接口 virtual_router_id 11 ## 虚拟路由的ID号,两个节点设置必须一样,建议用IP最后段 mcast_src_ip 1.2 ##指定本机物理主机IP priority 80 ## 节点优先级,值范围0-254,MASTER要比BACKUP高 nopreempt ## 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题 advert_int 1 ## 组播信息发送间隔,两个节点设置必须一样,默认 1s ## 设置验证信息,两个节点必须一致 authentication { auth_type PASS auth_pass 1111 } ## 将 track_script 块加入 instance 配置块 track_script { chk_nginx ## 执行 Nginx 监控的服务 } ## 虚拟 IP 池, 两个节点设置必须一样 virtual_ipaddress { 1.10 ## 虚拟ip,可以定义多个 } } virtual_server 1.10 8080 { ## 虚拟ip和nginx访问端口 delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 5 protocol TCP real_server 1.2 8080 { ##本机物理主机IP和nginx访问端口 weight 1 notify_down /data/keepalived/sbin/nginx_check.sh ##监测本地nginx进程端口宕掉后,执行脚本,停止keepalived TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 8080 #监测的NGINX的访问的TCP端口 } } }
当这个keepalived的配置改成这样后,监测脚本无法拉起nginx的情况下,keepalived服务也会因为TCP端口,就是nginx的访问端口宕掉,而触发脚本,将keepalived服务停止,而不会像前面的那样,发现nginx进程无法拉起后,一直重复执行拉起操作,但是不停止keepalived进程