现在很多多个服务器容灾的解决方案是用的nginx+keepalived,nginx用来反向代理以及负载均衡,keepalived用来监测nginx服务状态,一旦有nginx服务宕机,另一台服务器会自动接管请求,达到服务的高可用目的。
keepalived简单介绍:
keepalived基于VRRP协议(Virtual Router Redundancy Protocol)(虚拟路由冗余协议),VRRP协议的出现就是为了解决单点故障。
keepalived由三个模块组成,vrrp、core和check,其中vrrp用来实现VRRP协议,core是核心模块,负责加载配置文件、启动进程等操作,check负责健康检查,监测是否有宕机行为发生。
keepalived基本工作原理:keepalived为主备部署,一个master多个backup,当keepalived工作时,会不断向backup发送消息,告诉备份机自己还活着,一旦master挂掉了,backup就收不到心跳消息,此时backup会认为master已经挂了,会按优先级高的选举成为新的master,承担报文的转发功能。
接下来开始搞事!
[root@lgs2 keepalived-2.0.20]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
可以看到安装包已经下载到目录下了:
2. 解压安装包
[root@lgs2 nginx]# tar -zxvf nginx-1.16.1
#安装依赖包
[root@lgs2 nginx-1.16.1]# yum -y install gcc pcre-devel zlib-devel openssl openssl-devel
#执行nginx配置
[root@lgs2 nginx-1.16.1]# ./configure --prefix=/usr/software.nginx
–prefix参数指定nginx安装目录,不加的话就是默认路径:/usr/local/nginx
再make && make install
[root@lgs2 nginx-1.16.1]# make
[root@lgs2 nginx-1.16.1]# make install
此时在nginx安装目录下可以看到生成了一些文件:
…我这是启动之后的,多了一些_temp文件,刚安装好的没有这些_temp结尾的文件夹。
4. 启动nginx
进入到安装目录的/sbin下,执行./nginx启动
./nginx #启动
./nginx -s stop #停止
[root@lgs2 nginx-1.16.1]# ./nginx
[root@lgs sbin]# curl localhost
出现以下则启动成功:
也可以在浏览器输入ip检查是否启动成功,但是这就要服务器开启80端口防火墙:
#检查80端口防火墙是否开启
[root@lgs sbin]# firewall-cmd --query-port=80/tcp
出现no则没开启,以下命令开启防火墙并刷新防火墙状态
[root@lgs sbin]# firewall-cmd --zone=public --add-port=80/tcp --permanent
[root@lgs sbin]# firewall-cmd --reload
keepalived和nginx安装步骤差不多,首先进入官网下载:https://www.keepalived.org/download.html
自己选择合适的版本,我是选择当前最新的2.0.20
然后和nginx一样:
tar -zxvf keepalived-2.0.20.tar.gz
yum install -y libnl libnl-devel
yum install -y libnfnetlink-devel
configure --prefix=/usr/software/keepalived
make && make install
[guansheng@lgs keepalived-2.0.20]$ cp /usr/software/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf
[guansheng@lgs keepalived-2.0.20]$ ln -s /usr/software/keepalived/sbin/keepalived /usr/sbin/
#以下文件在源码包,也就是下载解压后的目录
cd /home/guans/documents/keepalived #我的安装包下载位置
[guansheng@lgs keepalived-2.0.20]$ cp keepalived/keepalived.service /etc/systemd/system
[guansheng@lgs keepalived-2.0.20]$ sudo cp keepalived/etc/init.d/keepalived /etc/init.d/
配置服务之前,先说一下准备配置的架构。
首先我这里有三台虚拟机,192.168.252.128,192.168.252.129,192.168.252.130,前面两台配置稍微高一些,我准备将128这台当做nginx主机,129这台当做nginx备份机,130单纯只部署项目服务,128、129各部署一个相同的项目服务,具体架构图如下:
这图实在有点丑,像我这种提起笔来,连个小鸡啄米图都画不出来的人,也就这么个画图水平了,还是稍微解释一下吧。
nginx的主备通过配置keepalived实现,128为主机,129为备份机,前端请求通过虚拟ip进来,keepalived判断主机是哪个,然后主机上的nginx负责反向代理和负载均衡,以默认轮询的方式请求128,129,130三台服务器上部署的springboot服务,springboot服务简单输出hello+ip来判断此刻是请求的哪台服务器。
在nginx安装目录/conf/nginx.conf文件中配置,如何配置可以参考这篇文章,很详细:Nginx的配置文件详解(超详细)
我的配置如下:
128主机:
#user nobody;
user root; #指定Nginx Worker进程运行用户以及用户组,默认由nobody账号运行
worker_processes 2; #指定了Nginx要开启的进程数。每个Nginx进程平均耗费10M~12M内存。建议指定和CPU的数量一致即可
#error_log logs/error.log; #用来定义全局错误日志文件。日志输出级别有debug、info、notice、warn、error、crit可供选择,其中,debug输出日志最为最详细,而crit输出日志最少
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid; #用来指定进程pid的存储文件位置
#worker_rlimit_nofile=65535; #worker_rlimit_nofile用于绑定worker进程和CPU, Linux内核2.4以上可用
#events事件指令是设定Nginx的工作模式及连接数上限
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#gzip on;
#负载均衡配置
upstream cycle.com{
#Weight:指定轮询权值,Weight值越大,分配到的访问机率越高
#方式:默认轮询,ip_hash:每个请求按访问IP的hash结果分配
#fair:比上面两个更加智能的负载均衡算法
#ip_hash; #方式:默认轮询
server 192.168.252.128:8081;
server 192.168.252.129:8081;
server 192.168.252.130:8081;
}
server {
listen 80;
server_name 192.168.252.128;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://cycle.com; #适用前面配置的负载均衡策略
}
#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;
}
}
129备份机:
user root;
worker_processes 2;
#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 cycle.com{
server 192.168.252.128:8081;
server 192.168.252.129:8081;
server 192.168.252.130:8081;
}
server {
listen 80;
server_name 192.168.252.129;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://cycle.com;
}
}
下面可以测试一下nginx负载均衡是否生效,启动三台机器身上的springboot项目,连接128的nginx来访问项目,分别点击三次,看是否是轮询来访问三台服务器:
可以看到确实已经负载均衡生效了,129服务器的nginx也测试过,一样的效果,到此nginx配置完毕,接下来配置keepalived。
配置文件本身的位置是在安装目录下的etc/keepalived/keepalived.conf,但是按安装完成的时候已经移动到/etc/keepalived/keepalived.conf了,所以修改/etc/keepalived/keepalived.conf就可以了。
先查看一下ip对应的网卡,绑定虚拟ip的时候需要:
ifconfig
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_128 # 路由id,在一个局域网内要唯一
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
#健康检测脚本,必须声明在vrrp_instance节点前
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" ## 检测 nginx 状态的脚本路径
interval 3 # 检测时间间隔,应该要大于脚本中的sleep时间
weight -20 # 如果条件成立,权重-20
}
#vrrp实例设置
vrrp_instance VI_1 {
state MASTER #MASTER为主机
interface ens33 #虚拟ip绑定的网卡
virtual_router_id 51 #虚拟路由ID标识,一组的keepalived配置中主备都是设置一致
priority 100 #优先级,主机应高于备份机即可
advert_int 1
authentication {
auth_type PASS #认证方式
auth_pass 123456 #认证密码
}
virtual_ipaddress {
192.168.252.131 #虚拟ip
}
track_script {
chk_nginx ## 执行 Nginx 监控的服务
}
}
检测脚本代码:
这段脚本的意思是:检测到nginx已停止,就启动nginx服务,如果没启动起来,就把keepalived停止。
记得#! /bin/bash这句开头必须定义,不然会出现:Error exec-ing command ‘/etc/keepalived/nginx_check.sh’, error 8: Exec format error的错误
#! /bin/bash
count=$(ps -C nginx --no-heading | wc -l)
if [ "$count" = "0" ]; then
#/usr/software/nginx/sbin/nginx #这里是启动nginx,为了方便后面的测试,先不写启动的功能,测试完了再解除注释
sleep 2
count=$(ps -C nginx --no-heading | wc -l)
if [ "${count}" = "0" ]; then
pkill keepalived
fi
fi
脚本写完之后,要保证其为可执行文件,如果不是,那就加权限:
#修改脚本文件为可执行
[root@lgs2 keepalived]# chmod +x nginx_check.sh
启动keepalived服务:service keepalived start(前面那几次copy已经将keepalived注册成系统服务了)
service keepalived start
可以查看日志文件,日志文件路径:/var/log/messages
查看虚拟Ip是否已经绑定:
ip addr
可以看到虚拟ip已经绑定到对应网卡上了:
接下来配置备份机的keepalived:
配置文件:
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_129
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" ## 检测 nginx 状态的脚本路径
interval 3 ## 检测时间间隔
weight -20 ## 如果条件成立,权重-20
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.252.131
}
track_script {
chk_nginx ## 执行 Nginx 监控的服务
}
}
备份机的健康检查脚本和主机一致
启动备份机的keepalived,不会生成虚拟ip,生成了那就是有问题,我确实出现了主备双机争抢vip(虚拟ip)的问题(脑裂现象),解决问题花了很久,我单独整理出来一篇文章:keepalived出现主备机同时绑定vip的解决方法
记录一下keepalived服务的启动和停止命令:
启动:service keepalived start 或 systemctl start keepalived.service
重启:service keepalived restart 或 systemctl restart keepalived.service
停止:service keepalived stop 或 systemctl stop keepalived.service
查看状态:systemctl status keepalived.service
将主机和备份机的keepalived和nginx都启动,三台服务器的项目都跑起来
1、先看一下主备机vip的绑定情况:
[guansheng@lgs keepalived]$ ip addr
2、通过虚拟ip访问项目:
可以访问,没有问题
3、停止主机的nginx,再通过虚拟ip访问(因为脚本已经暂时注释了重启nginx服务,所以停止nginx就模拟了nginx服务无法重启的情况)
[guansheng@lgs keepalived]$ /usr/software/nginx/sbin/nginx -s stop
再查看主机的vip绑定情况:
备份机vip绑定情况:
可以看到虚拟ip已经漂移到备份机了,此时备份机承担请求的转发任务。
再看主机的keepalived状态:
主机keepalived状态为死亡状态,由此可以看到:nginx结束了进程,主机健康检查检测到nginx已停止,所以关闭了keepalived,此时keepalived主机无法发送组播消息,备份机在规定时间未收到主机的组播消息,认为主机已挂,此时备份机接管主机的业务,虚拟ip漂移至备份机,以此保证服务的高可用。
4、 再次启动主机的keepalived和Nginx服务,模拟主机故障修复:
可以看到vip再次漂移到了主机上
备份机此时vip已解除绑定:
此时再访问项目,依然能访问:
由此可见,在整个过程中,主机与备份机的切换,都是keepalived自动进行的,而人工在这里仅仅只是修复了主机的故障而已,而且整个过程中,服务并没有停止。
到此,一个keepalived+nginx高可用部署方案就已经完成,其实keepalived+nginx还有其他的主备部署方案,那些方案更加节省服务器资源,只是作为初次接触者,我先试了最简单的一种而已!