Keepalived+LVS+nginx搭建nginx高可用集群

       nginx是一款很是优秀的反向代理工具,支持请求分发,负载均衡,以及缓存等等很是实用的功能。在请求处理上,nginx采用的是epoll模型,这是一种基于事件监听的模型,于是其具有很是高效的请求处理效率,单机并发能力可以达到上百万。nginx接收到的请求能够经过负载均衡策略分发到其下一级的应用服务器,这些服务器通常是以集群方式部署的,于是在性能不足的状况下,应用服务器能够经过加机器的方式扩展流量。此时,对于一些特大型的网站,性能的瓶颈就来自于nginx了,由于单机的nginx的并发能力是有上限的,而nginx自己是不支持集群模式的,于是此时对nginx的横向扩展就显得尤其重要。html

       keepalived是一款服务器状态检测和故障切换的工具。在其配置文件中,能够配置主备服务器和该服务器的状态检测请求。也就是说keepalived能够根据配置的请求,在提供服务期间不断向指定服务器发送请求,若是该请求返回的状态码是200,则表示该服务器状态是正常的,若是不正常,那么keepalived就会将该服务器给下线掉,而后将备用服务器设置为上线状态。java

        lvs是一款用于四层负载均衡的工具。所谓的四层负载均衡,对应的是网络七层协议,常见的如HTTP协议是创建在七层协议上的,而lvs做用于四层协议上,也即:传输层,网络层,数据链路层和物理层。这里的传输层主要协议有TCP和UDP协议,也就是说lvs主要支持的方式是TCP和UDP。也正是由于lvs是处于四层负载均衡上的,于是其处理请求的能力比常见的服务器要高很是多,好比nginx的请求处理就是创建在网络七层上的,lvs的负载均衡能力是nginx的十倍以上。nginx

       经过上面的介绍,咱们能够发现,在特大型网站中,应用服务器是能够横向扩容的,而nginx是不支持横向扩容的,此时nginx就会成为性能瓶颈。而lvs是一款负载均衡工具,于是若是咱们结合lvs和nginx,那么就能够经过部署多台nginx服务器,经过lvs的负载均衡能力,将请求均衡的分发到各个nginx服务器上,再由nginx服务器分发到各个应用服务器,这样,咱们就实现了nginx的横向扩展了。因为nginx本质上也是一款应用服务器,于是其也有可能宕机,于是这里结合keepalived就能够实现nginx的故障检测和服务切换。也就是说,经过keepalived+lvs+nginx,咱们实现了nginx的高可用集群模式。算法

       在上面的介绍中,咱们会注意到,虽然keepalived+lvs+nginx实现了nginx的集群模式,可是在咱们使用nginx的时候,其自己是有一个ip和端口的,默认监听的端口是80和443,那么lvs是如何实现将请求分发给具备不一样ip和端口的nginx服务器的呢?这里就是经过虚拟ip实现的,所谓虚拟ip就是对外提供一个公共的ip,外部客户端请求的都是这个ip,lvs在接收到虚拟ip的请求以后,经过配置的调度器和负载均衡策略,选择一个目标nginx服务器,而后将请求转发给该服务器。这里lvs有两个概念,就是调度器和负载均衡策略,所谓的调度器指的是lvs将会以何种方式处理请求和响应数据,其主要有三种调度器:shell

  • Virtual Server via Network Address Translation(VS/NAT):这种方式的主要原理是,用户发送请求到虚拟ip上后,lvs会根据负载均衡算法选择一个目标处理服务,而后将请求报文中的目标ip地址修改成计算获得的目标服务器,而且发送给该服务器。对于响应的报文,调度器会将目标服务器返回的响应数据中的源地址修改成虚拟ip地址。经过这种方式,对客户端而言,其形式上面向的是一台服务器。不过这种方式的缺点在于,全部的响应数据都须要经过调度器,若是请求量比较大的状况下,那么调度器就会成为整个系统的瓶颈。
  • Virtual Server via IP Tunneling(VS/TUN):这种方式主要解决的就是VS/NAT中,响应数据会通过调度器的问题。同VS/NAT同样 ,调度器仍是会接收请求的数据,而且将报文中的目标ip修改成目标服务的ip,可是在目标服务处理完数据以后,其会直接将响应报文中的源ip修改成虚拟ip,而后将请求发送给客户端。经过这种方式,响应数据就由各个目标服务进行了处理,而无需经过调度器进行返回,这种方式会大大提升系统的吞吐量,并且因为通常请求报文比响应报文小不少,调度器也只须要处理请求报文,那么系统的总体负载将会被均摊到各个服务器上。
  • Virtual Server via Direct Routing(VS/DR):这种方式相对于VS/TUN,其主要区别在于,VS/TUN是将请求报文中的ip地址修改成目标服务的ip地址,而VS/DR则是直接将请求报文中的MAC地址修改成目标地址,这种方式效率会更高,由于VS/TUN中的ip地址最终仍是须要转换为MAC地址来发送数据的。

1. 环境准备

1. VMware;
2. 4台CentOs7虚拟主机:172.16.28.130, 172.16.28.131, 172.16.28.132, 172.16.28.133
3. 系统服务:LVS, Keepalived
4. Web服务器:nginx
5. 集群搭建:LVS DR模式

2. 软件安装

        在四台虚拟机上,咱们以以下方式搭建集群:后端

172.16.28.130 lvs+keepalived
172.16.28.131 lvs+keepalived
172.16.28.132 nginx
172.16.28.133 nginx

        这里咱们使用172.16.28.130172.16.28.131两台机器做为lvs+keepalived的工做机器,也就是说这两台机器的做用主要是进行负载均衡和故障检测和下线的;咱们使用172.16.28.132172.16.28.133两台机器做为应用服务器,主要是对外提供服务的。这四台服务器做为整个后端集群服务,而且对外提供的虚拟ip是172.16.28.120。须要说明的是,这里的keepalived所检测的服务是两台lvs服务器,这两台服务器,一台做为master服务器,一台做为backup服务器,二者在负载均衡的配置上是彻底同样的。在正常状况下,客户端请求虚拟ip的时候,lvs会将该请求转发到master服务器上,而后master服务器根据配置的负载均衡策略选择一台应用服务器,而且将请求发送给该应用服务器进行处理。若是在某个时刻,lvs的master服务器因为故障宕机了,keepalived就会检测到该故障,而且进行故障下线,而后将backup机器上线用于提供服务,从而实现故障转移的功能。浏览器

2.1 lvs+keepalived安装

        在172.16.28.130172.16.28.131上安装ipvs和keepalived:缓存

# 安装ipvs
sudo yum install ipvsadm
# 安装keepalived
sudo yum install keepalived

        在172.16.28.132172.16.28.133上安装nginx:bash

# 安装nginx
sudo yum install nginx

        须要注意的是,在两台nginx服务器上须要将防火墙关闭,不然lvs+keepalived的两台机器就没法将请求发送到两台nginx服务器上来:服务器

# 关闭防火墙
systemctl disable firewalld.service

        查看两台负载均衡机器是否支持lvs:

sudo lsmod |grep ip_vs
# 若是看到以下结果,则说明是支持的
[zhangxufeng@localhost ~]$ sudo lsmod|grep ip_vs
ip_vs                 145497  0
nf_conntrack          137239  1 ip_vs
libcrc32c              12644  3 xfs,ip_vs,nf_conntrack

        若是上述命令没有任何结果,则执行sudo ipvsadm命令启动ipvs以后,再经过上述命令进行查看便可。启动ipvs以后,咱们就能够在/etc/keepalived/目录下编辑keepalived.conf文件,咱们以172.16.28.130机器做为master机器,master节点配置以下:

# Global Configuration
global_defs {
  lvs_id director1  # 指定lvs的id
}

# VRRP Configuration
vrrp_instance LVS {
  state MASTER	# 指定当前节点为master节点
  interface ens33	# 这里的ens33是网卡的名称,经过ifconfig或者ip addr能够查看
  virtual_router_id 51	# 这里指定的是虚拟路由id,master节点和backup节点须要指定同样的
  priority 151	# 指定了当前节点的优先级,数值越大优先级越高,master节点要高于backup节点
  advert_int 1	# 指定发送VRRP通告的间隔,单位是秒
  authentication {
    auth_type PASS	# 鉴权,默认经过
    auth_pass 123456	# 鉴权访问密码
  }

  virtual_ipaddress {
    172.16.28.120	# 指定了虚拟ip
  }

}

# Virtual Server Configuration - for www server
# 后台真实主机的配置
virtual_server 172.16.28.120 80 {
  delay_loop 1	# 健康检查的时间间隔
  lb_algo rr	# 负载均衡策略,这里是轮询
  lb_kind DR	# 调度器类型,这里是DR
  persistence_time 1	# 指定了持续将请求打到同一台真实主机的时间长度
  protocol TCP	# 指定了访问后台真实主机的协议类型

  # Real Server 1 configuration
  # 指定了真实主机1的ip和端口
  real_server 172.16.28.132 80 {
    weight 1	# 指定了当前主机的权重
    TCP_CHECK {
      connection_timeout 10	# 指定了进行心跳检查的超时时间
      nb_get_retry 3	# 指定了心跳超时以后的重复次数
      delay_before_retry 3	# 指定了在尝试以前延迟多长时间
    }
  }

  # Real Server 2 Configuration
  real_server 172.16.28.133 80 {
    weight 1	# 指定了当前主机的权重
    TCP_CHECK {
      connection_timeout 10	# 指定了进行心跳检查的超时时间
      nb_get_retry 3	# 指定了心跳超时以后的重复次数
      delay_before_retry 3	# 指定了在尝试以前延迟多长时间
    }
  }
}

        上面是master节点上keepalived的配置,对于backup节点,其配置与master几乎是一致的,只是其state和priority参数不一样。以下是backup节点的完整配置:

# Global Configuration
global_defs {
  lvs_id director2  # 指定lvs的id
}

# VRRP Configuration
vrrp_instance LVS {
  state BACKUP	# 指定当前节点为master节点
  interface ens33	# 这里的ens33是网卡的名称,经过ifconfig或者ip addr能够查看
  virtual_router_id 51	# 这里指定的是虚拟路由id,master节点和backup节点须要指定同样的
  priority 150	# 指定了当前节点的优先级,数值越大优先级越高,master节点要高于backup节点
  advert_int 1	# 指定发送VRRP通告的间隔,单位是秒
  authentication {
    auth_type PASS	# 鉴权,默认经过
    auth_pass 123456	# 鉴权访问密码
  }

  virtual_ipaddress {
    172.16.28.120	# 指定了虚拟ip
  }

}

# Virtual Server Configuration - for www server
# 后台真实主机的配置
virtual_server 172.16.28.120 80 {
  delay_loop 1	# 健康检查的时间间隔
  lb_algo rr	# 负载均衡策略,这里是轮询
  lb_kind DR	# 调度器类型,这里是DR
  persistence_time 1	# 指定了持续将请求打到同一台真实主机的时间长度
  protocol TCP	# 指定了访问后台真实主机的协议类型

  # Real Server 1 configuration
  # 指定了真实主机1的ip和端口
  real_server 172.16.28.132 80 {
    weight 1	# 指定了当前主机的权重
    TCP_CHECK {
      connection_timeout 10	# 指定了进行心跳检查的超时时间
      nb_get_retry 3	# 指定了心跳超时以后的重复次数
      delay_before_retry 3	# 指定了在尝试以前延迟多长时间
    }
  }

  # Real Server 2 Configuration
  real_server 172.16.28.133 80 {
    weight 1	# 指定了当前主机的权重
    TCP_CHECK {
      connection_timeout 10	# 指定了进行心跳检查的超时时间
      nb_get_retry 3	# 指定了心跳超时以后的重复次数
      delay_before_retry 3	# 指定了在尝试以前延迟多长时间
    }
  }
}

        将master和backup配置成彻底同样的缘由是,在master宕机时,能够根据backup的配置进行服务的无缝切换。

        在lvs+keepalived机器配置完成以后,咱们下面配置两台应用服务器的nginx配置。这里咱们是将nginx做为应用服务器,在其配置文件中配置返回状态码为200,而且会将当前主机的ip返回,以下是其配置:

worker_processes auto;
# pid /run/nginx.pid;

events {
  worker_connections 786;
}

http {
  server {
    listen 80;

    # 这里是直接返回200状态码和一段文本
    location / {
      default_type text/html;
      return 200 "Hello, Nginx! Server zhangxufeng@172.16.28.132\n";
    }
  }
}
worker_processes auto;
# pid /run/nginx.pid;

events {
  worker_connections 786;
}

http {
  server {
    listen 80;

    # 这里是直接返回200状态码和一段文本
    location / {
      default_type text/html;
      return 200 "Hello, Nginx! Server zhangxufeng@172.16.28.133\n";
    }
  }
}

        能够看到,两台机器返回的文本中主机ip是不同的。nginx配置完成后,能够经过以下命令进行启动:

sudo nginx

        在启动nginx以后,咱们须要配置虚拟ip,这是由于咱们使用的lvs调度器是DR模式,前面咱们讲到过,这种模式下,对客户端的响应是真实服务器直接返回给客户端的,而真实服务器须要将响应报文中的源ip修改成虚拟ip,这里配置的虚拟ip就是起这个做用的。咱们编辑/etc/init.d/lvsrs文件,写入以下内容:

#!/bin/bash

ifconfig lo:0 172.16.28.120 netmask 255.255.255.255 broadcast 172.16.28.120 up
route add -host 172.16.28.120 dev lo:0

echo "0" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

exit 0
  • lo:表示当前主机真实网卡的名称;
  • 172.16.28.120:表示虚拟ip;

        编写完成后运行该脚本文件便可。而后将两台lvs+keepalived机器上的keepalived服务启动起来便可:

sudo service keepalived start

        最后能够经过以下命令查看配置的lvs+keepalived的策略:

[zhangxufeng@localhost keepalived]$ sudo ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.16.28.120:80 rr
  -> 172.16.28.132:80             Route   1      0          0

2.2 集群测试

        根据上述步骤,咱们配置完成了一个lvs+keepalived+nginx的集群。在浏览器中,咱们能够访问http://172.16.28.120便可看到以下响应:

Hello, Nginx! Server zhangxufeng@172.16.28.132

        屡次刷新浏览器以后,能够看到浏览器中显示的文本切换以下,这是由于lvs的负载均衡策略产生的:

Hello, Nginx! Server zhangxufeng@172.16.28.133

3. 小结

        本文首先对lvs和keepalived的工做原理进行了讲解,分别介绍了其工做的几种模式,而后对lvs+keepalived+nginx搭建nginx集群的方式进行详细讲解,而且说明了其中所须要注意的问题。

相关文章
相关标签/搜索