ansible-devops/scripts/redis.sh

296 lines
10 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Redis哨兵集群部署与卸载脚本
# 颜色配置
GREEN="\033[32m"
YELLOW="\033[33m"
BLUE="\033[34m"
RED="\033[31m"
RESET="\033[0m"
# 提示函数
info() { echo -e "[ ${BLUE}INFO ${RESET}] $1"; }
success() { echo -e "[ ${GREEN}SUCCESS ${RESET}] $1"; }
warning() { echo -e "[ ${YELLOW}WARNING ${RESET}] $1"; }
error() { echo -e "[ ${RED}ERROR ${RESET}] $1"; exit 1; }
# 基础配置
REDIS_PORT=6379
SENTINEL_PORT=26379
SENTINEL_NAME="mymaster"
LOG_DIR="/var/log/redis"
CONFIG_DIR="/etc/redis"
SSH_OPTS="-T -o StrictHostKeyChecking=no -o LogLevel=ERROR"
# 全局变量
ACTION=""
NODES=()
NODE_COUNT=0
MASTER=""
SLAVES=()
QUORUM=1
PASSWORD=""
# 参数解析(支持--install/--uninstall、--ip、--passwd参数
parse_args() {
# 初始化参数变量
local ip_provided=0
local passwd_provided=0
# 遍历解析参数
while [[ $# -gt 0 ]]; do
case "$1" in
--install|--uninstall)
ACTION="$1"
shift
;;
--ip=*)
IP_LIST="${1#*=}"
ip_provided=1
shift
;;
--passwd=*)
PASSWORD="${1#*=}"
passwd_provided=1
shift
;;
*)
error "无效参数: $1 (使用帮助:--install/--uninstall --ip=IP1,IP2,IP3... --passwd=redis密码"
;;
esac
done
# 验证必要参数
if [[ -z "$ACTION" ]]; then
error "必须指定参数:--install/--uninstall --ip=IP1,IP2,IP3... --passwd=redis密码"
fi
if [[ $ip_provided -eq 0 ]]; then
error "必须指定参数:--install/--uninstall --ip=IP1,IP2,IP3... --passwd=redis密码"
fi
if [[ $passwd_provided -eq 0 ]]; then
error "必须指定参数:--install/--uninstall --ip=IP1,IP2,IP3... --passwd=redis密码"
fi
# 解析节点列表
IFS=',' read -ra NODES <<< "$IP_LIST"
NODE_COUNT=${#NODES[@]}
if [[ $NODE_COUNT -lt 1 ]]; then
error "IP列表不能为空至少需要1个节点"
fi
# 配置主从节点和投票阈值
MASTER="${NODES[0]}"
SLAVES=("${NODES[@]:1}")
QUORUM=$((NODE_COUNT / 2 + 1)) # 自动计算投票阈值
}
# 安装流程核心函数
install() {
echo -e "=========================================="
echo -e "=== ${GREEN}Redis哨兵集群安装部署${RESET} ==="
echo -e "=========================================="
info "部署节点总数:$NODE_COUNT 个(${NODES[*]}"
info "主节点:$MASTER | 从节点:${SLAVES[*]}(共${#SLAVES[@]}个)"
info "哨兵投票阈值QUORUM$QUORUM(自动计算:$NODE_COUNT/2 +1"
info "Redis密码******(已通过命令行传入)"
info "预估总耗时9-14 分钟(视节点数和网络)"
echo -e "==========================================\n"
# 步骤1初始化环境
info "步骤1/5初始化所有节点环境 [${YELLOW}预估5-9 分钟${RESET}]"
info "正在安装依赖、配置日志目录和防火墙..."
for node in "${NODES[@]}"; do
ssh $SSH_OPTS $node "
apt-get update -y >/dev/null 2>&1;
apt-get install -y redis-server redis-sentinel net-tools >/dev/null 2>&1;
mkdir -p $CONFIG_DIR $LOG_DIR;
chown -R redis:redis $CONFIG_DIR $LOG_DIR;
ufw disable >/dev/null 2>&1;
iptables -F INPUT >/dev/null 2>&1;
" >/dev/null 2>&1 || error "节点 $node 环境初始化失败"
done
success "步骤1完成所有节点环境初始化完毕\n"
# 步骤2配置主节点
info "步骤2/5配置主节点 $MASTER [${YELLOW}预估30秒${RESET}]"
ssh $SSH_OPTS $MASTER "
cat > $CONFIG_DIR/redis.conf <<EOF
bind 0.0.0.0
protected-mode no
port $REDIS_PORT
requirepass $PASSWORD
masterauth $PASSWORD
daemonize no
logfile "$LOG_DIR/redis.log"
dir /tmp
replica-serve-stale-data yes
replica-read-only yes
EOF
chown redis:redis $CONFIG_DIR/redis.conf;
cat > /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis Master Node
After=network.target
[Service]
User=redis
ExecStart=/usr/bin/redis-server $CONFIG_DIR/redis.conf
ExecStop=/usr/bin/redis-cli -p $REDIS_PORT -a $PASSWORD shutdown
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload;
systemctl restart redis;
systemctl enable redis;
" >/dev/null 2>&1 || error "主节点 $MASTER 配置失败"
success "步骤2完成主节点配置完毕\n"
# 步骤3配置从节点
info "步骤3/5配置从节点 [${YELLOW}预估:${#SLAVES[@]}*30秒${RESET}]"
info "从节点列表:${SLAVES[*]}"
for slave in "${SLAVES[@]}"; do
info "正在配置从节点:$slave"
ssh $SSH_OPTS $slave "
cat > $CONFIG_DIR/redis.conf <<EOF
bind 0.0.0.0
protected-mode no
port $REDIS_PORT
requirepass $PASSWORD
masterauth $PASSWORD
daemonize no
logfile "$LOG_DIR/redis.log"
dir /tmp
replica-serve-stale-data yes
replica-read-only yes
replicaof $MASTER $REDIS_PORT
EOF
chown redis:redis $CONFIG_DIR/redis.conf;
cat > /etc/systemd/system/redis.service <<EOF
[Unit]
Description=Redis Slave Node
After=network.target
[Service]
User=redis
ExecStart=/usr/bin/redis-server $CONFIG_DIR/redis.conf
ExecStop=/usr/bin/redis-cli -p $REDIS_PORT -a $PASSWORD shutdown
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload;
systemctl restart redis;
systemctl enable redis;
" >/dev/null 2>&1 || error "从节点 $slave 配置失败"
done
success "步骤3完成所有从节点配置完毕\n"
# 步骤4配置哨兵集群
info "步骤4/5配置哨兵集群 [${YELLOW}预估:$NODE_COUNT*30秒${RESET}]"
info "哨兵投票阈值:$QUORUM(需$QUORUM个哨兵确认主节点下线才触发转移"
for node in "${NODES[@]}"; do
info "正在配置哨兵节点:$node"
ssh $SSH_OPTS $node "
cat > $CONFIG_DIR/sentinel.conf <<EOF
port $SENTINEL_PORT
daemonize no
logfile "$LOG_DIR/sentinel.log"
sentinel monitor $SENTINEL_NAME $MASTER $REDIS_PORT $QUORUM
sentinel down-after-milliseconds $SENTINEL_NAME 5000
sentinel auth-pass $SENTINEL_NAME $PASSWORD
sentinel config-epoch $SENTINEL_NAME 0
EOF
chown redis:redis $CONFIG_DIR/sentinel.conf;
cat > /etc/systemd/system/redis-sentinel.service <<EOF
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
User=redis
ExecStart=/usr/bin/redis-sentinel $CONFIG_DIR/sentinel.conf
ExecStop=/usr/bin/redis-cli -p $SENTINEL_PORT shutdown
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload;
systemctl restart redis-sentinel;
systemctl enable redis-sentinel;
" >/dev/null 2>&1 || error "哨兵节点 $node 配置失败"
done
success "步骤4完成哨兵集群配置完毕\n"
# 步骤5验证集群
info "步骤5/5验证集群状态 [${YELLOW}预估1分钟${RESET}]"
info "验证主节点 $MASTER..."
master_info=$(ssh $SSH_OPTS $MASTER "redis-cli -p $REDIS_PORT -a $PASSWORD info replication | grep -E 'role:|connected_slaves'" 2>/dev/null)
echo " $master_info"
for slave in "${SLAVES[@]}"; do
info "验证从节点 $slave..."
slave_info=$(ssh $SSH_OPTS $slave "redis-cli -p $REDIS_PORT -a $PASSWORD info replication | grep -E 'role:|master_host|master_link_status'" 2>/dev/null)
echo " $slave_info"
done
info "验证哨兵集群..."
sentinel_info=$(ssh $SSH_OPTS $MASTER "redis-cli -p $SENTINEL_PORT info sentinel | grep 'master0:'" 2>/dev/null)
echo " $sentinel_info"
success "步骤5完成集群验证完毕\n"
# 部署总结
echo -e "=========================================="
echo -e "=== ${GREEN}部署成功!${RESET} ==="
echo -e "☆ 集群架构:$NODE_COUNT节点1主${#SLAVES[@]}$NODE_COUNT哨兵"
echo -e "☆ 核心配置Redis端口$REDIS_PORT | 哨兵端口$SENTINEL_PORT | 投票阈值$QUORUM"
echo -e "☆ 功能状态:主从同步正常 | 哨兵监控正常 | 故障转移就绪"
echo -e "=========================================="
}
# 卸载流程核心函数
uninstall() {
echo -e "=========================================="
echo -e "=== ${RED}Redis哨兵集群彻底卸载${RESET} ==="
echo -e "=========================================="
info "卸载节点列表:${NODES[*]}(共$NODE_COUNT个节点"
info "Redis密码******(已通过命令行传入)"
info "预估耗时3-6 分钟(清理所有资源)"
echo -e "==========================================\n"
# 逐节点卸载
for i in "${!NODES[@]}"; do
node="${NODES[$i]}"
idx=$((i + 1))
info "正在卸载节点($idx/$NODE_COUNT$node"
ssh $SSH_OPTS $node "
# 停止服务(使用传入的密码)
systemctl stop redis-sentinel >/dev/null 2>&1;
redis-cli -p $REDIS_PORT -a '$PASSWORD' shutdown >/dev/null 2>&1;
# 禁用服务
systemctl disable redis redis-sentinel >/dev/null 2>&1;
# 清理文件
rm -rf $CONFIG_DIR $LOG_DIR /etc/systemd/system/redis* >/dev/null 2>&1;
# 卸载依赖
apt-get remove -y redis-server redis-sentinel >/dev/null 2>&1;
apt-get autoremove -y >/dev/null 2>&1;
" >/dev/null 2>&1 || error "节点 $node 卸载失败"
success "节点 $node 卸载完成"
done
# 卸载总结
echo -e "\n=========================================="
echo -e "=== ${GREEN}卸载成功!${RESET} ==="
echo -e "✓ 已彻底清理所有Redis相关资源"
echo -e " - 服务redis-server、redis-sentinel停止+禁用)"
echo -e " - 文件配置目录、日志目录、systemd服务文件"
echo -e " - 依赖redis相关安装包及依赖组件"
echo -e "=========================================="
}
# 执行入口
parse_args "$@"
if [ "$ACTION" = "--install" ]; then
install
elif [ "$ACTION" = "--uninstall" ]; then
uninstall
fi