目标:
- 利用Nginx实现负载均衡及应用高可用
- 利用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安装
- 安装编译工具
yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
- 安装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
- 安装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
- 修改配置文件/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;
}
}
}
- 检查nginx.conf正确性
/usr/local/webserver/nginx/sbin/nginx -t
- 修改/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>
- 启动nginx
# nginx启动命令
/usr/local/webserver/nginx/sbin/nginx
启动成功
- 从浏览器访问占点ip
同样,在62节点上安装Nginx
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
- 负载均衡及服务高可用测试
创建两个返回值不同的springboot程序,分别在nginx01和nginx02上启动,端口与nginx.conf配置的一致,为8888
nginx01
nginx02
连续访问nginx01:80/test/两次会发现(根据配置文件,对80端口的/test请求被轮训路由到了nginx01:8888和nginx02:8888上),两次的返回值不一致
当我们kill掉nginx01上的服务,多次请求结果,与nginx02上的程序返回值一致
二、Keepalived安装
Keepalived的HA分 抢占模式 和 非抢占模式。
抢占模式 即MASTER从故障中恢复过来以后,会将VIP从BACKUP手中抢占过来。
非抢占模式 即MASTER从故障中恢复过来以后,不会抢占升级为MASTER的BACKUP的VIP。
- 利用yum安装Keepalived
yum -y install keepalived
- 修改配置文件/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
- 检测脚本创建
# 创建检测脚本
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
- 相关命令
# 启动
/bin/systemctl start keepalived.service
# 停止
/bin/systemctl stop keepalived.service
# 状态查看
/bin/systemctl status keepalived.service
- 抢占模式验证
因为nginx01上的Keepalived为MASTER,所以我们反着来,先启动nginx02上的,看是否会根据优先级priority 的不同,通过选举抢占VIP
先启动nginx02上的Keepalived,再启动nginx01上的Keepalived
# 查看vip绑定情况
ip add
我们会发现VIP绑定在了61节点的网卡上
查看Keepalived状态
/bin/systemctl status keepalived.service
对比发现,nginx02节点的为BUCKUP状态。
此时我们执行停掉nginx01上的Keepalived,会发现服务切换到了nginx02上
当我们再次启动nginx01上的服务时,nginx01抢占回VIP,nginx02再次变成BACKUP状态
- 非抢占模式验证
先启动nginx02上的Keepalived,我们会发现,即使nginx的优先级低,及priority值小,依旧拥有VIP
当我们停止nginx02上的服务再重启后,会发现nginx02处于BACKUP状态,并没有抢占VIP
推荐使用非抢占模式,因为原MASTER从故障中恢复后,不会抢占vip,这样就避免vip切换可能造成的服务延迟。
-
Keepalived高可用验证
用浏览器访问vip,会发现时机访问到的是nginx01上的nginx
此时我们停掉nginx01上的keepalived,再次访问VIP,会发现实际访问的变成了nginx02
三、最终效果- 访问VIP时(http://10.69.53.200:80/test/),依次返回nginx01和nginx02上程序的返回值
- 只kill掉nginx01上的服务,返回值为nginx02上的程序返回值
- 只kill掉nginx01上的nginx,nginx服务会自动启动(check_nginx_pid.sh脚本作用)
- 只kill掉nginx01上的Keepalived,VIP转移到nginx02上