新增功能:
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 $@