Nginx + Keepalived 构建高可用的负载层方法,nginxkeepalived
Nginx + Keepalived 构建高可用的负载层方法,nginxkeepalived
本文基于如下的拓扑图:
+-------------+ | uplink | +-------------+ | + MASTER keep|alived BACKUP 192.168.1.11 192.168.1.10 192.168.1.12 +-------------+ +-------------+ +-------------+ | Nginx VM1 |----| virtualIP |----| Nginx VM2 | +-------------+ +-------------+ +-------------+ | +------------------+------------------+ | | | +-------------+ +-------------+ +-------------+ | web01 | | web02 | | web03 | +-------------+ +-------------+ +-------------+
一共配置两台服务器:
第一台服务器:Nginx vm1 和 keepalived MASTER; 第二台服务器:Nginx vm2 和 keepalived BACKUP;一、准备工作
1、准备两台独立工作的 Nginx 系统
在我这里,安装两台 Nginx 的虚拟机IP地址分别是:
Nginx VM1:192.168.61.11:80 Nginx VM2:192.168.61.12:80nginx没有什么可配置的,因为它与keepalived并没有联系。但记住,2台nginx服务器上的配置应该是完全一样的(rsync同步),这样才能做到对用户透明,nginx.conf 里面的 server_name 尽量使用域名来代替,然后dns解析这个域名到虚拟IP 192.168.1.10。
还有一点需要特别需要注意的是:Nginx一定要监听到所访问的地址。
附:Nginx服务器的安装配置请参考:
Nginx 服务器安装与配置
Nginx 虚拟主机配置的三种方式(一)(基于IP)
Nginx 虚拟主机配置的三种方式(二)(基于端口)
Nginx 虚拟主机配置的三种方式(三)(基于域名)
2、在已安装好 Nginx 的两个虚拟机上分别安装 Keepalived
我的环境是CentOS 7.0 X86_64,直接通过yum方式安装最简单:
[root@bogon /]# yum install -y keepalived [root@bogon /]# keepalived -v [root@bogon /]# Keepalived v1.2.13 (08/03,2017)
附:源码安装:Keepalived服务器的安装配置请参考:Keepalived 服务器安装与配置
3、编写 nginx 监控脚本
该脚本检测 ngnix 的运行状态,并在 nginx 进程不存在时尝试重新启动 ngnix,如果启动失败则停止 keepalived,准备让其它机器接管。
[root@bogon /]# vim /etc/keepalived/check_nginx.sh #!/bin/sh if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then /usr/local/nginx/sbin/nginx fi sleep 2 if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then service keepalived stop fi
二、Nginx + Keepalived 最简配置
1、请再次确认前提
(首先,为了保证不会出现额外的问题,请首先关闭防火墙,当然正式环境里面,防火墙不能关闭)
外网进行 Nginx 访问的浮动IP:192.168.1.10; 我们将192.168.1.11这台服务器上运行的 Nginx 作为主要的 Nginx,其上的keepalived 服务我们设置成 Master 方式; 我们将192.168.1.12这台服务器上运行的Nginx作为备用的Nginx服务,其上的keepalived 服务我们设置为 Backup 方式。2、设置192.168.1.11上的MASTER
我们先来看看192.168.1.11上的原始IP信息:
[root@localhost ~]# ifconfig ens33: flags=4163mtu 1500 inet 192.168.1.11 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::2a8d:be6:a4a8:ea0 prefixlen 64 scopeid 0x20 ether 00:0c:29:1a:76:7e txqueuelen 1000 (Ethernet) RX packets 70 bytes 11009 (10.7 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 73 bytes 11927 (11.6 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1 (Local Loopback) RX packets 72 bytes 6252 (6.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 72 bytes 6252 (6.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
注意,这个11机器上的网卡设备号是ens33,而不是eth0,这个参数我们将在配置keepalived 的时候使用到。
下面是11上 keepalived 的最简配置:
! Configuration File for keepalived # global setting , notify email setting global_defs { #存在于同一个网段中,一组keepalived的各个节点都有不同的名字 #在全局设置中,我们还可以设置管理员的email信息等。 router_id LVS_V1 } #这个是我们在上一小结讲到的nginx检查脚本,我们保存在这个文件中(注意文件权限) vrrp_script chknginx { script "/etc/keepalived/check_nginx.sh" #每10秒钟,检查一次 interval 10 } #keepalived实例设置,是最重要的设置信息 vrrp_instance VI_1 { #state状态MASTER表示是主要工作节点。 #一个keepalived组中,最多只有一个MASTER节点,当然也可以没有 state MASTER #实例所绑定的网卡设备,我的网卡设备是ens33。您按照您自己的来 interface ens33 #同一个keepalived组,节点的设置必须一样,这样才会被识别 virtual_router_id 52 #节点优先级,BACKUP的优先级一定要比MASTER的优先级低 priority 100 #组播信息发送间隔,两个节点设置必须一样 advert_int 1 #实际的ens33上的固定ip地址 mcast_src_ip 192.168.1.11 #验证信息,只有验证信息相同,才能被加入到一个组中。 authentication { auth_type PASS auth_pass 1111 } #虚拟地址和绑定的端口,如果有多个,就绑定多个 #dev 是指定浮动IP要绑定的网卡设备号 virtual_ipaddress { 192.168.1.10 dev ens33 } #设置的检查脚本 #关联上方的“vrrp_script chknginx” track_script { chknginx } }
3、设置192.168.1.12上的BACKUP
再来看看192.168.1.12这个备用节点上 keepalived 的设置:
! Configuration File for keepalived # global setting , notify email setting global_defs { #这里和master节点不同 router_id LVS_V2 } #check nginx vrrp_script chknginx { script "/etc/keepalived/check_nginx.sh" interval 10 } # instance setting vrrp_instance VI_1 { # 这里和Master节点不一样 state BACKUP interface ens33 # 这里一定是一样的 virtual_router_id 52 # 这里的优先级比Master节点低 priority 99 advert_int 1 # 这里和Master节点不一样 mcast_src_ip=192.168.1.12 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.10 dev ens33 } track_script { chknginx } }
4、启动主节点和备用节点
以上配置中请注意几个关键点:
注意nginx状态检查的脚本的位置,根据自己创建文件的位置不一样,脚本检查的指定位置也不一样; 注意优先级,MASTER节点的优先级一定要高于所有的BACKUP节点; 注意局域网的组播地址,一定要可用。局域网内所有keepalived节点都是利用组播方式寻找对方; 谁说BACKUP节点只能有一个!? 最后,keepalived一定要注册成服务形式,您可以想象上面所有脚本、配置、命令如果重启后再来一次,会是什么情况。接下来,我们要开始启动 Master 节点和 Backup 节点了,为了准确的查看日志状态,您需要观察系统日志。系统日志所在的位置:
tail -f /var/log/messages
先启动Master节点:
[root@localhost ~]# service keepalived start
再启动Backup节点:
[root@localhost ~]# service keepalived start
如果设置和启动都是成功的,您不会在日志信息中收到任何的keepalived报错信息。接下来您就可以使用192.168.1.10这个IP访问Nginx了:
另外,这个绑定在192.168.1.11上的浮动ip:192.168.1.10,您通过ipconfig命令一般是看不到的,要使用ip addr命令进行查看:
# 使用ip命令配置的地址,ifconfig查看不了 [root@bogon system]# ip a|grep ens33 2: ens33:mtu 1500 qdisc pfifo_fast state UP qlen 1000 inet 192.168.1.11/24 brd 192.168.1.255 scope global dynamic ens33 inet 192.168.1.12/32 scope global ens33
为了试验,我们主动停止 Master 节点上的 keepalived 服务(注意,杀 Nginx 进程不起作用,因为我们的检查脚本会试图重新启动 Nginx 进程),接下来我们可以看到浮动IP漂移到了12备机上:
三、Nginx + Keepalived非抢占模式
通过上面的详细介绍,相信您对Nginx + Keepalived的安装方式有了一个明确的理解。keepalived的切换可以是自动的,但是却做不到毫秒级别,他怎么都需要几秒钟的时间进行切换。
这就有一个问题,虽然在主节点出现问题我们转向备份节点时,这个延时无可避免,但是在我们修复主节点后,实际上并没有必要再马上做一次切换,所以 Keepalived 提供了一种非抢占模式,来满足这个要求。
下面我们就来介绍一下Keepalived的非抢占模式的配置(无MASTER节点,全部依据优先级确定哪个节点进行工作):
1、原来主节点的配置改动
! Configuration File for keepalived # global setting , notify email setting global_defs { router_id LVS_V1 } vrrp_script chknginx { script "/etc/keepalived/check_nginx.sh" interval 10 # 一旦节点失效,节点的优先级就减少2 # 有多少个keepalived节点,就填写多少数量。 # 这样保证这个节点的优先级比其他节点都低 weight -2 # fall 表示多少次检查失败,就算节点失效。默认1 #fall 1 } vrrp_instance VI_1 { #state状态都是BACKUP表示是主要工作节点。 state BACKUP interface ens33 virtual_router_id 52 # 这个关键配置项,设置为“非抢占”模式 nopreempt # 每个节点的优先级一定要不一样 priority 100 advert_int 1 mcast_src_ip=192.168.1.11 authentication { auth_type PASS auth_pass 1111 } #虚拟地址和绑定的端口,如果有多个,就绑定多个 #dev 是指定浮动IP要绑定的网卡设备号 virtual_ipaddress { 192.168.1.10 dev ens33 } #设置的检查脚本 #关联上方的“vrrp_script chknginx” track_script { chknginx } }
原来的主节点设置更改完成。
2、原来备份节点的配置改动
加入“非抢占”模式的关键字、更改一个确定的优先级,设置检查失败后优先级的递减量,就行了。
附、配置过程中的问题
1、Nginx为什么会停止响应呢?在我的工作经验中,无非有以下几种情况:
Nginx的所有进程被强行终止(或管理进程);
这种情况,是我们需要检查和切换的。无论什么情况下进程被终止了,如果它不能重启,我们就要切换到备机。
Nginx日志盘的挂载点崩溃或者磁盘写满;
这个也是我们需要检查和切换的。
Nginx已经达到设置的最大连接数,暂时停止响应;
这种情况下,我们不能进行备机切换,因为通过VIP:192.168.61.100连接过来的用户请求比较多(在我们优化参数后,可以达到65535 / 4的数量),一旦我们进行备机切换,这些用户请求将全部异常。这个问题的解决需要靠增加负载机器,而不是主备切换。
Nginx物理机异常关机。
这个肯定是需要进行检查和切换的。
2、nginx监控脚本
#!/bin/sh if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then /usr/local/nginx/sbin/nginx fi sleep 2 if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then service keepalived stop fi
整个脚本的解释:
第一个判断说明的是,如果当前nginx的进程数量 == 0,那么执行nginx的启动命令,试图重新启动nginx;接下来等待2秒(这是为了给nginx一定的启动时间),然后再次查看Nginx的进程数量,如果仍然 == 0,那么停止这台机器的keepalived服务,以便备用的Keepalived节点检查到Keepalived已经停止这个事件,并将浮动IP切换到备用服务器上。
注意,这段脚本是和我机器上的Nginx安装路径、Keepalived服务的状态有关的,您如果要用的话,请进行相应的更改。
然后具体讲解一下每个命令的含义:
我们大致讲解一下“ps -C nginx –no-header | wc -l”这个命令:
ps 这个命令用来进行linux中进程相关的查询,-C 意思是按照进程名称进行查询。查询出来后的结果如下:[root@bogon /]# ps -C nginx PID TTY TIME CMD 3178 ? 00:00:00 nginx 3180 ? 00:00:00 nginx 3181 ? 00:00:00 nginx 3182 ? 00:00:00 nginx 3183 ? 00:00:00 nginx如果要去掉统计出来的结果表的头部,那么要使用 –no-header 参数,加上参数后,查询结果如下:
[root@bogon /]# ps -C nginx --no-header 3178 ? 00:00:00 nginx 3180 ? 00:00:00 nginx 3181 ? 00:00:00 nginx 3182 ? 00:00:00 nginx 3183 ? 00:00:00 nginx“|”,这是Linux中的管道流命令,将上一个命令的输出结果作为下一个命令的输入。 wc 统计命令,-l 参数,代表按行数进行统计。所以整个命令的输出结果为:
[root@bogon /]# ps -C nginx --no-header | wc -l 5
3、配置选项说明
global_defs
notification_email : keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的; router_id : 机器标识,通常可设为hostname。故障发生时,邮件通知会用到。vrrp_instance
state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER; interface : 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的; mcast_src_ip : 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址; virtual_router_id : 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址; priority : 设置本节点的优先级,优先级高的为master; advert_int : 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常; authentication : 定义认证方式和密码,主从必须一样; virtual_ipaddress : 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系,这里可以设置多个IP地址; track_script : 引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。vrrp_script
告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script
这里要提示一下script一般有2种写法:
通过脚本执行的返回结果,改变优先级,keepalived继续发送通告消息,backup比较优先级再决定; 脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP。上文 vrrp_script 配置部分,killall -0 nginx属于第1种情况,/etc/keepalived/check_nginx.sh属于第2种情况(脚本中关闭keepalived)。个人更倾向于通过shell脚本判断,但有异常时exit 1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance 优先级选举决定是否抢占VIP:
如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加; 如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少。其他情况,原本配置的优先级不变,即配置文件中priority对应的值。
提示:
优先级不会不断的提高或者降低; 可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行); 不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况; 在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换。以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
配置结束
在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。
评论暂时关闭