企业级web负载均衡高可用之nginx+Keepalived

一般为了维护方便,企业网站的服务器都在自己的内部机房里,只开放了Keepalived的VIP地址的两个端口80、443,通过防火墙映射出去,外网DNS对应映射后的公网IP。此架构的防火墙以及网络安全说明如下。
此系统架构仅映射内网VIP的80及443端口于外网的防火墙下,其他端口均关闭,内网所有机器均关闭iptables及ipfw防火墙。外网DNS指向即通过防火墙映射出来的外网地址。

网络拓扑图

1.Nginx+Keepalived的说明及环境说明

IP分配表
IP分配表

2.分别安装nginx负载均衡器及相关的配置文件

1)nginx的安装

useradd www
yum install -y gcc gcc-c++ openssl-devel pcre-devel
wget http://nginx.org/download/nginx-1.6.3.tar.gz
tar xvf nginx-1.6.3.tar.gz
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
make && make install

2)负载均衡相关的配置文件如下,纯http转发。

user www www;
worker_processes 4;

pid /usr/local/nginx/logs/nginx.pid;
worker_rlimit_nofile 65535;

events
{
use epoll;
worker_connections 65535;
}
http{
include       mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 8m;
sendfile on;
tcp_nopush     on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
gzip on;
gzip_min_length 1k;
gzip_buffers     4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types       text/plain application/x-javascript text/css application/xml;
gzip_vary on;

upstream backend
{
server 192.168.2.16:80;
server 192.168.2.17:80;

}
server {
listen 80;
server_name hqidi.com;
location / {
root /var/www ;
index index.jsp index.php index.htm index.html;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://backend;
}

location /nginx {
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file /usr/local/nginx/htpasswd;
}

log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
access_log /var/log/access.log access;

}
}

两台负载均衡器均是如上配置。在两台nginx负载均衡器上都执行/usr/local/nginx/sbin/nginx,启动nginx,

然后用lsof -i :80来检查nginx是否正常启动,此命令输出如下

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 2404 root 6u IPv4 13051 0t0 TCP *:http (LISTEN)
nginx 2405 www 6u IPv4 13051 0t0 TCP *:http (LISTEN)

nginx正常启动后,两台nginx负载均衡器就算安装成功了,接下来安装keepalived来实现这两台nginx负载均衡器的高可用。

3.在刚刚的两台机器上安装keepalived,让其分别作后端两台web的HA

keepalived的安装方法:

wget http://www.keepalived.org/software/keepalived-1.2.19.tar.gz
tar -zxvf keepalived-1.2.19.tar.gz
cd keepalived-1.2.19
./configure --prefix=/usr/local/keepalived
make
make install

2)安装好后,可做如下操作,方便日后使用

cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

3)分别设置主nginx和备用nginx上的keepalived配置文件。
mkdir /etc/keepalived
主上的配置:

[root@nginxM ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
notification_email {
hqd7792@163.com              #每行一个邮件地址,记得开启本机sendmail服务
}
notification_email_from Alexandre.Cassen@firewall.loc              #邮件发送地址
smtp_server 127.0.0.1              # smtp server地址
smtp_connect_timeout 30              #连接smtp server的超时时间
router_id LVS_DEVEL
}

vrrp_instance VI_1 {
state MASTER                     #配置为主服务器
interface eth0                      #绑定网卡
virtual_router_id 51          #路由标识
mcast_src_ip 192.168.2.13
priority 100                         #优先级,0-254 越大优先级越高
advert_int 1                        #通知间隔,实际部署时可以设置小一点,减少延时
authentication {
auth_type PASS                #验证类型,密码验证
auth_pass 9527                #验证密码
}
virtual_ipaddress {   #指定虚拟IP, 两个节点设置必须一样
        192.168.2.18/24
    }
}

从服务器设置:

[root@nginxB ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
notification_email {
hqd7792@163.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}

vrrp_instance VI_1 {
state BACKUP                          #配置为从服务器
interface eth0                          #绑定网卡
virtual_router_id 51               #路由标识,和主服务器相同
mcast_src_ip 192.168.2.14
priority 98                              #优先级,小于主服务器即可
advert_int 1                              #通知间隔,和主服务器相同
authentication {
auth_type PASS                       #验证类型,密码验证
auth_pass 9527                        #验证密码,和主服务器相同
}
virtual_ipaddress {   #指定虚拟IP, 两个节点设置必须一样
        192.168.2.18/24
}
}

在两台负载均衡器上分别启动keepalived程序
/etc/init.d/keepalived start
当两边的keepalived都启动好以后,我们就看到VIP已经绑定到主nginx上了。

1: lo:  mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:a5:b2:28 brd ff:ff:ff:ff:ff:ff
inet 192.168.2.13/24 brd 192.168.2.255 scope global eth0
inet 192.168.2.18/32 scope global eth0
inet6 fe80::20c:29ff:fea5:b228/64 scope link
valid_lft forever preferred_lft forever
3: eth1:  mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 00:0c:29:a5:b2:32 brd ff:ff:ff:ff:ff:ff

此时,我们用tcpdump在任意一台nginx负载均衡器上抓包的话,能抓到大量的vrrp包,命令如下
tcpdump vrrp
在备用nginx负载均衡器上抓包的同时,我们把主负载均衡器上的keepalived服务重启,我们能发现主备的切换是秒级的。就是说主负载均衡器上的keepalived服务在restart的时候,备用负载均衡器在一秒钟内经历了从 备用→主→备用 的过程。如下:

Mar 24 13:31:17 CentOS14 Keepalived_vrrp[883]: VRRP_Instance(VI_1) Transition to MASTER STATE
Mar 24 13:31:17 CentOS14 Keepalived_vrrp[883]: VRRP_Instance(VI_1) Received higher prio advert
Mar 24 13:31:17 CentOS14 Keepalived_vrrp[883]: VRRP_Instance(VI_1) Entering BACKUP STATE

关于VRRP

在现实的网络环境中,主机之间的通信都是通过配置静态路由(默认网关)完成的,而主机之间的路由器一旦出现故障,通信就会失败,因此,在这种通信模式中,路由器就成了一个单点瓶颈,为了解决这个问题,就引入了VRRP协议。
熟悉网络的朋友对VRRP协议应该并不陌生。它是一种主备模式的协议,通过VRRP可以在网络发生故障时透明地进行设备切换而不影响主机间的数据通信,这其中涉及两个概念:物理路由器和虚拟路由器。
VRRP可以将两台或多台物理路由器设备虚拟成一个虚拟路由器,这个虚拟路由器通过虚拟IP(一个或多个)对外提供服务,而在虚拟路由器内部是多个物理路由器协同工作,同一时间只有一台物理路由器对外提供服务,这台物理路由器被称为主路由器(处于MASTER角色)。一般情况下MASTER由选举算法产生,它拥有对外服务的虚拟IP,提供各种网络功能,如ARP请求、ICMP、数据转发等。而其他物理路由器不拥有对外的虚拟IP,也不提供对外网络功能,仅仅接收MASTER的VRRP状态通告信息,这些路由器被统称为备份路由器(处于BACKUP角色)。当主路由器失效时,处于BACKUP角色的备份路由器将重新进行选举,产生一个新的主路由器进入MASTER角色继续提供对外服务,整个切换过程对用户来说完全透明。
每个虚拟路由器都有一个唯一标识,称为VRID,一个VRID与一组IP地址构成了一个虚拟路由器。在VRRP协议中,所有的报文都是通过IP多播形式发送的,而在一个虚拟路由器中,只有处于MASTER角色的路由器会一直发送VRRP数据包,处于BACKUP角色的路由器只接收MASTER发过来的报文信息,用来监控MASTER运行状态,因此,不会发生BACKUP抢占的现象,除非它的优先级更高。而当MASTER不可用时,BACKUP也就无法收到MASTER发过来的报文信息,于是就认定MASTER出现故障,接着多台BACKUP就会进行选举,优先级最高的BACKUP将成为新的MASTER,这种选举并进行角色切换的过程非常快,因而保证了服务的持续可用性。

4.用nginx_pid.sh来监控nginx进程,实现真正意义上的负载均衡高可用

脚本思路,放在后台一直监控nginx进程,如果进程消失,则尝试重启nginx;如果失败,则立即停掉本机的keepalived服务,让另外一台负载均衡器接手。

#!/bin/bash
while :
   do
	nginxpid=`ps -C nginx --no-header | wc -l`
		if [ $nginxpid -eq 0 ];then
			/usr/local/nginx/sbin/nginx
			sleep 5
			 nginxpid=`ps -C nginx --no-header | wc -l`
			 echo $nginxpid
				if [ $nginxpid -eq 0 ];then
					/etc/init.d/keepalived stop
				fi
		fi
	sleep 5
   done

然后我们用 nohup /bin/bash /root/nginx_pid.sh & ,让此监控脚本长期跑在后台。

5.模拟故障测试

1)关掉一台nginx负载均衡器
2)down掉某台web机器的网线或者直接关机。
3)停掉其中一台nginx服务器的nginx服务。
我们发现无论在什么情况下,nginx+keepalived都可以正常提供服务

6.如何让后端的nginx服务器获取客户端的真实IP

通过修改nginx proxy的参数,令后端应用获取nginx发来的请求报文,并获取外网的IP,在nginx的配置文件中加上如下内容:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

7.如何让Nginx负载均衡器也支持HTTPS?

要让Nginx支持HTTPS,方法其实很简单,在负载均衡器上开启SSL功能,监听443端口(防火墙上也要做好映射),将证书放在Nginx负载均衡器上(不是后面的Web服务器),就可轻松解决此问题。详见以下nginx.conf配置文件,代码如下:

server
{
listen 443;
server_name hqidi.com;

ssl on;
ssl_certificate /usr/local/nginx/keys/hqidi.com.crt;
ssl_certificate_key /usr/local/nginx/keys/hqidi.com.key;

ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP;
}

证书可以到 https://www.startssl.com/ 申请,主流浏览器都会信任其颁发的证书。

原创文章,转载请注明: 转载自笛声

本文链接地址: 企业级web负载均衡高可用之nginx+Keepalived

暂无评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Copyright © 2015-2024 笛声博客 All Rights Reserved     浙ICP备15036123号-1