【均衡负载之LVS 系列三】 - 高可用 LVS+KeepAlived 集群
在该系列前两篇文章中,我们全面认识了LVS并配置完成了简单的DR-LVS集群。当集群的请求量过大时,LVS会有宕机的可能,为提高集群的高可用性并增加后端检测功能、简化配置,在集群中引入KeepAlived。
KeepAlived
KeepAlived 简介
KeepAlived最初是为LVS设计,用来管理并监控LVS集群系统中各个服务节点的状态,后来加入了VRRP功能,发展一个多功能、通用的轻量级高可用组件,可以为ipvs、nginx、haproxy等诸多服务提供高可用功能。
上图是Keepalived的功能体系结构,大致分两层
内核空间(kernel space):
- IPVS :IP虚拟服务器,用于实现网络服务的负载均衡
- NETLINK :提供高级路由及其他相关的网络功能
用户空间(user space):
- WatchDog:负载监控checkers和VRRP进程的状况
- VRRP Stack:负责负载均衡器之间的 FailOver 失败切换,如果只用一个负载均衡器,则VRRP不是必须的。
- Checkers:负责真实服务器的 healthchecking 健康检查,是keepalived最主要的功能。换言之,可以没有VRRP Stack,但healthchecking是一定要有的。
- IPVS wrapper:将用户设定的规则发送到内核ipvs
- Netlink Reflector:用来设定vrrp的vip地址等。
- Control Plane:配置文件分析器,用来实现配置文件的分析和加载
- Memory Mngt:内存管理组件
认识 VRRP
在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接。对于这样的情况,它们之间路由怎样选择?主机如何选定到达目的主机的下一跳路由,这个问题通常的解决方法有二种:
- 在主机上使用动态路由协议(RIP、OSPF等)
- 在主机上配置静态路由
很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过一竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。
VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)可以认为是实现路由器高可用的协议,简单的说,当一个路由器故障时可以由另一个备份路由器继续提供相同的服务。
即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master和多个backup,master上面有一个对外提供服务的网关ip和虚拟mac;master会发送224.0.0.18地址组播报文,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup作为master对外提供服务。这样的话就可以保证路由器的高可用,对于该路由器组所在局域网内其他主机来说还是相当于一台路由器,它们就可设置静态缺省路由网关为该路由器组ip了。
虚拟mac是虚拟路由器根据虚拟路由器ID生成MAC地址,格式为:00-00-5E-00-01-{VRID},当虚拟路由器回应ARP请求时,使用虚拟MAC地址,而不是接口的真实MAC地址。
工作机制
在一个VRRP虚拟路由器中,有多台物理的VRRP路由器,但是这多台的物理的机器并不能同时工作,而是由一台称为MASTER的负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP让每个VRRP路由器参与竞选,最终获胜的就是MASTER。MASTER拥有一些特权,比如,拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求。
VRRP根据优先级来确定虚拟路由器中每台路由器的角色(Master路由器或Backup路由器)。VRRP优先级的取值范围为0到255(数值越大表明优先级越高),可配置的范围是1到254,优先级0为系统保留给路由器放弃Master位置时候使用,255则是系统保留给IP地址拥有者使用。优先级越高,则越有可能成为Master路由器。当两台优先级相同的路由器同时竞争Master时,比较接口IP地址大小。接口地址大者当选为Master。
在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息(VRRPAdvertisement message),BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BACKUP收不到通告信息), 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性。由于安全性考虑,VRRP包使用了加密协议进行加密。
工作流程
- 初始化 Initialize 状态:
通过VRRP报文的交互获知虚拟路由器中其他成员的优先级(keepalived是通过配置文件配置优先级,所以配置定义为MASTER的主机优化级较高),其中优先级最高的成为Master路由器,其他成为Backup路由器;
当路由器处于Master状态时,它将会做下列工作:
- 设置定时通告定时器
- 以虚拟MAC地址响应对虚拟IP地址的ARP请求;
- 转发目的MAC地址为虚拟MAC地址的IP报文;
- 如果它是这个虚拟IP地址的拥有者,则接收目的IP地址为这个虚拟IP地址的IP报文;否则,丢弃这个IP报文;
- 当收到shutdown的事件时删除定时通告定时器,发送优先权级为0的通告包,转初始化状态;
- 如果定时通告定时器超时时,发送VRRP通告信息;
- 收到VRRP通告信息时,如果优先权为0,发送VRRP通告信息;若优先权非0,并且优先级高于本机,或优先权相等同时实际IP地址大于本机实际IP,则设置定时通告定时器,复位主机超时定时器,转BACKUP状态;否则,丢弃该通告包。
当路由器处于Backup状态时,它将会做下列工作:
- 设置主机超时定时器;
- 对虚拟IP地址的ARP请求,不做响应;
- 丢弃目的MAC地址为虚拟MAC地址的IP报文;
- 不接受目的是虚拟路由器IP的所有数据包;
- 当收到shutdown的事件时删除主机超时定时器,转初始化状态;
- 收到VRRP通告信息时,如果优先权为0,表示进入MASTER选举;否则判断数据的优先级是否高于本机,如果高的话承认MASTER有效,复位主机超时定时器;否则的话,丢弃该通告包;
- 主机超时定时器超时的时候,发送VRRP通告信息,广播ARP地址信息,转MASTER状态;
VRRP 与 KeepAlived
KeepAlived利用VRRP协议来实现集群中 LVS-VIP 的高可用,并解决各KeepAlived主机的角色选举及其状态问题。
KeepAlived 配置文件
keepalived只有一个配置文件keepalived.conf,里面主要包括以下几个配置区域,分别是global_defs、static_ipaddress、static_routes、vrrp_script、vrrp_instance和virtual_server。
global_defs区域
主要是配置故障发生时的通知对象以及机器标识
global_defs { notification_email { [email protected] [email protected] ... } notification_email_from [email protected] smtp_server smtp.abc.com smtp_connect_timeout 30 enable_traps router_id host163 vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 vrrp_lower_prio_no_advert vrrp_version <2 or 3> script_user <username> [groupname] enable_script_security }
notification_email
:故障发生时给谁发邮件通知。notification_email_from
:通知邮件从哪个地址发出。smpt_server
:通知邮件的smtp地址。smtp_connect_timeout
:连接smtp服务器的超时时间。enable_traps
:开启SNMP陷阱(Simple Network Management Protocol)。router_id
:主机标识,用于邮件通知。vrrp_strict
:严格执行VRRP协议规范,此模式不支持节点单播vrrp_garp_interval
:单位秒,在一个网卡上每组gratuitous arp消息之间的延迟时间,默认为0,一个发送的消息=n组 arp报文vrrp_gna_interval
:单位秒, 在一个网卡上每组na消息之间的延迟时间,默认为0vrrp_lower_prio_no_advert
:如果接收到一个低优先级的通告,只需要丢弃它,不用发送其他通告,字符类型:布尔值,false/truevrrp_version
:设置vrrp协议版本,默认是版本2script_user <username> [groupname]
:设置运行脚本的默认用户和组。如果没有指定,则默认用户为keepalived_script(需要该用户存在),否则为root用户。默认groupname同username。enable_script_security
:如果脚本路径的任一部分对于非root用户来说,都具有可写权限,则不会以root身份运行脚本。为了防止非root用户通过更改script来执行root权限的命令。
static_ipaddress和static_routes区域
static_ipaddress和static_routes区域配置的是本节点的IP和路由信息。如果你的机器上已经配置了IP和路由,那么这两个区域可以不用配置。其实,一般情况下你的机器都会有IP地址和路由信息的,因此没必要再在这两个区域配置。
static_ipaddress { 10.210.214.163/24 brd 10.210.214.255 dev eth0 ... } static_routes { 10.0.0.0/8 via 10.210.214.1 dev eth0 ... }
以上分别表示启动/关闭keepalived时在本机执行的如下命令:
# /sbin/ip addr add 10.210.214.163/24 brd 10.210.214.255 dev eth0 # /sbin/ip route add 10.0.0.0/8 via 10.210.214.1 dev eth0 //启动时 # /sbin/ip addr del 10.210.214.163/24 brd 10.210.214.255 dev eth0 # /sbin/ip route del 10.0.0.0/8 via 10.210.214.1 dev eth0 //关闭时
vrrp_script区域
用来做自身健康状态检查的,当时检查失败时会将 vrrp_instance 的 priority 减少相应的值。
vrrp_script chk_http_port { script "</dev/tcp/127.0.0.1/80" interval 1 weight -10 fall 3 rise 2 user keepalived_script }
script
:周期性执行的脚本。interval
:运行脚本的间隔时间,秒。weight
:执行失败时所加的权重(负值),priority加上此值要小于备服务的priority值。fall
:检测几次失败才为失败,整数。rise
:检测几次正常才为正常,整数。enable_traps
:执行脚本的用户或组。
以上意思是如果script
中的指令执行失败,认为本机不是很健康,那么相应的vrrp_instance的优先级会减少10个点。
vrrp_instance和vrrp_sync_group区域
vrrp_instance用来定义对外提供服务的VIP区域及其相关属性。
vrrp_rsync_group用来定义vrrp_intance组,使得这个组内成员动作一致。举个例子来说明一下其功能:
两个vrrp_instance同属于一个vrrp_rsync_group,那么其中一个vrrp_instance发生故障切换时,另一个vrrp_instance也会跟着切换(即使这个instance没有发生故障)。
vrrp_sync_group VG_1 { group { inside_network # name of vrrp_instance (below) outside_network # One for each moveable IP. ... } notify_master /path/to_master.sh notify_backup /path/to_backup.sh notify_fault "/path/fault.sh VG_1" notify /path/notify.sh smtp_alert } vrrp_instance VI_1 { state MASTER interface ens33 use_vmac <VMAC_INTERFACE> dont_track_primary track_interface { eth0 eth1 } mcast_src_ip <IPADDR> lvs_sync_daemon_interface eth1 garp_master_delay 10 virtual_router_id 1 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 12345678 } virtual_ipaddress { 10.210.214.253/24 brd 10.210.214.255 dev eth0 192.168.1.11/24 brd 192.168.1.255 dev eth1 } virtual_routes { 172.16.0.0/12 via 10.210.214.1 192.168.1.0/24 via 192.168.1.1 dev eth1 default via 202.102.152.1 } track_script { chk_http_port } nopreempt preempt_delay 300 debug notify_master <STRING>|<QUOTED-STRING> notify_backup <STRING>|<QUOTED-STRING> notify_fault <STRING>|<QUOTED-STRING> notify <STRING>|<QUOTED-STRING> smtp_alert }
notify_master/backup/fault
:分别表示切换为主/备/出错时所执行的脚本。notify
:表示任何一状态切换时都会调用该脚本,并且该脚本在以上三个脚本执行完成之后进行调用,keepalived会自动传递三个参数($1 = "GROUP"|"INSTANCE",$2 = name of group or instance,$3 = target state of transition(MASTER/BACKUP/FAULT))。smtp_alert
:表示是否开启邮件通知(用全局区域的邮件设置来发通知)。state
:可以是MASTER或BACKUP,不过当其他节点keepalived启动时会将priority比较大的节点选举为MASTER,因此该项其实没有实质用途。interface
:节点固有IP(非VIP)的网卡,用来发VRRP包。use_vmac
:是否使用VRRP的虚拟MAC地址。dont_track_primary
:忽略VRRP网卡错误。(默认未设置)track_interface
:监控以下网卡,如果任何一个不通就会切换到FALT状态。(可选项)mcast_src_ip
:修改vrrp组播包的源地址,默认源地址为master的IP。(由于是组播,因此即使修改了源地址,该master还是能收到回应的)lvs_sync_daemon_interface
:绑定lvs syncd的网卡。garp_master_delay
:当切为主状态后多久更新ARP缓存,默认5秒。virtual_router_id
:取值在0-255之间,用来区分多个instance的VRRP组播,如果使用组播发送vrrp的包那么该值必须每组唯一,如果vrrp的包采用单播进行发送那么该值平台可以统一。
注意: 同一网段中virtual_router_id的值不能重复,否则会出错,相关错误信息如下。
Keepalived_vrrp[27120]: ip address associated with VRID not present in received packet : one or more VIP associated with VRID mismatch actual MASTER advert bogus VRRP packet received on eth1 !!! receive an invalid ip number count associated with VRID! VRRP_Instance(xxx) ignoring received advertisment...
可以用这条命令来查看该网络中所存在的vrid: tcpdump -nn -i any net 224.0.0.0/8
priority
:用来选举master的,要成为master,那么这个选项的值最好高于其他机器50个点,该项取值范围是1-255(在此范围之外会被识别成默认值100)。advert_int
:发VRRP包的时间间隔,即多久进行一次master选举(可以认为是健康查检时间间隔)。authentication
:认证区域,认证类型有PASS和HA(IPSEC),推荐使用PASS(密码只识别前8位)。virtual_ipaddress
:vipvirtual_routes
:虚拟路由,当IP漂过来之后需要添加的路由信息。virtual_ipaddress_excluded
:发送的VRRP包里不包含的IP地址,为减少回应VRRP包的个数。在网卡上绑定的IP地址比较多的时候用。nopreempt
:允许一个priority比较低的节点作为master,即使有priority更高的节点启动。
首先nopreemt必须在state为BACKUP的节点上才生效(因为是BACKUP节点决定是否来成为MASTER的),其次要实现类似于关闭auto failback的功能需要将所有节点的state都设置为BACKUP,或者将master节点的priority设置的比BACKUP低。我个人推荐使用将所有节点的state都设置成BACKUP并且都加上nopreempt选项,这样就完成了关于autofailback功能,当想手动将某节点切换为MASTER时只需去掉该节点的nopreempt选项并且将priority改的比其他节点大,然后重新加载配置文件即可(等MASTER切过来之后再将配置文件改回去再reload一下)。
当使用track_script时可以不用加nopreempt,只需要加上preempt_delay 5,这里的间隔时间要大于vrrp_script中定义的时长。
preempt_delay
:启动keepalived后发现了一个低优先级的master后,多少秒开始抢占,并且前提是没有nopreempt选项。为使该选项工作,初始状态必须是BACKUP
virtual_server_group和virtual_server区域
virtual_server_group一般在超大型的LVS中用到,一般LVS用不到这东西
virtual_server IP Port { delay_loop <INT> lb_algo rr|wrr|lc|wlc|lblc|sh|dh lb_kind NAT|DR|TUN persistence_timeout <INT> persistence_granularity <NETMASK> protocol TCP ha_suspend virtualhost <STRING> alpha omega quorum <INT> hysteresis <INT> quorum_up <STRING>|<QUOTED-STRING> quorum_down <STRING>|<QUOTED-STRING> sorry_server <IPADDR> <PORT>virtualhost real_server <IPADDR> <PORT> { weight <INT> inhibit_on_failure notify_up <STRING>|<QUOTED-STRING> notify_down <STRING>|<QUOTED-STRING> # HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK HTTP_GET|SSL_GET { url { path <STRING> # Digest computed with genhash digest <STRING> status_code <INT> } connect_port <PORT> connect_timeout <INT> nb_get_retry <INT> delay_before_retry <INT> } } }
virtual_server
:定义虚拟服务的VIP及端口。delay_loop
:定义健康检查的时间间隔,单位为秒。lb_algo
:后端调试算法(load balancing algorithm)。lb_kind
:LVS调度类型NAT/DR/TUN。persistence_timeout
:单位ms,保持客户端的请求在<INT>时间段内全部发到同一个真实服务器。适用于动态网页session共享的环境。默认六分钟。persistence_granularity
:会话保持粒度,配合persistence_timeout
使用,通过子网掩码来定义会话保持对一个IP生效还是对一组IP生效。默认值为255.255.255.255,表示单个客户端分配到一个RS上;255.255.255.0表示客户端IP所在的整个网段的请求都会分配给同一台RSprotocol
:使用协议,TCP|UDP|SCTPha_suspend
:在LB节点状态从Master切换到Backup时,不启用对RS节点的健康检查virtualhost
:用来给HTTP_GET和SSL_GET配置请求header的。alpha
:在启动daemon时,默认所有的RS是down状态,healthcheck健康检查failed。这有助于其启动时误报错误,默认情况下禁用alpha模式 。omega
:开启omega模式,清除rs时会执行相应的脚本(rs的notify_up,quorum_up),默认为禁用模式。sorry_server
:当所有real server宕掉时,sorry server顶替。real_server
:真正提供服务的服务器。weight
:权重。inhibit_on_failure
:配置该项,在检测到后端RS节点故障后将weight值改为0,而不是从IPVS中删除notify_up/down
:当real server启动或宕掉时执行的脚本。HTTP_GET|SSL_GET
:健康检查的方式,还有 TCP_CHECK、MISC_CHECKpath
:请求real serserver上的路径。digest/status_code
:分别表示用genhash算出的结果和http状态码。connect_port
:健康检查,如果端口通则认为服务器正常。connect_timeout
:无响应超时时间,单位秒。nb_get_retry
:重试次数。在Keepalived 2.x版本之前使用nb_get_retry,2.x版本之后使用retry。delay_before_retry
:重试间隔时间,单位秒。
KeepAlived - LVS 部署
为模拟集群环境,我们准备了五台虚拟机分别为Client、LVS-1、LVS-2、RealServer1、RealServer2,VIP设为192.168.0.100
- Client :192.168.0.6
- LVS-1 :192.168.0.2
- LVS-2 :192.168.0.3
- RealServer1 :192.168.0.4
- RealServer2 :192.168.0.5
RealServer 配置
与系列二文章一样,需要在RealServer的进行以下操作
- 部署http服务
- 在设备lo上配置VIP,掩码/32
- 修改
arp_ignore/arp_announce
配置
[root@RealServer1 ~]# rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm [root@RealServer1 ~]# yum install nginx -y [root@RealServer1 ~]# chkconfig nginx on [root@RealServer1 ~]# systemctl start nginx //启动nginx [root@RealServer1 ~]# echo 'RealServer1 192.168.0.4' > /usr/share/nginx/html/index.html //默认html改为 'RealServer1 192.168.0.4',同理RealServer2 上改为 'RealServer2 192.168.0.5' [root@RealServer1 ~]# curl 127.0.0.1 RealServer1 192.168.0.4 //至此部署好了http服务 [root@RealServer1 ~]# ifconfig lo:0 192.168.0.100 broadcast 192.168.0.100 netmask 255.255.255.255 up [root@RealServer1 ~]# route add -host 192.168.0.100 dev lo:0 //将VIP添加到lo:0上,掩码为/32 [root@RealServer1 ~]# echo "1">/proc/sys/net/ipv4/conf/all/arp_ignore [root@RealServer1 ~]# echo "1">/proc/sys/net/ipv4/conf/lo/arp_ignore [root@RealServer1 ~]# echo "2">/proc/sys/net/ipv4/conf/all/arp_announce [root@RealServer1 ~]# echo "2">/proc/sys/net/ipv4/conf/lo/arp_announce //修改 arp_ignore/arp_announce 配置
手动配置比较繁琐,可以用以下脚本替代
realserver.sh
#!/bin/bash # Script to start LVS DR real server. # description: LVS DR real server . /etc/rc.d/init.d/functions VIP=192.168.0.100 #修改为VIP host=`/bin/hostname` case "$1" in start) /sbin/ifconfig lo down /sbin/ifconfig lo up 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 /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev lo:0 ;; stop) /sbin/ifconfig lo:0 down 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 ;; status) islothere=`/sbin/ifconfig lo:0 | grep $VIP` isrothere=`netstat -rn | grep "lo" | grep $VIP` if [ ! "$islothere" -o ! "isrothere" ];then # Either the route or the lo:0 device not found. echo "LVS-DR real server Stopped." else echo "LVS-DR real server Running." fi ;; *) # Invalid entry. echo "$0: Usage: $0 {start|status|stop}" exit 1 ;; esac exit 0
编辑好脚本后,测试下是否能正常运行
[root@RealServer1 ~]# vi realserver.sh [root@RealServer1 ~]# chmod +x realserver.sh //添加执行权限 [root@RealServer1 ~]# ./realserver.sh start [root@RealServer1 ~]# ifconfig ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.0.4 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fe80::20c:29ff:febd:38da prefixlen 64 scopeid 0x20<link> ether 00:0c:29:bd:38:da txqueuelen 1000 (Ethernet) RX packets 181 bytes 20289 (19.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 157 bytes 41577 (40.6 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo:0: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 192.168.0.100 netmask 255.255.255.255 // lo:0 配置生效 [root@RealServer1 ~]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.1 0.0.0.0 UG 100 0 0 ens33 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33 192.168.0.100 0.0.0.0 255.255.255.255 UH 0 0 0 lo // 路由添加成功 [root@RealServer1 ~]# cat /proc/sys/net/ipv4/conf/lo/arp_ignore 1 [root@RealServer1 ~]# cat /proc/sys/net/ipv4/conf/lo/arp_announce 2 [root@RealServer1 ~]# cat /proc/sys/net/ipv4/conf/all/arp_ignore 1 [root@RealServer1 ~]# cat /proc/sys/net/ipv4/conf/all/arp_announce 2 // arp_ignore/arp_announce 配置生效 [root@RealServer1 ~]#
至此RealServer配置完成
LVS 配置
LVS部署需完成以下步骤
- 部署http服务,当后端RealServer全部异常时返回本机告警页面
- 安装ipvsadm,用查看ipvs规则
- 安装并部署KeepAlived
安装 nginx、ipvsadm、keepalived
[root@LVS1 ~]# rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm [root@LVS1 ~]# yum install nginx -y [root@LVS1 ~]# chkconfig nginx on [root@LVS1 ~]# systemctl start nginx [root@RealServer1 ~]# echo 'LVS1 192.168.0.2' > /usr/share/nginx/html/index.html // 默认html 改为 'LVS1 192.168.0.2',同理 LVS2 改为 'LVS2 192.168.0.3' [root@LVS1 ~]# curl 127.0.0.1 LVS1 192.168.0.2 [root@LVS ~]# yum install ipvsadm -y // 安装 ipvsadm [root@LVS1 ~]# cd keepalived-xxx [root@LVS1 ~]# ./configure --prefix=/usr/local/keepalived --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --mandir=/usr/share [root@LVS1 ~]# make && make install // 示例为官网编译安装最新版本
配置keepalived.conf
! RealServer1 global_defs { router_id LVS1 #路由器标识 script_user root enable_script_security } vrrp_instance VI_1 { state BACKUP #为了使原来为主的机器异常恢复之后不会抢占现在为主的资源,所以主备两台机器都会配置为BACKUP,同时配置上非抢占模式-nopreempt interface ens33 #通告VRRP所用接口 priority 150 #另一台设置为50 nopreempt #开启非抢占模式,即便自身权值高也不抢占 virtual_router_id 1 advert_int 1 #VRRP通告间隔,单位秒 authentication { auth_type PASS auth_pass test } unicast_peer { #VRRP包的单播发送 192.168.0.3 #对端IP } virtual_ipaddress_excluded { 192.168.0.100 #VIP } } virtual_server 192.168.0.100 80 { delay_loop 5 lb_algo wrr lb_kind DR persistence_timeout 60 persistence_granularity 255.255.255.255 protocol tcp inhibit_on_failure on ha_suspend sorry_server 127.0.0.1 80 real_server 192.168.0.4 80 { weight 10 HTTP_GET{ url{ path / status_code 200 } connect_port 80 connect_timeout 2 retry 1 delay_before_retry 1 } } real_server 192.168.0.5 80 { weight 10 HTTP_GET{ url{ path / status_code 200 } connect_port 80 connect_timeout 2 retry 1 delay_before_retry 1 } } }
配置keepalived日志
由于keepalived日志默认保存在/var/log/message,不方便查看,为此我们将keepalived日志单独保存
[root@LVS1 ~]# vi /etc/sysconfig/keepalived // 改为 KEEPALIVED_OPTIONS="-D -d -S 0" [root@LVS1 ~]# vi /etc/rsyslog.conf // 增加以下两行 //# keepalived -S 0 //local0.* /var/log/keepalived.log [root@LVS1 ~]# systemctl restart rsyslog [root@LVS1 ~]# systemctl restart keepalived
集群测试
LVS1
[root@LVS1 ~]# netstat -ntlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7068/nginx: master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 7061/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 7224/master tcp6 0 0 :::22 :::* LISTEN 7061/sshd tcp6 0 0 ::1:25 :::* LISTEN 7224/master [root@LVS1 ~]# curl 127.0.0.1 LVS1 192.168.0.2 //测试nginx正常 [root@LVS1 ~]# systemctl start keepalived [root@LVS1 ~]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.100:80 wrr persistent 60 -> 192.168.0.4:80 Route 10 0 0 -> 192.168.0.5:80 Route 10 0 0 //调度到了后端两台RealServer上并且状态正常 [root@LVS1 ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:af:6b:f7 brd ff:ff:ff:ff:ff:ff inet 192.168.0.2/24 brd 192.168.0.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 192.168.0.100/32 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feaf:6bf7/64 scope link valid_lft forever preferred_lft forever // VIP成功挂在到网卡ens33上 [root@LVS1 ~]# tail /var/log/keepalived.log -n 50 // 查看keepalived日志
Client
在LVS2上启用keepalived服务后,LVS1仍然为Master
[root@Client ~]# arping 192.168.0.100 ARPING 192.168.0.100 from 192.168.0.6 ens33 Unicast reply from 192.168.0.100 [00:0C:29:AF:6B:F7] 1.191ms Unicast reply from 192.168.0.100 [00:0C:29:AF:6B:F7] 1.065ms Unicast reply from 192.168.0.100 [00:0C:29:AF:6B:F7] 0.836ms ^C Sent 3 probes (1 broadcast(s)) Received 3 response(s) [root@Client ~]# arping 192.168.0.2 ARPING 192.168.0.2 from 192.168.0.6 ens33 Unicast reply from 192.168.0.2 [00:0C:29:AF:6B:F7] 1.176ms Unicast reply from 192.168.0.2 [00:0C:29:AF:6B:F7] 0.771ms ^C Sent 2 probes (1 broadcast(s)) Received 2 response(s) //VIP在LVS1上 [root@Client ~]# curl 192.168.0.100 RealServer1 192.168.0.4 [root@Client ~]# curl 192.168.0.100 RealServer1 192.168.0.4 // 由于设置有persistence,短时间内请求会分发到同一台RealSever上