在使用 Nginx 做反向代理或者负载均衡的时候,都是以 Nginx 为入口,如果 Nginx 宕机了,那么所有的服务都无法正常提供,影响非常严重。所有我们需要保证 nginx 高可用,就是配置备份机,前一个挂了,还有后一个。
为了避免负载均衡服务器宕机造成严重影响,就需要建立一个备份机。主服务器和备份机上都运行高可用(High Availability)监控程序,通过传送诸如“I am alive”这样的信息来监控对方的运行状况。当备份机不能在一定的时间内收到这样的信息时,它就接管主服务器的服务IP并继续提供负载均衡服务;当备份管理器又从主管理器收到“I am alive”这样的信息时,它就释放服务IP地址,这样的主服务器就开始再次提供负载均衡服务。
高可用(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。如果一个系统能够一直提供服务,那么这个可用性则是百分之百,但是我们不能保证一个系统能永远不出问题,所以我们只能通过设计来尽可能的去减少由于系统的故障所造成的影响。
我们可以通过 keepalived 来实现 Nginx 的高可用,keepalived 是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。Keepalived的作用是检测 web 服务器的状态,如果有一台 web 服务器死机或工作出现故障,Keepalived 将能检测到,并将有故障的 web 服务器从系统中剔除,当web服务器工作正常后 Keepalived 会自动将该 web 服务器加入到服务器群中。这些工作全部都会自动完成,不需要人工干涉,需要人工做的只是修复故障的web服务器。keepalived 可以理解为一个健康检查的软件。
高可用至少需要 2 台服务器,主备都得装上keepalived,当请求访问主服务器时,备份服务器会一直检查主服务器的状态。
keepalived 需要绑定一个虚拟地址 vip ( Virtual IP Address ) ,这个虚拟 ip 地址绑定在哪台服务器上请求就会发送到哪台服务器,一开始会绑定在主服务器上。
首先准备两台服务器,这里我们准备了两台虚拟机。分别在这两台服务器上安装 Nginx 和 keepalived。
安装 keepalived 使用 yum 方式直接安装即可,该方式会自动安装依赖。安装 keepalived 命令:
yum -y install keepalived
安装完成后可以输入 rpm -q -a keepalived 命令检验安装是否成功:
通过 yum 方式安装的 keepalived 在安装完成之后,会在 /ect 目录下生成一个 keepalive 目录,该目录下存放着 keepalived 的配置文件 keepalived.conf :
首先需要修改 keepalived 的配置文件,keepalived 的配置文件在 /etc/keepalived 目录下。
主服务器和备份服务器的 keepalived 配置文件有一点不同。下面是主服务器的 keepalived.conf 文件内容,直接替代默认的 keepalived.conf 配置文件即可。
global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_ server 192.168.32.128 #主服务器的ip地址 smtp_connect_timeout 30 router_id LVS_DEVEL # LVS_DEVEL这字段在/etc/hosts文件中看;通过它访问到主机 } vrrp_script chk_http_ port { script "/usr/local/src/nginx_check.sh" #检测脚本 interval 2 # (检测脚本执行的间隔)2s weight 2 #权重,如果这个脚本检测为真,服务器权重+2 } vrrp_instance VI_1 { state MASTER # 指定keepalived的角色,MASTER为主,BACKUP为备。备份服务器上需将MASTER 改为BACKUP interface ens33 # 当前进行vrrp通讯的网络接口卡(当前centos的网卡) 用ifconfig查看你具体的网卡 virtual_router_id 51 # 虚拟路由编号,主、备机的virtual_router_id必须相同 priority 100 #优先级,数值越大,获取处理请求的优先级越高。主、备机取不同的优先级,主机值较大,备份机值较小 advert_int 1 # 检查间隔,默认为1s(vrrp组播周期秒数),每隔1s发送一次心跳 authentication { # 校验方式, 类型是密码,密码1111 auth type PASS #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信 auth pass 1111 } virtual_ipaddress { # 虛拟ip 192.168.32.50 # 定义虚拟ip(VIP),可多设,每行一个 } }
备份服务器的 keepalived 配置文件:
global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_ server 192.168.32.130 #备份服务器的ip地址 smtp_connect_timeout 30 router_id LVS_DEVEL # LVS_DEVEL这字段在/etc/hosts文件中看;通过它访问到主机 } vrrp_script chk_http_ port { script "/usr/local/src/nginx_check.sh" #检测脚本 interval 2 # (检测脚本执行的间隔)2s weight 2 #权重,如果这个脚本检测为真,服务器权重+2 } vrrp_instance VI_1 { state BACKUP # 指定keepalived的角色,MASTER为主,BACKUP为备。备份服务器上需将MASTER 改为BACKUP interface ens33 # 当前进行vrrp通讯的网络接口卡(当前centos的网卡) 用ifconfig查看你具体的网卡 virtual_router_id 51 # 虚拟路由编号,主、备机的virtual_router_id必须相同 priority 90 #优先级,数值越大,获取处理请求的优先级越高。主、备机取不同的优先级,主机值较大,备份机值较小 advert_int 1 # 检查间隔,默认为1s(vrrp组播周期秒数),每隔1s发送一次心跳 authentication { # 校验方式, 类型是密码,密码1111 auth type PASS #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信 auth pass 1111 } virtual_ipaddress { # 虛拟ip 192.168.32.50 # 定义虚拟ip(VIP),可多设,每行一个 } }
将上面的两个配置文件分别替换主备服务器的 keepalived 配置文件。
上面的配置文件中我们配置了检测脚本的名称和位置,即 /usr/local/src/nginx_check.sh,根据配置我们需要往主备服务器的 /usr/local/src 目录下分别创建一个 nginx_check.sh 脚本文件,文件内容如下:
#! /bin/bash #检测nginx是否启动了 A=`ps -C nginx -no-header | wc - 1` if [ $A -eq 0];then #如果nginx没有启动就启动nginx /usr/local/nginx/sbin/nginx #重启nginx sleep 2 if [`ps -C nginx --no-header| wc -1` -eq 0 ];then #nginx重启失败,则停掉keepalived服务,进行VIP转移 killall keepalived fi fi
最后分别启动主备服务器的 Nginx 和 keepalived:
cd /usr/local/nginx/sbin # 启动Nginx需要先切换到 Nginx 的脚本目录下 ./nginx -s stop #因为已经启动了,所以先关闭 Nginx ./nginx #启动Nginx ps -ef | grep nginx #查看 Nginx 进程的状态 systemctl start keepalived.service #启动keepalived ps -ef | grep keepalived #查看 keepalived 进程的状态
示例如下:
配置完之后,我们可以在 window 浏览器上输入上面配置的虚拟地址 192.168.32.50 来访问主服务器的 Nginx:
如果主服务器没有宕机,不管我们刷新几次,都是访问的主服务器上的资源。
如果我们关闭了主服务器上的 Nginx 和 keepalived:
systemctl stop keepalived.service # 关闭keepalived ./nginx -s stop # 关闭Nginx
示例:
此时再访问虚拟 ip 地址 192.168.32.50 仍能正常访问,因为备份服务器此时在工作了。我们可以修改两个服务器上的 Nginx 资源的内容以便能区分是哪个服务器的资源,如下可以证明此时确实是备份服务器 192.168.32.130 在工作:
keepalived 的默认配置文件如下:
! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.200.16 192.168.200.17 192.168.200.18 } } virtual_server 192.168.200.100 443 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.201.100 443 { weight 1 SSL_GET { url { path / digest ff20ad2481f97b1754ef3e12ecd3a9cc } url { path /mrtg/ digest 9b3a0c85a887a256d6939da88aabd8cd } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } } virtual_server 10.10.10.2 1358 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP sorry_server 192.168.200.200 1358 real_server 192.168.200.2 1358 { weight 1 HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.200.3 1358 { weight 1 HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334c } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334c } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } } virtual_server 10.10.10.3 1358 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.200.4 1358 { weight 1 HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.200.5 1358 { weight 1 HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } url { path /testurl3/test.jsp digest 640205b7b0fc66c1ea91c463fac6334d } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }