一、Keepalived 详解

1.Keepalived 定义

Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。Keepalived是VRRP的完美实现,因此在介绍keepalived之前,先介绍一下VRRP的原理。

2.VRRP 协议简介

在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接。对于这样的情况,它们之间路由怎样选择?主机如何选定到达目的主机的下一跳路由,这个问题通常的解决方法有二种:

  • 在主机上使用动态路由协议(RIP、OSPF等)

  • 在主机上配置静态路由

很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过一竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。

3.VRRP 工作机制

在一个VRRP虚拟路由器中,有多台物理的VRRP路由器,但是这多台的物理的机器并不能同时工作,而是由一台称为MASTER的负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP让每个VRRP路由器参与竞选,最终获胜的就是MASTER。MASTER拥有一些特权,比如,拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求。

VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(multicast)包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个周知的MAC地址。所以,在一个虚拟路由 器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对客户端来说,这种主从的切换是透明的。

在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息(VRRPAdvertisement message),BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BACKUP收不到通告信息), 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性。由于安全性考虑,VRRP包使用了加密协议进行加密。

1.1 安装keepalived

分别在两台httpd的server安装keeepalived,并启动

[root@linux-node1 ~]# yum install -y keepalived
[root@linux-node1 ~]# systemctl start keepalived

查看haproxy和httpd状态

[root@linux-node1 ~]# netstat -ntpl|grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3180/haproxy
tcp6 0 0 :::8080 :::* LISTEN 2719/httpd
[root@linux-node2 ~]#  netstat -ntpl|grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 5455/haproxy
tcp6 0 0 :::8080 :::* LISTEN 5280/httpd

1.2 keepalived配置文件详解

keepalived配置文件分为三类:

    • 全局配置:整个keepalived起效的配置
    • VRRPD配置:keepalived的核心
    • LVS配置:有关LVS的配置,此文章不需要 
      编辑配置文件生效,!和#表示注释

编辑配置文件

 
[root@linux-node1 ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email { #keepalived切换时发送email的对象,可以多个,每行一个
zsq@test.cn
}
notification_email_from haproxy-ha@test.cn #邮件来自哪里,haproxy-ha代表给haproxy做高可用
smtp_server 127.0.0.1 #本地配置的smtp
smtp_connect_timeout 30 #连接smtp超时时间30s
router_id haproxy-ha #运行haproxy_ha集群的标识,每个集群一个
}
vrrp_instance HAPROXY_HA { #vrrp实例的名字,根据业务定义
state MASTER #指定instance的初始状态,在两台router都启动后,竞选出Master,这里的state Master并不代表一直是Master
interface eth0 #该实例绑定的网卡设备
virtual_router_id 51 #VRIP,范围0~255,默认51
priority 150 #权重值,用来竞选,MASTER要高于BACKUP至少50,linux-node1权重值修改为150
advert_int 4 #竞选检查间隔,默认1s
authentication { #设置验证,防止局域网多个keepalived配置混乱
auth_type PASS
auth_pass haproxy_ha
}
virtual_ipaddress { #设置的虚拟ip地址
192.168.230.16
192.168.230.17
}
}

将配置文件拷贝到linux-node2上,并更改优先级,注意权重要大于50

[root@linux-node2 ~]# sed -i 's#priority 150#priority 100#g' /etc/keepalived/keepalived.conf 
[root@linux-node2 ~]# sed -i 's#state MASTER#state BACKUP#' /etc/keepalived/keepalived.conf 

启动

systemctl start keepalived.service

查看两台keepalived的虚拟ip情况

[root@linux-node1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:34:58:33 brd ff:ff:ff:ff:ff:ff
inet 192.168.230.130/24 brd 192.168.230.255 scope global dynamic eth0
valid_lft 1179sec preferred_lft 1179sec
inet 192.168.230.16/32 scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.230.17/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe34:5833/64 scope link
valid_lft forever preferred_lft forever [root@linux-node2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:00:dd:15 brd ff:ff:ff:ff:ff:ff
inet 192.168.230.131/24 brd 192.168.230.255 scope global dynamic eth0
valid_lft 1228sec preferred_lft 1228sec
inet6 fe80::20c:29ff:fe00:dd15/64 scope link
valid_lft forever preferred_lft forever

监控VRRP的包查看组播包 ,可以看出竞选的频率为4s,(4s太长了,建议改一秒)MASTER为linux-node1(权重值为150)

[root@linux-node1 ~]# tcpdump -n 'host 224.0.0.18'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:20:23.666534 IP 192.168.230.130 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 24
21:20:27.667590 IP 192.168.230.130 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 24

手动关闭linux-node1上的keepalived,查看ip,会发现此时VIP已经漂移到linxu-node2上

[root@linux-node2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:00:dd:15 brd ff:ff:ff:ff:ff:ff
inet 192.168.230.131/24 brd 192.168.230.255 scope global dynamic eth0
valid_lft 1450sec preferred_lft 1450sec
inet 192.168.230.16/32 scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.230.17/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe00:dd15/64 scope link
valid_lft forever preferred_lft forever

二、keepalived不抢占

当MASTER出现问题后,BACKUP会精选出新的MASTER,那么当之前的MASTER重新上线后,是继续成为MASTER还是变成BACKUP呢?默认情况下,不设会不抢占,那么之前的MASTER起来后会继续抢占成为MASTER,也就是说,整个过程需要发生两次切换。 
    1)MASTER -> BACKUP 
    2) BACKUP -> MASTER 
  这样对业务频繁的切换是不能容忍的,因此我们希望MASTER起来后成为BACKUP,所以要设置不抢占。keepalived里面提供了nopreempt这个配置,但是这个配置只能用在state为BACKUP的机器上,但是我们明明希望的是MASTER不进行抢占,没办法,MASTER的state也要设置成BACKUP,也就是说两台keepalived的state都要设置成BACKUP。 
具体配置为 
  1)两台的state处都修改为backup 
  2)最开始最为MASTER的keepalived的在instance配置段加上nopreempt参数,当此keepalived节点挂了,bakcup将抢占为主,原master恢复后不抢占。

三、配置脚本keepalived检查功能

在keepalived.conf中添加vrrp_script配置段

[root@linux-node1 ~]#cat  keepalived.conf

! Configuration File for keepalived
global_defs {
notification_email {
zsq@test.cn
}
notification_email_from haproxy-ha@test.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy-ha
}
vrrp_script chk_haproxy { #增加检测script
script "/root/shell/check_haproxy.sh"
interval 60
weight 2
}
vrrp_instance HAPROXY_HA
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 4
authentication {
auth_type PASS
auth_pass haproxy_ha
}
virtual_ipaddress {
192.168.230.16
192.168.230.17
}

track_script {
chk_haproxy
}

}

检查脚本:

cat /root/shell/check_haproxy.sh
#!/bin/sh
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
/etc/init.d/haproxy start
fi sleep 2
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
/etc/init.d/keepalived stop
fi

我们大致讲解一下“ps -C haproxy –no-header | wc -l”这个命令: - ps 这个命令用来进行Linux中进程相关的查询,-C 意思是按照进程名称进行查询。
如果要去掉统计出来的结果表的头部,那么要使用 –no-header参数
“|”,这是Linux中的管道流命令,将上一个命令的输出结果作为下一个命令的输入。
wc 统计命令,-l 参数,代表按行数进行统计

如果当前haproxy的进程数量 == 0,那么执行haproxy的启动命令,试图重新启动haproxy;接下来等待2秒(这是为了给haproxy一定的启动时间),然后再次查看haproxy的进程数量,如果仍然 == 0,那么停止这台机器的keepalived服务,以便备用的Keepalived节点检查到Keepalived已经停止这个事件,并将浮动IP切换到备用服务器上。

四、裂脑

4.1 解释裂脑

  在“双机热备”高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障,2个节点上的HA软件像“裂脑人”一样,“本能”地争抢“共享资源”、争起“应用服务”,就会发生严重后果:或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。 
  运行于备用主机上的Heartbeat可以通过以太网连接检测主服务器的运行状态,一旦其无法检测到主服务器的“心跳”则自动接管主服务器的资源。通常情况下,主、备服务器间的心跳连接是一个独立的物理连接,这个连接可以是串行线缆、一个由“交叉线”实现的以太网连接。Heartbeat甚至可同时通过多个物理连接检测主服务器的工作状态,而其只要能通过其中一个连接收到主服务器处于活动状态的信息,就会认为主服务器处于正常状态。从实践经验的角度来说,建议为Heartbeat配置多条独立的物理连接,以避免Heartbeat通信线路本身存在单点故障。

4.2 产生裂脑的原因

  • 高可用服务器之间心跳线链路故障,导致无法正常通信 
    1)心跳线坏了(线路老化或者意外断了) 
    2)网卡及相关驱动坏了,IP配置及冲突问题,网卡直连 
    3)心跳线间链接的设备故障(网卡及交换机) 
    4)仲裁的机器或者仲裁方案出问题
  • 高可用服务器对上开启了iptables防火墙阻挡了心跳消息传输
  • 高可用服务器对上心跳网卡地址等信息配置不争取额,导致发送心跳失败
  • 启发服务配置不当等原因,如心跳方式不同,心跳广播冲突,软件BUG等

4.3 防止发生裂脑的措施

    • 同时使用穿线电缆和以太网电缆连接,同时用两条线路,这样一条线路坏了,另一个还是好的,依然能传送心跳信息。
    • 当检测到裂脑时强行关闭一个心跳节点,需要特殊设备(Stonith,fence)。相当于程序上备节点发现心跳线故障,发送关机命令到主节点。
    • 做好对脑力额的监控报警(邮件短信值班等),发生问题时人为第一时间介入仲裁,降低损失。当然,在实施高可用方案时,要根据业务需求确定是否能容忍这样的损失,对于一般的网站常规业务,这个损失是可控的。
    • 启用磁盘锁,正在服务一方锁主共享磁盘,裂脑发生时,让对方完全无法抢占。

学习Keepalived(一)的更多相关文章

  1. 一脸懵逼学习keepalived(对Nginx进行热备)

    1:Keepalived的官方网址:http://www.keepalived.org/ 2:Keepalived:可以实现高可靠: 高可靠的概念: HA(High Available), 高可用性集 ...

  2. 深入学习keepalived之一 keepalived的启动

    1.keepalived的启动过程: 启动健康检查子进程和vrrp子进程.其中_WITH_LVS_,_WITH_VRRP_在configure和configure.in文件中定义. 源码如下: /* ...

  3. 学习Keepalived(三)

    1.1Keepalived高可用软件 Keepalived起初是专为LVS设计的,专门用来监控LVS集群系统中各个服务节点的状态,后来又加入了VRRP的功能,因此除了配合LVS服务外,也可以作为其他服 ...

  4. 学习Keepalived(二)

    一.keepalived简介 keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于,用来防止单点故障. 二.vrrp协议2.1 vrrp协议简介 在现实的网络环境中,两台需要通信 ...

  5. 深入学习keepalived之预备工作--线程

    1. 线程的定义 1.1 线程定义在scheduler.h文件中,其定义如下所示 /* Thread itself. */ typedef struct _thread { unsigned long ...

  6. 高可用实现KeepAlived原理简介

    一.简介 目前主流实现web网站及数据库服务高可用软件包括:keepalived.heartbeat.corosync,cman;高可用简称HA: 官方站点:https://www.keepalive ...

  7. 实战| Nginx+keepalived 实现高可用集群

    一个执着于技术的公众号 前言 今天通过两个实战案例,带大家理解Nginx+keepalived 如何实现高可用集群,在学习新知识之前您可以选择性复习之前的知识点: 给小白的 Nginx 10分钟入门指 ...

  8. 干货 | Keepalived高可用服务配置实例

    一个执着于技术的公众号 Keepalived系列导读 Keepalived入门学习 keepalived安装及配置文件详解 前言 在前面的章节中,我们学习了Keepalived简介.原理.以及Keep ...

  9. keepalived安装及配置文件详解

    一个执着于技术的公众号 在上一篇文章中,我们对Keepalived进行了简单入门学习: Keepalived入门学习 今天我们继续学习Keepalived服务. 一.安装Keepalived服务 两种 ...

随机推荐

  1. 思迈特软件Smartbi光鲜亮丽的背后是什么在支撑?

    思迈特软件Smartbi是国内知名BI厂商,自2011年成立以来就以提升和挖掘客户的价值为使命,致力于为客户提供一站式商业智能平台和BI解决方案,发展到如今已经获得了来自国家.地方政府.国内外权威分析 ...

  2. Docker容器里部署Apache+PHP+MariaDB+phpMyAdmin

    前面讲到了创建MariaDB,这次在前面的基础上搭建phpMyAdmin服务,以便友好的管理数据库MariaDB.MariaDB的docker独立出来,这样方便管理,易于扩展.这次我们基于Docker ...

  3. SQL Server 2005 - 让 SELECT 查詢結果额外增加递增序号

    /* 方法一*/SELECT 序號= (SELECT COUNT(客戶編號) FROM 客戶 AS LiMing                 WHERE LiMing.客戶編號<= Chan ...

  4. 商城秒杀系统总结(Java)

    本文写的较为零散,对没有基础的同学不太友好. 一.秒杀系统项目总结(基础版) classpath 在.properties中时常需要读取资源,定位文件地址时经常用到classpath 类路径指的是sr ...

  5. Linux系统LVM逻辑卷创建过程以及自动化脚本

    转至:https://cloud.tencent.com/developer/article/1068328 Linux系统LVM逻辑卷创建过程以及自动化脚本 2018-03-21阅读 6300   ...

  6. 2020ICPC上海站 C. Sum of Log

    题目大意: 给定T组X,Y,对于每组X,Y,求上面式子   的值,其中  当x为真时等于1,其他情况等于0. 其中. 思路: 对X,Y一起进行数位DP,我们把每一位枚举数字的上限以及数字之前是否有前导 ...

  7. Pycharm:安装anaconda中没有的第三方库

    Pycharm需要用到的pyKriging第三方库库,但是下载了Anaconda后无法在Pycharm中搜到,之前还能搜到的,所以一定是因为Anaconda的原因,后来经过摸索,终于找到了解决问题的办 ...

  8. Python:Scrapy(四) 命令行相关

    学习自Scrapy 2.4.1 documentation 这一部分是对官方文档的学习,主要是理解翻译,来对之前的应用部分进行详细的理论补充. 1.保存爬取到的要素的方式: ①运行scrapy指令时, ...

  9. Anaconda Navigator:this application failed to start because it could not find or load ...windows in

    原因:在Anaconda的根目录下,有一个叫 qt.conf的文件,用记事本或者Notepad打开 该问题是这些路径错误导致的(比如你把Anaconda挪动了位置,导致这里边的路径还是原来的位置). ...

  10. ShardingJdbc-分表;分库;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务

    目录 创建项目 分表 导包 表结构 Yml 分库 Yml Java 分库分表 数据库 Yml 读写分离 数据库 Yml 其他 只请求主库 读写分离判断逻辑代码 一主多从+分表 Yml 一主多从+分库分 ...