天天看点

实践:在CentOS7.3部署 keepalived 高可用nginx(负载均衡)

背景:

既然有了Lvs+keepalived这样高性能的组合,那为何还要有Nginx+keepalived呢,keepalived的初衷就是为了Lvs而设计的,我们都知道Lvs是一个四层的负载均衡设备,虽然有着高性能的优势,但同时它却没有后端服务器的健康检查机制,keepalived为lvs设计了一系列的健康检查机制TCP_CHECK,UDP_CHECK,HTTP_GET等。同时lvs也可以自己写健康检查脚脚本。或者结合ldirectory来实现后端检测。但是固LVS始终无法摆脱它是一个四层设备,无法对上层协议进行解析。Nginx不一样,Nginx是一个七层的设备可以对七层协议进行解析,可以对一些请求进行过滤,还可以对请求结果进行缓存。这些都是Nginx独有的优势。但是keepalived并没有为Nginx提供健康检测。需要自己去写一些脚步来进行健康检测。关于keepalived+lvs的构建可参考我的另一篇博文:

<a href="http://ljohn.blog.51cto.com/11932290/1980547" target="_blank">http://ljohn.blog.51cto.com/11932290/1980547</a>

更新:2017.11.28

笔者写了一个Ansible-role 一键部署《keppalived+nginx 高可用集群》

<a href="https://github.com/Ljohn001/Ansible-roles/tree/master/Ansible-keepalived-nginx-role">https://github.com/Ljohn001/Ansible-roles/tree/master/Ansible-keepalived-nginx-role</a>

CentOS6.9,CentOS7.4 经过反复测试没毛病。正真实现一件就搞定,都准备放弃脚本投奔Ansible了。

废话不多说开始构建 keppalived+nginx 高可用集群

1、首先还是要准备环境

四台机器(CentOS7.3)

192.168.0.56 ---&gt; proxy1 (nginx)

192.168.0.57 ---&gt; proxy2 (nginx)

192.168.0.58 ---&gt; web1 (httpd)

192.168.0.59 ---&gt; web1 (httpd)

拓扑

<a href="https://s5.51cto.com/oss/201711/13/b99635652a623d2b48bcb4da7f1fe025.jpg" target="_blank"> </a>

注:

<code>1、这里需要保持4台机器时间同步</code>

<code># ntpdate IP(ntp时钟服务器自行搭建不多介绍)</code>

<code>*</code><code>/5</code> <code>* * * * root </code><code>/usr/sbin/ntpdate</code> <code>192.168.1.99 &amp;&gt;</code><code>/dev/null</code><code>;hwclock -w</code>

<code>2、为了操作的方便后面配置对所有参与机器进行免密处理</code>

<code># ssh-keygen -t rsa -P '' -f "/root/.ssh/id_rsa"</code>

<code># for i in 56 57 58 59;do ssh-copy-id -i .ssh/id_rsa.pub [email protected].$i;done</code>

2、配置realserver(web1和web2)

a、安装web程序

注意这里的realserver 可以是任何web容器(tomcat、jetty、httpd、nginx..),因为是学习,所以这里使用httpd来演示

<code>#yum install httpd -y</code>

<code>#systemctl restart httpd</code>

<code># netstat -nultp| grep httpd##确保httpd启动</code>

<code>tcp6       0      0 :::80                   :::*                    LISTEN      4619</code><code>/httpd</code>

<code>配置页面</code>

<code>web1:</code>

<code># echo "&lt;h1&gt;The page from web1(58)&lt;/h1&gt;" &gt; /var/www/html/index.html</code>

<code>web2:</code>

<code># echo "&lt;h1&gt;The page from web1(59)&lt;/h1&gt;" &gt; /var/www/html/index.html</code>

b、设置VIP及内核参数

<code>#编写脚本如下:</code>

<code># cat setka.sh</code>

<code>#!/bin/bash</code>

<code>vip=192.168.0.100</code>

<code>case</code> <code>$1 </code><code>in</code>

<code>start)</code>

<code>echo</code> <code>1 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>echo</code> <code>1 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code>

<code>echo</code> <code>2 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>echo</code> <code>2 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>

<code>ifconfig</code> <code>lo:0 $vip broadcast $vip netmask 255.255.255.255 up</code>

<code>;;</code>

<code>stop)</code>

<code>ifconfig</code> <code>lo:0 down</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>echo</code> <code>0 &gt; </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>

<code>esac</code>

<code># bash setka.sh start   #运行该脚本设置相关内核参数及VIP地址。</code>

<code># cat /proc/sys/net/ipv4/conf/lo/arp_ignore   #内核参数设置成功</code>

<code>1</code>

<code># cat /proc/sys/net/ipv4/conf/all/arp_announce</code>

<code>2</code>

<code># ifconfig lo:0   #VIP设置成功</code>

<code>lo:0      Link encap:Local Loopback</code>

<code>inet addr:192.168.137.10  Mask:255.255.255.255</code>

<code>UP LOOPBACK RUNNING  MTU:65536  Metric:1</code>

<code># scp setka.sh [email protected]:/root  #拷贝一份给web2并执行</code>

<code>setka.sh                                                                                         100%  547     0.5KB</code><code>/s</code>   <code>00:00</code>

3、配置nginx proxy1和2 负载均衡

a、两台proxy都安装nginx

<code>yum </code><code>install</code> <code>-y nginx</code>

b、配置nginx proxy

<code>vim </code><code>/etc/nginx/nginx</code><code>.conf</code>

<code>upstream backserver {</code>

<code>server 192.168.0.58:80 weight=1 max_fails=3 fail_timeout=3s;</code>

<code>server 192.168.0.59:80 weight=2 max_fails=3 fail_timeout=3s;</code>

<code>}</code>

<code>server {</code>

<code>listen       80;</code>

<code>server_name  localhost;</code>

<code>location / {</code>

<code>root   html;</code>

<code>index  index.html index.htm;</code>

<code>proxy_pass http:</code><code>//backserver</code><code>;</code>

<code>proxy_set_header X-Real-IP $remote_addr;</code>

<code>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</code>

复制一份至另一台proxy(nginx)

<code># scp /etc/nginx/nginx.conf [email protected]:/etc/nginx/nginx.conf</code>

<code># systemctl restart nginx;ssh 192.168.0.57 ‘systemctl restart nginx’</code>

c、测试访问

<code># for i in {1..10};do curl http://192.168.0.56;done</code>

<code>&lt;h1&gt;The page from web1(58)&lt;</code><code>/h1</code><code>&gt;</code>

<code>&lt;h1&gt;The page from web1(59)&lt;</code><code>/h1</code><code>&gt;</code>

<code># for i in {1..10};do curl http://192.168.0.57;done</code>

#注:这里可以看出,每台proxy(nginx) 都完成了负载均衡配置,且实现了负载均衡调度。细心的同学发现后端real server 配置的权重1:2,调度大致请求调度返回也为1:2

4、配置keepalived 高可用nginx

a、每台proxy安装httpd 和keepalived

<code># yum install -y httpd keepalived</code>

每台proxy 配置Sorry页面,这里一旦后端服务器同时无法访问,会自动调用本地的httpd服务

<code># echo "&lt;h1&gt;Sorry,Under maintances(56).&lt;/h1&gt;" &gt;/var/www/html/index.html</code>

<code># echo "&lt;h1&gt;Sorry,Under maintances(57).&lt;/h1&gt;" &gt;/var/www/html/index.html</code>

<code># 编辑各个proxy 的 nginx.conf,添加在upstream下添加</code>

<code>server 127.0.0.1:8080 backup;</code>

<code>或者:</code><code># sed -i '/server 192.168.0.59:80 weight=2 max_fails=3 fail_timeout=3s;/a\server 127.0.0.1:8080 backup;' /etc/nginx/nginx.conf</code>

b、编辑配置文件

proxy1:

<code># cat /etc/keepalived/keepalived.conf</code>

<code>! Configuration File </code><code>for</code> <code>keepalived</code>

<code>global_defs {</code>

<code>notification_email {</code>

<code>root@localhost    </code><code>#定义邮箱报警的邮箱地址</code>

<code>notification_email_from root@localhost </code><code>#定义发送报警信息的地址</code>

<code>smtp_server 127.0.0.1 </code><code>#定义发送邮件的邮件服务器地址</code>

<code>smtp_connect_timeout 30 </code><code>#定义发送邮件的超时时间</code>

<code>router_id ha_nginx </code><code>#全局标识</code>

<code>vrrp_script chk_nginx {    </code><code>#定义检查nginx服务的脚本</code>

<code>script </code><code>"/etc/keepalived/chk_nginx.sh"</code>  <code>#脚本重启nginx,如果进程还是无法检测到,则强制停止keepalived</code>

<code>interval 2 </code><code>#检查的间隔时间</code>

<code>weight -2 </code><code>#检查失败的话权重减2</code>

<code>fall 2 </code><code>#检查失败2次才认为是真正的检查失败</code>

<code>vrrp_instance VI_1 {</code>

<code>state MASTER</code>

<code>interface ens33</code>

<code>virtual_router_id 51</code>

<code>priority 100  </code><code>#备用机器的keepalived的权重要小于这个权重,并且当nginx服务挂掉后100-2要小于备用机器的权重。</code>

<code>advert_int 1</code>

<code>smtp_alert </code><code>#比较重要 定义使用邮件发送,不然上面的邮件定义都是没有用的,使用了这个当状态发生改变就会发送邮件报警</code>

<code>authentication {</code>

<code>auth_type PASS</code>

<code>auth_pass 1111</code>

<code>track_script {    </code><code>#定义使用哪个脚本来检查。</code>

<code>chk_nginx</code>

<code>virtual_ipaddress {</code>

<code>192.168.0.100</code><code>/16</code> <code>dev ens33 label ens33:1</code>

##拷贝配置文件至proxy2

<code># scp /etc/keepalived/keepalived.conf [email protected]:/etc/keepalived/keepalived.conf</code>

proxy2:

修改keepalived.conf 如下两个参数:

state BACKUP

priority 99

#这里贴出我实验的配置

# cat /etc/keepalived/keepalived.conf

<code>script </code><code>"/etc/keepalived/chk_nginx.sh"</code> <code>#脚本重启nginx,如果进程还是无法检测到,则强制停止keepalived</code>

<code>state BACKUP</code>

<code>priority 99  </code><code>#备用机器的keepalived的权重要小于这个权重,并且当nginx服务挂掉后100-2要小于备用机器的权重。</code>

c、nginx检测脚本

#脚本先判断是否有nginx进程,然后如果没有,则会重启nginx,如果进程还是无法检测到,则强制停止keepalived,启用备用节点的作为master。

#该脚本可以有效防止HA脑裂,发现无发启动nginx尝试重启,不行再将keepalived关闭,彻底移除此节点。

<code>#cat /etc/keepalived/chk_nginx.sh</code>

<code>N=`</code><code>ps</code> <code>-C nginx --no-header|</code><code>wc</code> <code>-l`</code>

<code>if</code> <code>[ $N -</code><code>eq</code> <code>0 ];</code><code>then</code>

<code>systemctl restart keepalived</code>

<code>sleep</code> <code>1</code>

<code>if</code> <code>[ `</code><code>ps</code> <code>-C nginx --no-header|</code><code>wc</code> <code>-l` -</code><code>eq</code> <code>0 ];</code><code>then</code>

<code>systemctl stop keepalived</code>

<code>fi</code>

d、启动keepalived及nginx

<code># systemctl restart nginx;ssh 192.168.0.57 'systemctl restart nginx'</code>

<code># systemctl restart keepalived.service;ssh 192.168.0.57 'systemctl restart keepalived.service'</code>

5、测试

1、查看地址是否在proxy1上:

<code># ip a</code>

<code>1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN qlen 1</code>

<code>link</code><code>/loopback</code> <code>00:00:00:00:00:00 brd 00:00:00:00:00:00</code>

<code>inet 127.0.0.1</code><code>/8</code> <code>scope host lo</code>

<code>valid_lft forever preferred_lft forever</code>

<code>inet6 ::1</code><code>/128</code> <code>scope host</code>

<code>2: ens33: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000</code>

<code>link</code><code>/ether</code> <code>00:0c:29:d6:84:65 brd ff:ff:ff:ff:ff:ff</code>

<code> </code><code>inet 192.168.0.56</code><code>/24</code> <code>brd 192.168.0.255 scope global ens33</code>

<code>  </code><code>inet 192.168.0.100</code><code>/16</code> <code>scope global ens33:1</code>

<code>inet6 fe80::20c:29ff:fed6:8465</code><code>/64</code> <code>scope link</code>

测试网页是否能够打开。

<code># for i in {1..5};do curl http://192.168.0.100;done</code>

这里能够正常访问,测试通过。

2、关闭主节点的keepalived测试VIP是否能够漂移至备用节点

<code>[root@node2 keepalived]</code><code># ip a</code>

<code>link</code><code>/ether</code> <code>00:0c:29:7c:92:ae brd ff:ff:ff:ff:ff:ff</code>

<code>   </code><code>inet 192.168.0.57</code><code>/24</code> <code>brd 192.168.0.255 scope global ens33</code>

<code> </code><code>inet 192.168.0.100</code><code>/16</code> <code>scope global ens33:1</code>

<code>inet6 fe80::20c:29ff:fe7c:92ae</code><code>/64</code> <code>scope link</code>

查看VIP是否能正常访问

5、由于我们配置的抢占模式,一旦主节点恢复,则VIP会直接漂回去。

<code>[root@node1 ~]</code><code># systemctl  start  keepalived</code>

<code>[root@node1 ~]</code><code># ip a</code>

<code>inet 192.168.0.56</code><code>/24</code> <code>brd 192.168.0.255 scope global ens33</code>

测试VIP访问

VIP地址又被主节点抢回来,服务正常访问,通过测试

最后我们来看下一下备用节点的在主节点keepalived关闭时,系统到底做了什么

##查看日志,观察VIP漂移的整个过程

1、传递MASTER的状态

2、设置自己为MASTER状态,

3、设置VIP 虚拟地址

4、发送ARP广播地址 ,地址为:192.168.0.100 #告诉大家我现在叫MASTER,对外提供服务了。

备用节点上/var/log/messages:

Nov 13 16:46:02 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) Transition to MASTER STATE

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) Entering MASTER STATE

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) setting protocol VIPs.

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: Sending gratuitous ARP on ens33 for 192.168.0.100

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.0.100

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: Sending gratuitous ARP on ens33 for 192.168.0.100

Nov 13 16:46:03 localhost Keepalived_vrrp[12348]: Remote SMTP server [127.0.0.1]:25 connected.

FAQ:

Q:再/var/log/messages日志中发现:Unable to access script `killall`

A:因为centos7精简安装,没有killall命令,需要安装一下

# yum install psmisc -y

至此在CentOS7.3上完成了:keepalived 高可用nginx,有兴趣的同学可以玩一下,有什么问题,还请批评指正。

本文转自 ljohnmail 51CTO博客,原文链接:http://blog.51cto.com/ljohn/1981369,如需转载请自行联系原作者

继续阅读