生产环境nginx+keepalived负载均衡及高可用方案

目标:

  1. 利用Nginx实现负载均衡及应用高可用
  2. 利用Keepalived实现服务器高可用

规划:

ip hostname Nginx Keepalived
10.69.53.61 nginx01
10.69.53.62 nginx02

Nginx负载均衡策略,网上有许多完整的讲解,请自行百度,这里我们选择默认的轮询策略。
Keepalived选择非抢占模式。

注意:一定要关闭防火墙!

# 禁用防火墙
systemctl stop firewalld
# 禁止开机启动
sytemctl disable firewalld
# 关闭selinux
vi /etc/sysconfig/selinux
#修改
SELINUX=disabled

一、Nginx安装

  1. 安装编译工具
yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel
  1. 安装PCRE使Nginx支持rewrite功能
#  下载压缩包
cd /usr/local/src/
wget http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz
# 解压
tar zxvf pcre-8.35.tar.gz
# 进入安装目录
cd pcre-8.35
# 编译安装
./configure
make && make install
# 查看版本
pcre-config --version
  1. 安装Nginx
# 下载压缩包
cd /usr/local/src/
wget http://nginx.org/download/nginx-1.6.2.tar.gz
# 解压
tar zxvf nginx-1.6.2.tar.gz
# 进入安装目录
cd nginx-1.6.2
# 编译安装
./configure --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.35
make
make install
# 查看版本
/usr/local/webserver/nginx/sbin/nginx -v
# 创建nginx运行用户
/usr/sbin/groupadd www 
/usr/sbin/useradd -g www www
  1. 修改配置文件/usr/local/webserver/nginx/conf/nginx.conf,注意两台节点的ip不同
# !注意文件路径
vim /usr/local/webserver/nginx/conf/nginx.conf
user  www www;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    # 路由地址,两个节点配置相同
    upstream myServer {
        server 10.69.53.61:8888; 
        server 10.69.53.62:8888;
    }
    server {
        listen       80; 
        server_name  localhost nginx01 10.69.53.61; # 当前节点ip、hostname
       
        #charset koi8-r;

        #access_log  logs/host.access.log  main;
		# 需要拦截的请求
        location ^~ /test/ {
	    proxy_pass http://myServer;
            root /usr/local/webserver/nginx/html; 
            index  index.html index.htm index.php;
        }
        location / {
            root /usr/local/webserver/nginx/html; 
            index  index.html index.htm index.php;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
  1. 检查nginx.conf正确性
/usr/local/webserver/nginx/sbin/nginx -t

生产环境nginx+keepalived负载均衡及高可用方案

  1. 修改/usr/local/webserver/nginx/html/index.html,以区分nginx01和nginx02
# !注意文件路径
vim /usr/local/webserver/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx01!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx01!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

  1. 启动nginx
# nginx启动命令
/usr/local/webserver/nginx/sbin/nginx

生产环境nginx+keepalived负载均衡及高可用方案
启动成功

  1. 从浏览器访问占点ip

生产环境nginx+keepalived负载均衡及高可用方案
同样,在62节点上安装Nginx
生产环境nginx+keepalived负载均衡及高可用方案
10. 相关命令

# Nginx运行时,修改配置文件/usr/local/webserver/nginx/conf/nginx.conf后,可进行配置文件重载
/usr/local/webserver/nginx/sbin/nginx -s reload
# Nginx重启
/usr/local/webserver/nginx/sbin/nginx -s reopen
# Nginx停止
/usr/local/webserver/nginx/sbin/nginx -s stop
# Nginx启动
/usr/local/webserver/nginx/sbin/nginx
  1. 负载均衡及服务高可用测试
    创建两个返回值不同的springboot程序,分别在nginx01和nginx02上启动,端口与nginx.conf配置的一致,为8888
    nginx01
    生产环境nginx+keepalived负载均衡及高可用方案

nginx02
生产环境nginx+keepalived负载均衡及高可用方案

连续访问nginx01:80/test/两次会发现(根据配置文件,对80端口的/test请求被轮训路由到了nginx01:8888和nginx02:8888上),两次的返回值不一致

生产环境nginx+keepalived负载均衡及高可用方案
生产环境nginx+keepalived负载均衡及高可用方案

当我们kill掉nginx01上的服务,多次请求结果,与nginx02上的程序返回值一致
生产环境nginx+keepalived负载均衡及高可用方案

二、Keepalived安装

Keepalived的HA分 抢占模式 和 非抢占模式。
抢占模式 即MASTER从故障中恢复过来以后,会将VIP从BACKUP手中抢占过来。
非抢占模式 即MASTER从故障中恢复过来以后,不会抢占升级为MASTER的BACKUP的VIP。
  1. 利用yum安装Keepalived
yum -y install keepalived
  1. 修改配置文件/etc/keepalived/keepalived.conf
    1)抢占模式配置

MASTER(10.69.53.61)

global_defs {
 router_id nginx01 #标识本节点的名称,通常为hostname
}
 
# keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。
# 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加。如果脚本执行结果非0,
# 并且weight配置的值小于 0,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中priority对应的值。
vrrp_script chk_nginx {
  script "/usr/local/src/check_nginx_pid.sh" # 检测脚本路径
  interval 2 #每2秒检测一次nginx的运行状态
  weight -20 #失败一次,将自己的优先级-20
}
 
vrrp_instance VI_1 {
 state MASTER # 状态,主节点为MASTER,备份节点为BACKUP
 interface eth0    # 绑定VIP的网络接口,通过ifconfig查看自己的网络接口
 virtual_router_id 99   # 虚拟路由的ID号,两个节点设置必须一样,可选IP最后一段使用,相同的VRID为一个组,他将决定多播的MAC地址
 mcast_src_ip 10.69.53.61 # 本机IP地址
 priority 100     # 节点优先级,值范围0~254,MASTER要比BACKUP高
 advert_int 1     # 组播信息发送时间间隔,两个节点必须设置一样,默认为1秒
 # 设置验证信息,两个节点必须一致
 authentication {
  auth_type PASS
  auth_pass 1111
 }
 # 虚拟IP,两个节点设置必须一样。可以设置多个,一行写一个(随便写一个,只要没被占用就可以)
 virtual_ipaddress {
  10.69.53.200
 }
 
 track_script {
  chk_nginx # nginx存活状态检测脚本
 }
}

BACKUP(10.69.53.62)

global_defs {
 router_id nginx02 #标识本节点的名称,通常为hostname
}
 
# keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。
# 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加。如果脚本执行结果非0,
# 并且weight配置的值小于 0,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中priority对应的值。
vrrp_script chk_nginx {
  script "/usr/local/src/check_nginx_pid.sh" # 检测脚本路径
  interval 2 #每2秒检测一次nginx的运行状态
  weight -20 #失败一次,将自己的优先级-20
}
 
vrrp_instance VI_1 {
 state BACKUP    # 状态,主节点为MASTER,备份节点为BACKUP
 interface eth0    # 绑定VIP的网络接口,通过ifconfig查看自己的网络接口
 virtual_router_id 99   # 虚拟路由的ID号,两个节点设置必须一样,可选IP最后一段使用,相同的VRID为一个组,他将决定多播的MAC地址
 mcast_src_ip 10.69.53.62 # 本机IP地址
 priority 90      # 节点优先级,值范围0~254,MASTER要比BACKUP高
 advert_int 1     # 组播信息发送时间间隔,两个节点必须设置一样,默认为1秒
 # 设置验证信息,两个节点必须一致
 authentication {
  auth_type PASS
  auth_pass 1111
 }
 # 虚拟IP,两个节点设置必须一样。可以设置多个,一行写一个(随便写一个,只要没被占用就可以)
 virtual_ipaddress {
  10.69.53.200
 }
 
 track_script {
  chk_nginx # nginx存活状态检测脚本
 }
}

抢占模式两节点配置文件差异点

 router_id  		不同,均为本节点hostname
 state 				不同,61为MASTER,62为BACKUP
 interface 			本节点的网络接口,通过ifconfig查看
 mcast_src_ip   	不同,均为本节点的IP
 priority 			节点优先级,MASTER要大于BACKUP

2)非抢占模式配置

MASTER(10.69.53.61)

global_defs {
 router_id nginx01 #标识本节点的名称,通常为hostname
}
 
# keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。
# 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加。如果脚本执行结果非0,
# 并且weight配置的值小于 0,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中priority对应的值。
vrrp_script chk_nginx {
  script "/usr/local/src/check_nginx_pid.sh" # 检测脚本路径
  interval 2 #每2秒检测一次nginx的运行状态
  weight -20 #失败一次,将自己的优先级-20
}
 
vrrp_instance VI_1 {
 state BACKUP    # 状态,主节点为MASTER,备份节点为BACKUP
 interface eth0    # 绑定VIP的网络接口,通过ifconfig查看自己的网络接口
 virtual_router_id 99   # 虚拟路由的ID号,两个节点设置必须一样,可选IP最后一段使用,相同的VRID为一个组,他将决定多播的MAC地址
 mcast_src_ip 10.69.53.61 # 本机IP地址
 priority 100     # 节点优先级,值范围0~254,MASTER要比BACKUP高
 advert_int 1     # 组播信息发送时间间隔,两个节点必须设置一样,默认为1秒
 nopreempt
 # 设置验证信息,两个节点必须一致
 authentication {
  auth_type PASS
  auth_pass 1111
 }
 # 虚拟IP,两个节点设置必须一样。可以设置多个,一行写一个(随便写一个,只要没被占用就可以)
 virtual_ipaddress {
  10.69.53.200
 }
 
 track_script {
  chk_nginx # nginx存活状态检测脚本
 }
}

BACKUP(10.69.53.62)

global_defs {
 router_id nginx02 #标识本节点的名称,通常为hostname
}
 
# keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。
# 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加。如果脚本执行结果非0,
# 并且weight配置的值小于 0,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中priority对应的值。
vrrp_script chk_nginx {
  script "/usr/local/src/check_nginx_pid.sh" # 检测脚本路径
  interval 2 #每2秒检测一次nginx的运行状态
  weight -20 #失败一次,将自己的优先级-20
}
 
vrrp_instance VI_1 {
 state BACKUP    # 状态,主节点为MASTER,备份节点为BACKUP
 interface eth0    # 绑定VIP的网络接口,通过ifconfig查看自己的网络接口
 virtual_router_id 99   # 虚拟路由的ID号,两个节点设置必须一样,可选IP最后一段使用,相同的VRID为一个组,他将决定多播的MAC地址
 mcast_src_ip 10.69.53.62 # 本机IP地址
 priority 90      # 节点优先级,值范围0~254,MASTER要比BACKUP高
 advert_int 1     # 组播信息发送时间间隔,两个节点必须设置一样,默认为1秒
 nopreempt
 # 设置验证信息,两个节点必须一致
 authentication {
  auth_type PASS
  auth_pass 1111
 }
 # 虚拟IP,两个节点设置必须一样。可以设置多个,一行写一个(随便写一个,只要没被占用就可以)
 virtual_ipaddress {
  10.69.53.200
 }
 
 track_script {
  chk_nginx # nginx存活状态检测脚本
 }
}

非抢占模式两节点配置文件差异点

 router_id  		不同,均为本节点hostname
 interface 			本节点的网络接口,通过ifconfig查看
 mcast_src_ip   	不同,均为本节点的IP
 priority 			节点优先级,MASTER要大于BACKUP

与抢占模式配置文件的差异点

nopreempt 			在vrrp_instance块下都配置了,所以MASTER从故障中恢复后,不会抢占vip
state 				均为BACKUP
  1. 检测脚本创建
# 创建检测脚本
vim /usr/local/src/check_nginx_pid.sh

在Keepalived启动后,此脚本会检测nginx是否启动,并启动nginx;如果一段时间后nginx没有启动,则会kill掉Keepalived,进行VIP转移,请自行测试。

#!/bin/bash
#检测nginx是否启动了
A=`ps -C nginx --no-header |wc -l`        
if [ $A -eq 0 ];then    #如果nginx没有启动就启动nginx                        
      /usr/local/webserver/nginx/sbin/nginx    #启动nginx
      sleep 5		#注意一定要比nginx启动时间长,否则nginx还没起来,脚本就继续执行kill掉keepalived了
      if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then    #nginx重启失败,则停掉keepalived服务,进行VIP转移
              killall keepalived                    
      fi
fi
# 加执行权
chmod 775 check_nginx_pid.sh
  1. 相关命令
# 启动
/bin/systemctl start keepalived.service
# 停止
/bin/systemctl stop keepalived.service
# 状态查看
/bin/systemctl status keepalived.service
  1. 抢占模式验证

因为nginx01上的Keepalived为MASTER,所以我们反着来,先启动nginx02上的,看是否会根据优先级priority 的不同,通过选举抢占VIP

先启动nginx02上的Keepalived,再启动nginx01上的Keepalived
生产环境nginx+keepalived负载均衡及高可用方案
生产环境nginx+keepalived负载均衡及高可用方案

# 查看vip绑定情况
ip add

我们会发现VIP绑定在了61节点的网卡上
生产环境nginx+keepalived负载均衡及高可用方案
查看Keepalived状态

/bin/systemctl status keepalived.service

生产环境nginx+keepalived负载均衡及高可用方案
生产环境nginx+keepalived负载均衡及高可用方案
对比发现,nginx02节点的为BUCKUP状态。
此时我们执行停掉nginx01上的Keepalived,会发现服务切换到了nginx02上
生产环境nginx+keepalived负载均衡及高可用方案

生产环境nginx+keepalived负载均衡及高可用方案
当我们再次启动nginx01上的服务时,nginx01抢占回VIP,nginx02再次变成BACKUP状态
生产环境nginx+keepalived负载均衡及高可用方案
生产环境nginx+keepalived负载均衡及高可用方案

  1. 非抢占模式验证

先启动nginx02上的Keepalived,我们会发现,即使nginx的优先级低,及priority值小,依旧拥有VIP
生产环境nginx+keepalived负载均衡及高可用方案
生产环境nginx+keepalived负载均衡及高可用方案
当我们停止nginx02上的服务再重启后,会发现nginx02处于BACKUP状态,并没有抢占VIP
生产环境nginx+keepalived负载均衡及高可用方案

推荐使用非抢占模式,因为原MASTER从故障中恢复后,不会抢占vip,这样就避免vip切换可能造成的服务延迟。

  1. Keepalived高可用验证
    用浏览器访问vip,会发现时机访问到的是nginx01上的nginx
    生产环境nginx+keepalived负载均衡及高可用方案
    此时我们停掉nginx01上的keepalived,再次访问VIP,会发现实际访问的变成了nginx02
    生产环境nginx+keepalived负载均衡及高可用方案
    三、最终效果

    1. 访问VIP时(http://10.69.53.200:80/test/),依次返回nginx01和nginx02上程序的返回值
    2. 只kill掉nginx01上的服务,返回值为nginx02上的程序返回值
    3. 只kill掉nginx01上的nginx,nginx服务会自动启动(check_nginx_pid.sh脚本作用)
    4. 只kill掉nginx01上的Keepalived,VIP转移到nginx02上
上一篇:java中import、package作用和用法


下一篇:Android_适配器(adapter)之ArrayAdapter