根据主机IP列表自动部署指定规模的redis cluster

新增功能:

1、特殊环境下部署,添加针对少于3台(0台,1台,2台)机器的时候的提示,规划和部署。

2、添加集群初始端口和集群规模的默认值。

#!/bin/bash
 
 
#集群初始端口,递增1
port=${2:-'6379'}
 
#集群的master个数
cluster_size=${3:-'3'}

iplist=$1
 
total_parameters=$#
function check_parameters()
{
    if [[ $total_parameters -lt 1 ]];then
        echo "参数个数不匹配,请检查"
        echo "------------usage-----------------"
        echo "iplist=$1		#机器IP文件,必选参数"
        echo "port=$2			#redis集群初始端口,递增1,如未提供,默认初始端口为6379"
        echo "cluster_size=$3		#redis集群的master个数,如未提供,默认值是3"
        exit
    fi
} 
 
function make_cluster_map()
{
[ -f master_slave_map ] && >master_slave_map


#当tag大于集群cluster_size时用于退出循环
tag=0
tag2=0

#控制读取的机器IP文件的第几行
i=1

#获取机器IP文件的最后一行内容,如果循环未结束,区分在等于master或slave时候,重置i的值
last_row=$(cat iplist | sed -n "$"p)

rows=$(cat iplist | wc -l)
 
while true
do
    let tag=tag+1
    if [[ $tag -le $cluster_size ]];then
		if [[ $rows -eq 0 ]];then
			echo "至少需要一台机器,请检查iplist文件"
			exit
		elif [[ $rows -eq 1 ]];then
			master_instance=$last_row
			echo -n "$master_instance:$port#" >> master_slave_map
			slave_instance=$last_row
			let port=port+1
			echo "$slave_instance:$port" >> master_slave_map
			let port=port+1
		elif [[ $rows -eq 2 ]];then
			line1=$(cat iplist | sed -n "1"p)
			line2=$(cat iplist | sed -n "2"p)
			if [[ $tag2 -eq 0 ]];then
				master_instance=$line1
				slave_instance=$line2
				echo "$master_instance:$port#$slave_instance:$port" >> master_slave_map
				let port=port+1
				let tag2=1
				continue
			fi
			if [[ $tag2 -eq 1 ]];then
				master_instance=$line2
				slave_instance=$line1
				echo "$master_instance:$port#$slave_instance:$port" >> master_slave_map
				let port=port+1
				let tag2=0
				continue
			fi
		
		elif [[ $rows -gt 2 ]];then
			master_instance=$(cat iplist | sed -n "$i"p)
			#如果master对应的是机器IP文件的最后1行
			if [[ "$master_instance" == "$last_row" ]];then
				master_instance=$last_row
				#slave对应的就应该是机器IP文件的第1行
				slave_instance=$(cat iplist | sed -n "1"p)
				echo "$master_instance:$port#$slave_instance:$port" >> master_slave_map
				#如果循环没有退出,那么下一次的master应该是对应机器IP文件的第2行,即置i=2
				let i=2	
			else	
				let i=i+1
				slave_instance=$(cat iplist | sed -n "$i"p)
				#如果slave对应的机器IP文件的最后1行
				if [[ "$slave_instance" == "$last_row" ]];then
					echo "$master_instance:$port#$slave_instance:$port" >> master_slave_map
					#如果循环没有退出,那么下一次的master应该是对应机器IP文件的第1行,即置i=1
					let i=1
				else
					echo "$master_instance:$port#$slave_instance:$port" >> master_slave_map
					let i=i+1
				fi
			fi
			#循环未结束,下一批次的端口加1
			#let port=port+1
		fi
	else
		#生成指定规模的集群实例后退出循环
		break
	fi
done
 

}
 
 
 
function check_exists_port()
{
[ -f check_exists_port ] && >check_exists_port
 
cat master_slave_map | tr '#' '
' > all_redis_instance
for line in $(cat all_redis_instance)
do
    {
    check_ip=$(echo $line | awk -F':' '{print $1}')
    check_port=$(echo $line | awk -F':' '{print $2}')
    nums=$(ssh $check_ip "ss -utp state listening sport == :${check_port} |wc -l")
    if [[ $nums -ge 2 ]];then
        echo "$check_ip机器上已存在端口$check_port" >> check_exists_port
    fi
    }&
done
 
wait
 
if [[ -s check_exists_port ]];then
    echo "存在端口冲突,退出部署,详情请查看check_exists_port文件内容。"
    exit
fi
}
 
 
 
function create_user_copy_redis_soft()
{
[ -f "copy_hosts" ] && >copy_hosts
 
for i in `cat iplist`
do
    echo $i | tr '.' '_' | awk '{print "["$1"]"}' >> copy_hosts
    echo $i  >> copy_hosts
    echo >> copy_hosts
done
 
 
for ip in `cat iplist`
do
    ansible -i copy_hosts $ip -m user -a "name=redis home=/home/redis shell=/sbin/nologin" --become  --become-method=sudo --become-user=root
    ansible -i copy_hosts $ip -m copy -a "src=/usr/local/redis-5.0.3.tar dest=/usr/local/ owner=redis group=redis mode=0755"
    ansible -i copy_hosts $ip -m shell -a "cd /usr/local/; tar xf redis-5.0.3.tar"
    ansible -i copy_hosts $ip -m shell -a "chown -R redis:redis /usr/local/redis-5.0.3"
done
}
 
 
function make_ansible_inventory()
{
cat master_slave_map |tr '#' '
' | awk '{print "ip_"$1}'| sort -t ':' -nk1 | tr ':' '_' | tr '.' '_' > all_instance
 
[ -f "ip.list" ] && >ip.list
 
for i in `cat all_instance`
do
    echo "[$i]" >> ip.list
    myip=$(grep $i all_instance | awk -F'_' '{print $2"."$3"."$4"."$5}')
    myport=$(grep $i all_instance | awk -F['_'] '{print $NF}')
    echo "$myip redis_port=$myport" >> ip.list
    echo >> ip.list
done
}
 
 
 
function make_dirs_copy_cnf_change_cnf()
{
for i in `cat all_instance`
do
    myip=$(grep $i all_instance | awk -F'_' '{print $2"."$3"."$4"."$5}')
    myport=$(grep $i all_instance | awk -F['_'] '{print $NF}')
    ansible -i ip.list ${myip} -m shell -a "mkdir -pv /etc/redis/;mkdir -pv /dbdata/redis/redis5.0.3/$myport/{data,conf,log};chown -R redis:redis /dbdata/redis/redis5.0.3/$myport"
    ansible -i ip.list ${myip} -m copy -a "src=/usr/local/redis.conf dest=/etc/redis owner=redis group=redis mode=0755"
    ansible -i ip.list ${myip} -m shell -a "cd /etc/redis;mv redis.conf redis_$myport.conf;sed -i 's/27008/'$myport'/g' redis_$myport.conf"
done
}
 
 
 
function start_all_redis_instance()
{
for i in `cat all_instance`
do
    myip=$(grep $i all_instance | awk -F'_' '{print $2"."$3"."$4"."$5}')
    myport=$(grep $i all_instance | awk -F['_'] '{print $NF}')
    ansible -i ip.list ${myip} -m shell -a "/usr/local/redis-5.0.3/src/redis-server /etc/redis/redis_$myport.conf"
done
}
 
 
function make_redis_cluster_only_master()
{
cat master_slave_map  | awk -F'#' '{print $1}' | tr '
' ' '  > create_cluster_strings
command="/usr/local/redis-5.0.3/src/redis-cli --cluster create `cat create_cluster_strings`"
 
/usr/bin/expect <<-EOF
spawn $command
expect "yes"
send "yes
"
expect eof
EOF
 
sleep 30
#这里执行完毕后需要等待一会,否则可能会出现Nodes don't agree about configuration!的提示
}
 
 
function add_slave_of_matched_master()
{
for i in `cat master_slave_map`
do
    master_ip=$(echo $i | awk -F['#'] '{print $1}'| awk -F[':'] '{print $1}')
    master_port=$(echo $i | awk -F['#'] '{print $1}'| awk -F[':'] '{print $2}')
    slave_ip=$(echo $i | awk -F['#'] '{print $2}'| awk -F[':'] '{print $1}')
    slave_port=$(echo $i | awk -F['#'] '{print $2}'| awk -F[':'] '{print $2}')
    existing_ip_port=$master_ip:$master_port
    master_id=$(/usr/local/redis-5.0.3/src/redis-cli -h $master_ip -p $master_port cluster nodes | awk '/'$master_ip':'$master_port'/{print $1}')
    /usr/local/redis-5.0.3/src/redis-cli --cluster add-node $slave_ip:$slave_port $existing_ip_port --cluster-slave --cluster-master-id $master_id  
done
}
 
#if [[ $? -eq 0 ]];then
#   rm -rf all_instance
#   rm -rf copy_hosts
#   rm -rf create_cluster_strings
#   rm -rf hosts
#   rm -rf ip.list 
#fi
 
function main()
{
# 0、 检查传参
check_parameters

# 1、根据主机列表生成待部署的集群实例对应关系
make_cluster_map
 
# 2、在目标机器上检查对应的端口是否被占用
check_exists_port
 
# 3、在目标主机上创建redis用户组和用户,拷贝redis二进制包
create_user_copy_redis_soft
 
# 4、根据master_slave_map文件生成ansible的inventory文件
make_ansible_inventory
 
# 5、调用ansible创建redis相关实例的目录,配置文件并修改配置文件
make_dirs_copy_cnf_change_cnf
 
# 6、调用ansible批量启动所有redis实例
start_all_redis_instance
 
# 7、创建redis cluster集群,只添加master角色
make_redis_cluster_only_master
 
# 8、根据master_slave_map文件的对应关系,分别master添加对应的slave实例
add_slave_of_matched_master
}
 
main $@

  

原文地址:https://www.cnblogs.com/imdba/p/14071010.html