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