KeepAlived
KeepAlived

KeepAlived

高可用集群

集群类型

LB:Load Balance 负载均衡
LVS/HAProxy/nginx(http/upstream, stream/upstream)
HA:High Availability 高可用集群
数据库、Zookeeper、Redis
KeepAlived 通用的高可用集群
SPoF: Single Point of Failure,解决单点故障
HPC:High Performance Computing 高性能集群
https://www.top500.org

系统可用性

SLA:Service-Level Agreement 服务等级协议(提供服务的企业与客户之间就服务的品质、水准、性能等方面所达成的双方共同认可的协议或契约)
A = MTBF / (MTBF+MTTR)

99.95%:(60*24*30)*(1-0.9995)=21.6分钟 #一般按一个月停机时间统计

指标 :99.9%, 99.99%, 99.999%,99.9999%

实现高可用

提升系统高用性的解决方案:降低MTTR- Mean Time To Repair(平均故障时间)
解决方案:建立冗余机制
active/passive 主/备
active/active 双主
active –> HEARTBEAT –> passive
active <–> HEARTBEAT <–> active

高可用相关技术

HA Service
资源:组成一个高可用服务的“组件”,比如:vip,service process,shared storage
passive node的数量
资源切换
Shared Storage
NAS(Network Attached Storage):网络附加存储,基于网络的共享文件系统。
SAN(Storage Area Network):存储区域网络,基于网络的块级别的共享
Network partition 网络分区
quorum 法定人数,仲裁
with quorum: > total/2
without quorum: <= total/2
隔离设备 fence
node:STONITH = Shooting The Other Node In The Head(强制下线/断电)

参考资料:
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html/high_availability_add-on_reference/s1-unfence-haar
双节点集群(TWO nodes Cluster)
辅助设备:仲裁设备,ping node, quorum disk
Failover:故障切换,即某资源的主节点故障时,将资源转移至其它节点的操作
Failback:故障移回,即某资源的主节点故障后重新修改上线后,将之前已转移至其它节点的资源重新切回的过程

HA Cluster 实现方案
AIS:Applicaiton Interface Specification 应用程序接口规范
RHCS:Red Hat Cluster Suite 红帽集群套件
参考资料:https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/5/html/cluster_suite_overview/ch.gfscs.cluster-overview-cso
heartbeat:基于心跳监测实现服务高可用
pacemaker+corosync:资源管理与故障转移

VRRP:Virtual Router Redundancy Protocol
虚拟路由冗余协议,解决静态网关单点风险
物理层:路由器、三层交换机
软件层:keepalived
VRRP
VRRP 网络层硬件实现
参考链接:
https://support.huawei.com/enterprise/zh/doc/EDOC1000141382/19258d72/basic-concepts-of-vrrp
https://wenku.baidu.com/view/dc0afaa6f524ccbff1218416.html
https://wenku.baidu.com/view/281ae109ba1aa8114431d9d0.html

VRRP 相关术语
虚拟路由器:Virtual Router
虚拟路由器标识:VRID(0-255),唯一标识虚拟路由器
VIP:Virtual IP
VMAC:Virutal MAC (00-00-5e-00-01-VRID)
物理路由器:
master:主设备
backup:备用设备
priority:优先级

VRRP 相关技术
通告:心跳,优先级等;周期性
工作方式:抢占式,非抢占式

安全认证:
无认证
简单字符认证:预共享密钥
MD5

工作模式:
主/备:单虚拟路由器
主/主:主/备(虚拟路由器1),备/主(虚拟路由器2)

Keepalived介绍

vrrp 协议的软件实现,原生设计目的为了高可用 ipvs服务
官网:http://keepalived.org/
功能:
基于vrrp协议完成地址流动
为vip地址所在的节点生成ipvs规则(在配置文件中预先定义)
为ipvs集群的各RS做健康状态检测
基于脚本调用接口完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务

Keepalived 架构

官方文档:
https://keepalived.org/doc/
http://keepalived.org/documentation.html

·用户空间核心组件:
 vrrp stack:VIP消息通告
 checkers:监测 Real Server
 system call:实现 vrrp 协议状态转换时调用脚本的功能
 SMTP:邮件组件
 IPVS wrapper:生成 IPVS 规则
 Netlink Reflector:网络接口
 WatchDog:监控进程
·控制组件:提供keepalived.conf 的解析器,完成Keepalived配置
·IO复用器:针对网络目的而优化的自己的线程抽象
·内存管理组件:为某些通用的内存管理功能(例如分配,重新分配,发布等)提供访问权限

Keepalived进程树
Keepalived <-- Parent process monitoring children
\_ Keepalived <-- VRRP child
\_ Keepalived <-- Healthchecking child

keepalived安装

apt -y isntall keepalived
yum -y install keepalived

脚本编译安装

#!/bin/bash
#
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-10-26
#FileName:          install_keepalived.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************
KEEPALIVED_VERSION=2.2.7
#KEEPALIVED_VERSION=2.2.2
#KEEPALIVED_VERSION=2.0.20
KEEPALIVED_FILE=keepalived-${KEEPALIVED_VERSION}.tar.gz

KEEPALIVED_INSTALL_DIR=/apps/keepalived
SRC_DIR=/usr/local/src
KEEPALIVED_URL=https://keepalived.org/software/

CPUS=grep -c processor  /proc/cpuinfo

. /etc/os-release


color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


download_file (){
    cd  ${SRC_DIR}
    if [ $ID = 'centos' -o $ID = 'rocky' ];then
        rpm -q wget &> /dev/null || yum -y install wget 
    elif [ $ID = 'ubuntu' ];then
        dpkg -l |grep wget || { apt update;  apt install -y wget; } 
    else
        color "不支持此操作系统,退出!" 1
        exit
    fi
    if [ ! -e ${KEEPALIVED_FILE} ];then
        wget --no-check-certificate  ${KEEPALIVED_URL}${KEEPALIVED_FILE} 
        [ $? -ne 0 ] && { color "KEEPALIVED源码包下载失败" 1 ; exit; }
    fi
}

install_keepalived () {
    if [ $ID = 'centos' -o $ID = 'rocky' ];then
        yum -y install make gcc ipvsadm autoconf automake openssl-devel libnl3-devel iptables-devel net-snmp-devel glib2-devel pcre2-devel  libmnl-devel systemd-devel &> /dev/null
    elif [ $ID = 'ubuntu' ];then
        apt update 
        apt -y install make gcc ipvsadm build-essential pkg-config automake autoconf libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev
    else
        color "不支持此操作系统,退出!" 1
    fi
    tar xf ${KEEPALIVED_FILE}
    cd keepalived-${KEEPALIVED_VERSION}
    ./configure --prefix=${KEEPALIVED_INSTALL_DIR} --disable-fwmark
    make -j $CPUS && make install
    if [ $? -eq 0 ];then
        color "KEEPALIVED编译安装成功" 0
    else
        color "KEEPALIVED编译安装失败,退出!" 1
        exit
    fi
    [ -d /etc/keepalived ] || mkdir -p /etc/keepalived
    cp ${KEEPALIVED_INSTALL_DIR}/etc/keepalived/keepalived.conf.sample  /etc/keepalived/keepalived.conf
    cp ./keepalived/keepalived.service /lib/systemd/system/
}

start_keepalived () {
    systemctl daemon-reload
    systemctl enable --now keepalived &> /dev/null 
    systemctl is-active keepalived
    if [ $? -eq 0 ] ;then
        color "Keepalived 服务安装成功!" 0  
    else
        color "Keepalived 服务安装失败!" 1
        exit 1
    fi
}

download_file

install_keepalived

start_keepalived

KeepAlived 配置说明

配置文件组成部分

配置文件:/etc/keepalived/keepalived.conf

GLOBAL CONFIGURATION
Global definitions:定义邮件配置,route_id,vrrp配置,多播地址等
VRRP CONFIGURATION
VRRP instance(s):定义每个vrrp虚拟路由器
LVS CONFIGURATION
Virtual server group(s)
Virtual server(s):LVS集群的VS和RS

配置语法说明

man keepalived.conf
cat /usr/local/src/keepalived-2.2.7/doc/man/man5/keepalived.conf.5

全局配置
#/etc/keepalived/keepalived.conf
global_defs {
notification_email {
root@localhost #keepalived 发生故障切换时邮件发送的目标邮箱,可以按行区分写多个
root@shuhong.com
985347841@qq.com
}
notification_email_from keepalived@localhost #发邮件的地址
smtp_server 127.0.0.1 #邮件服务器地址
smtp_connect_timeout 30 #邮件服务器连接timeout
router_id ka1.example.com #每个keepalived主机唯一标识,建议使用当前主机名,如果多节点重名可能会影响切换脚本执行
vrrp_skip_check_adv_addr #对所有通告报文都检查,会比较消耗性能,启用此配置后,如果收到的通告报文和上一个报文是同一个路由器,则跳过检查,默认值为全检查
vrrp_strict #严格遵守VRRP协议,启用此项后以下状况将无法启动服务:1.无VIP地址 2.配置了单播邻居 3.在VRRP版本2中有IPv6地址,开启动此项并且没有配置vrrp_iptables时会自动开启iptables防火墙规则,默认导致VIP无法访问,建议不加此项配置
vrrp_garp_interval 0 #gratuitous ARP messages 报文发送延迟,0表示不延迟
vrrp_gna_interval 0 #unsolicited NA messages (不请自来)消息发送延迟
vrrp_mcast_group4 224.0.0.18 #指定组播IP地址范围:224.0.0.0到239.255.255.255,默认值:224.0.0.18
vrrp_iptables #此项和vrrp_strict同时开启时,则不会添加防火墙规则,如果无配置
vrrp_strict项,则无需启用此项配置,注意:新版加此项仍有iptables规则
}
配置虚拟路由器
vrrp_instance <STRING> { #<String>为vrrp的实例名,一般为业务名称
配置参数
......
}
#配置参数:
state MASTER|BACKUP#当前节点在此虚拟路由器上的初始状态,状态为MASTER或者BACKUP
interface IFACE_NAME #绑定为当前虚拟路由器使用的物理接口,如:eth0,bond0,br0,可以和VIP不在一个网卡
virtual_router_id VRID #每个虚拟路由器唯一标识,范围:0-255,每个虚拟路由器此值必须唯一,否则服务无法启动,同属一个虚拟路由器的多个keepalived节点必须相同,务必要确认在同一网络中此值必须唯一
priority 100 #当前物理节点在此虚拟路由器的优先级,范围:1-254,每个keepalived主机节点此值不同
advert_int 1 #vrrp通告的时间间隔,默认1s
authentication { #认证机制
auth_type AH|PASS #AH为IPSEC认证(不推荐),PASS为简单密码(建议使用)
auth_pass <PASSWORD> #预共享密钥,仅前8位有效,同一个虚拟路由器的多个keepalived节点必须一样
}
virtual_ipaddress { #虚拟IP,生产环境可能指定几十上百个VIP地址
<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
192.168.200.100 #指定VIP,不指定网卡,默认为eth0,注意:不指定/prefix,默认为/32
192.168.200.101/24 dev eth1 #指定VIP的网卡,建议和interface指令指定的网卡不在一个网卡
192.168.200.102/24 dev eth2 label eth2:1 #指定VIP的网卡label
}
track_interface { #配置监控网络接口,一旦出现故障,则转为FAULT状态实现地址转移
eth0
eth1
...
}

启用 Keepalived 日志功能

#查看启动文件,寻找配置环境文件
[root@keepalived01 ~]#cat /lib/systemd/system/keepalived.service 
[Unit]
Description=LVS and VRRP High Availability Monitor
After=network-online.target syslog.target 
Wants=network-online.target 
Documentation=man:keepalived(8)
Documentation=man:keepalived.conf(5)
Documentation=man:genhash(1)
Documentation=https://keepalived.org

[Service]
Type=notify
NotifyAccess=all
PIDFile=/run/keepalived.pid
KillMode=process
EnvironmentFile=-/apps/keepalived/etc/sysconfig/keepalived
ExecStart=/apps/keepalived/sbin/keepalived --dont-fork $KEEPALIVED_OPTIONS
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

#添加日志选项
[root@keepalived01 ~]#vim  /apps/keepalived/etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -S 6"
[root@keepalived01 ~]#vim /etc/rsyslog.d/keepalived.conf
local6.* /var/log/keepalived.log
[root@keepalived01 ~]#systemctl restart keepalived.service rsyslog.service 
[root@keepalived01 ~]#tail  -f /var/log/keepalived.log 
Oct 26 20:34:03 keepalived01 Keepalived_vrrp[29640]: VRRP sockpool: [ifindex(  2), family(IPv4), proto(112), fd(12,13) multicast, address(224.0.0.18)]
Oct 26 20:34:07 keepalived01 Keepalived_vrrp[29640]: (VI_1) Receive advertisement timeout
Oct 26 20:34:07 keepalived01 Keepalived_vrrp[29640]: (VI_1) Entering MASTER STATE
Oct 26 20:34:07 keepalived01 Keepalived_vrrp[29640]: (VI_1) setting VIPs.
Oct 26 20:34:07 keepalived01 Keepalived_vrrp[29640]: (VI_1) Sending/queueing gratuitous ARPs on eth0 for 10.0.0.10
Oct 26 20:34:07 keepalived01 Keepalived_vrrp[29640]: Sending gratuitous ARP on eth0 for 10.0.0.10
Oct 26 20:34:07 keepalived01 Keepalived_vrrp[29640]: message repeated 4 times: [ Sending gratuitous ARP on eth0 for 10.0.0.10]
Oct 26 20:34:12 keepalived01 Keepalived_vrrp[29640]: (VI_1) Sending/queueing gratuitous ARPs on eth0 for 10.0.0.10

实现 Keepalived 独立子配置文件

[root@keepalived01 ~]#mkdir /etc/keepalived/conf.d
[root@keepalived01 ~]#vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
  
global_defs {
   router_id keepalived01
   vrrp_skip_check_adv_addr
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 224.0.100.10
}
include /etc/keepalived/conf.d/*.conf

[root@keepalived01 ~]#vim /etc/keepalived/conf.d/www.shuhong.com.conf 
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10
    }
}
[root@keepalived01 ~]#systemctl restart keepalived.service 

Keepalived 实现 VRRP

#MASTER配置
[root@keepalived01 ~]#vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
  
global_defs {
   router_id keepalived01
   vrrp_skip_check_adv_addr   #所有报文都检查比较消耗性能,此配置为如果收到的报文和上一个报文是同一个路由器则跳过检查报文中的源地址
   vrrp_garp_interval 0    #ARP报文发送延迟
   vrrp_gna_interval 0     #消息发送延迟
   vrrp_mcast_group4 224.0.100.10  #默认组播IP地址,可指定组播范围:224.0.0.0到239.255.255.255
}
include /etc/keepalived/conf.d/*.conf

[root@keepalived01 ~]#vim /etc/keepalived/conf.d/www.shuhong.com.conf 
vrrp_instance VI_1 {
    state MASTER    #在另一个结点上为BACKUP
    interface eth0  
    virtual_router_id 66   #每个虚拟路由器必须唯一,同属一个虚拟路由器的多个keepalived节点必须相同
    priority 100    #在另一个结点上要比这个低
    advert_int 1
    authentication {
        auth_type PASS   #预共享密钥认证,同一个虚拟路由器的keepalived节点必须一样
        auth_pass 123456 #预共享密钥认证,同一个虚拟路由器的keepalived节点必须一样
    }
    virtual_ipaddress {
        10.0.0.10  dev eth0 label eth0:0
    }
}

#BACKUP配置
[root@keepalived02 conf.d]#cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
  
global_defs {
   router_id keepalived02
   vrrp_skip_check_adv_addr
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 224.0.100.10
}
include /etc/keepalived/conf.d/*.conf
[root@keepalived02 conf.d]#cat /etc/keepalived/conf.d/www.shuhong.com.conf 
vrrp_instance VI_1 {
    state BACKUP 
    interface eth0
    virtual_router_id 66
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
}


#测试
[root@keepalived01 ~]#hostname -I
10.0.0.201 10.0.0.10
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 
[root@ubuntu2004 ~]#tcpdump -i eth0 -nn host 224.0.100.10
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:50:09.825127 IP 10.0.0.201 > 224.0.100.10: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
20:50:10.825857 IP 10.0.0.201 > 224.0.100.10: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
20:50:11.825573 IP 10.0.0.201 > 224.0.100.10: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20

[root@keepalived01 ~]#systemctl stop keepalived.service 
[root@keepalived01 ~]#hostname -I
10.0.0.201
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 10.0.0.10 
[root@ubuntu2004 ~]#tcpdump -i eth0 -nn host 224.0.100.10
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:51:09.808537 IP 10.0.0.202 > 224.0.100.10: VRRPv2, Advertisement, vrid 66, prio 90, authtype simple, intvl 1s, length 20
20:51:10.809239 IP 10.0.0.202 > 224.0.100.10: VRRPv2, Advertisement, vrid 66, prio 90, authtype simple, intvl 1s, length 20

脑裂

主备节点同时拥有VIP,此时为脑裂理象
注意:脑裂现象原因
心跳线故障
防火墙错误配置
Keepalived 配置错误

#通过iptables复现脑裂情况
[root@keepalived01 ~]#hostname -I
10.0.0.201 10.0.0.10
[root@keepalived02 conf.d]#iptables  -I INPUT -s  10.0.0.201 -j DROP 
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 10.0.0.10 

#可以用该命令监控是否发生脑裂
[root@ubuntu2004 ~]#arping  -I eth0 -c1 10.0.0.10
ARPING 10.0.0.10
60 bytes from 00:0c:29:b4:13:50 (10.0.0.10): index=0 time=1.041 msec
60 bytes from 00:0c:29:1a:c3:54 (10.0.0.10): index=1 time=1.096 msec

--- 10.0.0.10 statistics ---
1 packets transmitted, 2 packets received,   0% unanswered (1 extra)
rtt min/avg/max/std-dev = 1.041/1.068/1.096/0.028 ms

抢占模式和非抢占模式

默认为抢占模式 preempt,即当高优先级的主机恢复在线后,会抢占低先级的主机的master角色,造成网络抖动,建议设置为非抢占模式 nopreempt ,即高优先级主机恢复后,并不会抢占低优先级主机的master 角色

注意: 非抢占模式下,如果原主机down机, VIP迁移至的新主机, 后续新主机也发生down时,VIP还会迁移回修复好的原主机

但如果新主机的服务down掉(keepalived服务正常),原主机也不会接管VIP,仍会由新主机拥有VIP即非抢占式模式,只是适合当主节点宕机,切换到从节点的一次性的高可用性,后续即使当原主节点修复好,仍无法再次起到高用功能

注意:要关闭 VIP抢占,必须将各 Keepalived 服务器 state 配置为 BACKUP

#ka1主机配置
vrrp_instance VI_1 {
state BACKUP #都为BACKUP
interface eth0
virtual_router_id 66
priority 100 #优先级高
advert_int 1
nopreempt #添加此行,设为nopreempt


#ka2主机配置
vrrp_instance VI_1 {
state BACKUP #都为BACKUP
interface eth0
virtual_router_id 66
priority 80 #优先级低
advert_int 1
#nopreempt #注意:如果ka2主机也是非抢占式,会导致ka1即使优先级降低于ka2,VIP也不会切换至ka2

抢占延迟模式 preempt_delay

抢占延迟模式,即优先级高的主机恢复后,不会立即抢回VIP,而是延迟一段时间(默认300s)再抢回VIP

preempt_delay # #指定抢占延迟时间为#s,默认延迟300s
注意:需要各keepalived服务器state为BACKUP,并且不要启用 vrrp_strict

#ka1主机配置
vrrp_instance VI_1 {
state BACKUP #都为BACKUP
interface eth0
virtual_router_id 66
priority 100 #优先级高
advert_int 1
preempt_delay 60 #抢占延迟模式,默认延迟300s
#ka2主机配置
vrrp_instance VI_1 {
state BACKUP #都为BACKUP
interface eth0
virtual_router_id 66
priority 80 #优先级低
advert_int 1

VIP 单播配置

默认keepalived主机之间利用多播相互通告消息,会造成网络拥塞,可以替换成单播,减少网络流量
另外:有些公有云不支持多播,可以单播实现
注意:启用 vrrp_strict 时,不能启用单播

#在所有节点vrrp_instance语句块中设置对方主机的IP,建议设置为专用于对应心跳线网络的地址,而非使
用业务网络
unicast_src_ip <IPADDR> #指定发送单播的源IP
unicast_peer {
<IPADDR> #指定接收单播的对方目标主机IP
......
}
#MASTER
[root@keepalived01 conf.d]#cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
   router_id keepalived01
   vrrp_skip_check_adv_addr
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 224.0.100.10  #单播优先级高于多播
}
include /etc/keepalived/conf.d/*.conf
[root@keepalived01 conf.d]#cat /etc/keepalived/conf.d/www.shuhong.com.conf 
vrrp_instance VI_1 {
    state MASTER
    interface eth1
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.201   #本机地址
    unicast_peer{ 
        192.168.10.202              #对方地址,可以配置多个
    }

}

#BACKUP
[root@keepalived02 conf.d]#cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
  
global_defs {
   router_id keepalived02
   vrrp_skip_check_adv_addr
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 224.0.100.10
}
include /etc/keepalived/conf.d/*.conf
[root@keepalived02 conf.d]#cat /etc/keepalived/conf.d/www.shuhong.com.conf 
vrrp_instance VI_1 {
    state BACKUP 
    interface eth1
    virtual_router_id 66
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.202 
    unicast_peer{
        192.168.10.201
    }
}

[root@keepalived02 conf.d]#tcpdump -i eth1 -nn host 192.168.10.201
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
21:26:12.053545 IP 192.168.10.201 > 192.168.10.202: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
21:26:13.053404 IP 192.168.10.201 > 192.168.10.202: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
21:26:14.053834 IP 192.168.10.201 > 192.168.10.202: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20

[root@keepalived01 conf.d]#tcpdump -i eth1 -nn host 192.168.10.201
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
21:26:30.022471 IP 192.168.10.201 > 192.168.10.202: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
21:26:31.022684 IP 192.168.10.201 > 192.168.10.202: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20
21:26:32.022919 IP 192.168.10.201 > 192.168.10.202: VRRPv2, Advertisement, vrid 66, prio 100, authtype simple, intvl 1s, length 20

Keepalived 通知脚本配置

当keepalived的状态变化时,可以自动触发脚本的执行,比如:发邮件通知用户
默认以用户keepalived_script身份执行脚本,如果此用户不存在,以root执行脚本
可以用下面指令指定脚本执行用户的身
global_defs {
……
script_user <USER>
……
}

通知脚本类型:

当前节点成为主节点时触发的脚本
notify_master <STRING>|<QUOTED-STRING>

当前节点转为备节点时触发的脚本
notify_backup <STRING>|<QUOTED-STRING>

当前节点转为“失败”状态时触发的脚本
notify_fault <STRING>|<QUOTED-STRING>

通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知
notify <STRING>|<QUOTED-STRING>

当停止VRRP时触发的脚本
notify_stop <STRING>|<QUOTED-STRING>

脚本的调用方法:

在 vrrp_instance VI_1 语句块的末尾加下面行
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
[root@keepalived01 keepalived]#cat notify.sh 
#!/bin/bash
#
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-10-26
#FileName:          notify.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************
contact='985347841@qq.com'
email_send='985347841@qq.com'
email_passwd='hgxbxniljwlfbdii'
email_smtp_server='smtp.qq.com'

. /etc/os-release

msg_error() {
  echo -e "\033[1;31m$1\033[0m"
}

msg_info() {
  echo -e "\033[1;32m$1\033[0m"
}

msg_warn() {
  echo -e "\033[1;33m$1\033[0m"
}

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


install_sendemail () {
    if [[ $ID =~ rhel|centos|rocky ]];then
        rpm -q sendemail &> /dev/null ||  yum install -y sendemail
    elif [ $ID = 'ubuntu' ];then
        dpkg -l |grep -q sendemail  || { apt update; apt install -y libio-socket-ssl-perl libnet-ssleay-perl sendemail ; } 
    else
        color "不支持此操作系统,退出!" 1
        exit
    fi
}

send_email () {
    local email_receive="$1"
    local email_subject="$2"
    local email_message="$3"
    sendemail -f $email_send -t $email_receive -u $email_subject -m $email_message -s $email_smtp_server -o message-charset=utf-8 -o tls=yes -xu $email_send -xp $email_passwd
    [ $? -eq 0 ] && color "邮件发送成功!" 0 || color "邮件发送失败!" 1 
}

notify() {
    if [[ $1 =~ ^(master|backup|fault)$ ]];then
        mailsubject="$(hostname) to be $1, vip floating"
        mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
        send_email "$contact" "$mailsubject" "$mailbody"
   else
        echo "Usage: $(basename $0) {master|backup|fault}"
        exit 1
   fi
}

install_sendemail 
notify $1

[root@keepalived01 keepalived]#chmod +x notify.sh

[root@keepalived01 keepalived]#vim conf.d/www.shuhong.com.conf
vrrp_instance VI_1 {
    state MASTER
    interface eth1
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.201
    unicast_peer{
        192.168.10.202
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}
[root@keepalived01 keepalived]#systemctl restart keepalived.service 
#keepalived02配置同上

#测试
[root@keepalived01 keepalived]#systemctl stop keepalived.service 

实现 Master/Master 的 Keepalived 双主架构

#BACKUP
[root@keepalived01 conf.d]#vim www.shuhong.io.conf 
vrrp_instance VI_2 {
    state BACKUP
    interface eth1
    virtual_router_id 88
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 654321
    }
    virtual_ipaddress {
        10.0.0.100 dev eth0 label eth0:1
    }
    unicast_src_ip 192.168.10.201
    unicast_peer{
        192.168.10.202
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}
[root@keepalived01 conf.d]#systemctl restart keepalived.service 
[root@keepalived01 conf.d]#hostname -I
10.0.0.201 10.0.0.10 192.168.10.201 

#MASTER
[root@keepalived02 conf.d]#vim www.shuhong.io.conf 
vrrp_instance VI_2 {
    state MASTER
    interface eth1
    virtual_router_id 88
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 654321
    }
    virtual_ipaddress {
        10.0.0.100 dev eth0 label eth0:1
    }
    unicast_src_ip 192.168.10.202
    unicast_peer{
        192.168.10.201
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"

}
[root@keepalived02 conf.d]#systemctl restart keepalived.service 
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 10.0.0.100 192.168.10.202 

实现多主模架构

#第一个节点ka1配置:
virtual_router_id 1 , Vrrp instance 1 , MASTER,优先级 100
virtual_router_id 3 , Vrrp instance 2 , BACKUP,优先级 80
#第二个节点ka2配置:
virtual_router_id 2 , Vrrp instance 1 , MASTER,优先级 100
virtual_router_id 1 , Vrrp instance 2 , BACKUP,优先级 80
#第三个节点ka3配置:
virtual_router_id 3 , Vrrp instance 1 , MASTER,优先级 100
virtual_router_id 2 , Vrrp instance 2 , BACKUP,优先级 80

三个节点的三主六从架构实现

#第一个节点ka1配置:
virtual_router_id 1 , Vrrp instance 1 , MASTER,优先级100
virtual_router_id 2 , Vrrp instance 2 , BACKUP,优先级80
virtual_router_id 3 , Vrrp instance 3 , BACKUP,优先级60
#第二个节点ka2配置:
virtual_router_id 1 , Vrrp instance 1 , BACKUP,优先级60
virtual_router_id 2 , Vrrp instance 2 , MASTER,优先级100
virtual_router_id 3 , Vrrp instance 3 , BACKUP,优先级80
#第三个节点ka3配置:
virtual_router_id 1 , Vrrp instance 1 , BACKUP,优先级80
virtual_router_id 2 , Vrrp instance 2 , BACKUP,优先级60
virtual_router_id 3 , Vrrp instance 3 , MASTER,优先级100

同步组

vrrp_sync_group VG_1 {
group {
VI_1 # name of vrrp_instance (below)
VI_2 # One for each moveable IP
}
}
vrrp_instance VI_1 {
eth0
vip
}
vrrp_instance VI_2 {
eth1
dip
}

实现 IPVS 的高可用性

IPVS 相关配置

虚拟服务器配置结构:
virtual_server IP port {
...
real_server {
...
}
real_server {
...
}
...
}

Virtual Server (虚拟服务器)的定义格式:
virtual_server IP port #定义虚拟主机IP地址及其端口
virtual_server fwmark int #ipvs的防火墙打标,实现基于防火墙的负载均衡集群
virtual_server group string #使用虚拟服务器组

虚拟服务器组:
将多个虚拟服务器定义成一个组,统一对外服务,如:http和https定义成一个虚拟服务器组
#参考文档:/usr/share/doc/keepalived/keepalived.conf.virtual_server_group
virtual_server_group <STRING> {
# Virtual IP Address and Port
<IPADDR> <PORT>
<IPADDR> <PORT>
...
# <IPADDR RANGE> has the form
# XXX.YYY.ZZZ.WWW-VVV eg 192.168.200.1-10
# range includes both .1 and .10 address
<IPADDR RANGE> <PORT># VIP range VPORT
<IPADDR RANGE> <PORT>
...
# Firewall Mark (fwmark)
fwmark <INTEGER>
fwmark <INTEGER>
...
}

虚拟服务器配置:
virtual_server IP port { #VIP和PORT
delay_loop <INT> #检查后端服务器的时间间隔
lb_algo rr|wrr|lc|wlc|lblc|sh|dh #定义调度方法
lb_kind NAT|DR|TUN #集群的类型,注意要大写
persistence_timeout <INT> #持久连接时长
protocol TCP|UDP|SCTP #指定服务协议,一般为TCP
sorry_server <IPADDR> <PORT> #所有RS故障时,备用服务器地址
real_server <IPADDR> <PORT> { #RS的IP和PORT
weight <INT> #RS权重
notify_up <STRING>|<QUOTED-STRING> #RS上线通知脚本
notify_down <STRING>|<QUOTED-STRING> #RS下线通知脚本
HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... } #定义当前主机健康状态检测方法
}
}
#注意:括号必须分行写,两个括号写在同一行,如: }} 会出错

应用层监测:
应用层检测:HTTP_GET|SSL_GET
HTTP_GET|SSL_GET {
url {
path <URL_PATH> #定义要监控的URL
status_code <INT> #判断上述检测机制为健康状态的响应码,一般为 200
}
connect_timeout <INTEGER> #客户端请求的超时时长, 相当于haproxy的timeout server
nb_get_retry <INT> #重试次数
delay_before_retry <INT> #重试之前的延迟时长
connect_ip <IP ADDRESS> #向当前RS哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #向当前RS发出健康状态检测请求时使用的源地址
bind_port <PORT> #向当前RS发出健康状态检测请求时使用的源端口
}

TCP监测:
传输层检测:TCP_CHECK
TCP_CHECK {
connect_ip <IP ADDRESS> #向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #发出健康状态检测请求时使用的源地址
bind_port <PORT> #发出健康状态检测请求时使用的源端口
connect_timeout <INTEGER> #客户端请求的超时时长, 等于haproxy的timeout server
}

实现单主的 LVS-DR 模式

#准备web服务器DR模式
[root@ubuntu2004 ~]#cat lvs_dr_rs.sh 
#!/bin/bash
#
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-10-27
#FileName:          lvs_dr_rs.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************
vip=10.0.0.10
mask='255.255.255.255'
dev=lo:1

case $1 in
start)
     echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
     echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
     echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
     echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
     ifconfig $dev $vip netmask $mask #broadcast $vip up
     #route add -host $vip dev $dev
     echo "The RS Server is Ready!"
     ;;
stop)
    ifconfig $dev down
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
    echo "The RS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac

[root@ubuntu2004 ~]#bash lvs_dr_rs.sh start
The RS Server is Ready!
[root@ubuntu2004 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
    inet 10.0.0.10/32 scope global lo:1
       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 fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:91:aa:7d brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.203/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe91:aa7d/64 scope link 
       valid_lft forever preferred_lft forever
#keepalived01
[root@keepalived01 conf.d]#cat www.shuhong.com.conf 
vrrp_instance VI_1 {
    state MASTER
    interface eth1
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.201
    unicast_peer{ 
        192.168.10.202
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}
virtual_server 10.0.0.10 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.203 80 {
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }
    real_server 10.0.0.204 80 {
        weight 1
        TCP_CHECK { 
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
}

#keepalived02
[root@keepalived02 conf.d]#cat www.shuhong.com.conf 
vrrp_instance VI_1 {
    state BACKUP 
    interface eth1
    virtual_router_id 66
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.202 
    unicast_peer{
        192.168.10.201
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"

}
virtual_server 10.0.0.10 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.203 80 {
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }
    real_server 10.0.0.204 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
}


#测试keepalived故障
[root@keepalived01 conf.d]#hostname -I
10.0.0.201 10.0.0.10 192.168.10.201 
[root@keepalived01 conf.d]#systemctl stop keepalived.service 
[root@keepalived01 conf.d]#hostname -I
10.0.0.201 192.168.10.201

#不间断的访问
[root@ubuntu2004 ~]#while :;do curl www.shuhong.com;sleep 1 ;done
web02 10.0.0.204
web01 10.0.0.203
web02 10.0.0.204
web01 10.0.0.203
....
web01 10.0.0.203
web02 10.0.0.204
web01 10.0.0.203
web02 10.0.0.204
web01 10.0.0.203
web02 10.0.0.204
web01 10.0.0.203
web02 10.0.0.204
web01 10.0.0.203

#测试后端web服务宕机一台
[root@ubuntu2004 ~]#systemctl stop nginx
web02 10.0.0.204
web01 10.0.0.203
web02 10.0.0.204
curl: (7) Failed to connect to www.shuhong.com port 80: 拒绝连接
web02 10.0.0.204
web02 10.0.0.204
web02 10.0.0.204

实现双主的 LVS-DR 模式

#增加两台wed服务器按照前面的脚本运行开启内核参数添加ip,注意修改脚本内的vip地址
#基于上面的配置增加一个新的子配置文件,
#keepalived01
[root@keepalived01 conf.d]#cat www.shuhong.io.conf 
vrrp_instance VI_2 {
    state BACKUP
    interface eth1
    virtual_router_id 88
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 654321
    }
    virtual_ipaddress {
        10.0.0.100 dev eth0 label eth0:1
    }
    unicast_src_ip 192.168.10.201
    unicast_peer{ 
        192.168.10.202
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}
virtual_server 10.0.0.100 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.205 80 {
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }
    real_server 10.0.0.206 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
}

#keepalived02
[root@keepalived02 conf.d]#cat www.shuhong.io.conf 
vrrp_instance VI_2 {
    state MASTER 
    interface eth1
    virtual_router_id 88
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 654321
    }
    virtual_ipaddress {
        10.0.0.100 dev eth0 label eth0:1
    }
    unicast_src_ip 192.168.10.202 
    unicast_peer{
        192.168.10.201
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"

}
virtual_server 10.0.0.100 80 {
    delay_loop 3
    lb_algo rr
    lb_kind DR
    protocol TCP
    sorry_server 127.0.0.1 80
    real_server 10.0.0.205 80 {
        weight 1
        HTTP_GET {
            url {
                path /
                status_code 200
            }
            connect_timeout 1
            nb_get_retry 3
            delay_before_retry 1
        }
    }
    real_server 10.0.0.206 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 5
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }
}

#测试
[root@keepalived01 conf.d]#systemctl stop keepalived.service 
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 10.0.0.100 10.0.0.10 192.168.10.202 
[root@ubuntu2004 ~]#systemctl stop nginx.service 
[root@ubuntu2004 ~]#systemctl stop apache2.service 
[root@ubuntu2004 ~]#while :;do curl www.shuhong.io;sleep 1;curl www.shuhong.com;sleep 1 ;done
apache01 10.0.0.205
nginx02 10.0.0.204
apache02 10.0.0.206
nginx01 10.0.0.203
apache01 10.0.0.205
nginx02 10.0.0.204
...
nginx02 10.0.0.204
apache02 10.0.0.206
nginx02 10.0.0.204
apache01 10.0.0.205
nginx02 10.0.0.204
curl: (7) Failed to connect to www.shuhong.io port 80: 拒绝连接
nginx02 10.0.0.204
apache01 10.0.0.205
nginx02 10.0.0.204
apache01 10.0.0.205
nginx02 10.0.0.204
apache01 10.0.0.205
...

实现单主的 LVS-DR 模式,利用FWM绑定成多个服务为一个集群服务

#两个keepalived节点都执行以下操作
[root@keepalived02 conf.d]#iptables -t mangle -A PREROUTING -d 10.0.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6
[root@keepalived01 conf.d]#iptables -t mangle -A PREROUTING -d 10.0.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6

#配置文件中
virtual_server fwmark 6  #指定FWM为6对应上面的mark

基于 VRRP Script 实现其它应用的高可用性

keepalived利用 VRRP Script 技术,可以调用外部的辅助脚本进行资源监控,并根据监控的结果实现优先动态调整,从而实现其它应用的高可用性功能

参考配置文件:/usr/share/doc/keepalived/keepalived.conf.vrrp.localcheck

VRRP Script 配置

定义脚本
vrrp_script:自定义资源监控脚本,vrrp实例根据脚本返回值,公共定义,可被多个实例调用,定义在vrrp实例之外的独立配置块,一般放在global_defs设置块之后,是和global_defs平级的语句块通常此脚本用于监控指定应用的状态。一旦发现应用的状态异常,则触发对MASTER节点的权重减至低于SLAVE节点,从而实现 VIP 切换到 SLAVE 节点
当 keepalived_script 用户存在时,会以此用户身份运行脚本,否则默认以root运行脚本
注意: 此定义脚本的语句块一定要放在下面调用此语句vrrp_instance语句块的前面

vrrp_script <SCRIPT_NAME> {
script <STRING>|<QUOTED-STRING> #此脚本返回值为非0时,会触发下面OPTIONS执行
OPTIONS
}

调用脚本
track_script:调用vrrp_script定义的脚本去监控资源,定义在VRRP实例之内,调用事先定义的
vrrp_script

track_script {
SCRIPT_NAME_1
SCRIPT_NAME_2
}

定义 VRRP script

vrrp_script <SCRIPT_NAME> { #定义一个检测脚本,在global_defs 之外配置
script <STRING>|<QUOTED-STRING> #shell命令或脚本路径
interval <INTEGER> #间隔时间,单位为秒,默认1秒
timeout <INTEGER> #超时时间
weight <INTEGER:-254..254> #默认为0,如果设置此值为负数,当上面脚本返回值为非0时,会将此值与本节点权重相加可以降低本节点权重,即表示fall. 如果是正数,当脚本返回值为0,会将此值与本节点权重相加可以提高本节点权重,即表示 rise.通常使用负值
fall <INTEGER> #执行脚本连续几次都失败,则转换为失败,建议设为2以上
rise <INTEGER> #执行脚本连续几次都成功,把服务器从失败标记为成功
user USERNAME [GROUPNAME] #执行监测脚本的用户或组
init_fail #设置默认标记为失败状态,监测成功之后再转换为成功状态
}

调用 VRRP script

vrrp_instance VI_1 {
...
track_script {
<SCRIPT_NAME>
}
}

利用脚本实现主从角色切换

#keepalived01
[root@keepalived01 keepalived]#vim conf.d/www.shuhong.com.conf 
vrrp_script check_down {
    script "[ ! -f /etc/keepalived/down ]"
    interval 1
    weight -30
    fall 3
    rise 2
    timeout 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth1
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.201
    unicast_peer{
        192.168.10.202
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
    track_script {
        check_down #调用前面定义的脚本
    }
}

#keepalived02 同上

#测试
[root@keepalived01 keepalived]#hostname -I
10.0.0.201 10.0.0.10 192.168.10.201 
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 10.0.0.100 192.168.10.202 

[root@keepalived01 keepalived]#touch down 
[root@keepalived01 keepalived]#hostname -I
10.0.0.201 192.168.10.201
[root@keepalived02 conf.d]#hostname -I
10.0.0.202 10.0.0.100 10.0.0.10 192.168.10.202

实现双主模式的 Nginx 反向代理的高可用

#keepalived01
[root@keepalived01 keepalived]#cat conf.d/www.shuhong.com.conf 
vrrp_script check_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 1
    weight -30
    fall 3
    rise 5
    timeout 2
}
vrrp_instance VI_1 {
    state MASTER
    interface eth1
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        10.0.0.10 dev eth0 label eth0:0
    }
    unicast_src_ip 192.168.10.201
    unicast_peer{ 
        192.168.10.202
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
    track_script {
        check_nginx
    }
}
[root@keepalived01 keepalived]#cat check_nginx.sh 
#!/bin/bash
#
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-10-27
#FileName:          ../check_nginx.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************
/usr/bin/killall -0 nginx


[root@keepalived01 keepalived]#cat /etc/nginx/conf.d/www.shuhong.com.conf 
upstream www.shuhong.com{
    server 10.0.0.203;
    server 10.0.0.204; 
}

server{
    listen 80;
    server_name www.shuhong.com;
    location /{
        proxy_pass http://www.shuhong.com/;
    }
}

[root@keepalived01 keepalived]#cat /etc/nginx/conf.d/www.shuhong.io.conf 
upstream www.shuhong.io{
    server 10.0.0.205;
    server 10.0.0.206;
}

server{
    listen 80;
    server_name www.shuhong.io;
    location /{
        proxy_pass http://www.shuhong.io/;
    }
}

#keepalived02配置同上注意修改主备对应信息
[root@keepalived01 keepalived]#systemctl restart keepalived.service nginx.service 


#测试
[root@keepalived01 keepalived]#systemctl stop nginx.service 
[root@keepalived01 keepalived]#hostname -I
10.0.0.201 192.168.10.201
[root@ubuntu2004 ~]#while true ;do curl www.shuhong.com;sleep 1; curl www.shuhong.io ;sleep 1 ;done
nginx01 10.0.0.203
apache01 10.0.0.205
nginx02 10.0.0.204
apache02 10.0.0.206
nginx01 10.0.0.203
apache01 10.0.0.205
....
ginx02 10.0.0.204
apache02 10.0.0.206
nginx01 10.0.0.203
apache01 10.0.0.205
nginx02 10.0.0.204
apache02 10.0.0.20