一、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. Clickhouse - Replication机制

    Clickhouse - Replication机制 1. Replication引擎族 Replication仅对于MergeTree引擎族提供支持, 两者是正交的: ReplicatedMerge ...

  2. scrapy初体验

    1. 构建scrapy项目 scrapy startproject ['项目名'] 在spiders下生成文件 cd spiders scrapy genspider douban_spider [' ...

  3. 【01】Spring Boot配置文件相关

    1.Spring Boot 获取属性的属性源,优先级从高到低 (1)命令行参数 (2)java:comp/env里的JNDI属性 (3)JVM系统属性 (4)操作系统的环境变量 (5)随机生成的的带r ...

  4. 【C# IO 操作】使用StringWriter和StringReader的好处

    当你有一组应用程序接口(API)只允许用Writer或Reader作为输入,但你又想使用String,这时可以用StringWriter或StringReader. 假设有下面这样一个process方 ...

  5. Java中读写锁的介绍

    读写锁的简单介绍 所谓的读写锁,就是将一个锁拆分为读锁和写锁两个锁,然后你加锁的时候,可以加读锁,也可以加写锁. ReentrantLock lock=new ReentrantLock(); loc ...

  6. SqlServer 局域网内不能连接对方数据库?

    一直都是连接的远程测试服务器的数据库,今天想把自己的数据库开放出来让公司同事连接,竟然连接失败!转了很大一个圈终于搞定了. 接下来就把这次心历路程发出来,希望能帮助到有需要的博友. PS: 我和同事的 ...

  7. 函数式编程 高阶函数 map&reduce filter sorted

    函数式编程 纯函数:没有变量的函数 对于纯函数而言:只要输入确定,那么输出就是确定的.纯函数是没有副作用的. 函数式编程:允许把函数本身作为参数传入另一个函数,还允许返回一个函数 高阶函数:一个函数的 ...

  8. LeetCode-016-最接近的三数之和

    最接近的三数之和 题目描述:给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 nums 中的三个整数,使得它们的和与 target 最接近.返回这三个数的和.假定每组输入只 ...

  9. vm虚拟机安装CentOS8.2服务器系统

    前言   开发服务器应用,需要使用到CentOS8.2,安装到虚拟机上方便快捷.   提前准备 Vmware 16虚拟机软件  下载VM16版本及以上的vmware虚拟机版本,否则没有CentOs8选 ...

  10. 1.java连接pulsar服务

    目录 是什么 安装 Java客户端 1.引入GAV 2.创建配置项 3.验证测试 其他及代码下载 是什么 Pulsar 是一个用于服务器到服务器的消息系统,具有多租户.高性能等优势.详见 安装 本文主 ...