在 lvs+keepalived 环境里面,lvs 主要的工作是提供调度算法,把客户端请求按照需求调度在 real 服务器,keepalived 主要的工作是提供 lvs 控制器的一个冗余,并且对 real 服务器做健康检查,发现不健康的 real 服务器,就把它从 lvs 集群中剔除,real 服务器只负责提供服务。
LVS
LVS 是一个开源的软件,可以实现 LINUX 平台下的简单负载均衡。LVS 是 Linux Virtual Server 的缩写,意思是 Linux 虚拟服务器。
LB 集群的架构和原理很简单,就是当用户的请求过来时,会直接分发到 Director Server 上,然后它把用户的请求根据设置好的调度算法,智能均衡地分发到后端真正服务器 (real server) 上。为了避免不同机器上用户请求得到的数据不一样,需要用到了共享存储,这样保证所有用户请求的数据是一样的。
LVS 是 Linux Virtual Server 的简称,也就是 Linux 虚拟服务器。这是一个由章文嵩博士发起的一个开源项目,它的官方网站是 http://www.linuxvirtualserver.org 现在 LVS 已经是 Linux 内核标准的一部分。使用 LVS 可以达到的技术目标是:通过 LVS 达到的负载均衡技术和 Linux 操作系统实现一个高性能高可用的 Linux 服务器集群,它具有良好的可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的性能。LVS 是一个实现负载均衡集群的开源软件项目,LVS 架构从逻辑上可分为调度层、Server 集群层和共享存储。
目前有三种 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 隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连 在同一物理网段上。
三种模式的主要区别
VS/NAT
VS/TUN
VS/DR
server
any
tunneling
non-arp device
server network
private
LAN/WAN
LAN
server number
low (10~20)
high
high
server gateway
load balancer
own router
own router
模式与特点
NAT 模式
IPIP 模式
DR 模式
对服务器的要求
服务节点可以使任何操作系统
必须支持 IP 隧道,目前只有 Linux 系统支持
服务器节点支持虚拟网卡设备,能够禁用设备的 ARP 响应
网络要求
拥有私有 IP 地址的局域网络
拥有合法 IP 地址的局域,网或广域网
拥有合法 IP 地址的局域,服务器节点与负载均衡器必须在同一个网段
通常支持节点数量
10 到 20 个,根据负载均衡器的处理能力而定
较高,可以支持 100 个服务节点
较高,可以支持 100 个服务节点
网关
负载均衡器为服务器节点网关
服务器的节点同自己的网关或者路由器连接,不经过负载均衡器
服务节点同自己的网关或者路由器连接,不经过负载均衡器
服务节点安全性
较好,采用内部 IP,服务节点隐蔽
较差,采用公用 IP 地址,节点安全暴露
较差,采用公用 IP 地址,节点安全暴露
IP 要求
仅需要一个合法的 IP 地址作为 VIP 地址
除了 VIPO 地址外,每个服务器界定啊需要拥有合法的 IP 地址,可以直接从路由到客户端
除了 VIP 外,每个服务节点需拥有合法的 IP 地址,可以直接从路由到客户端
特点
地址转换
封装 IP
修改 MAC 地址
配置复杂度
简单
复杂
复杂
基本工作原理
当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间
PREROUTING 链首先会接收到用户请求,判断目标 IP 确定是本机 IP,将数据包发往 INPUT 链
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 方式的实现原理和数据包的改变。
(1). 当用户请求到达 Director Server,此时请求的数据报文会先到内核空间的 PREROUTING 链。 此时报文的源 IP 为 CIP,目标 IP 为 VIP (2). PREROUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链 (3). IPVS 比对数据包请求的服务是否为集群服务,若是,修改数据包的目标 IP 地址为后端服务器 IP,然后将数据包发至 POSTROUTING 链。 此时报文的源 IP 为 CIP,目标 IP 为 RIP (4). POSTROUTING 链通过选路,将数据包发送给 Real Server (5). Real Server 比对发现目标为自己的 IP,开始构建响应报文发回给 Director Server。 此时报文的源 IP 为 RIP,目标 IP 为 CIP (6). Director Server 在响应客户端前,此时会将源 IP 地址修改为自己的 VIP 地址,然后响应给客户端。 此时报文的源 IP 为 VIP,目标 IP 为 CIP
LVS/NAT 模型的特性
RS 应该使用私有地址,RS 的网关必须指向 DIP
DIP 和 RIP 必须在同一个网段内
请求和响应报文都需要经过 Director Server,高负载场景中,Director Server 易成为性能瓶颈
支持端口映射
RS 可以使用任意操作系统
缺陷:对 Director Server 压力会比较大,请求和响应都需经过 director server
(1) 当用户请求到达 Director Server,此时请求的数据报文会先到内核空间的 PREROUTING 链。 此时报文的源 IP 为 CIP,目标 IP 为 VIP (2) PREROUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链 (3) IPVS 比对数据包请求的服务是否为集群服务,若是,将请求报文中的源 MAC 地址修改为 DIP 的 MAC 地址,将目标 MAC 地址修改 RIP 的 MAC 地址,然后将数据包发至 POSTROUTING 链。 此时的源 IP 和目的 IP 均未修改,仅修改了源 MAC 地址为 DIP 的 MAC 地址,目标 MAC 地址为 RIP 的 MAC 地址 (4) 由于 DS 和 RS 在同一个网络中,所以是通过二层来传输。POSTROUTING 链检查目标 MAC 地址为 RIP 的 MAC 地址,那么此时数据包将会发至 Real Server。 (5) RS 发现请求报文的 MAC 地址是自己的 MAC 地址,就接收此报文。处理完成之后,将响应报文通过 lo 接口传送给 eth0 网卡然后向外发出。 此时的源 IP 地址为 VIP,目标 IP 为 CIP (6) 响应报文最终送达至客户端
LVS/DR 模型的特性
特点 1:保证前端路由将目标地址为 VIP 报文统统发给 Director Server,而不是 RS
在原有的 IP 报文外再次封装多一层 IP 首部,内部 IP 首部(源地址为 CIP,目标 IIP 为 VIP),外层 IP 首部(源地址为 DIP,目标 IP 为 RIP)
(1) 当用户请求到达 Director Server,此时请求的数据报文会先到内核空间的 PREROUTING 链。 此时报文的源 IP 为 CIP,目标 IP 为 VIP 。 (2) PREROUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链 (3) IPVS 比对数据包请求的服务是否为集群服务,若是,在请求报文的首部再次封装一层 IP 报文,封装源 IP 为 DIP,目标 IP 为 RIP。然后发至 POSTROUTING 链。 此时源 IP 为 DIP,目标 IP 为 RIP (4) POSTROUTING 链根据最新封装的 IP 报文,将数据包发至 RS(因为在外层封装多了一层 IP 首部,所以可以理解为此时通过隧道传输)。 此时源 IP 为 DIP,目标 IP 为 RIP (5) RS 接收到报文后发现是自己的 IP 地址,就将报文接收下来,拆除掉最外层的 IP 后,会发现里面还有一层 IP 首部,而且目标是自己的 lo 接口 VIP,那么此时 RS 开始处理此请求,处理完成之后,通过 lo 接口送给 eth0 网卡,然后向外传递。 此时的源 IP 地址为 VIP,目标 IP 为 CIP (6) 响应报文最终送达至客户端
LVS/TUN 模型特性
RIP、VIP、DIP 全是公网地址
RS 的网关不会也不可能指向 DIP
所有的请求报文经由 Director Server,但响应报文必须不能进过 Director Server
不支持端口映射
RS 的系统必须支持隧道
其实企业中最常用的是 DR 实现方式,而 NAT 配置上比较简单和方便,后边实践中会总结 DR 和 NAT 具体使用配置过程。
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 倍
加权最少链接 wlc(Weighted Least Connections) 在集群系统中的服务器性能差异较大的情况下,调度器采用 “加权最少链接” 调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
基于局部性的最少链接 lblc(Locality-Based Least Connections) “基于局部性的最少链接” 调度算法是针对目标 IP 地址的负载均衡,目前主要用于 Cache 集群系统。该算法根据请求的目标 IP 地址找出该目标 IP 地址最近使用的服务器,若该服务器 是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用 “最少链接” 的原则选出一个可用的服务 器,将请求发送到该服务器。
带复制的基于局部性最少链接 lblcr(Locality-Based Least Connections with Replication) “带复制的基于局部性最少链接” 调度算法也是针对目标 IP 地址的负载均衡,目前主要用于 Cache 集群系统。它与 LBLC 算法的不同之处是它要维护从一个 目标 IP 地址到一组服务器的映射,而 LBLC 算法维护从一个目标 IP 地址到一台服务器的映射。该算法根据请求的目标 IP 地址找出该目标 IP 地址对应的服务 器组,按 “最小连接” 原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器,若服务器超载;则按 “最小连接” 原则从这个集群中选出一 台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的 程度。
目标地址散列 dh(Destination Hashing) “目标地址散列” 调度算法根据请求的目标 IP 地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
源地址散列 sh(Source Hashing) “源地址散列” 调度算法根据请求的源 IP 地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
# 静态地址和路由配置范例 static_ipaddress { 192.168.1.1/24 brd + dev eth0 scope global 192.168.1.2/24 brd + dev eth1 scope global } static_routes { src $SRC_IP to $DST_IP dev $SRC_DEVICE src $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 不要搞混淆了切记切记
Commands: Either long or short options are allowed. --add-service -A add virtual service with options --edit-service -E edit virtual service with options --delete-service -D delete virtual service --clear -C clear the whole table --restore -R restore rules from stdin --save -S save rules to stdout --add-server -a add real server with options --edit-server -e edit real server with options --delete-server -d delete real server --list -L|-l list the table --zero -Z zero counters in a service or all services --set tcp tcpfin udp set connection timeout values --start-daemon start connection sync daemon --stop-daemon stop connection sync daemon --help -h display this help message
Options: --tcp-service -t service-address service-address is host[:port] --udp-service -u service-address service-address is host[:port] --fwmark-service -f fwmark fwmark is an integer greater than zero --ipv6 -6 fwmark entry uses IPv6 --scheduler -s scheduler one of rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq, the default scheduler is wlc. --pe engine alternate persistence engine may be sip, not set by default. --persistent -p [timeout] persistent service --netmask -M netmask persistent granularity mask --real-server -r server-address server-address is host (and port) --gatewaying -g gatewaying (direct routing) (default) --ipip -i ipip encapsulation (tunneling) --masquerading -m masquerading (NAT) --weight -w weight capacity of real server --u-threshold -x uthreshold upper threshold of connections --l-threshold -y lthreshold lower threshold of connections --mcast-interface interface multicast interface for connection sync --syncid sid syncid for connection sync (default=255) --connection -c output of current IPVS connections --timeout output of timeout (tcp tcpfin udp) --daemon output of daemon information --stats output of statistics information --rate output of rate information --exact expand numbers (display exact values) --thresholds output of thresholds information --persistent-conn output of persistent connection info --nosort disable sorting output of service/server entries --sort does nothing, for backwards compatibility --ops -o one-packet scheduling --numeric -n numeric output of addresses and ports --sched-flags -b flags scheduler flags (comma-separated)
# 编写 DS 脚本,推荐用 keepalived 配置文件 #!/bin/sh # Startup script handle the initialisation of LVS # chkconfig: - 28 72 # description: Initialise the Linux Virtual Server for TUN # ### BEGIN INIT INFO # Provides: ipvsadm # Required-Start: $local_fs $network $named # Required-Stop: $local_fs $remote_fs $network # Short-Description: Initialise the Linux Virtual Server # Description: The Linux Virtual Server is a highly scalable and highly # available server built on a cluster of real servers, with the load # balancer running on Linux. # description: start LVS of TUN LOCK=/var/lock/lvs-tun.lock VIP=10.10.36.11 RIP1=10.10.36.4 RIP2=10.10.36.7 . /etc/rc.d/init.d/functions
then echo"The LVS-TUN Server is already running !" else #Load the tun mod /sbin/modprobe tun /sbin/modprobe ipip #Set the tun Virtual IP Address /sbin/ifconfig tunl0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev tunl0 #Clear IPVS Table /sbin/ipvsadm -C #The icmp recruit setting echo"0" >/proc/sys/net/ipv4/ip_forward echo"0" >/proc/sys/net/ipv4/conf/all/send_redirects echo"0" >/proc/sys/net/ipv4/conf/default/send_redirects #Set Lvs /sbin/ipvsadm -At $VIP:80 -s rr /sbin/ipvsadm -at $VIP:80 -r $RIP1:80 -i -w 1 /sbin/ipvsadm -at $VIP:80 -r $RIP2:80 -i -w 1 /bin/touch $LOCK #Run Lvs echo"starting LVS-TUN-DIR Server is ok !" fi }
stop() { #stop Lvs server /sbin/ipvsadm -C /sbin/ifconfig tunl0 down >/dev/null #Remove the tun mod /sbin/modprobe -r tun /sbin/modprobe -r ipip rm -rf $LOCK echo"stopping LVS-TUN-DIR server is ok !" }
status() { if [ -e $LOCK ]; then echo"The LVS-TUN Server is already running !" else echo"The LVS-TUN Server is not running !" fi }
#!/bin/sh # # Startup script handle the initialisation of LVS # chkconfig: - 28 72 # description: Initialise the Linux Virtual Server for TUN # ### BEGIN INIT INFO # Provides: ipvsadm # Required-Start: $local_fs $network $named # Required-Stop: $local_fs $remote_fs $network # Short-Description: Initialise the Linux Virtual Server # Description: The Linux Virtual Server is a highly scalable and highly # available server built on a cluster of real servers, with the load # balancer running on Linux. # description: start LVS of TUN-RIP LOCK=/var/lock/ipvsadm.lock VIP=10.10.36.11 . /etc/rc.d/init.d/functions start() { PID=`ifconfig | grep tunl0 | wc -l` if [ $PID -ne 0 ]; then echo"The LVS-TUN-RIP Server is already running !" else #Load the tun mod /sbin/modprobe tun /sbin/modprobe ipip #Set the tun Virtual IP Address /sbin/ifconfig tunl0 $VIP netmask 255.255.255.255 broadcast $VIP up /sbin/route add -host $VIP dev tunl0 echo"1" >/proc/sys/net/ipv4/conf/tunl0/arp_ignore echo"2" >/proc/sys/net/ipv4/conf/tunl0/arp_announce echo"1" >/proc/sys/net/ipv4/conf/all/arp_ignore echo"2" >/proc/sys/net/ipv4/conf/all/arp_announce echo"0" > /proc/sys/net/ipv4/conf/tunl0/rp_filter echo"0" > /proc/sys/net/ipv4/conf/all/rp_filter /bin/touch $LOCK echo"starting LVS-TUN-RIP server is ok !" fi }
stop() { /sbin/ifconfig tunl0 down echo"0" >/proc/sys/net/ipv4/conf/tunl0/arp_ignore echo"0" >/proc/sys/net/ipv4/conf/tunl0/arp_announce echo"0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo"0" >/proc/sys/net/ipv4/conf/all/arp_announce #Remove the tun mod /sbin/modprobe -r tun /sbin/modprobe -r ipip rm -rf $LOCK echo"stopping LVS-TUN-RIP server is ok !" }
status() { if [ -e $LOCK ]; then echo"The LVS-TUN-RIP Server is already running !" else echo"The LVS-TUN-RIP Server is not running !" fi }
# 关于 3 中模式的参数 [packet-forwarding-method] -g, --gatewaying Use gatewaying (direct routing). This is the default. -i, --ipip Use ipip encapsulation (tunneling). -m, --masquerading Use masquerading (network access translation, or NAT). Note: Regardless of the packet-forwarding mechanism specified, real servers for addresses forwhich there are interfaces on the local node will be use the local forwarding method, then packets for the servers will be passed to upper layer on the local node. This cannot be specified by ipvsadm, rather it set by the kernel as real servers are added or modified.
在 ARP 协议中,为了减少 arp 请求的次数,当主机接收到询问自己的 arp 请求的时候,就会把源 ip 和源 Mac 放入自 己的 arp 表里面,方便接下来的通讯。如果收到不是询问自己的包(arp 是广播的,所有人都收到),就会丢掉,这样不会造成 arp 表里面无用数据太多导致 有用的记录被删除。
在 LVS 的 VS/DR 模式下,当内网的真实服务器(Linux 主机)要发送一个到外部网络的 ip 包(LVS 负载器分配置过来的作业的处理结果),那么它就会请求路由器的 Mac 地址,发送一个 arp 请求,这个 arp 请求里面包括了自己的 ip 地址和 Mac 地址。而 linux 主机默认是使用 ip 数据包的源 ip 地址作为 arp 里面的源 ip 地址,而不是使用发送设备上面网络接口卡的 ip 地址。这样在 LVS 的 VS/DR 架构下,所有真实服务器在响应外部请求时的 IP 数据包的源地址都是同一个 VIP 地址,那么 arp 请求就会包括 VIP 地址和设备 Mac。而路由器收到这个 arp 请求就会更新自己的 arp 缓存,这样就会造成 ip 欺骗了,VIP 被抢夺,所以就会有问题。
# Options for keepalived. See `keepalived --help'output and keepalived(8) and # keepalived.conf(5) man pages for a list of all options. Here are the most # common ones : # # --vrrp -P Only run with VRRP subsystem. # --check -C Only run with Health-checker subsystem. # --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTEs on daemon stop. # --dont-release-ipvs -I Dont remove IPVS topology on daemon stop. # --dump-conf -d Dump the configuration data. # --log-detail -D Detailed log messages. # --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON) #