在使用keepalived(vip)作为mysql主从高可用时,通常架构如下:
在这里keepalived的作用就是负责vip漂移,作为一个应用端和数据库端的一个桥梁或者代理,应用不直接访问物理主库的ip地址,而是访问一个虚拟ip,这个虚拟ip(vip)可以在异常情况下漂移到备库中,使得应用代码可以对数据库进行透明访问(即使主库实例宕机,vip可以漂移至备库,实现对应用的无感知切换)。
keepalived负责vip的切换,负责对mysql不可访问时及网络不可达时的监控,负责两个mysql实例间有效沟通的一个检测和后续操作的触发器。
相信大家从软件的名字上就可以猜到他的含义:keep-alived 保持存活,也可以理解为保持在线 也就是所谓的高可用或者热备,在集群管理中的一个轻量级的保障集群高可用的一个软件。
说到keepalived就不得不说vrrp协议,vrrp全称virtual router redundancy protocol,即虚拟路由冗余协议,目的是解决静态路由的单点故障,可以说vrrp就是keepalived实现的基础。
1. 采用单播
单播:在同一局域网内,两个设备点对点的通信就是单播通信。
组播:在同一网络可达范围内,一个网络设备与关心其数据的部分设备进行通信就是组播。
广播:在同一网络可达范围内,一个网络设备向本网络内所有设备进行通信就是广播。
简单地说,单播->组播->广播,是通信数量不断增加的通信方式。当然,通信数量的增多,带来的是通信设备的资源消耗更大,整体网络环境的复杂度更高。
keepalived中如果不进行额外的配置,默认是组播,在组播模式下所有的信息都会向224.0.0.18的组播地址发送,产生众多的无用信息,并且会产生干扰和冲突,所以需要将其组播的模式改为单播。这是一种安全的方法,避免局域网内有大量的keepalived造成虚拟路由id的冲突,导致keepalived异常。
单播模式需要关闭vrrp_strict这个选项。
单播需要在vip实例配置段加入单播的源地址和目标地址
下面给出单播的配置详情,请参考如下:
[root@mysql-01 ~]# cat /etc/keepalived/keepalived.conf
! configuration file for keepalived
global_defs {
smtp_connect_timeout 30
router_id mysql_master_214
vrrp_skip_check_adv_addr
# vrrp_strict # vrrp_strict严格执行vrrp协议,这会导致:禁止0 vips的情形,禁止单播对等点,禁止在ipv6中设置vrrp_version为2。如果上游交换机禁用了组播功能,则master只能采用单播方式向backup发送vrrp广告包。设置vrrp_strict会导致无法单播。
}
vrrp_script check_mysql_stat {
script "/etc/keepalived/checkmysql.sh 3307"
interval 3 # 检测间隔时间,即3秒检测一次
fall 3 # 检测失败的最大次数,超过3次认为节点资源发生故障
rise 1 # 检测成功的次数,有1次成功就认为节点恢复正常
}
vrrp_instance vi_1 {
state backup # 初始状态 master|backup 当其他vrrp实例的priority更高时,会发起选举,具有最高priority的vrrp实例将会成为master。
interface ens192 # 网卡名称
virtual_router_id 51 # 虚拟路由id号
priority 100 # 优先级
unicast_src_ip 10.211.7.214 # 指定单播vrrp包源ip地址,
unicast_peer { # 通过单播方式向以下ip地址(可以是ipv4 和ipv6)发送vrrp包
10.211.7.215 # 配置单播的目标地址,即对方备节点地址,备有多台就配置多个地址
}
advert_int 1 # 心跳检测频率1秒
nopreempt # 非抢占模式,# 当一个具有更高priority的vrrp实例上线后,通常会抢占低priority的master身份。nopreempt允许在具有更高priority的vrrp实例上线的情形下,仍由低priority的vrrp实例继续维持master角色。注意:如果采用此选项,则初始状态state选项必须设为backup。
authentication {
auth_type pass # 可选值:pass(简单密码,建议)
auth_pass 1111 # vrrp密码,在互为主备的主机上应该是相同的。只会使用前8个字符。
}
virtual_ipaddress { # 必选 设置vip。vip只会绑定在master上,主备切换时,vip会随之绑定到新的master上。dev指定vip绑定的网口,默认为eth0。
10.211.7.11 dev ens192 label ens192:1 # vip地址
}
track_script { # 使用脚本进行监控(check_mysql_stat是vrrp_script配置项的名称)
check_mysql_stat
}
}
2. 设置非抢占模式
简单点说抢占模式就是,当master宕机后,backup 接管服务。后续当master恢复后,vip漂移到master上,master重新接管服务,多了一次多余的vip切换,而在实际生产中尽多数是不需要这样(这样对业务频繁的切换是不能容忍的,因此我们希望master起来后成为backup,所以要设置不抢占。)。实际生产中是,当 原先的master恢复后,状态变为backup,不接管服务,这是非抢占模式。
设置非抢占模式:在配置文件vrrp_instance段中加入关键字:nopreempt
非抢占模式下,注意点如下:
- 主设备、 从设备中的 state 都设置为 backup
- 默认主设备(priority 值大的 keepalived 节点) 配置一定要加上 nopreempt,否则非抢占不起作用
- 默认组播时,防火墙需要配置允许组播(主、备两台设备上都需要配置, keepalived 使用 224.0.0.18 作为 master 和backup 健康检查的通信 ip),否则主备两节点间的心跳检测会异常。
- 如果使用 非抢占模式,就不能通过优先级 priority 来判断谁应该是master或者slave,而应该根据检测脚本的返回值。
附:单播组播的一些tcp抓包信息
#主节点确实使用了组播向224.0.0.18地址发送心跳包
[root@nginx keepalived]# /usr/sbin/tcpdump -i ens33 -nn -p vrrp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type en10mb (ethernet), capture size 262144 bytes
21:17:57.446287 ip 192.168.9.101 > 224.0.0.18: vrrpv2, advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
21:17:58.446695 ip 192.168.9.101 > 224.0.0.18: vrrpv2, advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
21:17:59.447752 ip 192.168.9.101 > 224.0.0.18: vrrpv2, advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
#现在就变成单播模式了,主节点只对备节点发送心跳包
[root@master keepalived]# tcpdump -i ens33 -nn -p vrrp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type en10mb (ethernet), capture size 262144 bytes
21:29:13.033272 ip 192.168.9.101 > 192.168.9.102: vrrpv2, advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
21:29:14.034674 ip 192.168.9.101 > 192.168.9.102: vrrpv2, advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
21:29:15.034943 ip 192.168.9.101 > 192.168.9.102: vrrpv2, advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
3. 设置keepalived的日志位置
修改 /etc/sysconfig/keepalived 文件,将keepalived_options="-d -d -s 0" 将入文件内容中:
[root@mysql-01 ~]# cat /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"
keepalived_options="-d -d -s 0"
修改/etc/rsyslog.conf,添加local0.* 指定keepalived日志路径为/var/log/keepalived.log
[root@c1 ~]# cat /etc/rsyslog.conf|grep -v '^#'|grep -v '^$'
$modload imuxsock # provides support for local system logging (e.g. via logger command)
$modload imjournal # provides access to the systemd journal
$workdirectory /var/lib/rsyslog
$actionfiledefaulttemplate rsyslog_traditionalfileformat
$includeconfig /etc/rsyslog.d/*.conf
$omitlocallogging on
$imjournalstatefile imjournal.state
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
mail.* -/var/log/maillog
cron.* /var/log/cron
*.emerg :omusrmsg:*
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
local0.* /var/log/keepalived.log
重启生效:
systemctl restart rsyslog
systemctl start keepalived
4. 编译安装常见错误
tips1: 安装过程中提示: warning – this build will not support ipvs with ipv6. please install libnl/libnl-3 dev libraries to support ipv6 with ipvs.
解决方式: yum install libnl-dev
tips2: 安装过程中提示:
check/libcheck.a(check_ssl.o): in function `build_ssl_ctx':
/usr/local/nginx/keepalived-2.0.0/keepalived/check/check_ssl.c:72: undefined reference to `openssl_init_ssl'
/usr/local/nginx/keepalived-2.0.0/keepalived/check/check_ssl.c:73: undefined reference to `openssl_init_ssl'
/usr/local/nginx/keepalived-2.0.0/keepalived/check/check_ssl.c:82: undefined reference to `tls_method'
collect2: error: ld returned 1 exit status
make[2]: *** [keepalived] error 1
make[2]: leaving directory `/usr/local/nginx/keepalived-2.0.0/keepalived'
make[1]: *** [all-recursive] error 1
make[1]: leaving directory `/usr/local/nginx/keepalived-2.0.0/keepalived'
make: *** [all-recursive] error 1
解决方式: 指定ldflags
cd /mysqlsoft/keepalived-2.0.20
ldflags="$ldfags -l /usr/local/openssl/lib/" ./configure --prefix=/usr/local/keepalived --sysconf=/etc
make
make install
tips3: 安装过程中提示openssl is not properly installed on your system. !!!
解决方式: yum -y install openssl-devel
tips4: 安装过程中提示 fatal error zlib.h: no such file or directory # include
解决方式: yum -y install zlib-devel
https://www.keepalived.org/documentation.html#