作者:HelloDog
原文地址:LVS+Keepalived 使用指北, 感谢原作者分享。由于原文地址已经不可访问,所以在此进行备份。
LVS+Keepalived 使用指南
HelloDog 2018-08-07 65 阅读
keepalived LVS
前言
负载均衡技术是构建大型网站必不可少的架构策略之一。它的目的是把用户的请求分发到多台后端的设备上,用以均衡服务器的负载。我们可以把负载均衡器划分为两大类:硬件负载均衡器和软件负载均衡器。这里重点介绍软件实现方法中的LVS+Keepalived。
学习使用 LVS+Keepalived
关键词:
- LB (Load Balancer 负载均衡)
- HA (High Available 高可用)
- FailOver (失败切换)
- CLUSTER (集群)
- LVS (Linux Virtual Server Linux 虚拟服务器)
- RealServer 后端真实服务器,这个概念相对于LVS Director,指lvs集群中真正执行客户端请求的服务器。
- Director 前端调度器,指安装lvs(ipvsadm)的服务器,负责调度 realserver 提供负载均衡。
- VIP (Virtual_IP_address) 虚拟的IP地址
- DIP (Director IP) 前段调度器的IP地址
- RIP (RealServer IP) 后端正式服务器的IP地址
负载均衡(LB Cluster)
负载均衡实现方法有两种:硬件实现和软件实现
硬件比较常见的有:
- F5 Big-IP
- Citrix Netscaler
软件比较常见的有:
- LVS(Linux Virtual Server)
- HAProxy
- Nginx
LVS特点是:
- 首先它是基于4层的网络协议的,抗负载能力强,对于服务器的硬件要求除了网卡外,其他没有太多要求;
- 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,大大减少了人为出错的几率;
- 应用范围比较广,不仅仅对web服务做负载均衡,还可以对其他应用(mysql)做负载均衡;
- LVS架构中存在一个虚拟IP的概念,需要向IDC多申请一个IP来做虚拟IP。
Nginx负载均衡器的特点是:
- 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构;
- Nginx安装和配置比较简单,测试起来比较方便;
- 也可以承担高的负载压力且稳定,一般能支撑超过上万次的并发;
- Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测;
- Nginx对请求的异步处理可以帮助节点服务器减轻负载;
- Nginx能支持http和Email,这样就在适用范围上面小很多;
- 默认有三种调度算法: 轮询、weight以及ip_hash(可以解决会话保持的问题),还可以支持第三方的fair和url_hash等调度算法;
HAProxy的特点是:
- HAProxy是工作在网络7层之上;
- 支持Session的保持,Cookie的引导等;
- 支持url检测后端的服务器出问题的检测会有很好的帮助;
- 支持的负载均衡算法:动态加权轮循(Dynamic Round Robin),加权源地址哈希(Weighted Source Hash),加权URL哈希和加权参数哈希(Weighted Parameter Hash);
- 单纯从效率上来讲HAProxy更会比Nginx有更出色的负载均衡速度;
- HAProxy可以对Mysql进行负载均衡,对后端的DB节点进行检测和负载均衡。
LVS+keepalived 简介
在lvs+keepalived环境里面,lvs主要的工作是提供调度算法,把客户端请求按照需求调度在real服务器,keepalived主要的工作是提供lvs控制器的一个冗余,并且对real服务器做健康检查,发现不健康的real服务器,就把它从lvs集群中剔除,real服务器只负责提供服务。
LVS
LVS是一个开源的软件,可以实现LINUX平台下的简单负载均衡。LVS是Linux Virtual Server的缩写,意思是Linux虚拟服务器。
目前有三种IP负载均衡技术(VS/NAT,VS/TUN,VS/DR)
Virtual Server via Network Address Translation(VS/NAT)
通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。
Virtual Server via IP Tunneling(VS/TUN)
采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报 文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用 VS/TUN技术后,集群系统的最大吞吐量可以提高10倍。
Virtual Server via Direct Routing(VS/DR)
VS/DR通过改写请求报文的MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地 提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连 在同一物理网段上。
八种调度算法(rr,wrr,lc,wlc,lblc,lblcr,dh,sh)
工作模式
原生只有3种模式(NAT,TUN,DR), fullnat工作模式默认不支持
LVS是四层负载均衡,也就是说建立在OSI模型的第四层——传输层之上,传输层上有我们熟悉的TCP/UDP,LVS支持TCP/UDP的负载均衡。因为LVS是四层负载均衡,因此它相对于其它高层负载均衡的解决办法,比如DNS域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的。
LVS的IP负载均衡技术是通过IPVS模块来实现的,IPVS是LVS集群系统的核心软件,它的主要作用是:安装在Director Server上,同时在Director Server上虚拟出一个IP地址,用户必须通过这个虚拟的IP地址访问服务。这个虚拟IP一般称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达负载调度器,然后由负载调度器从Real Server列表中选取一个服务节点响应用户的请求。 当用户的请求到达负载调度器后,调度器如何将请求发送到提供服务的Real Server节点,而Real Server节点如何返回数据给用户,是IPVS实现的重点技术,IPVS实现负载均衡机制有几种,分别是NAT、DR、TUN及FULLNAT。
lvs-nat
NAT(Network Address Translation 网络地址转换)是一种外网和内外地址映射的技术,内网可以是私有网址,外网可以使用NAT方法修改数据报头,让外网与内网能够互相通信。NAT模式下,网络数据报的进出都要经过LVS的处理。LVS需作为RS(真实服务器)的网关。当包到达LVS时,LVS做目标地址转换(DNAT),将目标IP改为RS的IP。RS接收到包以后,仿佛是客户端直接发给它的一样。RS处理完,返回响应时,源IP是RS IP,目标IP是客户端的IP。这时RS的包通过网(LVS)中转,LVS会做源地址转换(SNAT),将包的源地址改为VIP,这样,这个包对客户端看起来就仿佛是LVS直接返回给它的。客户端无法感知到后端RS的存在。
(1)RIP和DIP必须在同一个IP网络,且应该使用私网地址;RS的网关要指向DIP;
(2)请求报文和响应报文都必须经由Director转发;Director易于成为系统瓶颈;
(3)支持端口映射,可修改请求报文的目标PORT;
(4)vs必须是Linux系统,rs可以是任意系统;
缺点:在整个过程中,所有输入输出的流量都要经过LVS 调度服务器。显然,LVS 调度服务器的网络I/O压力将会非常大,因此很容易成为瓶颈,特别是对于请求流量很小,而响应流量很大的Web类应用来说尤为如此。
优点:NAT模式的优点在于配置及管理简单,由于了使用NAT技术,LVS 调度器及应用服务器可以在不同网段中,网络架构更灵活,应用服务器只需要进行简单的网络设定即可加入集群。
lvs-dr
lvs-dr工作模式最为常用
DR(Direct Routing 直接路由模式)此模式时LVS 调度器只接收客户发来的请求并将请求转发给后端服务器,后端服务器处理请求后直接把内容直接响应给客户,而不用再次经过LVS调度器。LVS只需要将网络帧的MAC地址修改为某一台后端服务器RS的MAC,该包就会被转发到相应的RS处理,注意此时的源IP和目标IP都没变。RS收到LVS转发来的包时,链路层发现MAC是自己的,到上面的网络层,发现IP也是自己的,于是这个包被合法地接受,RS感知不到前面有LVS的存在。而当RS返回响应时,只要直接向源IP(即用户的IP)返回即可,不再经过LVS。
注意:
(1) 确保前端路由器将目标IP为VIP的请求报文发往Director:
(a) 在前端网关做静态绑定;
(b) 在RS上使用arptables;
(c) 在RS上修改内核参数以限制arp通告及应答级别;
arp_announce
arp_ignore
(2) RS的RIP可以使用私网地址,也可以是公网地址;RIP与DIP在同一IP网络;RIP的网关不能指向DIP,以确保响应报文不会经由Director;
(3) RS跟Director要在同一个物理网络;
(4) 请求报文要经由Director,但响应不能经由Director,而是由RS直接发往Client;
(5) 此模式不支持端口映射;
缺点:唯一的缺陷在于它要求LVS 调度器及所有应用服务器在同一个网段中,因此不能实现集群的跨网段应用。
优点:可见在处理过程中LVS Route只处理请求的直接路由转发,所有响应结果由各个应用服务器自行处理,并对用户进行回复,网络流量将集中在LVS调度器之上。
lvs-tun
TUN(virtual server via ip tunneling IP 隧道)调度器把请求的报文通过IP隧道转发到真实的服务器。真实的服务器将响应处理后的数据直接返回给客户端。这样调度器就只处理请求入站报文。此转发方式不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而在原IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源IP是VIP,目标IP是CIP),由于一般网络服务应答数据比请求报文大很多,采用lvs-tun模式后,集群系统的最大吞吐量可以提高10倍
注意:
(1) DIP, VIP, RIP都应该是公网地址;
(2) RS的网关不能,也不可能指向DIP;
(3) 请求报文要经由Director,但响应不能经由Director;
(4) 此模式不支持端口映射;
(5) RS的操作系统得支持隧道功能
缺点:由于后端服务器RS处理数据后响应发送给用户,此时需要租借大量IP(特别是后端服务器使用较多的情况下)。
优点:实现lvs-tun模式时,LVS 调度器将TCP/IP请求进行重新封装并转发给后端服务器,由目标应用服务器直接回复用户。应用服务器之间是通过IP 隧道来进行转发,故两者可以存在于不同的网段中。
lvs-fullnat
lvs-fullnat工作模式默认不支持
此模式类似DNAT,它通过同时修改请求报文的源IP地址和目标IP地址进行转发
注意:
(1) VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;因此,RIP的网关一般不会指向DIP;
(2) RS收到的请求报文源地址是DIP,因此,只需响应给DIP;但Director还要将其发往Client;
(3) 请求和响应报文都经由Director;
(4) 支持端口映射;
调度算法
针对不同的网络服务需求和服务器配置,IPVS调度器实现了如下八种负载调度算法:
轮叫(Round Robin)
调度器通过”轮叫”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。
加权轮叫(Weighted Round Robin)
调度器通过”加权轮叫”调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
最少链接(Least Connections)
调度器通过”最少连接”调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用”最小连接”调度算法可以较好地均衡负载。
加权最少链接(Weighted Least Connections)
在集群系统中的服务器性能差异较大的情况下,调度器采用”加权最少链接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
基于局部性的最少链接(Locality-Based Least Connections)
“基于局部性的最少链接” 调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器 是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用”最少链接”的原则选出一个可用的服务 器,将请求发送到该服务器。
带复制的基于局部性最少链接(Locality-Based Least Connections with Replication)
“带复制的基于局部性最少链接”调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个 目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。该算法根据请求的目标IP地址找出该目标IP地址对应的服务 器组,按”最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器,若服务器超载;则按”最小连接”原则从这个集群中选出一 台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的 程度。
目标地址散列(Destination Hashing)
“目标地址散列”调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
源地址散列(Source Hashing)
“源地址散列”调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
keepalived
Keepalived 是运行在lvs之上,是一个用于做双机热备(HA)的软件,它的主要功能是实现真实机的故障隔离及负载均衡器间的失败切换,提高系统的可用性。
运行原理
keepalived通过选举(看服务器设置的权重)挑选出一台热备服务器做MASTER机器,MASTER机器会被分配到一个指定的虚拟ip,外部程序可通过该ip访问这台服务器,如果这台服务器出现故障(断网,重启,或者本机器上的keepalived crash等),keepalived会从其他的备份机器上重选(还是看服务器设置的权重)一台机器做MASTER并分配同样的虚拟IP,充当前一台MASTER的角色。
选举策略
选举策略是根据VRRP协议,完全按照权重大小,权重最大(0~255)的是MASTER机器,下面几种情况会触发选举
- keepalived启动的时候
- master服务器出现故障(断网,重启,或者本机器上的keepalived crash等,而本机器上其他应用程序crash不算)
- 有新的备份服务器加入且权重最大
LVS(NAT和DR)模式详细配置
环境准备
分别准备两台web服务器,两台服务器配置相同
[root@web1 ~]# yum install httpd* -y [root@web1 ~]# iptables -F [root@web1 ~]# /etc/init.d/iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ] [root@web1 ~]# /etc/init.d/iptables stop iptables: Setting chains to policy ACCEPT: filter [ OK ] iptables: Flushing firewall rules: [ OK ] iptables: Unloading modules: [ OK ] [root@web1 ~]# chkconfig iptables off [root@web1 ~]# sed -i "s/SELINUX=enforcing/SELINUX disabled/g" /etc/selinux/config [root@web1 ~]# setenforce 0 [root@web1 ~]# /etc/init.d/httpd start [root@web1 ~]# ps -ef | grep httpd root 1482 1 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1484 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1485 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1486 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1487 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1488 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1489 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1490 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd apache 1491 1482 0 18:24 ? 00:00:00 /usr/sbin/httpd root 1494 1331 0 18:24 pts/0 00:00:00 grep httpd [root@web1 ~]# netstat --lntup | grep 80 [root@web1 ~]# netstat -lntup | grep 80 tcp 0 0 :::80 :::* LISTEN 1482/httpd [root@web1 ~]# echo "webserver1" > /var/www/html/index.html# LVS在3种方式下均需要打开ip_forward 功能 echo "1" > /proc/sys/net/ipv4/ip_forward vim /etc/sysctl.conf net.ipv4.ip_forward = 1# 设置snat,如需永久保存可以编辑/etc/sysconfig/iptables /sbin/iptables -t nat -A POSTROUTING -j MASQUERADvim /etc/sysconfig/iptables*nat :PREROUTING ACCEPT [6:504] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [1:52] :POSTROUTING ACCEPT [1:52] # SNAT -A POSTROUTING -j MASQUERADE COMMIT*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] # 配置外网白名单 -A INPUT -s 180.168.36.198 -j ACCEPT -A INPUT -s 180.168.34.218 -j ACCEPT -A INPUT -s 222.73.202.251 -j ACCEPT # 控制端口 -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 22 -j ACCEPT # For keepalived # allow vrrp -A INPUT -p vrrp -j ACCEPT -A INPUT -p igmp -j ACCEPT # allow multicast -A INPUT -d 224.0.0.18 -j ACCEPT # 配置内网白名单 -A INPUT -s 10.0.0.0/8 -j ACCEPT -A INPUT -s 172.16.0.0/12 -j ACCEPT -A INPUT -s 192.168.0.0/16 -j ACCEPT # 开放本地和Ping -A INPUT -i lo -j ACCEPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT # 拒绝其它 -A INPUT -j DROP -A FORWARD -j DROP # 开放出口 -A OUTPUT -j ACCEPT COMMIT# 重启生效 service iptables restart # 复查结果 iptables -nvL
LVS-NAT模式
image
VS/NAT 是最简单的方式,所有的 RealServer只需要将自己的网关指向 lvs(负载均衡器)即可,客户端可以是任意操作系统。VS/NAT 将报文的目标IP地址与目标端口改写成选定服务器(realserver)的地址,最后将修改后的报文发送给选定的服务器(realserver)
# 安装ipvsadm[root@LVS ~]# yum install ipvsadm* -y [root@LVS ~]# lsmod | grep lv_ [root@LVS ~]# lsmod | grep ip_vs ip_vs_rr 1420 0 ip_vs 126897 2 ip_vs_rr libcrc32c 1246 1 ip_vs ipv6 336282 270 ip_vs,ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6# 配置脚本如下#!/bin/bashVIP=192.168.10.10 #外网用户直接访问网站的IP地址 RIP1=192.168.84.104 #后端web1服务器的IP地址 RIP2=192.168.84.105 #后端web2服务器的IP地址case "$1" in start)echo "Start LVS as the mode NAT"echo "1" > /proc/sys/net/ipv4/ip_forward #开启LVS服务器的IP路由转发功能/sbin/ifconfig eth0:0 $VIP netmask 255.255.255.0 up #设定VIP地址/sbin/ipvsadm -A -t $VIP:80 -s rr/sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -m/sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -m/sbin/ipvsadm ;; stop)echo "Stop LVS"echo "0" > /proc/sys/net/ipv4/ip_forward/sbin/ifconfig eth0:0 down;; *) echo "Usage:$0 {start|stop}"exit 1 esac# 运行脚本后结果如下[root@LVS ~]# sh lvs_nat.sh start Start LVS as the mode NAT IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.10.10:http rr-> 192.168.84.104:http Masq 1 0 0 -> 192.168.84.105:http Masq 1 0 0 # web服务器需要删除默认的路由网关,重新设置路由网关为LVS主机IP地址[root@web1 ~]# route del default [root@web1 ~]# route add default gateway 192.168.84.103 [root@web1 ~]# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.84.0 * 255.255.255.0 U 0 0 0 eth0 link-local * 255.255.0.0 U 1002 0 0 eth0 default 192.168.84.103 0.0.0.0 UG 0 0 0 eth0# 通过curl命令查看是否成功[root@LVS ~]# curl 192.168.10.10 webserver2 [root@LVS ~]# curl 192.168.10.10 webserver1 [root@LVS ~]# curl 192.168.10.10 webserver2 [root@LVS ~]# curl 192.168.10.10 webserver1 [root@LVS ~]# curl 192.168.10.10 webserver2 [root@LVS ~]# curl 192.168.10.10 webserver1
LVS-DR模式
image
在 web服务中, 请求的流量一般小于回应的流量,VS/DR 方式利用这种非对称的特点,Director只负责调度请求, 而RealServer直接将相应的报文返回给客户机。VS/DR 方式是通过改写请求报文中的 “MAC” 地址部分来实现的, Director 和 RealServer 必需在同一个广播域/vlan的局域网。
RealServer 上绑定的VIP配置在各自 Non-ARP 网络设备上(如 lo 或 tunl),Director的VIP地址对外可见, RealServer的VIP对外是不可见的。
# LVS-DR RealServer服务器脚本,由于VS/DR工作原理,Realserver 需要抑制arp广播 #!/bin/bash VIP=192.168.84.200 /etc/rc.d/init.d/functions case "$1" in start) echo "start LVS of RealServer DR" /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev lo:0 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 ;; stop) /sbin/ifconfig lo:0 down echo "close LVS of RealServer DR" echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0 # Lvs-DR 启动脚本#!/bin/bash VIP=192.168.84.200 RIP1=192.168.84.104 RIP2=192.168.84.105 /etc/rc.d/init.d/functions case "$1" in start) echo "start LVS of DirectorServer DR" /sbin/ifconfig eth0:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev eth0:0 echo "1" >/proc/sys/net/ipv4/ip_forward /sbin/ipvsadm -C /sbin/ipvsadm -A -t $VIP:80 -s rr /sbin/ipvsadm -a -t $VIP:80 -r $RIP1:80 -g /sbin/ipvsadm -a -t $VIP:80 -r $RIP2:80 -g /sbin/ipvsadm ;; stop) echo "stop LVS of DirectorServer DR" echo "0" >/proc/sys/net/ipv4/ip_forward /sbin/ipvsadm -C /sbin/ifconfig eth0:0 down ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0
ipvsadm
# 每台realserver index.html文件内容为ip 地址,例如: echo "172.27.233.43" > /var/www/html/index.html echo "172.27.233.44" > /var/www/html/index.html# 启动http服务 /etc/init.d/httpd start# 客户端模拟请求 for((i=1;i<=10;i++));do curl http://172.27.233.45/; done 172.27.233.44 172.27.233.43 172.27.233.44 172.27.233.43 172.27.233.44 172.27.233.43 172.27.233.44 172.27.233.43 172.27.233.44 172.27.233.43 # 请求分配结果 ipvsadm -Ln --stats IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes -> RemoteAddress:Port TCP 172.27.233.45:80 10 50 0 4330 0 -> 172.27.233.43:80 5 25 0 2165 0 -> 172.27.233.44:80 5 25 0 2165 0 参数含义 --stats 显示统计信息 Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes 连接数 输入包 输出包 输入流量 输出流量
keepalived的配置文件说明
Keepalived 是运行在lvs之上,它的主要功能是实现RealServer(真实服务器)的故障隔离及Director(负载均衡器)间的FailOver(失败切换).
- keepalived 是lvs的扩展项目,因此它们之间具备良好的兼容性
- 对RealServer的健康检查,实现对失效机器/服务的故障隔离
- 负载均衡器之间的失败切换 failover
全局定义
全局配置又包括两个子配置
- 全局定义(global definition)
- 静态路由配置(static ipaddress/routes)
# 全局定义(global definition) global_defs { notification_email { acassen@firewall.loc failover@firewall.locsysadmin@firewall.loc}notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL } notification_email: 表示keepalived在发生诸如切换操作时需要发送email通知以及email发送给哪些邮件地址邮件地址可以多个每行一个 notification_email_from admin@example.com: 表示发送通知邮件时邮件源地址是谁 smtp_server 127.0.0.1: 表示发送email时使用的smtp服务器地址这里可以用本地的sendmail来实现 smtp_connect_timeout 30: 连接smtp连接超时时间 router_id node1: 机器标识,通常配置主机名# 静态地址和路由配置范例 static_ipaddress {192.168.1.1/24 brd + dev eth0 scope global192.168.1.2/24 brd + dev eth1 scope global } static_routes {src $SRC_IP to $DST_IP dev $SRC_DEVICEsrc $SRC_IP to $DST_IP via $GW dev $SRC_DEVICE } 这里实际上和系统里面命令配置IP地址和路由一样例如 192.168.1.1/24 brd + dev eth0 scope global 相当于: ip addr add 192.168.1.1/24 brd + dev eth0 scope global 就是给eth0配置IP地址路由同理,一般这个区域不需要配置 这里实际上就是给服务器配置真实的IP地址和路由的在复杂的环境下可能需要配置一般不会用这个来配置我们可以直接用vi /etc/sysconfig/network-script/ifcfg-eth1来配置切记这里可不是VIP不要搞混淆了切记切记
VRRPD配置
包括三个类:
- VRRP同步组(synchroization group)
- VRRP实例(VRRP Instance)
- VRRP脚本
# VRRP同步组(synchroization group)配置范例 vrrp_sync_group VG_1 { //注意vrrp_sync_group 后面可自定义名称如lvs_httpd ,httpd group { http mysql } notify_master /path/to/to_master.sh notify_backup /path_to/to_backup.sh notify_fault "/path/fault.sh VG_1" notify /path/to/notify.sh smtp_alert } 其中http和mysql是实例名和下面的实例名一致 notify_master /path/to/to_master.sh //表示当切换到master状态时要执行的脚本 notify_backup /path_to/to_backup.sh //表示当切换到backup状态时要执行的脚本 notify_fault "/path/fault.sh VG_1" // keepalived出现故障时执行的脚本 notify /path/to/notify.sh smtp_alert //表示切换时给global defs中定义的邮件地址发送邮件通知# VRRP实例(instance)配置范例 vrrp_instance http { //注意vrrp_instance 后面可自定义名称如lvs_httpd ,httpd state MASTER interface eth0 dont_track_primary track_interface { eth0 eth1 } mcast_src_ip <IPADDR> garp_master_delay 10 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS autp_pass 1234 } virtual_ipaddress { #<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPT> label <LABEL> 192.168.200.17/24 dev eth1 192.168.200.18/24 dev eth2 label eth2:1 } virtual_routes { # src <IPADDR> [to] <IPADDR>/<MASK> via|gw <IPADDR> dev <STRING> scope <SCOPE> tab src 192.168.100.1 to 192.168.109.0/24 via 192.168.200.254 dev eth1 192.168.110.0/24 via 192.168.200.254 dev eth1 192.168.111.0/24 dev eth2 192.168.112.0/24 via 192.168.100.254 } nopreempt preemtp_delay 300 debug }
state: state指定instance(Initial)的初始状态就是说在配置好后这台 服务器的初始状态就是这里指定的但这里指定的不算还是得要通过竞选通过优先级来确定里如果这里设置为master但如若他的优先级不及另外一台 那么这台在发送通告时会发送自己的优先级另外一台发现优先级不如自己的高那么他会就回抢占为master
interface: 实例绑定的网卡因为在配置虚拟VIP的时候必须是在已有的网卡上添加的
dont track primary: 忽略VRRP的interface错误
track interface: 跟踪接口设置额外的监控里面任意一块网卡出现问题都会进入故障(FAULT)状态例如用nginx做均衡器的时候内网必须正常工作如果内网出问题了这个均衡器也就无法运作了所以必须对内外网同时做健康检查
mcast src ip: 发送多播数据包时的源IP地址这里注意了这里实际上就是在那个地址上发送VRRP通告这个非常重要一定要选择稳定的网卡端口来发送这里相当于heartbeat的心跳端口如果没有设置那么就用默认的绑定的网卡的IP也就是interface指定的IP地址
garp master delay: 在切换到master状态后延迟进行免费的ARP(gratuitous ARP)请求,默认5s
virtual router id: 这里设置VRID这里非常重要相同的VRID为一个组他将决定多播的MAC地址
priority 100: 设置本节点的优先级优先级高的为master
advert int: 设置MASTER与BACKUP负载均衡之间同步即主备间通告时间检查的时间间隔,单位为秒,默认1s
virtual ipaddress: 这里设置的就是VIP也就是虚拟IP地址他随着state的变化而增加删除当state为master的时候就添加当state为backup的时候删除这里主要是有优先级来决定的和state设置的值没有多大关系这里可以设置多个IP地址
virtual routes: 原理和virtual ipaddress一样只不过这里是增加和删除路由
lvs sync daemon interface: lvs syncd绑定的网卡,类似HA中的心跳检测绑定的网卡
authentication: 这里设置认证
auth type: 认证方式可以是PASS或AH两种认证方式
auth pass: 认证密码
nopreempt: 设置不抢占master,这里只能设置在state为backup的节点上而且这个节点的优先级必须别另外的高,比如master因为异常将调度圈交给了备份serve,master serve检修后没问题,如果不设置nopreempt就会将调度权重新夺回来,这样就容易造成业务中断问题
preempt delay: 抢占延迟多少秒,即延迟多少秒后竞选master
debug:debug级别
notify master:和sync group这里设置的含义一样可以单独设置例如不同的实例通知不同的管理人员http实例发给网站管理员mysql的就发邮件给DBA
# VRRP脚本 # 如下所示为相关配置示例 vrrp_script check_running {script "/usr/local/bin/check_running"interval 10weight 10 }vrrp_instance http {state BACKUPsmtp_alertinterface eth0virtual_router_id 101priority 90advert_int 3authentication {auth_type PASSauth_pass whatever}virtual_ipaddress {1.1.1.1}track_script {check_running } } # 首先在vrrp_script区域定义脚本名字和脚本执行的间隔和脚本执行的优先级变更,如下所示: vrrp_script check_running {script "/usr/local/bin/check_running"interval 10 #脚本执行间隔weight 10 #脚本结果导致的优先级变更10表示优先级+10-10则表示优先级-10} # 然后在实例(vrrp_instance)里面引用有点类似脚本里面的函数引用一样先定义后引用函数名 track_script {check_running }
注意:
VRRP脚本(vrrp_script)和VRRP实例(vrrp_instance)属于同一个级别
keepalived会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级。一般脚本检测返回的值为0,说明脚本检测成功,如果为非0数值,则说明检测失败
如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加, 如果weight为非0,则优先级不变
如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少, 如果weight为0,则优先级不变
其他情况,维持原本配置的优先级,即配置文件中priority对应的值。
这里需要注意的是:
1) 优先级不会不断的提高或者降低
2) 可以编写多个检测脚本并为每个检测脚本设置不同的weight
3) 不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况
这样可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
virtual_server 虚拟主机配置
关于keeplived的虚拟主机配置有三种如下所示
virtual server IP port
virtual server fwmark int
virtual server group string
以常用的第一种为例
virtual_server 192.168.1.2 80
含义:设置一个virtual server: VIP:Vport
delay_loop 3
含义:设置service polling的delay时间即服务轮询的时间间隔
lb_algo rr|wrr|lc|wlc|lblc|sh|dh
含义:设置LVS调度算法
lb_kind NAT|DR|TUN
含义:设置LVS集群模式
persistence_timeout 120
含义:设置会话保持时间秒为单位即以用户在120秒内被分配到同一个后端realserver,超过此时间就重新分配
persistence_granularity
含义:设置LVS会话保持粒度ipvsadm中的-M参数默认是0xffffffff即每个客户端都做会话保持
protocol TCP
含义:设置健康检查用的是TCP还是UDP
ha_suspend
含义:suspendhealthchecker’s activity
virtualhost
含义:HTTP_GET做健康检查时检查的web服务器的虚拟主机即host头
sorry_server
含义:设置backupserver就是当所有后端realserver节点都不可用时就用这里设置的也就是临时把所有的请求都发送到这里
real_server
含义:设置后端真实节点主机的权重等设置主要后端有几台这里就要设置几个
weight 1
含义:设置给每台的权重0表示失效(不知给他转发请求知道他恢复正常)默认是1
inhibit_on_failure
含义:表示在节点失败后把他权重设置成0而不是冲IPVS中删除
notify_up |
含义:设置检查服务器正常(UP)后要执行的脚本
notify_down |
含义:设置检查服务器失败(down)后要执行的脚本
注:keepalived检查机制说明
keepalived健康检查方式有:HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK几种如下所示
#HTTP/HTTPS方式 HTTP_GET|SSL_GET { #设置健康检查方式url { #设置要检查的URL可以有多个 path / #设置URL具体路径 digest <STRING> #检查后的摘要信息这些摘要信息可以通过genhash命令工具获取 status_code 200 #设置返回状态码 } connect_port 80 #设置监控检查的端口 bindto <IPADD> #设置健康检查的IP地址 connect_timeout 3 #设置连接超时时间 nb_get_retry 3 #设置重连次数 delay_before_retry 2 #设置重连间隔 } #TCP方式 TCP_CHECK { connect_port 80 #设置监控检查的端口 bindto <IPADD> #设置健康检查的IP地址 connect_timeout 3 #设置连接超时时间 nb_get_retry 3 #设置重连次数 delay_before_retry 2 #设置重连间隔 } #SMTP方式 (这个可以用来给邮件服务器做集群) SMTP_CHECK { host { connect_ip <IP ADDRESS> connect_port <PORT> #默认检查25端口 14 KEEPALIVED bindto <IP ADDRESS> } connect_timeout <INTEGER> retry <INTEGER> delay_before_retry <INTEGER> helo_name <STRING>|<QUOTED-STRING> } #MISC方式 这个可以用来检查很多服务器只需要自己会些脚本即可 MISC_CHECK { misc_path <STRING>|<QUOTED-STRING> #外部程序或脚本 misc_timeout <INT> #脚本或程序执行超时时间 misc_dynamic #这个就很好用了可以非常精确的来调整权重是后端每天服务器的压力都能均衡调配这个主要是通过执行的程序或脚本返回的状态代码来动态调整weight值使权重根据真实的后端压力来适当调整不过这需要有过硬的脚本功夫才行哦 #返回0健康检查没问题不修改权重 #返回1健康检查失败权重设置为0 #返回2-255健康检查没问题但是权重却要根据返回代码修改为返回码-2例如如果程序或脚本执行后返回的代码为200#那么权重这回被修改为 200-2 }
以上就是keepalived的配置项说明虽然配置项很多但很多时候很多配置项保持默认即可
lvs+keepalived配置实践
防火墙的配置不在本文的范围,请关闭selinux和firewall
# 关闭防火墙 systemctl disable firewalld systemctl stop firewalld# 禁用selinux setenforce 0 vi /etc/selinux/configSELINUX=disabled# 安装keepalived,ipvsadm yum install keepalived ipvsadm -y# 开启LVS服务器的IP路由转发功能 echo "1" > /proc/sys/net/ipv4/ip_forward # 添加路由转发至sysctl.conf vi /etc/sysctl.conf net.ipv4.ip_forward = 1
最简单的keepalived做HA
# 编辑keepalived配置文件 vi /etc/keepalived/keepalived.confvrrp_sync_group VI_GOP_NC1_LB1 {group {VI_VI_GOP_NC1_LB1_1VI_VI_GOP_NC1_LB1_2} }vrrp_instance VI_VI_GOP_NC1_LB1_1 {state BACKUPinterface bond0virtual_router_id 28priority 100advert_int 1nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {10.65.32.28/23 dev bond0} }vrrp_instance VI_VI_GOP_NC1_LB1_2 {state BACKUPinterface bond0virtual_router_id 29priority 100advert_int 1nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {10.65.32.29/23 dev bond0} }
配置LVS-DR
# Install keepalived # Ubuntu apt-get install keepalived ipvsadm # CentOS yum install keepalived ipvsadm # mod iptables vim /etc/sysconfig/iptables# LVS configuration ## For keepalived: ### allow vrrp (112) -A INPUT -p vrrp -j ACCEPT -A INPUT -p igmp -j ACCEPT ### allow multicast -A INPUT -d 224.0.0.18 -j ACCEPT# restart iptables service iptables restart# example # two vip for lvs-drvrrp_sync_group GOP {group {VI_PRI_CONNECTVI_PRI_AUTH} }vrrp_instance VI_PRI_CONNECT {state BACKUPinterface bond0virtual_router_id 128priority 100advert_int 1nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {10.65.32.28/23 dev bond0} }virtual_server 10.65.32.28 80 {delay_loop 6lb_algo rrlb_kind DRprotocol TCPreal_server 10.65.32.13 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}}real_server 10.65.32.14 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}}real_server 10.65.32.15 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}}real_server 10.65.32.16 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}}real_server 10.65.32.17 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}}real_server 10.65.32.18 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}} }virtual_server 10.65.32.28 443 {delay_loop 6lb_algo rrlb_kind DRprotocol TCPreal_server 10.65.32.13 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}}real_server 10.65.32.14 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}}real_server 10.65.32.15 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}}real_server 10.65.32.16 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}}real_server 10.65.32.17 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}}real_server 10.65.32.18 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}} }vrrp_instance VI_PRI_AUTH {state BACKUPinterface bond0virtual_router_id 129priority 100advert_int 1nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {10.65.32.29/23 dev bond0} }virtual_server 10.65.32.29 80 {delay_loop 6lb_algo rrlb_kind DRprotocol TCPreal_server 10.65.32.22 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}}real_server 110.65.32.23 80 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 80}} }virtual_server 10.65.32.29 443 {delay_loop 6lb_algo rrlb_kind DRprotocol TCPreal_server 10.65.32.22 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}}real_server 110.65.32.23 443 {weight 100TCP_CHECK {connect_timeout 3nb_get_retry 3delay_before_retry 3connect_port 443}} }# enable and start keepalived systemctl start keepalived systemctl enable keepalived watch ipvsadm -L -n --stats
real server
- Edit “/etc/sysconfig/network-scripts/ifcfg-lo” to patch bug in Centos 7 (if using Centos 7). Add TYPE=Loopback to the file.
- Add loopback for each Virtual IP on each worker. E.g. first virtual IP create file “/etc/sysconfig/network-scripts/ifcfg-lo:0”.
- Start adapters if not yet started
# add TYPE=Loopback echo "TYPE=Loopback" >> /etc/sysconfig/network-scripts/ifcfg-lo # add ifcfg-lo:0 cat > /etc/sysconfig/network-scripts/ifcfg-lo:0 << EOF DEVICE=lo:0 IPADDR=10.65.32.28 NETMASK=255.255.255.255 ONBOOT=yes EOF# ifup lo:0 ifup lo:0# add real_start cat > /root/real_start.sh << EOF #!/bin/bash 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 EOF# chmod 755 chmod 755 /root/real_start.sh# add real.service cat > /usr/lib/systemd/system/real.service << EOF [Unit] Description=autostart lvs real After=network.target remote-fs.target nss-lookup.target[Service] Type=forking ExecStart=/root/real_start.sh[Install] WantedBy=multi-user.target EOF# enable service systemctl enable real.service# lvs real server example vim /root/lvs_real.sh#!/bin/bash ### BEGIN INIT INFO # Provides: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start realserver # Description: Start realserver ### END INIT INFO# change the VIP to proper value VIP=10.65.32.28case "$1" instart)echo "Start REAL Server"/sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 upecho "1" >/proc/sys/net/ipv4/conf/lo/arp_ignoreecho "2" >/proc/sys/net/ipv4/conf/lo/arp_announceecho "1" >/proc/sys/net/ipv4/conf/all/arp_ignoreecho "2" >/proc/sys/net/ipv4/conf/all/arp_announce;;stop)/sbin/ifconfig lo:0 downecho "Stop REAL Server"echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignoreecho "0" >/proc/sys/net/ipv4/conf/lo/arp_announceecho "0" >/proc/sys/net/ipv4/conf/all/arp_ignoreecho "0" >/proc/sys/net/ipv4/conf/all/arp_announce;;restart)$0 stop$0 start;;*)echo "Usage: $0 {start|stop}"exit 1;; esacexit 0
常见问题
ARP导致MAC地址冲突
[root@sg-gop-10-65-32-35 wangao]# arp -n Address HWtype HWaddress Flags Mask Iface 10.65.32.31 ether 48:8e:ef:7b:c6:0a C bond0 10.65.32.83 ether 50:5d:ac:ed:89:dd C bond0 10.65.32.254 ether 00:00:0c:9f:f0:ec C bond0 10.65.32.252 ether bc:16:65:68:07:81 C bond0 10.65.32.34 ether 50:1d:93:f5:eb:97 C bond0 10.65.32.8 ether 48:8e:ef:7c:0a:8d C bond0 10.65.32.253 ether 18:e7:28:97:e5:01 C bond0 [root@sg-gop-10-65-32-35 wangao]# arp -d 10.65.32.31 [root@sg-gop-10-65-32-35 wangao]# [root@sg-gop-10-65-32-35 wangao]# [root@sg-gop-10-65-32-35 wangao]# telnet 10.65.32.31 12100 Trying 10.65.32.31... Connected to 10.65.32.31. Escape character is '^]'.[root@sg-gop-10-65-32-35 wangao]# arp -n Address HWtype HWaddress Flags Mask Iface 10.65.32.31 ether 48:8e:ef:7b:c7:5a C bond0 10.65.32.70 ether 00:2e:c7:3a:a5:b5 C bond0 10.65.32.83 ether 50:5d:ac:ed:89:dd C bond0 10.65.32.254 ether 00:00:0c:9f:f0:ec C bond0 10.65.32.252 ether bc:16:65:68:07:81 C bond0 10.65.32.34 ether 50:1d:93:f5:eb:97 C bond0 10.65.32.8 ether 48:8e:ef:7c:0a:8d C bond0 10.65.32.253 ether 18:e7:28:97:e5:01 C bond0