MongoDB分片集群自动化部署

OS:CentOS Linux release 7.9.2009 (Core)

场景:

需要半自动化或者自动化部署MongoDB集群时,可用此脚本。提高交付效率。

脚本实现架构图:

脚本:

check_clear_host.sh #此脚本有2个功能及是检查 资源规格和清理资源上的MognoDB 实全,清理动作禁止在生产或者重要的环境执行。

powershell 复制代码
#!/bin/bash

without=$(python  cluster_mongodb_mutil.py 'argument') #获取IP地址和密码
ips=$(echo $without|cut -d'|' -f1|cut -d':' -f2)
sshpassword=$(echo $without|cut -d'|' -f2|cut -d':' -f2)
sshuser='root'

/usr/bin/which sshpass ;if [[ "$?" != "0" ]];then  yum -y install sshpass ;fi

operation=1 # 1检查机器资源配置 0删除mongodb集群(生产环境禁止使用)

function mongo_clear(){

   IFS='|' read -ra elements <<< "$1"

   for ip in "${elements[@]}"; do
     pid=$(sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "ps -ef|grep mongo|grep -vE 'grep'|awk -F' ' '{print \$2}'")
     if [ -n "$pid" ]; then
        sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "kill -9 $pid"
     fi
     echo $ip
     sshpass -p $2   ssh  $3@${ip} -o StrictHostKeyChecking=no "userdel mongodb"
     sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "rm -fr  /data/*"
     sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "cd /usr/local/ && unlink mongodb"
     sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "rm -fr /opt/mongodb-linux-x86_64-rhel70-4.4.18"
    done
}

function mongo_check(){
   IFS='|' read -ra elements <<< "$1"
   for ip in "${elements[@]}"; do
     {
       cpu=$(sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "cat /proc/cpuinfo | grep 'process'|wc -l")
       sshpass -p $2   ssh  $3@${ip} -o StrictHostKeyChecking=no "df -h|grep data"
       fre=$(sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "free -m|sed -n 2p|awk -F' ' '{print \$2}'")
       dik=$(sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "df -h|awk -F' ' '{print \$2}' |grep G|cut -d'G' -f1|awk '{if(NR == 1) {max = \$1} else {if(\$1 > max) {max = \$1}}} END {print max}'")
       dik_free=$(sshpass -p $2  ssh  $3@${ip} -o StrictHostKeyChecking=no "df -h|grep ${dik}|awk -F' ' '{print \$4}'")
       echo ${ip}': '${cpu}'c,'${fre}m,${dik}g,'磁盘可用'$dik_free
     } &
  done
  wait
}

ipss=`echo $ips|sed 's/ /|/g'`

if [ "$operation" == 0 ];then
   mongo_clear ${ipss} ${sshpassword} ${sshuser}
elif [ "$operation" == 1 ];then
   mongo_check $ipss $sshpassword $sshuser
fi

dbenvset_mult.sh

powershell 复制代码
#!/bin/bash

sshuser='root'
without=$(python  cluster_mongodb_mutil.py 'argument') #获取IP地址和密码
ips=$(echo $without|cut -d'|' -f1|cut -d':' -f2)
sshpassword=$(echo $without|cut -d'|' -f2|cut -d':' -f2)

for ip in $ips
do
    {
       ipp=$(ip a|grep  'inet 172'|awk -F' ' '{print $2}'|cut -d'/' -f1)
      if [ "$ipp" == "$ip" ];then
          sh dbenvset.sh /data 0 0
      elif [ "$ipp" != "$ip" ];then
         /usr/bin/sshpass -p ${sshpassword} scp dbenvset.sh  root@${ip}:${dataroot}
        sshpass -p $sshpassword  ssh  ${sshuser}@${ip} -o StrictHostKeyChecking=no "sh dbenvset.sh /data 0 0" # /data为你的数据挂载盘,请根据实际情况修改
     fi
    } &
done
wait

dbenvset.sh

powershell 复制代码
#!/bin/sh
addcmd(){
addText=$1
file=$2
#判断 file.sh 文件中是否存在该字符串
if ! grep -q "$addText" $file
then
#不存在,添加字符串
   echo "$addText" >> $file
else
#存在,不做处理
   echo "$addText"" exist in "$file
fi
}

if [ $# -ne 3 ];then
    echo "Error: please use $0 datadir ishdd ispm"
fi
datadir=$1  #数据目录,当前规范/data
ishdd=$2    #机械硬盘为1,ssd为0
ispm=$3     #物理机1,虚机0,容器2
#source /etc/profile

if [ $ispm -ne 2 ];then
   systemctl stop tuned
   systemctl disable tuned
fi
if [ $ispm -eq 1 ];then
   systemctl enable cpupower.service
   systemctl restart cpupower.service
fi
yum install -y libaio wget telnet net-tools strace gdb lsof sysstat bc numactl grubby ntp traceroute s3cmd zstd jq
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
if [ $ispm -ne 2 ];then
   if [ $ishdd -eq 1 ];then
      #机械盘
      #数据盘禁用atime
      awk '$2=="'$datadir'"{$4="defaults,noatime"}1' /etc/fstab > tmp && mv tmp /etc/fstab -f
      mount -o remount,noatime $datadir
      #内核设置存储介质的 I/O 调度器
      grubby --update-kernel=ALL --args="elevator=deadline"
   else
      #ssd
      #数据盘禁用atime,discard for ssd del data
      awk '$2=="'$datadir'"{$4="defaults,noatime,discard"}1' /etc/fstab > tmp && mv tmp /etc/fstab -f
      mount -o remount,noatime,discard $datadir
      grubby --update-kernel=ALL --args="elevator=noop"
   fi
fi
#设置当前不限制输出corefile,打开文件数,用户打开线程数
ulimit -c unlimited
ulimit -n 1048576
ulimit -u 1024000
#设置不限制输出corefile,打开文件数,用户打开线程数永久生效
addcmd '*  soft  core  unlimited' /etc/security/limits.conf
addcmd '*  hard  core  unlimited' /etc/security/limits.conf
addcmd '*  soft  nofile   1048576' /etc/security/limits.conf
addcmd '*  hard  nofile   1048576' /etc/security/limits.conf
addcmd '*  soft  nproc   1024000' /etc/security/limits.conf
addcmd '*  hard  nproc   1024000' /etc/security/limits.conf
addcmd '*  soft  stack   32768' /etc/security/limits.conf
addcmd '*  hard  stack   32768' /etc/security/limits.conf
#修改当前的内核配置立即关闭透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
#内核关闭透明大页
grubby --args="transparent_hugepage=never" --update-kernel `grubby --default-kernel`
#设置操作系统预读扇区readahead(主要为了优化mongodb),/为数据盘目录,预读64个扇区为32k(网上资料说mongodb针对32k预读有优化,暂未从官方文档查实),对应随机读多的应用较小预读可以提升性能。
blockdev --setra 64 `df | grep -w $datadir | awk '{print $1}'`

cat > /etc/systemd/system.conf << EOF
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See systemd-system.conf(5) for details.

[Manager]
#LogLevel=info
#LogTarget=journal-or-kmsg
#LogColor=yes
#LogLocation=no
DumpCore=yes
#CrashShell=no
#ShowStatus=yes
#CrashChVT=1
#CtrlAltDelBurstAction=reboot-force
#CPUAffinity=1 2
#JoinControllers=cpu,cpuacct net_cls,net_prio
#RuntimeWatchdogSec=0
#ShutdownWatchdogSec=10min
#CapabilityBoundingSet=
#SystemCallArchitectures=
#TimerSlackNSec=
#DefaultTimerAccuracySec=1min
#DefaultStandardOutput=journal
#DefaultStandardError=inherit
#DefaultTimeoutStartSec=90s
#DefaultTimeoutStopSec=90s
#DefaultRestartSec=100ms
#DefaultStartLimitInterval=10s
#DefaultStartLimitBurst=5
#DefaultEnvironment=
#DefaultCPUAccounting=no
#DefaultBlockIOAccounting=no
#DefaultMemoryAccounting=no
#DefaultTasksAccounting=no
#DefaultTasksMax=
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=
#DefaultLimitSTACK=
#DefaultLimitCORE=
#DefaultLimitRSS=
DefaultLimitNOFILE=1048576
#DefaultLimitAS=
DefaultLimitNPROC=1024000
#DefaultLimitMEMLOCK=
#DefaultLimitLOCKS=
#DefaultLimitSIGPENDING=
#DefaultLimitMSGQUEUE=
#DefaultLimitNICE=
#DefaultLimitRTPRIO=
#DefaultLimitRTTIME=
EOF
systemctl daemon-reexec
cat > /etc/sysctl.conf << EOF
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
#表示内核允许分配所有的物理内存,而不管当前的内存状态如何
vm.overcommit_memory = 1
fs.file-max = 6553560
#关闭系统swap
vm.swappiness = 0
#服务端所能accept即处理数据的最大客户端数量,即完成连接上限,默认值是128
net.core.somaxconn=32768
#服务端所能接受SYN同步包的最大客户端数量,即半连接上限,默认值是128
net.core.netdev_max_backlog=16384
#处于SYN_RECV的TCP最大连接数,SYN_RECV状态的TCP连接数超过该值后丢弃后续的SYN报文
net.ipv4.tcp_max_syn_backlog=16384
#表示关闭SYN Cookies。避免不使用SYN半连接队列的情况下成功建立连接
net.ipv4.tcp_syncookies = 0
#为TCP socket预留用于接收缓冲的内存缺省值(以字节为单位)
net.core.rmem_default=262144
#为TCP socket预留用于发送缓冲的内存缺省值(以字节为单位)
net.core.wmem_default=262144
#为TCP socket预留用于接收缓冲的内存最大值
net.core.rmem_max=16777216
#为TCP socket预留用于发送缓冲的内存最大值
net.core.wmem_max=16777216
#表示每个套接字所允许的最大缓冲区的大小
net.core.optmem_max=16777216
#表示用于向外连接的端口范围.缺省情况下过窄:32768到61000,改为1024到65535
net.ipv4.ip_local_port_range=1024 65535
#自动调优所使用的接收缓冲区的值,最少字节数/默认值/最大字节数
net.ipv4.tcp_rmem=1024 4096 16777216
#自动调优所使用的发送缓冲区的值
net.ipv4.tcp_wmem=1024 4096 16777216
#不设0可能大量丢包
#net.ipv4.tcp_tw_recycle = 0
EOF

sysctl -p
swapoff -a

cluster_mongodb_mutil.py

python 复制代码
#!/usr/bin/python
#! _*_ coding:utf-8 _*_

import os,re
import sys
import time
import random,string
import subprocess
passw='xxx'

account_verify = 1 # Cluster validation start ,0 关闭验证(Turn off validation) / 1开启验证(Enable verification)

#mongos IP, port:30000
iplist_so = '''
1x2.x1.2x8.160
 1x2.x1.2x8.5
1x2.x1.2x8.35
'''
#config IP,port:27017
iplist_co = '''
  1x2.x1.2x8.177
1x2.x1.2x8.139
 1x2.x1.2x8.95
'''
#shard IP shard are separated by '|',port 40001-4000n
iplisto = '''
1x2.x1.2x8.186
1x2.x1.2x8.127
1x2.x1.2x8.151
|
 1x2.x1.2x8.117
1x2.x1.2x8.181
1x2.x1.2x8.193
|
1x2.x1.2x8.197
1x2.x1.2x8.58
1x2.x1.2x8.178
'''


def ip_handle_shard(ip_list):#shard副本集的ip串处理函数
   slist = []
   slistz = []
   for s in ip_list.split('|'):
      slist.append(s.strip().replace("\n", " "))
      slistz.append(slist)
      slist = []
   return slistz
def ip_handle_sc(ip_list):#mongos/config的ip串处理函数
   slist = []
   for s in ip_list.split('\n'):
      slist.append(s.strip())
   clean_iplist = [item for item in slist if item]
   clean_iplist_clsp = ' '.join(clean_iplist)
   iplist_ss = []
   iplist_ss.append(clean_iplist_clsp)
   return iplist_ss

iplist_s = ip_handle_sc(iplist_so)
iplist_c = ip_handle_sc(iplist_co)
iplist = ip_handle_shard(iplisto)

def main(argv): #外部程序调入逻辑,获取密码和ip地址串
   if len(argv) < 2:
       return argv
   argument = argv[1]
   ts = ' '
   sip = ''
   for shad_ip in iplist:
      if shad_ip != iplist[-1]:
         sip = sip + shad_ip[0] + ts
      else:
         sip = sip + shad_ip[0]
   ipsc = iplist_s[0] + ' ' + iplist_c[0] + ' ' + sip
   print('ips:'+ipsc+'|sshpassword:'+passw)
   sys.exit(1)
if __name__ == "__main__":
    main(sys.argv)

os.system('/usr/bin/which sshpass;if [[ "$?" != "0" ]];then  yum -y install sshpass ;fi')
# update your ip search location
num = string.ascii_letters+string.digits
password =  "".join(random.sample(num,12))
if os.path.exists('create_user.js'):
   os.remove('create_user.js')
file = open('create_user.js', 'a')
file.write('db.createUser({user:"admin", pwd:"%s", roles:[{role:"userAdminAnyDatabase",db:"admin"}]});\n' %(password))
file.write('db.createUser({user: "root",pwd: "%s",roles:[{role: "root", db: "admin"}]});\n' %(password))
file.close()

#检实例安装结果函数
def function_psef(ip,passw):
   # 执行命令
   command = "sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no 'netstat -tnlp|grep mongo'"%(passw,ip)
   process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   # 等待命令执行完成
   stdout, stderr = process.communicate()
   # 检查命令是否执行成功
   if process.returncode == 0:
      return 'successful_install'
   else:
      return "failure_install"

#检副本集是否已经选举出 PRIMARY-函数
def function_primary(ip,passw,port):
   command = 'sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no "echo \'rs.status()\'|/usr/local/mongodb/bin/mongo %s:%s|grep PRIMARY"'%(passw,ip,ip,port)
   process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   stdout, stderr = process.communicate()
   if process.returncode == 0:
      return 'PRIMARY'
   else:
      return 'SECONDARY'

os.system('openssl rand -base64 753 > keyFile;chmod 400 keyFile')
shardname='rsshd'

shards = 0
# extype部署类型 1.mongod 2.config 3.mongos
extype = 1
port = 40000
add_user_ip = []
for ips in iplist:
   shards += 1
   shardnamez = shardname+str(shards)
   ip1=ips[0].split(' ')[0]
   add_user_ip.append(ip1)
   #1.1 副本集批量安装
   #传送副本集IP组给脚本安装副本集
   os.system("sh mongo_mutil.sh  \'%s\' %s %s %s" %(ips[0],extype,passw,shards))
   #判断副本集实例都安装成功
   while True:
      successfuls = []
      for ip in ips[0].split(' '):
         example_ps = function_psef(ip,passw)
         successfuls.append(example_ps)
      for n in range(60):
         time.sleep(n)
         if successfuls.count('successful_install') == len(ips[0].split()) and list(set(successfuls))[0] == 'successful_install':
            pd = 'successful_install'
            break
         else:
            pd = ''
            if n == 30:#判断sharding副本集节点部署没有全部成功,退出脚本
               print('安装副本集'+ips[0]+'失败!')
               exit()
            break
      if pd == 'successful_install':
         print('副本集 '+ips[0]+' 实例安装成功!')
         break

   #1.2. 副本集初始化命令拼接
   rsinit_head = 'rs.initiate({\\"_id\\": \\"%s\\",\\"members\\" :[' %(shardnamez)
   rsinit_tail = ']})'
   port = port + 1
   #  副本集IP拼接
   st = ','
   ipstr = ''
   for i in range(len(ips[0].split(' '))):
      print(i)
      ip=ips[0].split(' ')[i]
      print ip
      if ip != ips[0].split(' ')[-1]:
         ipst = '{\\"_id\\": %s,\\"host\\" : \\"%s:%s\\"}'%(i,ip,port)
         ipstr = ipstr + ipst + st
      elif ip == ips[0].split(' ')[-1]:
         ipst = '{\\"_id\\": %s,\\"host\\" : \\"%s:%s\\"}'%(i,ip,port)
         ipstr = ipstr + ipst
   rsinit_coun =  rsinit_head + ipstr + rsinit_tail
   time.sleep(3)
   # 1.3 副本集初始化操作
   print('副本集 '+ips[0]+' 初始化开始......')
   os.system('sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no "echo \'%s\'|/usr/local/mongodb/bin/mongo %s:%s"' %(passw,ip1,rsinit_coun,ip1,port))
   #判断shard的副本集是否产生主节点
   while True:
      primary_node = function_primary(ip1,passw,port)
      for n in range(60):
         time.sleep(n)
         if primary_node == 'PRIMARY':
            pd = 'PRIMARY'
            # 获取副本集主节点IP地址
            ip_str = os.popen('sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no "echo \'rs.status()\'|/usr/local/mongodb/bin/mongo localhost:%s|grep -E \'name|stateStr\'|sed \'N;s/\\n//\'|grep PRIMARY"'%(passw,ip1,port)).read().strip().split(':')[1].replace('"','')
            ipList = re.findall( r'[0-9]+(?:\.[0-9]+){3}',ip_str)[0]
            os.system('sshpass -p %s scp %s  root@%s:/root/' %(passw,'create_user.js',ipList))
            #副本集主节点创建管理账号
            os.system('sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no  "/usr/local/mongodb/bin/mongo %s:%s/admin < create_user.js"' %(passw,ipList,ipList,port))
            break
         else:
            pd = ''
            if n == 30:#判断副本集在30秒内没有选举出primary,退出脚本
               print('安装sharding副本集'+ips[0]+'在30秒内没有选举出primary,退出脚本.')
               exit()
            break
      if pd == 'PRIMARY':
         break

#// 2、 config节点部署
extype = 2
# 2.1 config节点复制集部署
os.system("sh mongo_mutil.sh  \'%s\' %s %s" %(iplist_c[0],extype,passw))

replSetName = "rscnf" #config复制集名
rsinit_head = 'rs.initiate({\\"_id\\": \\"%s\\",\\"members\\" :[' %(str(replSetName))
rsinit_tail = ']})'
ip1=iplist_c[0].split(' ')[0]

#检查config副本集实例安装结果
while True:
   successfuls = []
   for ip in iplist_c[0].split(' '):
      example_ps = function_psef(ip,passw)
      successfuls.append(example_ps)
   for n in range(60):
      time.sleep(n)
      if successfuls.count('successful_install') == len(iplist_c[0].split()) and list(set(successfuls))[0] == 'successful_install':
         print('config副本集'+iplist_c[0]+'实例部署成功!')
         pd = 'successful_install'
         break
      else:
         pd = ''
         if n == 30:#判断副本集节点部署没有全部成功,退出脚本
            print('安装config副本集'+iplist_c[0]+'失败!,退出脚本.')
            exit()
         break
   if pd == 'successful_install':
      print('副本集 '+iplist_c[0]+' 实例安装成功!')
      break

# config副本集IP拼接
st = ','
ipstr = ''
ipstc = ''
portc = '27017'
for i in range(len(iplist_c[0].split(' '))):
   print i
   ip=iplist_c[0].split(' ')[i]
   print ip
   if ip != iplist_c[0].split(' ')[-1]:
      ipst = '{\\"_id\\": %s,\\"host\\" : \\"%s:%s\\"}'%(i,ip,portc)
      ipsc = ip + ':' + portc
      ipstc = ipstc + ipsc + st
      ipstr = ipstr + ipst + st
   elif ip == iplist_c[0].split(' ')[-1]:
      ipst = '{\\"_id\\": %s,\\"host\\" : \\"%s:%s\\"}'%(i,ip,portc)
      ipsc = ip + ':' + portc
      ipstc = ipstc + ipsc
      ipstr = ipstr + ipst
rsinit_coun =  rsinit_head + ipstr + rsinit_tail
# 2.2 config副本集初始化
os.system('sshpass -p \'%s\'  ssh  root@%s -o StrictHostKeyChecking=no "echo \'%s\'|/usr/local/mongodb/bin/mongo %s:%s"' %(passw,ip1,rsinit_coun,ip1,portc))

#判断config的副本集是否已产生主节点
while True:
   primary_node = function_primary(ip,passw,portc)
   for n in range(60):
      time.sleep(n)
      if primary_node == 'PRIMARY':
         pd = 'PRIMARY'
         break
      else:
         pd = ''
         if n == 30:#判断config副本集在30秒内没有选举出primary,退出脚本
            print('初始化config副本集'+iplist_c[0]+'在30秒内没有选举出primary,退出脚本.')
            exit()
         break
   if pd == 'PRIMARY':
      break

# 获取副本集主节点IP地址
ip_str = os.popen('sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no "echo \'rs.status()\'|/usr/local/mongodb/bin/mongo %s:%s|grep -E \'name|stateStr\'|sed \'N;s/\\n//\'|grep PRIMARY"' %(passw,ip1,ip1,portc)).read().strip().split(':')[1].replace('"','')
ipList = re.findall( r'[0-9]+(?:\.[0-9]+){3}',ip_str)[0]
#副本集主节点创建管理账号
os.system('sshpass -p %s scp %s  root@%s:/root/' %(passw,'create_user.js',ipList))
time.sleep(1)
os.system('sshpass -p\'%s\'  ssh  root@%s -o StrictHostKeyChecking=no  "/usr/local/mongodb/bin/mongo %s:%s/admin < create_user.js"' %(passw,ipList,ipList,portc))
time.sleep(1)

#// 3、 mongos节点部署
extype = 3
cfdbs = '  configDB: '+replSetName+'/'+ipstc
print('开始部署mongos......')
os.system('sed -i "s|`grep configDB mongos_install.sh`|%s|g" mongos_install.sh'%(cfdbs))

#// 3.1 安装mongos节点
os.system("sh mongo_mutil.sh  \'%s\' %s %s" %(iplist_s[0],extype,passw))

while True:
   successfuls = []
   for ip in ips[0].split(' '):
      example_ps = function_psef(ip,passw)
      successfuls.append(example_ps)
   for n in range(60):
      print(n)
      time.sleep(n)
      if successfuls.count('successful_install') == 3 and list(set(successfuls))[0] == 'successful_install':
         print('mongos实例节点部署成功!')
         pd = 'successful_install'
         break
      else:
         pd = ''
         if n == 30:#判断安装mongos在30秒内没有选举出primary,退出脚本
            print('安装mongos'+iplist_s[0]+'失败!,退出脚本.')
            exit()
         break
   if pd == 'successful_install':
      print('mongos '+iplist_s[0]+' 实例安装成功!')
      break
time.sleep(3)
shardn = 0
port = 40000
# 3.2 添加集群分片
for ips in iplist:
   shardn += 1
   port = port + 1
   addshard_head = 'sh.addShard(\\"'
   # 添加分片的副本集ip串拼接
   ipsts = ''
   st= ','
   for i in range(len(ips[0].split(' '))):
      print(i)
      ip=ips[0].split(' ')[i]
      print ip
      if ip != ips[0].split(' ')[-1]:
         ipss = ip+':'+str(port)
         ipsts = ipsts + ipss + st
      elif ip == ips[0].split(' ')[-1]:
         ipss = ip+':'+str(port)
         ipsts = ipsts + ipss
   addshard = shardname+str(shardn)+'/'+ipsts
   addshard_tail = '\\")'
   addshardc = addshard_head + addshard + addshard_tail
   shows = 'sh.status()'
   os.system('sshpass -p \'%s\'  ssh  root@%s -o StrictHostKeyChecking=no "echo \'%s\'|/usr/local/mongodb/bin/mongo localhost:30000"' %(passw,iplist_s[0].split(' ')[0],addshardc))
   time.sleep(3)
#将密码写入日志中,方便后续查看
file = open('/data/mongodb/logs/mongo_route.log','a')
file.write('%s mongodb_password: %s \n' %(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()),password))
file.close()
#把mognodb集群信息记录到集群config库的mongodb_configs集合中
os.system("echo 'db.mongodb_configs.insert({\"mongos_30000\" : \"%s\",\"config_%s\" : \"%s\",\"shards_40001-%s\":\"%s\"})'|/usr/local/mongodb/bin/mongo localhost:30000/config" %(iplist_s,portc,iplist_c,port,iplist))

# 获取IP
mongos = os.popen("echo 'db.mongodb_configs.find({},{\"mongos_30000\":1, \"_id\":0})'|/usr/local/mongodb/bin/mongo localhost:30000/config|grep mongos_30000|grep -Po '(?<=\[).*?(?=\])'|tail -n1").read().strip()
config = os.popen("echo 'db.mongodb_configs.find({},{\"config_27017\":1, \"_id\":0})'|/usr/local/mongodb/bin/mongo localhost:30000/config|grep config_27017|grep -Po '(?<=\[).*?(?=\])'|tail -n1").read().strip()
shards = os.popen("echo 'db.mongodb_configs.find({},{\"shards_40001-%s\":1, \"_id\":0})'|/usr/local/mongodb/bin/mongo localhost:30000/config|grep shards_40001|grep -Po '(?<=\"\[).*?(?=\]\")'|grep -Po '(?<=\[).*?(?=\])'" %(port)).read().strip().replace("\n", " ")
all_ip = mongos + ' ' + config + ' ' + shards
print all_ip
# Closing remarks
n = 1
for i in range(20,14,-1):
   print(' '*i+'*'*n)
   n = n + 2
n = 11
for i in range(15,19):
   print(' '*i+'*'*n)
   n = n - 2
for i in range(3):
   print(' '*19+'*'*1+' '+'*'*1)
print(' '*20+'*'*1)
s = "[ MongoDB ]"
x = '★★★'
print('\033[1;33;40m%s\033[0m''分片集群已经部署完成''\033[1;34;40m%s\033[0m''~ 集群重启中~' %(s,x))
print('MongoDB集群密码在日志里-_- mongodb_password')
if account_verify == 1:
   os.system("sh cluster_add_security_key.sh \'%s\' \'%s\' \'%s\' \'%s\' %s " %(mongos,config,shards,all_ip,passw))
elif account_verify == 0:
   exit()

mongo_mutil.sh

powershell 复制代码
#!/bin/bash


#shardid=1
vers='4.4.18'
dataroot='/data'
passw=$3

function  install_shard(){
  IFS='|' read -ra elements <<< "$1"
  for ip in "${elements[@]}"; do
     {
      ipp=$(ping `hostname` -c 1|grep PING|grep -Po '(?<=\().*?(?=\))'|grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"|head -n 1)
      if [ "$ipp" == "$ip" ];then
         sh  mongodb_install.sh $2 $3 $4
      elif [ "$ipp" != "$ip" ];then
         shardnamen='rsshd'$4
         shardnamey=$(grep replSetName mongodb_install.sh|cut -d':' -f2|grep -Po '(?<=\").*?(?=\")'|tail -n1)
         sed -i "s|$shardnamey|$shardnamen|g" mongodb_install.sh
         sshpass -p $5  ssh  root@${ip} -o StrictHostKeyChecking=no "if [ ! -d $2 ];then  mkdir $2;fi"
         sshpass -p $5 scp mongodb_install.sh mongodb-linux-x86_64-rhel70-$3.tgz  root@${ip}:$2
         echo '副本集节点传入shards '$4
         sshpass -p $5  ssh  root@${ip} -o StrictHostKeyChecking=no "cd $2;sh  mongodb_install.sh $2 $3 $4"
      fi
 echo 'install mongod ......'
     } &
 done
 wait
}

function  install_config(){
  IFS='|' read -ra elements <<< "$1"
  for ip in "${elements[@]}"; do
    {
    ipp=$(ping `hostname` -c 1|grep PING|grep -Po '(?<=\().*?(?=\))'|grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"|head -n 1)
    if [ "$ipp" == "$ip" ];then
       sh config_install.sh $2 $3
    elif [ "$ipp" != "$ip" ];then
      sshpass -p $4  ssh  root@${ip} -o StrictHostKeyChecking=no "if [ ! -d $2 ];then  mkdir $2;fi"
      sshpass -p $4  scp config_install.sh mongodb-linux-x86_64-rhel70-$3.tgz  root@${ip}:$2
      sshpass -p $4  ssh  root@${ip} -o StrictHostKeyChecking=no "cd $2;sh  config_install.sh $2 $3"
    fi
  echo 'install config ......'
    } &
  done
  wait
}

function  install_mongos(){
  IFS='|' read -ra elements <<< "$1"
  for ip in "${elements[@]}"; do
    {
    ipp=$(ping `hostname` -c 1|grep PING|grep -Po '(?<=\().*?(?=\))'|grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"|head -n 1)
    if [ "$ipp" == "$ip" ];then
       sh mongos_install.sh $2 $3
    elif [ "$ipp" != "$ip" ];then
      sshpass -p $4  ssh  root@${ip} -o StrictHostKeyChecking=no "if [ ! -d $2 ];then  mkdir $2;fi"
      sshpass -p $4 scp mongos_install.sh mongodb-linux-x86_64-rhel70-${vers}.tgz  root@${ip}:$2
      sshpass -p $4  ssh  root@${ip} -o StrictHostKeyChecking=no "cd $2;sh mongos_install.sh $2 $3"
    fi
  echo 'install mongos ......'
    } &
  done
  wait
}


if [ "$2" == 1 ];then # mongod
  ips=`echo $1|sed 's/ /|/g'`
  rss=$4
  install_shard $ips ${dataroot} ${vers} ${rss} ${passw}
elif [ "$2" == 2 ];then # config
  ips=`echo $1|sed 's/ /|/g'`
  install_config $ips ${dataroot} ${vers} ${passw}

elif [ "$2" == 3 ];then # mongos
  ips=`echo $1|sed 's/ /|/g'`
  install_mongos $ips ${dataroot} ${vers} ${passw}
fi

mongodb_install.sh

powershell 复制代码
#!/bin/bash

# /data/mongodb /{data,logs,conf}

dataroot=$1
ver=$2
shardid=$3
setip='0.0.0.0'
if [ $# -ne 3 ];then
    echo "Error: please use $0 dataroot ver shardid"
    exit 1
fi
addcmd(){
addText=$1
file=$2
#判断 file.sh 文件中是否存在该字符串 # Check whether the character string exists in the file.sh file
if ! grep "$addText" $file  >/dev/null
then
#不存在,添加字符串 # Does not exist, add a string
   echo $addText >> $file
else
#存在,不做处理
   echo $addText" exist in "$file
fi
}
#wget mongodb-linux-x86_64-rhel70-4.4.18.tgz
tar xzvf mongodb-linux-x86_64-rhel70-$ver.tgz -C /opt
ln -snf /opt/mongodb-linux-x86_64-rhel70-$ver /usr/local/mongodb
basedir='/usr/local/mongodb'
datadir=$dataroot'/mongodb/data'
logdir=$dataroot'/mongodb/logs'


# rm $datadir/* -rf
mkdir -p $logdir

mkdir ${dataroot}/mongodb/conf

addcmd 'export PATH=$PATH:/usr/local/mongodb/bin' ~/.bash_profile
source ~/.bash_profile
groupadd mongodb
useradd -g mongodb mongodb
cat > /usr/lib/systemd/system/mongod_multiple_mongod@.service << EOF
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network-online.target
Wants=network-online.target
[Service]
User=mongodb
Group=mongodb
#EnvironmentFile=-$basedir/etc/default/mongod
ExecStart=$basedir/bin/mongod --config ${dataroot}/mongodb/conf/mongo_shard%i.yml
ExecStop=$basedir/bin/mongod --config ${dataroot}/mongodb/conf/mongo_shard%i.yml --shutdown
PIDFile=$datadir/%i/mongo_%i.pid
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
i=$shardid
#for ((i=1; i<=j; i++))
#do
    mkdir -p $datadir/shard$i
    if [ ! -f $basedir/conf/mongo_shard$i.yml ]; then
    touch ${dataroot}/mongodb/conf/mongo_shard$i.yml
    fi
    port=`expr $i + 40000`
    cat > ${dataroot}/mongodb/conf/mongo_shard$i.yml << EOF
systemLog:
  destination: file
  path: "$logdir/mongo_shard$i.log"
  logAppend: true
  logRotate: rename
storage:
  journal:
    enabled: true
    commitIntervalMs: 162
  dbPath: "$datadir/shard$i"
  syncPeriodSecs: 67
  engine: wiredTiger
  wiredTiger:
    engineConfig:
         cacheSizeGB: 6
processManagement:
  fork: false
net:
  bindIp: $setip
  #注意修改端口  # Notice Modifying the port
  port: $port
setParameter:
  enableLocalhostAuthBypass: true
replication:
  #复制集名称 # Replication set name
  replSetName: "rsshd3"
  oplogSizeMB: 24576
sharding:
  #作为分片服务 # As a shard service
  clusterRole: shardsvr
#security:
#  keyFile: "/data/mongodb/conf/keyFile"
#  authorization: enabled
EOF
sed -i "s|`grep cacheSizeGB ${dataroot}/mongodb/conf/mongo_shard$i.yml|sed 's/^[ \t]*//g'`|cacheSizeGB: "$(echo `free -m|grep Mem|awk -F' ' '{print $4}'`*0.85/1000|bc|cut -d'.' -f1)"|g"  ${dataroot}/mongodb/conf/mongo_shard$i.yml

    chown -R mongodb:mongodb $dataroot/mongodb
    chown -R mongodb:mongodb $basedir
    cd $basedir
    rpath=`pwd -P`
    chown -R mongodb:mongodb $rpath
    systemctl restart mongod_multiple_mongod@$i.service
    systemctl enable mongod_multiple_mongod@$i.service
#done

config_install.sh

powershell 复制代码
#!/bin/bash
# config install
# /data/mongodb /{data,logs,conf}

dataroot=$1
ver=$2
setip='0.0.0.0'
addcmd(){
addText=$1
file=$2
#判断 file.sh 文件中是否存在该字符串
#Check whether the character string exists in the file.sh file
if ! grep "$addText" $file  >/dev/null
then
#不存在,添加字符串
# Does not exist, add a string
   echo $addText >> $file
else
#存在,不做处理
#Exist, do not process
   echo $addText" exist in "$file
fi
}
#wget mongodb-linux-x86_64-rhel70-4.4.18.tgz
tar xzvf mongodb-linux-x86_64-rhel70-$ver.tgz -C /opt
ln -snf /opt/mongodb-linux-x86_64-rhel70-$ver /usr/local/mongodb
basedir='/usr/local/mongodb'
datadir=$dataroot'/mongodb'
logdir=$dataroot'/mongodb/logs'


# rm $datadir/* -rf
mkdir -p $logdir

#mkdir -p ${dataroot}/mongodb/config
mkdir ${dataroot}/mongodb/{conf,config}

addcmd 'export PATH=$PATH:/usr/local/mongodb/bin' ~/.bash_profile
source ~/.bash_profile
groupadd mongodb
useradd -g mongodb mongodb
cat > /usr/lib/systemd/system/mongod_multiple_config@.service << EOF
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network-online.target
Wants=network-online.target
[Service]
User=mongodb
Group=mongodb
#EnvironmentFile=-$basedir/etc/default/mongod
ExecStart=$basedir/bin/mongod --config ${dataroot}/mongodb/conf/mongo_config.yml
ExecStop=$basedir/bin/mongod --config ${dataroot}/mongodb/conf/mongo_config.yml --shutdown
PIDFile=$datadir/%i/mongo_%i.pid
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
    if [ ! -f $basedir/conf/mongo_config.yml ]; then
    touch ${dataroot}/mongodb/conf/mongo_config.yml
    fi
    cat > ${dataroot}/mongodb/conf/mongo_config.yml << EOF
systemLog:
  destination: file
#注意修改路径
#Note the modification path
  path: "$logdir/mongo_config.log"
  logAppend: true
storage:
  journal:
    enabled: true
#注意修改路径
#Note the modification path
  dbPath: "$datadir/config"
  engine: wiredTiger
  wiredTiger:
    engineConfig:
         cacheSizeGB: 1
processManagement:
  fork: false
net:
  bindIp: 0.0.0.0
#注意修改端口
#Notice Modifying the port
  port: 27017
setParameter:
  enableLocalhostAuthBypass: true
replication:
#复制集名称
#Replication set name
  replSetName: "rscnf"
sharding:
#作为配置服务
#As configuration service
  clusterRole: configsvr
#security:
#  keyFile: "/data/mongodb/conf/keyFile"
#  authorization: enabled
EOF
sed -i "s|`grep cacheSizeGB ${dataroot}/mongodb/conf/mongo_config.yml|sed 's/^[ \t]*//g'`|cacheSizeGB: "$(echo `free -m|grep Mem|awk -F' ' '{print $4}'`*0.85/1000|bc|cut -d'.' -f1)"|g"  ${dataroot}/mongodb/conf/mongo_config.yml

    chown -R mongodb:mongodb $dataroot/mongodb
    chown -R mongodb:mongodb $basedir
    cd $basedir
    rpath=`pwd -P`
    chown -R mongodb:mongodb $rpath
    systemctl restart mongod_multiple_config@1.service
    systemctl enable mongod_multiple_config@1.service

mongos_install.sh

powershell 复制代码
#!/bin/bash
# config install
# /data/mongodb /{data,logs,conf}

dataroot=$1
ver=$2
setip='0.0.0.0'
addcmd(){
addText=$1
file=$2
#判断 file.sh 文件中是否存在该字符串  # Check whether the character string exists in the file.sh file
if ! grep "$addText" $file  >/dev/null
then
#不存在,添加字符串  # Does not exist, add a string
   echo $addText >> $file
else
#存在,不做处理 # Exist, do not process
   echo $addText" exist in "$file
fi
}
#wget mongodb-linux-x86_64-rhel70-4.4.18.tgz
tar xzvf mongodb-linux-x86_64-rhel70-$ver.tgz -C /opt
ln -snf /opt/mongodb-linux-x86_64-rhel70-$ver /usr/local/mongodb
basedir='/usr/local/mongodb'
datadir=$dataroot'/mongodb'
logdir=$dataroot'/mongodb/logs'


# rm $datadir/* -rf
mkdir -p $logdir

#mkdir -p ${dataroot}/mongodb/config
mkdir ${dataroot}/mongodb/conf

addcmd 'export PATH=$PATH:/usr/local/mongodb/bin' ~/.bash_profile
source ~/.bash_profile
groupadd mongodb
useradd -g mongodb mongodb
cat > /usr/lib/systemd/system/mongod_multiple_mongos@.service << EOF
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network-online.target
Wants=network-online.target
[Service]
User=mongodb
Group=mongodb
#EnvironmentFile=-$basedir/etc/default/mongod
ExecStart=$basedir/bin/mongos --config ${dataroot}/mongodb/conf/mongo_route.yml
ExecStop=$basedir/bin/mongos --config ${dataroot}/mongodb/conf/mongo_route.yml --shutdown
PIDFile=$datadir/%i/mongo_%i.pid
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
    if [ ! -f $basedir/conf/mongo_route.yml ]; then
    touch ${dataroot}/mongodb/conf/mongo_route.yml
    fi
    cat > ${dataroot}/mongodb/conf/mongo_route.yml << EOF
systemLog:
  destination: file
#  注意修改路径  # Note the modification path
  path: "/data/mongodb/logs/mongo_route.log"
  logAppend: true
processManagement:
  fork: false
net:
  bindIp: 0.0.0.0
#  注意修改端口 # Notice Modifying the port
  port: 30000
setParameter:
  enableLocalhostAuthBypass: true
replication:
  localPingThresholdMs: 15
sharding:
#  关联配置服务  # Associated configuration service
  configDB: rscnf/1x2.x1.2x8.177:27017,1x2.x1.2x8.139:27017,1x2.x1.2x8.95:27017
#security:
#  keyFile: "/data/mongodb/conf/keyFile"
EOF

cat >  /root/.mongorc.js << EOF
//host=db.serverStatus().host;
host=\``hostname`\`
cmdCount=1;
prompt=function(){
return db+"@"+host+" "+(cmdCount++) +">";
}

function showDate(){

var today = new Date();
var year = today.getFullYear() + "年";
var month = (today.getMonth() +1) + "月";
var date = today.getDate() + "日";
var week = '星期' + today.getDay();
var quarter = "一年中的第" + Math.floor((today.getMonth() +3) / 3) + "个季度";

var text = "[ 欢迎回来,今天是" + year + month + date  + week +"," + quarter + "。]";
print(text);

}

showDate();
EOF

    chown -R mongodb:mongodb $dataroot/mongodb
    chown -R mongodb:mongodb $basedir
    cd $basedir
    rpath=`pwd -P`
    chown -R mongodb:mongodb $rpath
    systemctl restart mongod_multiple_mongos@1.service
    systemctl enable mongod_multiple_mongos@1.service

部署效果:

本文章为原创,github地址 https://github.com/gg2038/mongo-sharding-install