Nginx&Keepalived 实现高可用

keepalived是什么

Keepalived 是一种高性能的服务器高可用或热备解决方案, Keepalived 可以用来防止服务器单点故障的发生,通过配合 Nginx 可以实现 web 前端服务的高可用。虽然nginx的抗压性很强,很少出现宕机,但是如果不做热备,nginx一挂服务都会挂掉,所以热备是必须的,当然,根据自己的实际业务需求来决定。

keepalived 原理

keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol(虚拟路由冗余协议)

keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议

虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内其他机器的默认路由为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级选举一个backup当master。这样的话就可以保证路由器的高可用了。

keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。

keepalived 结构

keepalived只有一个配置文件keepalived.conf。里面主要包括以下几个配置区域,分别是global_defsvrrp_instance、和virtual_server

global_defs区域

主要是配置故障发生时的通知对象以及机器标识,通俗点说就是出状况后发邮件通知的一个配置。

global_defs {
    notification_email {    故障发生时给谁发邮件通知
        a@abc.com
        b@abc.com
        ...
    }
    notification_email_from alert@abc.com    通知邮件从哪个地址发出
    smtp_server smtp.abc.com        smpt_server 通知邮件的smtp地址。
    smtp_connect_timeout 30       连接smtp服务器的超时时间
    enable_traps      开启SNMP陷阱
    router_id host163      标识本节点的字条串,通常为hostname
}
vrrp_instance区域

vrrp_instance用来定义对外提供服务的VIP区域及其相关属性

vrrp_instance VI_1 {
    state MASTER         state 可以是MASTER或BACKUP
    interface ens33        本机网卡的名字
    virtual_router_id 51      取值在0-255之间,用来区分多个instance的VRRP组播
    priority 100            权重
    advert_int 1       发VRRP包的时间间隔,即多久进行一次master选举
    authentication {        身份认证区
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {        虚拟ip地址
        192.168.27.160
    }
}
virtual_server

超大型的LVS中用到,我在这里不用它。

virtual_server 192.168.200.100 443 {
    delay_loop 6                                延迟轮询时间(单位秒)
    lb_algo rr                                 后端调试算法
    lb_kind NAT                               LVS调度类型
    persistence_timeout 50 
    protocol TCP

    real_server 192.168.201.100 443 {                              真正提供服务的服务器
        weight 1
        SSL_GET {
            url {
              path /
              digest ff20ad2481f97b1754ef3e12ecd3a9cc         表示用genhash算出的结果
            }
            url {
              path /mrtg/
              digest 9b3a0c85a887a256d6939da88aabd8cd
            }
            connect_timeout 3
            nb_get_retry 3                                                           重试次数
            delay_before_retry 3                                                下次重试的时间延迟
        }
    }
}

keepalived安装

yum install keepalived -y 

环境模拟

我准备了四个主机,ip是192.168.27.166-169,都搭建nginx服务,然后把166和167分别当主备机。

nginx配置
upstream centos_pool{
        server s168:80;
        server s169:80;
}
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
       # root   /usr/share/nginx/html;
       # index  index.html index.htm;
        proxy_pass http://centos_pool;
    }

四个主机都用该配置启动,看起来是4个nginx服务,在这个实例里不是这样的,不同的是166和167是nginx服务,168和169是web服务(用nignx开放80端口来模仿服务)。

换句话说,166和167用来做负载均衡,168和169是web服务主机。

我在168和169的主机/usr/share/nginx/html/index.html里做了简单的标识:





注意对照地址栏看变化。就把168和169当作普通的web服务。

好了,下来配置keepalived

配置keepalived

166主机配置:

! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL
}

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 {
        192.168.27.160
    }
}

可以说是最核心的配置了,也是最简配置,想要配置邮件服务可以对照上文中的模块介绍注释去弄。lvs配置也一样。

167热备配置:

! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.27.160
    }
}

可以看出,除了state MASTER/BACKUPpriority 100属性不同,其他都相同也必须相同。
好了,现在启动keepalived,从ip路由就能看出谁是主机(接管节点的网卡会绑定VIP地址192.168.27.160)

测试

1. 访问虚拟ip:
2. 查看主机路由
166主机
167主机
3. 情景演练

一切配置正常后,我把166上的nginx停了,会发生什么呢?

167会接手虚拟ip地址,完成双机热备任务吗?答案是不会,因为你回头看看,keepalived没有一点是和nginx有关系的,两服务互不影响。keepalived其实是监控master上的keepalived的心跳的。所以,我把keepalived服务也关掉。

[root@s166 keepalived]# nginx -s stop
[root@s166 keepalived]# service keepalived stop
Redirecting to /bin/systemctl stop keepalived.service

然后再查看166的ip路由

[root@s166 keepalived]# ip addr
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:7b:59:07 brd ff:ff:ff:ff:ff:ff
    inet 192.168.27.166/24 brd 192.168.27.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::83ee:6998:a0d4:7974/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::2513:4c77:5da7:f031/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::99b3:c79:5377:c3fe/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever

可以看到是没有192.168.27.160这个虚拟ip了。那我们再看一下167是否有,如果有,证明配置生效。


那我们继续刷新192.168.27.160这个链接,会发现运行正常。

脚本优化

既然keepalived和nginx没有关联,那我们可以写个脚本监听nginx,如果nginx挂了,然后用命令把keepalived也停掉,这样就会完成双机热备的任务。

创建脚本check_nginx.sh

#!/bin/bash
A=`ps -C nginx --no-header | wc -l`
if [ $A -eq 0 ];then
    echo "restart the nginx server" >> /etc/keepalived/keepalived_error.log
    /usr/sbin/nginx
    sleep 2
    if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
    echo "keepalived is closed" >> /etc/keepalived/keepalived_error.log
    /usr/bin/ps -ef | grep "keepalived" | grep -v "grep" | cut -c 9-15 | xargs kill -9
    echo /usr/bin/ps -ef | grep "keepalived" >> /etc/keepalived/keepalived_error.log
    fi
fi

对了,记住修改脚本可执行权限。为什么要重定向呢,因为echo不会打印在控制台上,我们可以跟踪keepalived_error.log来判断脚本是否执行。

那既然这样,我们的脚本如何控制时间呢?sleep的时间也得控制好,在保持高性能下转换越快越好。所以,我们把脚本加载到keepalived配置中,keepalived每进行一次选举,就执行一次脚本。

把脚本添加到keepalived任务中

! Configuration File for keepalived 
 
global_defs { 
   router_id LVS_DEVEL 
} 
 
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 {
        192.168.27.160
    }
    track_script {
       chk_nginx  # nginx存活状态检测脚本
    }
}

vrrp_script chk_nginx {
       script "/etc/keepalived/check_nginx.sh"
       interval 2 
       weight -20
}

同理,BACKUP主机也要配置

! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.27.160
    }
    track_script {
       chk_nginx
    }
}
vrrp_script chk_nginx {
       script "/etc/keepalived/check_nginx.sh"
       interval 2 
       weight -20
}
优化后测试

日志也会发现一直有在执行脚本。

那如何测试不重启nginx,让它直接关keepalived,然后启用BACKUP呢。我把那行重启nginx脚本注释掉。然后再跑。

#!/bin/bash
A=`ps -C nginx --no-header | wc -l`
if [ $A -eq 0 ];then
#    echo "restart the nginx server" >> /etc/keepalived/keepalived_error.log
#    /usr/sbin/nginx
#    sleep 2
#    if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
    echo "keepalived is closed" >> /etc/keepalived/keepalived_error.log
    /usr/bin/ps -ef | grep "keepalived" | grep -v "grep" | cut -c 9-15 | xargs kill -9
    echo /usr/bin/ps -ef | grep "keepalived" >> /etc/keepalived/keepalived_error.log

#    fi
fi

说明脚本和keepalived整合没问题,将注释去掉。任务完成。

思考

[root@s166 keepalived]# ip addr
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:7b:59:07 brd ff:ff:ff:ff:ff:ff
    inet 192.168.27.166/24 brd 192.168.27.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.27.160/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::83ee:6998:a0d4:7974/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::2513:4c77:5da7:f031/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::99b3:c79:5377:c3fe/64 scope link tentative dadfailed 
       valid_lft forever preferred_lft forever
[root@s167 keepalived]# ip addr
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:d4:26:34 brd ff:ff:ff:ff:ff:ff
    inet 192.168.27.167/24 brd 192.168.27.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.27.160/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::99b3:c79:5377:c3fe/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

虽然我们把s166都关闭了keepalived,但是ip路由还会有虚拟ip 192.168.27.160,这个可能是keepalived并没有完全终止。但是我在刷新的时候没有出现错误页面,证明并没有影响到服务的正常运行。不属于裂脑问题。我将脚本中的强制killkeepalived的操作换成更委婉的/usr/sbin/service keepalived stop,解决了该问题.

拓展:高可用之裂脑问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容