在该系列前两篇文章中,我们全面认识了 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 {
a@abc.com
b@abc.com
...
}
notification_email_from alert@abc.com
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 消息之间的延迟时间,默认为 0 -
vrrp_lower_prio_no_advert
:如果接收到一个低优先级的通告,只需要丢弃它,不用发送其他通告, 字符类型:布尔值,false/true -
vrrp_version
:设置 vrrp 协议版本,默认是版本 2 -
script_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
:vip -
virtual_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 所在的整个网段的请求都会分配给同一台 RS -
protocol
:使用协议,TCP|UDP|SCTP -
ha_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_CHECK -
path
:请求 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 上