Keepalived是一个基于VRRP协议来实现LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会使用2台服务器运行Keepalived,一台为主服务器MASTER,另一台为备份服务器BACKUP,但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候,备份服务器就会接管虚拟IP,继续提供服务,从而保证高可用性。Keepalived是VRRP的完美实现
1、内核组件
1)LVS 框架:使用 getsockopt 和 setsockopt 调用来获取和设置套接字上的选项。
2)Netfilter框架:支持NAT和伪装的IPVS代码。
3)Netlink 接口:设置和删除网络接口上的 VRRP 虚拟 IP。
4)组播:VRRP 通告发送到保留的 VRRP MULTICAST 组 (224.0.0.18)。
2、原子元素
包含有控制平面(Control Plane)、调度器 - I/O 多路复用器(Scheduler - I/O Multiplexer)、内存管理(Memory Management)、看门狗(WatchDog)、VRRP协议栈(VRRP Stack)等
3、健康检查
采用tcp、http,udp 、echo请求等方式对实际的服务器进行保活,可以通过自定义监测脚本来自定义健康监测内容机制
4、故障切换
Keepalived 实现了用于控制器故障转移的VRRP 协议,VRRP数据包调度程序负责为每个VRRP实例解复用特定的 I/O。
主要应用在主备上,当主服务器出现问题时自动由备用服务器顶上,最大程度的保证系统的稳定性
配置文件是etc/keepalived/keepalived.conf,该文件主要由global_defs、vrrp_instance和virtual_server三个模块构成。global_defs:全局配置;vrrp_instance:可配置虚拟路由,可以用来做高可用;virtual_server:虚拟服务器,可以用来做负载均衡
负载一般会放在nginx上使用,主要了解一下global_defs、vrrp_instance这两个模块,看看高可用是怎么做的,先看看配置文件
! Configuration File for keepalived
# 全局配置
global_defs {
# 接收邮件
notification_email {
[email protected]
[email protected]
}
# 发送的邮箱
notification_email_from [email protected]
# 邮件服务器
smtp_server 127.0.0.1
# 邮件服务器超时时间
smtp_connect_timeout 30
# 路由id,唯一的
! router_id LVS_DEVEL
! vrrp_skip_check_adv_addr
# 开启了此项后没有设置vrrp_iptables则会自动开启iptables防火墙规则,导致VIP地址无法访问,建议不加此项
! vrrp_strict
# 与vrrp_strict同时设置时可禁止iptables规则的生成,注释或者无vrrp_strict时可不加此项
! vrrp_iptables
# 设置ARP接口之间发送报文的延迟时间,可以精确到毫秒,默认是0
! vrrp_garp_interval 0
# 设置非请求消息的发送延迟时间,默认为0
! vrrp_gna_interval 0
# 指定要在其下运行脚本的默认用户名/组名,如果未指定此选项,则如果该用户存在,则用户默认为keepalived_script,否则为root,如果未指定groupname,则默认为用户的组。
script_user root
}
# 配置虚拟路由器
vrrp_instance VIP_1 {
# 设置此虚拟路由器的初始状态,可选择MASTER或者BACKUP
state MASTER
# 绑定当前虚拟路由器所使用的物理接口,如eth0、lo等
interface eth0
# 设置虚拟路由器的唯一标识,取值范围为0-255,每个虚拟路由器的该项值必须是唯一的,否则无法启动服务,并且同属一个虚拟路由器的多个keepalived节点必须相同,务必要确认在同一网络中此值必须唯一
virtual_router_id 51
# 设置当前物理节点在此虚拟路由器中的优先级,优先级取值范围为1-254,值越大优先级越高,每个keepalived节点取值不同
priority 100
# 设置VRRP通告的时间间隔,默认为1秒
advert_int 1
# 设置认证机制
authentication {
# 认证类型,可选择AH和PASS两种,AH为IPSC互联网安全协议认证,PASS为简单密码认证,推荐PASS认证
auth_type PASS
# 预共享秘钥设置,仅前8位有效,同一虚拟路由器的多个keepalived节点auth_pass值必须保持一致
auth_pass 1111
}
# 添加虚拟路由器的IP,并可设置IP对应的子网掩码、网卡和标签等,生产中可能会在同一个虚拟路由器上添加上百个IP,不同的IP分行隔开,不指定网卡时默认添加在eth0上,不设置子网掩码时默认为32位。在添加IP地址时,需确保将要使用的IP不存在
virtual_ipaddress {
10.211.55.11
}
#指定当切换到master时,执行的脚本
notify_master /opt/keepalived/etc/script/notify_fifo.sh
#指定当切换到backup时,执行的脚本
notify_backup /opt/keepalived/etc/script/notify_fifo.sh
#故障时执行的脚本
notify_fault /opt/keepalived/etc/script/notify_fifo.sh
# 通知
notify /opt/keepalived/etc/script/notify_fifo.sh
#使用global_defs中提供的邮件地址和smtp服务器发送邮件通知
smtp_alert
}
这个是把默认配置文件中常用的一些说明都写出来了,接下来我来讲一下我个人对于keepalived做高可用的配置的一些理解,看是否能有助于各位理解
global_defs主要是全局配置,其实很多都是关于邮件通知的配置,如果你不需要邮件通知(这个在大中国也确实不怎么实用),其他的一些配置一般情况下用不到,总之这里的配置对于我们的总体功能使用没有太大影响,如果是新学的,可以暂时不太关注这块
vrrp_instance模块,这个就是虚拟路由,这个就是高可用的配置模块了,虚拟路由顾名思义,会生成一个虚拟的路由地址,我们可以理解为虚拟IP,就是virtual_ipaddress里面配置的地址,有了IP我们需要给他绑定到一个网卡上,interface这个就是设置你需要绑定的网卡,这个时候我们就基本上知道了,访问这个虚拟IP所有流量都会走interface绑定的网卡,OK,到这里这个模块的核心功能你已经知道了
当有多台机器都部署keepalived并且配置跟这个机器一摸一样的vrrp_instance模块,那么是不是每个机器都会有这么一个虚拟IP呢,要知道同一网络下IP是不能重复的,所以即使部署了N台机器,同一时间也只会有一台机器的网卡绑定虚拟IP,多台机器不就构成了一个集群,我们再通过authentication来设置新增的机器是否可以加入这个集群,到这儿网络方面的配置基本上就好了,同一个IP可以自动绑定在多台机器上,多台机器只有一台机器绑定,这个时候一个集群不就好了
在etc/keepalived/samples/下有一个官方给的一个邮件脚本sample_notify_fifo.sh
1、配置邮箱服务器
要想发送邮件就必须要一个邮箱服务器,keepalived官方默认用的是sendmail,我们也配置这个,很多机器上默认就有这个,但是、但是、但是,别理他删了再说,这玩意儿我不知道为啥,反正不能用,直接把他干掉,然后重新装一个
# 干掉自带sendmail,如果本来就没有那就算了
yum remove -y sendmail
# 看看有没有mail,有的话也干掉,避免抢占邮件服务器端口,注意卸妆的时候是mailx
yum install -y mailx
# 重新安装
yum install -y sendmail
# 查看一下sendmail服务,是否起来没有起来就起来
查看状态:systemctl status sendmail
启动:systemctl start sendmail
重启:systemctl restart sendmail
停止:systemctl stop sendmail
# 查看25端口是否已经存在
netstat -tunlp|grep 25
# 正常返回
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1864/sendmail: acce
OK,现在可以试试是否能够发送邮件
# 测试一下,可能会比较慢,耐心等待一下
echo "这是邮件内容" | sendmail -s "这是邮件主题" [email protected]
当然很大可能你的邮件发不出去,可以查看一下日志 vim /var/log/messages,好的,日志没有一点报错信息
接下来想到邮件服务器,查看一下状态 systemctl start sendmail
看来我的域名解析有点问题,那就改一下吧。vim /etc/hosts,把提示的域名和hostname都加到127.0.0.1和:::1后面 保存之后再次测试,
也可以使用其他方式,条条大路通罗马,官方给了一个样例在etc/keepalived/samples这个地方,sample_notify_fifo.sh. 样例通知脚本
1、默认的日志位置在/var/log/message,我们打开看一下可以发现几乎系统下的应用日志都输出到了这里而不仅仅只有keepalived日志
2、怎么把日志剥离出来,自定义我们的日志位置
根据keepalived.service可以看到启动参数在etc/sysconfig/keepalived,打开文件之后发现有很多参数
# 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)
#
KEEPALIVED_OPTIONS="-D"
默认-D,日志输出的messages,日志的高级配置参数是"--log-facility",该参数的作用就是借用syslog的0-7用户自定义功能来定制keepalived服务的日志信息。我们可以基于该参数来定制我们的keepalived日志。
# 编辑启动参数,加入-S 0,使用0用户输出日志信息
vim /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -S 0"
# 编辑rsyslog配置文件,定制rsyslog的用户自定义日志功能
vim /etc/rsyslog.conf
local0.* /var/log/keepalived.log
# 重启rsyslog服务
systemctl restart rsyslog
# 重启keepalived服务
systemctl restart keepalived
最开始我定义的日志文件在我keepalived的安装目录下,发现没有keepalived.log文件生成,然后通过日志发现是没有权限,后来查了一下资料https://www.rsyslog.com/rsyslog-error-2433/ 好像是系统制定的规则,所以老老实实在/var/log/下单独配置一个keepalived的日志文件了
根据上面的配置即可
我们知道了IP会在发生故障的时候自动切换到别的机器,这个就是IP漂移,那么IP是根据什么进行切换的?那么就涉及到了主备切换的模式,keepalived有两种模式:抢占式和非抢占式
1、抢占式:一种动态的调度策略,当主节点出现故障时,备份节点会抢占成为新的主节点。在抢占模式下,主节点和备份节点之间会进行竞争,优先级高的节点会成为新的主节点。这种调度策略适用于需要快速恢复服务的情况,可以减少故障时间
2、非抢占式:一种静态的调度策略,主节点和备份节点之间不会进行竞争。在非抢占模式下,不会轻易发生IP漂移。这种调度策略适用于需要保证服务稳定性的情况,可以避免由于竞争导致的网络不稳定。之所以说不会轻易发生IP漂移是只有当keepalived发生故障的时候(当前节点不可用)其他节点才会出来干活
在vrrp_instance中可以配置track_script,来通过自定义脚本监测服务状态,而track_script中的weight可以控制当前节点的优先级,在抢占模式中,节点中的角色就可以通过这个值来控制
关于通知除了上面提到过的邮件通知外,还有一些配置再进行一些说明
以下是notify_fifo、notify_fifo_script、vrrp_notify_fifo、vrrp_notify_fifo_script、notify_master、notify_backup、notify_fault、notify这些配置项的简要说明:
notify_fifo:
这是一个FIFO(First In, First Out)文件,用于在Keepalived进程之间传递通知事件。当Keepalived实例接收到通知事件时,它会将事件写入到该FIFO文件中
notify_fifo_script:
这是一个脚本,当Keepalived实例接收到通知事件时,它会执行这个脚本。脚本的输出会被写入到notify_fifo文件中,格式为:INSTANCE "VI_x" MASTER yyyy,其中x是虚拟路由器的ID,yyyy是优先级值。
vrrp_notify_fifo 和 vrrp_notify_fifo_script:
这些配置项与上述的notify_fifo和notify_fifo_script类似,但它们是专门用于VRRP(Virtual Router Redundancy Protocol)的通知
当VRRP实例接收到通知事件时,它会使用这些配置项来处理通知。
notify_master、notify_backup、notify_fault:
这些是通知类型,用于指定当特定的事件发生时发送通知。
notify_master:当主节点变为备份节点时发送通知。
notify_backup:当备份节点变为主节点时发送通知。
notify_fault:当节点出现故障时发送通知。
1、机器server、application、client,每台机器上安装nginx,然后启动
2、每台机器上安装keepalived
配置如下
! Configuration File for keepalived
# 全局配置
global_defs {
# 接收邮件
notification_email {
[email protected]
}
# 发送的邮箱
notification_email_from root@server
# 邮件服务器
smtp_server 127.0.0.1
# 邮件服务器超时时间
smtp_connect_timeout 30
# 指定要在其下运行脚本的默认用户名
script_user root
# enable_script_security
}
vrrp_script check_nginx{
# 指定脚本绝对路径
script /opt/keepalived/etc/script/nginx_check_status.sh
# 脚本执行的时间间隔(以秒为单位)
interval 1
# 权重值。weight为正数时,执行结果为真,优先级提升;执行结果为假,优先级保持不变;weight为负数时,执行结果为真,优先级不变;执行结果为假,优先级会提升。
weight -2
}
# 配置虚拟路由器
vrrp_instance VI_1 {
# 设置此虚拟路由器的初始状态,可选择MASTER或者BACKUP
state BACKUP
# 绑定当前虚拟路由器所使用的物理接口,如eth0、lo等
interface eth0
virtual_router_id 50
priority 100
# 设置VRRP通告的时间间隔,用于设定MASTER与BACKUP主机之间同步检查的时间间隔,单位是秒。默认为1秒
advert_int 1
# 非抢占模式,默认抢占模式
# nopreempt
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
10.211.55.11
}
track_script{
check_nginx
}
smtp_alert
}
nginx_check_status.sh脚本如下
#!/bin/sh
check_command=`pidof nginx 2> /dev/null`
if [ -z "$check_command" ] ; then
exit 2
fi
exit 0
在application和client配置和它一样的配置
3、观察虚拟IP在哪个机器上
1)浏览器访问虚拟IP:10.211.55.11
看到现在IP是在server上
4通过停止nginx来模拟服务中断,观察IP是否会漂移
停止server上的nginx,看是否还能访问,IP在哪里?
我们看到当我们把server上的nginx停止之后,IP自动漂移到了application机器上,原来的虚拟iP正常访问只是服务已经由application提供,这样已经达到了我们的目的
实战说明:
这里配置的很潦草,只能说明大概的一个配置方式,最终使用的时候还是根据大家不同的业务场景和需求去定制化配置各自的高可用,在这个里面,如果是线上环境的话通知是必不可少的,我这里实际上也配置了邮件通知,只不过时灵时不灵,跟邮件服务器有关系,邮件在国内还是有点鸡肋,不多做介绍,大家可以使用notify_master、notify_backup、notify_fault这些指令,通过自定义脚本去定制化自己的通知,比如钉钉之类的可用性会更好一点
说在最后,我不是在教学,我只是希望大家和我一起学习