一、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. python为什么是高级语言和解释型编程语言?它是如何粘合其它语言写的代码的?

    学习python之初,不知道大家对于python有没有疑惑,应当是有的.这里我整理出来了自己的一些疑惑,供大家参考. 为什么python是高级程序设计语言 ​ Java,C,C++这些语言是高级语言, ...

  2. Zookeeper应用场景和ZAB协议

    Zookeeper应用场景 数据发布/订阅(配置中心) 我们平常的开发过程中,经常会碰到这样的需求:系统中需要一些通用的配置信息,如一些运行时的开关.前端需要展示的通知信息.数据库配置信息等等.这些需 ...

  3. OS模块的补充使用---执行终端命令

    Python基础至os模块 由于近期的项目需要用到对应的终端命令去调用其他程序,因此温习一下os.system()函数: 参考文献:https://zhuanlan.zhihu.com/p/51716 ...

  4. JZ-056-删除链表中重复的结点

    删除链表中重复的结点 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4-> ...

  5. 《手把手教你》系列基础篇(七十三)-java+ selenium自动化测试-框架设计基础-TestNG实现启动不同浏览器(详解教程)

    1.简介 上一篇文章中,从TestNg的特点我们知道支持变量,那么我们这一篇就通过变量参数来启动不同的浏览器进行自动化测试.那么如何实现同时启动不同的浏览器对脚本进行测试,且听宏哥娓娓道来. 2.项目 ...

  6. Linux命令大全(查看日志)

    1.查看日志常用命令     tail:          -n  是显示行号:相当于nl命令:例子如下:             tail -100f test.log      实时监控100行日 ...

  7. 分布式 PostgreSQL 集群(Citus)官方教程 - 迁移现有应用程序

    将现有应用程序迁移到 Citus 有时需要调整 schema 和查询以获得最佳性能. Citus 扩展了 PostgreSQL 的分布式功能,但它不是扩展所有工作负载的直接替代品.高性能 Citus ...

  8. MYSQL安装后自带用户的作用

    user表中host列的值的意义%                   匹配所有主机localhost      localhost不会被解析成IP地址,直接通过UNIXsocket连接127.0.0 ...

  9. AngularJS集成富文本编辑器

    最近在Angular中需要集成富文本编辑器,本来已经集成好百度的UEditor,后台觉得配置太多,让我弄个别的,然后就找到了wangEditor,这个配置和上手都要简单一些,下面来看看具体操作步骤吧: ...

  10. kafka 第一次小整理(草稿篇)————演变[二]

    前言 简单整理一些kafka的设计. 正文 前文提及到log 的重要性,以及kafka在其中的作用,起着一个日志管理分发的作用,对于其他服务来说相当于新闻报社,订阅某种主题就会收到某类信息. 当人们意 ...