Nginx负载均衡,反向代理,双机热备
方案想法
两台xmail放置企业内网环境,为确保数据信息安全,外网用户无法直接访问,因此,给外网用户一个单独的入口做反向代理,其实一台Nginx服务器即可,但如果xmail服务比较多,唯一的出口不幸挂了,会导致所有用户都无法访问,所以采用双机做负载均衡。至于内网的两台xmail,用一台也行,另外一台作为备份,若两台都要正常正常提供服务,则需要考虑数据库,存储等乱七八糟的同步问题,下一次分享就围绕各种同步复制,看如何解决这个问题。
一: 均衡负载和反向代理
环境准备,两台Xmail,两台初始干净的机器
xmail1:ip地址:192.168.67.128
xmail2:ip地址:192.168.67.129
nginx1:初始的centos系统 ip:192.168.67.133
nginx2:初始的centos系统 ip:192.168.67.134
(其实xmail2和xmail2装好后,本身有nginx服务,提供网页访问,但直接把两台xmail暴漏在公网,安全性则是问题,所以单独搞两台服务器放前端,做个防护)
以下所有配置,全部都是针对前端的两台nginx,两台xmail机器暂时不动
两台Nginx主机均要下载Nginx依赖,Nginx,以及安装Nginx。两台Nginx主机可以同时操作。
Nginx官网地址:nginx.org
提前下好了,分别传到两台主机下,或者通过wget下载都可以。
机器系统安装好了以后,改个名字,便于后期的维护和管理。更改hosts或者直接使用hostnamectl命令都可以。
[root@nginx1 ~]# yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel [root@nginx1 ~]# yum install wget [root@nginx1 ~]# wget http://nginx.org/download/nginx-1.20.1.tar.gz
下载完成后,解压nginx,此处演示环境下的软件下载好,默认就在/root目录下
[root@nginx1 ~]# ll 总用量 1044 -rw-------. 1 root root 1253 5月 10 15:54 anaconda-ks.cfg -rw-r--r--. 1 root root 1061461 5月 25 2021 nginx-1.20.1.tar.gz [root@nginx1 ~]# pwd /root [root@nginx1 ~]# tar -zxvf nginx-1.20.1.tar.gz [root@nginx1 ~]# cd nginx-1.20.1 [root@nginx1 nginx-1.20.1]# #执行nginx启动配置,放到/usr/local/nginx目录下面 [root@nginx1 nginx-1.20.1]# ./configure --prefix=/usr/local/nginx #然后执行编译 [root@nginx1 nginx-1.20.1]# make #编译好后,安装nginx [root@nginx1 nginx-1.20.1]# make install
2.编辑nginx配置文件
路径:/usr/local/nginx/conf
进入该目录下,或者直接vi 也行,只是,更改配置文件前,先备份。
[root@nginx1 conf]# cd /usr/local/nginx/conf [root@nginx1 conf]# cp nginx.conf nginx.conf.bak [root@nginx1 conf]# vi nginx.conf
35行开始,进行相应的修改。
先在35行上面,插入:
upstream mail.xmail.com { server 192.168.67.128:80 weight=5; server 192.168.67.129:80 weight=1; }
说明:在vi/vim命令模式下,输入冒号,可进入末行模式,输入set nu 回车,即可看到行号。
环境下默认只有vi编辑命令,想用vim的话,yum自行安装即可。
upstream是均衡负载的用法,mail.xmail.com是自定义名称,可以改成域名,或者自己取个名字。
两个ip,128是xmail1,129是xmail2,其中weight=5代表权重,意思是6次的访问里面,xmail5被访问5次,xmail2被访问1次,也可以设置一样,或者不设置,就是平均分配,雨露均沾,但如果两台机器的配置不同,xmail1性能更好一些,xmail2弱一些,就需要根据情况来考虑权重的分配了。
接下来在47行,找到location的位置,
添加:proxy_pass http://mail.xmail.com;表示引用上面upstream配置的反向代理地址,如果前面自定义是:abc,此处就写abc。
两台机器都来一次。然后就可以启动nginx了.
[root@nginx1 conf]# cd /usr/local/nginx/sbin [root@nginx1 sbin]# ./nginx
关闭nginx的防火墙,或者在防火墙上放开80端口都可以,为测试方便,直接粗暴了关闭了防火墙。
systemctl stop firewalld #关闭防火墙 systemctl disable firewalld #永久关闭防火墙
如果是生产环境下或者客户环境下,是不可能关闭防火墙的。那就使用命令开启指定端口。
firewall-cmd --zone=public --add-port=80/tcp --permanent
其中permanent代表永久生效
然后再次输入:
firewall-cmd --reload
重新载入防火墙配置即可生效。
--add是添加,--remove是移除
然后本机hosts添加上我们定义的mail.xmail.com对应的nginx服务器的ip地址,(注意:不是xmail的ip,然后测试验证下)
或者直接访问nginx服务器的ip:192.168.67.133或者134,如果可以正常邮箱的登录页,说明配置已完成。
不仅仅是web,smtp,pop,imap的问题,都可以通过nginx来配置,改下端口就好了。例如再添加一个smtp 和imap
upstream mail.xmail.com { server 192.168.67.128:25 weight=1; server 192.168.67.129:25 weight=1; } upstream mail.xmail.com { server 192.168.67.128:143 weight=1; server 192.168.67.129:143 weight=1; }
负载均衡和反向代理完成。
二: 双机热备
接下来难度稍微高一点点
万一nginx1挂了,用户访问是随机的,咋整?
双机热备,是说nginx的热备,一主一从,nginx1为主机-Master,nginx2为备机-Backup,nginx2监控nginx1,当发现nginx1不行了,nginx2马上接替nginx1的位置.
此处用到的软件:
Keepalived (双机热备的关键服务)
既然要到这玩意儿,就总得简单了解下它的工作流程。
简述keepalived工作原理
1).Keepalived 定义
Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。Keepalived是VRRP的完美实现,因此在介绍keepalived之前,先介绍一下VRRP的原理。
2).VRRP 协议简介
在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接。对于这样的情况,它们之间路由怎样选择?主机如何选定到达目的主机的下一跳路由,这个问题通常的解决方法有二种:
-
在主机上使用动态路由协议(RIP、OSPF等)
-
在主机上配置静态路由
很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。
配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。
VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过--竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。
3).VRRP 工作机制
在一个VRRP虚拟路由器中,有多台物理的VRRP路由器,但是这多台的物理的机器并不能同时工作,而是由一台称为MASTER的负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP让每个VRRP路由器参与竞选,最终获胜的就是MASTER。MASTER拥有一些特权,比如,拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求。 VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(multicast)包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个周知的MAC地址。所以,在一个虚拟路由 器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对客户端来说,这种主从的切换是透明的。 在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息(VRRPAdvertisement message),BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BACKUP收不到通告信息), 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性。由于安全性考虑,VRRP包使用了加密协议进行加密。
4).VRRP 工作流程
(a).初始化:
路由器启动时,如果路由器的优先级是255(最高优先级,路由器拥有路由器地址),要发送VRRP通告信息,并发送广播ARP信息通告路由器IP地址对应的MAC地址为路由虚拟MAC,设置通告信息定时器准备定时发送VRRP通告信息,转为MASTER状态;否则进入BACKUP状态,设置定时器检查定时检查是否收到MASTER的通告信息。
(b).Master
-
设置定时通告定时器;
-
用VRRP虚拟MAC地址响应路由器IP地址的ARP请求;
-
转发目的MAC是VRRP虚拟MAC的数据包;
-
如果是虚拟路由器IP的拥有者,将接受目的地址是虚拟路由器IP的数据包,否则丢弃;
-
当收到shutdown的事件时删除定时通告定时器,发送优先权级为0的通告包,转初始化状态;
-
如果定时通告定时器超时时,发送VRRP通告信息;
-
收到VRRP通告信息时,如果优先权为0,发送VRRP通告信息;否则判断数据的优先级是否高于本机,或相等而且实际IP地址大于本地实际IP,设置定时通告定时器,复位主机超时定时器,转BACKUP状态;否则的话,丢弃该通告包;
(c).Backup
-
设置主机超时定时器;
-
不能响应针对虚拟路由器IP的ARP请求信息;
-
丢弃所有目的MAC地址是虚拟路由器MAC地址的数据包;
-
不接受目的是虚拟路由器IP的所有数据包;
-
当收到shutdown的事件时删除主机超时定时器,转初始化状态;
-
主机超时定时器超时的时候,发送VRRP通告信息,广播ARP地址信息,转MASTER状态;
-
收到VRRP通告信息时,如果优先权为0,表示进入MASTER选举;否则判断数据的优先级是否高于本机,如果高的话承认MASTER有效,复位主机超时定时器;否则的话,丢弃该通告包;
5).ARP查询处理
当内部主机通过ARP查询虚拟路由器IP地址对应的MAC地址时,MASTER路由器回复的MAC地址为虚拟的VRRP的MAC地址,而不是实际网卡的 MAC地址,这样在路由器切换时让内网机器觉察不到;而在路由器重新启动时,不能主动发送本机网卡的实际MAC地址。如果虚拟路由器开启的ARP代理 (proxy_arp)功能,代理的ARP回应也回应VRRP虚拟MAC地址。
大概了解keepalived的流程后,就开始实操了。
Keepalive的安装和配置
1.nginx1和nginx2分别都安装keepalived这个软件
[root@nginx1 sbin]# yum install -y keepalived
安装后的路径:/etc/keepalived
[root@nginx1 sbin]# cd /etc/keepalived
2.修改配置文件(先备份,习惯要养成)
[root@nginx1 keepalived]# cp keepalived.conf keepalived.conf.bak [root@nginx1 keepalived]# vi keepalived.conf
看下默认配置,19-34行
说明:state Master #主机地址,目前改的是nginx1,这里不动。
interface eth0 #网卡地址,这里可能要改,检查下机器网卡信息,我这里的网卡名为ens33,因此,要改成对应主机的网卡名。
virtual_route_id 51 #虚拟路由的id号,不用动
priority 100 #优先级,主优先级要大于备优先级,那这里默认的是主,优先级100,不动了,把备的优先级改小于100就行
authentication #认证信息,不用动.
virtual_ipaddress #虚拟ip地址,默认给了3个,建议修改为同一个网段的,否则会出现各种奇葩问题,别问我为啥知道..
改完后,保存退出
然后再改nginx2的。
把state Master 改成:state Slave, interface eth0修改成对应的网卡名,如果是虚拟机,多半都是ens33。然后是priority 100,把优先级改成99
重启两台机器的keepalived服务,并加入开机自启
[root@nginx2 keepalived]# systemctl restart keepalived [root@nginx2 keepalived]# systemctl enable keepalived [root@nginx1 keepalived]# systemctl restart keepalived [root@nginx1 keepalived]# systemctl enable keepalived
重新再检查下nginx1的ip地址,发现虚拟ip已经添加进来了。
(如果检查没有新增加的这个虚拟ip,说明上面的操作有问题,检查配置,主要是几个特别注明的地方,主机备机的名字要区分开,网卡名要正确。优先级不能错,虚拟ip地址要统一)
主备配置完成了,接下来是最重要的一环,监测!
本来想法是nginx2监测nginx1,翻了不少资料,没找到。
所以,换了思路,nginx1主机自己监测自己。
在nginx1上写一个脚本,就放到keepalived目录下面
#!/bin/bash A=`ps -C nginx --no-header |wc -l` if [ $A -eq 0 ];then systemctl kill keepalived fi
说明:这个脚本的意思是赋值A,A的工作是检查自己的nginx还活着没,如果nginx服务挂了,就杀掉keepalived的进程,然后这台机器的keepalived就会自动回收那个虚拟ip,此时,虚拟ip自动给nginx2使用。
脚本应该能优化,就是keepalived发现Nginx的服务挂了,应该先重启nginx,如果nginx恢复了,就啥都不用动,直接退出。如果nginx启动失败,那需要修改keepalived的配置信息,把master改为backup,同时要优先级改低,可以加个weight-2之类的,大概意思是权重100-2,变成98,同时还要修改nginx2的配置,把backup提升为master。
脚本比较复杂了,找开发去写,思路应该就是这个。我只是测试验证下万一Nginx1挂了,那个虚拟ip能切换到Nginx2上就行。
测试也粗暴,直接停掉nginx的服务测试就行了。vip(virtual ip)能飘到nginx2上面,就算完成任务。好多人管这叫vip飘移
回归正题:
[root@nginx1 keepalived]# pwd /etc/keepalived [root@nginx1 keepalived]# vi check_ngnix.sh [root@nginx1 keepalived]# cat check_nginx.sh #!/bin/bash A=`ps -C nginx --no-header |wc -l` if [ $A -eq 0 ];then systemctl kill keepalived fi
这个check_nginx.sh就把上面的脚本直接搬过来了,然后赋予执行权限。
[root@nginx1 keepalived]# chmod 711 check_nginx.sh
711啥意思?谁能解释下
read/write/execute
接下来,脚本写好了,可以做个定时任务,资料说keeplived里面可以配置脚本策略,并调用脚本,符合由keepalived去监控nginx这一说法。所以,不设置定时任务了,咱配置到keeplived里面去
[root@nginx1 keepalived]# vi keepalived.conf
把写好的脚本,做个策略,插入到keepalived.conf里面去 (此处留意下,只是有策略不够,别忘了还要脚本去执行这个策略)
内容:
vrrp_script check_nginx { #配置脚本策略 script "/etc/keepalived/check_nginx.sh" #执行对应目录的脚本文件 interval 1 #时间间隔定义为1秒 }
然后再找到之前配置虚拟ip的位置,设置一个执行这个策略的调用。
track_script { check_nginx }
配置完成后,重启,nginx2也做相同的策略,毕竟nginx2也配置这个虚拟ip呢,只是所有请求都会到nginx1,因为它优先级高,所以两台机器同时开启着keepalive服务的时候,vip只绑定到master上面,backup只有自己的ip,当master挂了,vip会自动收回,飘移到了backup身上.
最后就是测试验证阶段了。修改本机hosts,把定义的vip192.168.67.10绑定到mail.xmail.com上面,或者直接访问67.10测试也行。
回头wm页面自定义的时候,加个标识,比如xmail1的页面,加个ip128,xmail2页面加上个129,就能确认均衡负载以及热备的问题了。
直接访问vip地址:192.168.67.10测试验证:
接下来把nginx1的nginx服务,或者keepalived服务关了,都行,keepalived是监控nginx服务,vip是keepalived提供的,所以不论关那个,理论上都会由nginx2的keepliaved接管.
接下来,停止nginx1的nginx服务测试验证效果。