由于Jumpserver 本身不支持Reids高可用部署,采用Redis 哨兵模式实现Redis自身主备节点数据同步以及故障切换,但Jumpserver无法感知Redis主节点的IP切换,因此本文采用Redis 哨兵模式+Keepalived浮动IP的方式实现Redis的高可用,通过Keepalived监控Redis主节点的故障IP切换,实现浮动IP始终跟随Redis集群主节点,Jumpserver只用连接浮动IP即可始终连接Redis集群主节点。

1、配置防火墙

6379: Redis监听端口
26379:Redis-Sentinel监听端口

firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="10.255.200.1/30" port protocol="tcp" port="6379" accept"
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="10.255.200.1/30" port protocol="tcp" port="26379" accept"

firewall-cmd --reload

2、安装 redis

yum install -y redis

# 创建数据保存目录,将数据保存至SSD磁盘
mkdir /ssd/redis
mkdir /ssd/redis-sentinel
chown -R redis:redis /ssd/redis
chown -R redis:redis /ssd/redis-sentinel

3、修改redis配置文件

# 以下仅列出需要修改的配置项
vi /etc/redis.conf

# 修改数据保存位置
dir "/ssd/redis"

# 设置密码
requirepass xxxxxxxx

# 主服务器密码,与前面设置的密码一致
masterauth xxxxxxxx

# 指定主服务器,集群主服务器(第一个启动的节点)不需要配置,其它2个从节点需要配置
slaveof 10.255.200.1 6379

4、修改redis-sentinel配置文件

# 备份原始配置文件
cp /etc/redis-sentinel.conf /etc/redis-sentinel.conf.bak 

# 以下配置为全部配置项,只保留了必要配置,其它配置项可全部删除或根据需要修改
vi /etc/redis-sentinel.conf

# 监听IP及端口设置
bind 0.0.0.0
protected-mode no
port 26379

# 修改数据保存位置
dir "/ssd/redis-sentinel"

logfile "/var/log/redis/sentinel.log"

# 设置监控的主服务器信息及认证密码,密码需与前面Redis配置的密码一致
sentinel monitor redismaster 10.255.200.1 6379 2
sentinel auth-pass redismaster xxxxxxxx

# 将故障切换时间改为5秒,默认值为30秒
sentinel down-after-milliseconds redismaster 5000
sentinel failover-timeout redismaster 30000
supervised systemd

5、启动 redis 高可用集群

# 注意启动的顺序。首先是主节点的Redis服务进程,然后启动从机的Redis服务进程,最后启动3个哨兵的服务进程

systemctl start redis
systemctl status redis
systemctl enable redis

systemctl start redis-sentinel
systemctl status redis-sentinel
systemctl enable redis-sentinel

6、集群状态确认及数据同步状态确认

# 查看Redis集群相关状态,xxxxxxxx 为认证密码,应重点关注当前节点的role是否与实际情况一致(1主2从),master_host 是否是主节点IP,master_link_status 是否为 up 。
redis-cli -a xxxxxxxx info replication

# 查看Redis-Sentinel集群相关状态,xxxxxxxx 为认证密码,应重点关注主节点 ip 是否与实际情况一致,flags 标识是否为 master ,主节点正常时 flags不应为s_down / o_down ,num-slaves 从节点数是否为 2 ,num-other-sentinels 其它哨兵节点数是否为 2 ,quorum 认定主节点故障的“法定人数”是否为 2 。
redis-cli -p 26379 -a xxxxxxxx sentinel master redismaster

# 可以通过在主节点写入/删除数据,在从节点验证数据同步是否正常
redis-cli 

# 授权认证
auth xxxxxxxx

# 主节点写入数据
set test hello-world

# 3个节点读取数据,验证是否同步
get test

# 主节点删除数据
del test

# 3个节点再次读取数据,验证是否均己删除
get test

7、集群切换验证

# 停止主节点redis服务
systemctl stop redis

# 等待约5秒,在其它节点上验证集群状态
redis-cli -a xxxxxxxx info replication
redis-cli -p 26379 -a xxxxxxxx sentinel master redismaster

# 也可通过日志查看集群切换过程
tail -100 /var/log/redis/sentinel.log

8、配置 keepalived 实现浮动 IP 跟随 redis 主节点切换


# redis集群状态检查脚本,需注意脚本字符串比较时回车换行的处理
# 首先检查 redis 服务是否正常运行,再检查当前节点是否为主节点,再检查当前节点是否持有浮动IP
vi /etc/keepalived/check_redis.sh

#!/bin/bash
</dev/tcp/127.0.0.1/6379
if [ $? -eq 0 ]; then
    ROLE=`redis-cli -a xxxxxxxx info replication | grep role`
    MASTER=`echo -e "role:master\r\n"`
    if [ "$ROLE" == "$MASTER" ]; then
                exit 0
    fi

    MASTERIP=`ip add | grep 10.255.200.4 | wc -l`
    if [ $MASTERIP -eq 0 ]; then
                exit 0
        fi
fi
exit 1

# 编写 Redis 集群切换邮件通知脚本,修改通知标题及正文内容
cp /etc/keepalived/email_tengine.sh /etc/keepalived/email_redis.sh 
vi  /etc/keepalived/email_redis.sh 

#!/bin/bash
contact='xxxx@xxxx.com'
notify() {
    mailsubject="[Devops Redis VIP 切换] $(hostname) -> $1"
    mailbody="[$(date +'%F %T')]: Devops Redis VIP 切换, $(hostname) 切换为 $1 !"
    echo "$mailbody" | mail -s "$mailsubject" $contact
}
case $1 in
master)
    notify master
    ;;
backup)
    notify backup
    ;;
fault)
    notify fault
    ;;
*)
    echo "Usage: $(basename $0) {master|backup|fault}"
    exit 1
    ;;
esac

# 修改keepalived配置,添加一个新的VRRP实例,并添加相关的状态检查脚本
# 注意新的VRRP实例名称以及虚拟路由器ID应与之前的Tengine相关配置不同
# 注意 keepalived 3个节点须工作在非抢占模式下,角色均设置为BACKUP,优先级相同。
vi /etc/keepalived/keepalived.conf

vrrp_script chk_redis {
    script "/etc/keepalived/check_redis.sh"
    interval 1
}

vrrp_instance VI_REDIS {
    state BACKUP
    nopreempt
    interface bond-app
    virtual_router_id 52
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass xxxxxxxx
    }
    virtual_ipaddress {
        10.255.200.4/24
    }
    track_script {
        chk_redis
    }

    notify_master "/etc/keepalived/email_redis.sh master"
    notify_backup "/etc/keepalived/email_redis.sh backup"
    notify_fault "/etc/keepalived/email_redis.sh fault"
}

# 重新启动 keepalived 服务
systemctl restart keepalived
systemctl status keepalived

# 检查浮动IP是否在主节点上
redis-cli -a xxxxxxxx info replication | grep role
ip add

# 停用主节点redis服务,进行集群切换验证,验证浮动IP是否跟随主节点
# 具体操作参考前面“集群切换验证”内容

9、极端情况下Redis服务恢复

Redis 哨兵模式 配置为2个哨兵监控到主服务无响应时才进行集群切换,这样可以保证集群切换的可靠性,但是在极端情况下,可能会出现集群3个节点中有2个节点暂时无法提供服务的情况,此时集群中哨兵个数则不满足集群切换的“法定人数”,造成存后存活的Redis节点角色可能一直为从节点角色,此时需手动重启Redis服务,使其角色变成主节点,从恢复Redis服务。