nginx高可用集群方案
<h1>一、目的</h1>
<p>目前越来越多的线上环境都采用nginx做反向代理、负载均衡,为了避免因为负载均衡服务器的宕机从而影响整个系统运行的问题,需要建立一个备份机。主服务器和备份服务器上都运行监控程序,通过传送心跳信息来监控对方的运行状况。当备份服务器在一定的时间内没有收到主服务器的心跳信息时,它就自动接管主服务器的服务IP,继续提供负载均衡服务;当备份服务器又从主服务器收到心跳信息时,它就释放服务IP地址,这样的主服务器就开始再次提供负载均衡服务,由此引出该方案,负载均衡服务器主备冗余,实现高可用。</p>
<h1>二、高可用技术方案</h1>
<p>采用keepalived+NGINX实现主备、负载均衡</p>
<h1>三、keepalived工作原理</h1>
<p>Keepalived高可用服务对之间的故障切换转移,是通过VRRP来实现的。在keepalived服务工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用来告诉备Backup节点自己还活着。当主节点发生故障时,就无法发送心跳的消息了,备节点也因此无法继续检测到来自主节点的心跳了。于是就会调用自身的接管程序,接管主节点的IP资源和服务。当主节点恢复时,备节点又会释放主节点故障时自身接管的IP资源和服务,恢复到原来的备用角色。
<img src="http://60.191.64.5:16100/server/index.php?s=/api/attachment/visitFile/sign/b53dd404c69ad456a1a2310095e08ff8" alt="" /></p>
<h1>四、keepalived实现主备机冗余功能</h1>
<p>1.当nignx负载均衡服务器发生宕机时,keepalived通过主备机共用VIP,VIP对外提供访问,主机宕机了,备机会立即启动将VIP占用,接替主机的工作。
2、对后端的web服务器负载均衡(冗余)+健康监测
Keepalived的作用是检测服务器的状态,如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。</p>
<ul>
<li>服务器分配(可根据服务器数量自行分配)</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align: left;">服务器</th>
<th style="text-align: left;">IP</th>
<th style="text-align: left;">端口</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">VIP</td>
<td style="text-align: left;">192.168.5.198</td>
<td style="text-align: left;"></td>
</tr>
<tr>
<td style="text-align: left;">nginx主机:node1</td>
<td style="text-align: left;">192.168.5.160</td>
<td style="text-align: left;">7001</td>
</tr>
<tr>
<td style="text-align: left;">nginx备机:node2</td>
<td style="text-align: left;">192.168.5.162</td>
<td style="text-align: left;">7001</td>
</tr>
<tr>
<td style="text-align: left;">web01</td>
<td style="text-align: left;">192.168.5.160</td>
<td style="text-align: left;">8081</td>
</tr>
<tr>
<td style="text-align: left;">web02</td>
<td style="text-align: left;">192。168.5.162</td>
<td style="text-align: left;">8081</td>
</tr>
<tr>
<td style="text-align: left;">...</td>
<td style="text-align: left;">...</td>
<td style="text-align: left;">...</td>
</tr>
</tbody>
</table>
<h1>五、实现过程</h1>
<h2>安装keepalived</h2>
<p><strong>keepalived源码包下载地址</strong>:<a href="http://101.69.243.254:5010/share/MQhhdxSV">http://101.69.243.254:5010/share/MQhhdxSV</a></p>
<h4>1.新建keepalived安装目录:</h4>
<pre><code class="language-java">mkdir -p /risen/soft/keepalived</code></pre>
<h4>2.下载安装包至/risen/soft/package</h4>
<h4>3.检查依赖</h4>
<pre><code class="language-java">centos:yum install -y gcc libnl libnl-devel libnfnetlink-devel openssl-devel
ubantu、麒麟:apt-get install -y gcc libnl libnl-devel libnfnetlink-devel</code></pre>
<h4>4.源码解压编译安装</h4>
<pre><code class="language-java">tar -xvf /risen/soft/package/keepalived-2.2.4.tar.gz -C /risen/soft/package</code></pre>
<p><strong>切换目录:</strong></p>
<pre><code class="language-java">cd /risen/soft/package/keepalived-2.2.4
chmod +x ./configure &amp;&amp; ./configure --prefix=/risen/soft/keepalived &amp;&amp; make &amp;&amp; make install</code></pre>
<h4>5.开机自启</h4>
<pre><code class="language-java">cp /risen/soft/package/keepalived-2.2.4/keepalived/etc/init.d/keepalived /etc/init.d/</code></pre>
<p>需要提前在/etc下创建keepalived目录</p>
<pre><code class="language-java">cp /risen/soft/package/keepalived-2.2.4/keepalived/etc/init.d/keepalived /etc/init.d/
mkdir -p /etc/keepalived
cp /risen/soft/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
cp /risen/soft/keepalived/etc/sysconfig/keepalived /etc/sysconfig/</code></pre>
<pre><code class="language-java">启动
systemctl start keepalived.service
关闭
systemctl stop keepalived.service
重启
systemctl restart keepalived.service
开机自启
systemctl enbale keepalived.service</code></pre>
<h4>6.修改keepalivd配置文件(NODE1和NODE2)</h4>
<p>配置文件路径:/etc/keepalived/keepalived.conf。建议下载修改,修改完重新上传
node1配置文件参考:</p>
<pre><code class="language-java">! Configuration File for keepalived
global_defs {
router_id node1
vrrp_garp_interval 0
vrrp_gna_interval 0
}
#检测脚本
vrrp_script chk_http_port {
script &quot;/risen/sh/check_nginx_pid.sh&quot; #心跳执行的脚本,检测nginx是否启动
interval 2 #(检测脚本执行的间隔,单位是秒)
weight 2 #权重
}
vrrp_instance VI_1 {
state MASTER #指定keepalived的角色,MASTER为主,BACKUP为备
interface ens192 # 网卡名,用ifconfig查看你具体的网卡
virtual_router_id 66 # 虚拟路由编号,主从要一致
priority 100 # 优先级,数值越大,获取处理请求的优先级越高
advert_int 1 # 检查间隔,默认为1s(vrrp组播周期秒数)
authentication {
auth_type PASS #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
auth_pass 2222
}
track_script {
chk_http_port #(调用检测脚本)
}
virtual_ipaddress {
192.168.5.198 # 定义虚拟ip(VIP),可多设,每行一个
}
}
virtual_server 192.168.5.198 7001 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 60
protocol TCP
real_server 192.168.5.160 7001 {
weight 2
HTTP_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 192.168.5.162 7001 {
weight 2
HTTP_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}</code></pre>
<p>node2配置文件参考:</p>
<pre><code class="language-java">! 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 node2
#vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
#检测nginx心跳脚本
vrrp_script chk_http_port {
script &quot;/risen/sh/check_nginx_pid.sh&quot; #心跳执行的脚本,检测nginx是否启动
interval 2 #(检测脚本执行的间隔,单位是秒)
weight 2 #权重
}
vrrp_instance VI_1 {
state BACKUP #指定keepalived的角色,MASTER为主,BACKUP为备
interface ens192 # 网卡名,用ifconfig查看你具体的网卡
virtual_router_id 66 # 虚拟路由编号,主从要一致
priority 99 # 优先级,数值越大,获取处理请求的优先级越高
advert_int 1 # 检查间隔,默认为1s(vrrp组播周期秒数)
authentication {
auth_type PASS #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信
auth_pass 2222
}
track_script {
chk_http_port #(调用检测脚本)
}
virtual_ipaddress {
192.168.5.198 # 定义虚拟ip(VIP),可多设,每行一个
}
}
virtual_server 192.168.5.198 7001 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 60
protocol TCP
real_server 192.168.5.160 7001 {
weight 2
HTTP_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 192.168.5.162 7001 {
weight 2
HTTP_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}</code></pre>
<h4>7.检测脚本(NODE1和NODE2)</h4>
<p>创建nginx检测心跳脚本:</p>
<pre><code class="language-java">vim /risen/sh/check_nginx_pid.sh</code></pre>
<p>编辑以下内容:</p>
<pre><code class="language-java">#!/bin/bash
#检测nginx是否启动了
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then #如果nginx没有启动就启动nginx
/risen/soft/nginx/sbin/nginx #重启nginx
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then #nginx重启失败,则停掉keepalived服务,进行VIP转移
killall keepalived
fi
fi</code></pre>
<p>脚本授权:</p>
<pre><code class="language-java">chmod +x /risen/sh/check_nginx_pid.sh</code></pre>
<p>说明:脚本必须通过授权,不然没权限执行,VIP(virtual_ipaddress:192.168.5.198),我们在生产环境是直接通过vip来访问服务。</p>
<h4>8.安装nginx【NODE1和NODE2】(参考nginx安装手册)</h4>
<p>两台nginx主备机各负载两个web后端节点,搭建负载均衡集群(具体参考负载均衡策略)
六、模拟故障场景
1.修改两个服务器默认访问的Nginx的html页面作为区别。
2.首先访问192.168.5.198,通过vip进行访问,页面显示192.168.5.170;说明当前是主服务器提供的服务。
这个时候192.168.5.160主服务器执行命令
/risen/soft/nginx/sbin/nginx -s stop
<img src="http://60.191.64.5:16100/server/index.php?s=/api/attachment/visitFile/sign/67d7659d31185ed3bda8ba1ebd59352a" alt="" />
再次访问vip(192.168.5.198)发现这个时候页面显示的还是:192.168.5.160,这是脚本里面当检测到nginx停止,会自动重启nginx,只有当nginx重启失败,则停掉keepalived服务,进行VIP转移。
现在直接将192.168.5.160服务器关闭或者停掉keepalived服务,在此访问vip(192.168.5.198)现在发现页面显示192.168.5.162这个时候keepalived就自动故障转移了,一套企业级生产环境的高可用方案就搭建好了。</p>