前言
在之前的学习中,学习了通过LVS构建4层负载均衡集群和通过Nginx的反向代理构建7层负载均衡,了解到负载均衡是由调度服务基于调度算法把请求平摊到后端的服务器中,可见,调度器的作用可是相当重要的,当一个负载均衡集群中,调度器发生故障不能提供服务时,整个集群将会失效,所以需要对调度器做高可用,保证当调度器出现故障时,由其他服务器负责调度任务。其中高可用实现方案中,可以使用VRRP协议来实现冗余达到高可用目的。
VRRP协议
VRRP协议是为消除在静态缺省路由环境下的缺省路由器单点故障引起的网络失效而设计的主备模式的协议,使得在发生故障而进行设备功能切换时可以不影响内外数据通信,不需要再修改内部网络的网络参数。VRRP协议需要具有IP地址备份,优先路由选择,减少不必要的路由器间通信等功能。
VRRP的几个术语
- 虚拟路由器:
由一个Master路由器和多个Backup路由器组成。主机将虚拟路由器当作默认网关。
- 虚拟路由器标识 VRID
虚拟路由器的标识。由相同VRID的一组路由器构成一个虚拟路由器。 - Master路由器:
虚拟路由器中承担报文转发任务的路由器。
- Backup路由器:
Master路由器出现故障时,能够代替Master路由器工作的路由器。
- 虚拟IP地址:
虚拟路由器的IP地址。一个虚拟路由器可以拥有一个或多个IP地址。
- 优先级:
VRRP根据优先级来确定虚拟路由器中每台路由器的地位。
- 虚拟MAC地址:
一个虚拟路由器拥有一个虚拟MAC地址。虚拟MAC地址的格式为00-00-5E-00-01-{VRID}。通常情况下,虚拟路由器回应ARP请求使用的是虚拟MAC地址,只有虚拟路由器做特殊配置的时候,才回应接口的真实MAC地址。
VRRP的基础
在VRRP虚拟结构中,虚拟路由器是通过"MAC+VRID"的形式来标识的,如"00-00-5E-00-01-{VRID}"。在VRRP同一虚拟路由,MASTER和BACKUP路由器的VRID是一致的
VRRP结构中路由器之间的通信是通过IP多播的方式实现的(也可以配置为其它通信方式)。要想保持自己一直时MASTER身份, 则在间隔时间往多播地址发送VRRP状态消息,可以理解为心跳包,告诉BACKUP自己还或者,当BACKUP路由器收不到MASTER的心跳包时,则认为MASTER宕机,会重新选举一个MASTER。
keepalived
简介
Keepalived在设计之初就是LVS的一个辅助工具,因此它和LVS的兼容性非常好,能对后端的RS作健康检查,当后端的RS宕机,能在该RS从集群中剔除。也能高可用IPVS服务。Keepalived基于vrrp协议完成地址流动,能为当前虚拟路由地址所在的节点生成ipvs规则,还能基于脚本调用接口通过执行脚本完成脚本中定义的功能。
keepalived架构
架构图:

组件说明:
checkers:用于检查后端RS的健康状态,并且也能管理后端RS,该组件使用独立的子进程负责,由父进程管理。
VRRPstack:基于VRRP协议实现高可用的组件,它能够提供故障转移功能,并且能单独使用,即不对后端做健康检查,运行为一个独立的子进程由父进程管理
System Call:提供读取自定义脚本的功能
IPVS wrapper:能够读取配置文件的规则,通过系统调用直接管理ipvs
Netlink Reflector:用于管理和检查VIP地址
Watch Dog:用于检查Checkers和VRRPstack进程
安装Keepalived
在base仓库已经包含了Keepalived程序包,直接安装即可。
[root@nginx_proxy ~]# yum install keepalived -y
[root@nginx_proxy ~]# rpm -ql keepalived
/etc/keepalived
/etc/keepalived/keepalived.conf #keepalived的配置文件
/etc/sysconfig/keepalived #一些keepalived的选项参数设置,例如对日志的记录选项
/usr/bin/genhash #keepalive能对TCP的返回内容做哈希检查,这个程序是计算哈希的
/usr/lib/systemd/system/keepalived.service #unit file
/usr/libexec/keepalived
/usr/sbin/keepalived #keepalived的程序
修改keepalived的输出日志文件
keepalived的日志默认输出到/var/log/messages,可以设置输出为一个单独文件。
首先对/etc/sysconfig/keepalived这个文件的选项作修改
KEEPALIVED_OPTIONS="-D -S 0" #-D -S 0 即把详细的日志信息记录到本地syslog local 0 这个设备上面
然后修改rsyslog的配置文件/etc/rsyslog.conf,添加该设备记录日志的级别和路径。
添加local 0 设置的日志路径
#keepalive log messages
local0.* /var/log/keepalived.log
重启rsyslog
[root@nginx_proxy ~]# systemctl restart rsyslog
Keepalived的配置文件详解
Keepalived的配置文件分为3部分:
全局配置,配置对全局都生效
VRRP部分,即高可用部分,vrrp部分的配置文件主要影响VRRP STACK组件
配置详解:
global_defs { #全局部分基本都是定义邮件报警设置
notification_email { #定义报警邮件的收件箱
acassen@firewall.loc #收件人地址
}
notification_email_from Alexandre.Cassen@firewall.loc #报警邮件的发件人
smtp_server 192.168.200.1 #Smtp的服务器
smtp_connect_timeout 30 #连接超时时间
router_id LVS_DEVEL #标识keepalived服务器的字符串,实现高可用时需要使用它标识节点
vrrp_strict #执行严格的VRRP协议遵从性
vrrp_mcast_group4 224.0.0.18 # 设置ipv4的组播地址
}
#定义vrrp虚拟路由器(实例)。一个配置文件中可以实现多实例。
vrrp_instance <STRING> {
....
}
专用参数:
state MASTER|BACKUP #义实例的角色状态是master还是backup
interface IFACE_NAME #绑定的网卡接口,即用于发送接受VRRP协议的接口
virtual_router_id VRID #同组实例中VRID必须一样,取值范围0-255
priority 100 #表示当前主机在此实例中的优先级,范围1-254;
advert_int 1 #VRRP协议报文的通告间隔
authentication { #定义vrrp的认证,防止滥竽充数
auth_type AH|PASS #简单的PASS认证
auth_pass <PASSWORD> #不超过8位,超过8位则取前8位
}
virtual_ipaddress { #定义流动IP,绑定在网卡上
<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
192.168.200.17/24 dev eth1
192.168.200.18/24 dev eth2 label eth2:1
}
track_interface { #配置要监控的网络接口,一旦接口出现故障,则转为FAULT状态;
eth0
eth1
...
}
nopreempt #定义主机处在非抢占模式下
preempt_delay 300 #抢占式模式下,节点上线后触发新选举操作的延迟时长;
定义通知脚本:
notify_master <STRING>|<QUOTED-STRING> #当前节点转为master时触发的脚本
notify_backup <STRING>|<QUOTED-STRING> #当此节点转为backup时触发的脚本
notify_fault <STRING>|<QUOTED-STRING> #当前节点转为“失败”状态时触发的脚本;
notify <STRING>|<QUOTED-STRING> #通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知;
-------分割线,上面是定义VRRP的高可用,实现地址流动,下面是定义ipvs负载规则-------
#LVS 虚拟服务的定义
虚拟服务器:
配置参数:
virtual_server IP port 或者
virtual_server fwmark int
{
...
real_server {
...
}
...
}
常用参数:
delay_loop <INT> #对后端健康检查的间隔;
lb_algo rr|wrr|lc|wlc|lblc|sh|dh #调度算法
lb_kind NAT|DR|TUN #集群的类型;
persistence_timeout <INT> #持久连接的时长
protocol TCP #服务类型,只支持TCP
sorry_server <IPADDR> <PORT> #当所有的后端都宕机时,由哪台服务器继续提供服务
real_server <IPADDR> <PORT> #定义后端Real server
{
weight <INT> #权重
notify_up <STRING>|<QUOTED-STRING> #当出现匹配字符串时,就认为服务是up的
notify_down <STRING>|<QUOTED-STRING> #当出现匹配字符串时,就认为服务是down的
HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... } #定义当前主机的健康状态检测方法;
}
HTTP_GET|SSL_GET { #定义应用层检测
url {
path <URL_PATH> #定义要监控的URL
status_code <INT> #定义以什么状态码作为正常。
digest <STRING> #判断上述检测机制为健康状态的响应的内容的校验码;
}
nb_get_retry <INT> #重试次数;
delay_before_retry <INT> #在重试前,等待多长时间
connect_ip <IP ADDRESS> #连接RS的哪个IP
connect_port <PORT> #连接RS的哪个端口
bindto <IP ADDRESS> #使用哪个地址作为源IP
bind_port <PORT> #使用哪个端口作为源端口
connect_timeout <INTEGER> #连接请求的超时时长;
}
TCP_CHECK {
connect_ip <IP ADDRESS> #向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #发出健康状态检测请求时使用的源地址;
bind_port <PORT> #发出健康状态检测请求时使用的源端口;
connect_timeout <INTEGER> #连接请求的超时时长;
}