Docker / Podman 建立MongoDB 副本集群

Docker / Podman 建立MongoDB 副本集群

Docker / Podman 建立MongoDB 副本集群

本文介绍的MongoDB副本集群建立方法只能在Linux系统上使用,其他类Unix系统不适用于此方法。

建立生成Docker-compose.yaml脚本

建立mongoReplSetBuild.sh如下:

#! /bin/bash
:<<'COMMENT'
本脚本用来生成建立Mongo副本集群的docker-compose.yaml或podman-compose.yaml
许阳
2020年12月17日
COMMENT

# 读取容器类型
read_container_type() {
	local dt
	echo '请输入容器类型:'
	echo '1): Docker'
	echo '2): Podman'
	echo -n '[Docker]:'
	read dt
	
	dt=${dt,,}

	if [ -z $dt ]; then
		c_type=1
	else
		case $dt in
		docker)
			c_type=1
			;;
		podman)
			c_type=2
			;;
		1)
			c_type=1
			;;
		2)
			c_type=2
			;;
		*)
			echo '非法输入!'
			exit
		esac
	fi

}

# 读取生成文件要用的文件名
read_file_name() {
	local fn
	echo -n '请输入文件名[docker-compose.yaml]:'
	read fn

	if [ -z $fn ]; then
		file_name='docker-compose.yaml'
	else
		ext=`echo $fn | sed -r "s/.*\.(\w*)$/\1/g"`
		ext=${ext^^}

		if [[ "$ext" =~ "YAML" ]]; then
			fn=`echo $fn | sed -r "s/^(\w*)\.\w*$/\1/g"`
		fi

		file_name=$fn.yaml
	fi
}

# 整数转换
conver_number(){
	local num_v

	if [ -z "$1" ]; then
		return
	fi

	num_v=`echo $1 | sed -rn "s/^([0-9]+)$/\1/gp"`

	if [ -z "$num_v" ]; then
		echo '非法的整数输入'
	else
		num_out=$num_v
		return $num_v
	fi
}

# 读取要生成的副本个数
read_replSet_number() {
	local rn
	echo -n '请输入副本个数[3]:'
	read rn

	conver_number $rn
	nn=$num_out

	if [ -z "$rn" ]; then
		replSetNumber=3
	elif [ -z "$nn" ]; then
		echo '无效的副本个数'
		exit
	else
		replSetNumber=$rn
	fi	
}

# 读取根用户名
read_root_username() {
	local user_name
	echo -n '请输入根用户名[root]:'
	read user_name

	if [ -z "$user_name" ]; then
		v_uname='root'
	else
		v_uname=$user_name
	fi
}

# 读取根用户密码
read_root_password() {
	local pass_word
	echo -e '请输入根用户密码:\c'
	while : ;
	do
		local char=`
		stty cbreak -echo
		dd if=/dev/tty bs=1 count=1 2>/dev/null
		stty -cbreak echo
		`
		if [ "$char" = "" ]; then
			echo
			break
		fi
		v_password="$v_password$char"
		echo -n "*"
	done

	if [ -z "$v_password" ]; then
		echo '非法的密码!'
		exit
	fi
}

# 读取是否需要选举节点
read_arbiter_flag() {
	local arf
	echo -n '是否需要选举节点(yes|no)[yes]:'
	read arf
	
	if [ -z $arf ]; then
		v_arf=1
		arf=1
	fi
	
	arf=${arf,,}

	case $arf in
		1)
			v_arf=1
			;;
		0)
			v_arf=0
			;;
		y)
			v_arf=1
			;;
		n)
			v_arf=0
			;;
		yes)
			v_arf=1
			;;
		no)
			v_arf=0
			;;
		*)
			echo '非法输入!'
			exit
	esac
}

# 读取数据持久化文件夹前缀
read_data_db() {
	local db_path
	echo -n '请输入数据文件夹前缀[/opt/mongo/data/db]:'
	read db_path

	if [ -z "$db_path" ]; then
		dbpath='/opt/mongo/data/db'
	else
		dbpath=$db_path
	fi
}

# 读取设定文件夹
read_config_path() {
	local configd
	echo -n '请输入设定文件夹[/opt/mongo/mongo_key]:'
	read configd

	if [ -z "$configd" ]; then
		cnfpath='/opt/mongo/mongo_key'
	else
		cnfpath=$configd
	fi
}

# 读取密钥文件名
read_key_file(){
	local keyf
	echo -n '请输入密钥文件名[mongo.key]:'
	read keyf

	if [ -z "$keyf" ]; then
		keyfile='mongo.key'
	else
		keyfile=$keyf
	fi
}

# 读取最高端口号
read_start_port(){
	local finalport
	echo -n '请输入最高(起始)端口号[30000]:'
	read finalport

	conver_number $finalport
	local tmp=$num_out

	if [ -z "$finalport" ]; then
		v_port=30000
	else
		v_port=$tmp
	fi
}

read_port_step(){
	local step_v
	echo -n '请输入端口步长[1]:'
	read step_v

	conver_number $step_v
	local tmpsv=$num_out

	if [ -z "$step_v" ]; then
		step_num=1
	else
		step_num=$tmpsv
	fi 
}

# 生成yaml文件
write_file(){
	local start_p=$v_port
	local content=`cat<<EOF
version: "$1"
services:
EOF`
	local ct=$3

	if [ $v_arf -eq 1 ]; then
		ct=$(($ct + 1))
	fi

	for ((fp=0; fp<$ct; fp++))
	do
		local pp=$(($start_p - $fp * $step_num))
		
		if [ $v_arf -eq 1 ] && [ $fp -eq $3 ]; then
			m=`cat<<EOF
  mongo_arbiter:
EOF`
		else	
			m=`cat<<EOF
  mongo_repl_$fp:
EOF`
		fi

		m=`cat<<EOF
$m
    image: mongo:latest
EOF`
	
		if [ $v_arf -eq 1 ] && [ $fp -eq $3 ]; then
			m=`cat<<EOF
$m
    container_name: mongo_arbiter
EOF`
		else
			m=`cat<<EOF
$m
    container_name: mongo_replSet$fp
EOF`
		fi

		if [ $c_type -eq 1 ]; then
			m=`cat<<EOF
$m
    restart: unless-stopped    
EOF`
		fi

        	m=`cat<<EOF
$m
    ports:
      - $pp:27017
    volumes:
      - $dbpath$fp:/data/db
      - $cnfpath:/data/configdb
    environment:
      MONGO_INITDB_ROOT_USERNAME: $v_uname
      MONGO_INITDB_ROOT_PASSWORD: $v_password
    command: 'mongod --auth --keyFile /data/configdb/$keyfile --dbpath /data/db --bind_ip_all --replSet MongoRS --oplogSize 128'
EOF`


		if [ $fp -eq 0 ]; then
			content=`cat<<EOF
$content
$m
EOF`
		else
			content=`cat<<EOF
$content

$m
EOF`
		fi
	done

	cat>$2<<EOF
$content
EOF
}

read_container_type
read_file_name
read_replSet_number
read_arbiter_flag
read_root_username
read_root_password
read_data_db
read_config_path
read_key_file
read_start_port
read_port_step

case $c_type in
	1)
		cc_v=3.3
		;;
	2)
		cc_v=1.0
		;;
esac

write_file $cc_v $file_name $replSetNumber $v_arf

Docker 下部署:

拷贝脚本到要部署的机器上

scp mongoReplSetBuild.sh 目标机器:build.sh

Docker / Podman 建立MongoDB 副本集群

登录目标机器,执行脚本

ssh 目标机器
./build.sh

Docker / Podman 建立MongoDB 副本集群Docker / Podman 建立MongoDB 副本集群Docker / Podman 建立MongoDB 副本集群

建立相关目录

mkdir -p /opt/mongo/data/db0
mkdir -p /opt/mongo/data/db1
mkdir -p /opt/mongo/data/db2
mkdir -p /opt/mongo/data/db3
mkdir -p /opt/mongo/mongo_key
cd /opt/mongo/mongo_key
openssl rand -base64 700 > mongo.key
chmod 400 mongo.key
cd ~

Docker / Podman 建立MongoDB 副本集群

使用docker-compse启动mongo实例

docker-compose --file mongo.yaml up -d

Docker / Podman 建立MongoDB 副本集群

进入容器【mongo_replSet0】建立集群

docker exec -ti mongo_replSet0 /bin/bash
mongo
use admin
db.auth('root', passwordPrompt())
rs.initiate({
_id: 'MongoRS',
members: [
{ _id: 0, host: '公网地址:30000', priority: 3 },
{ _id: 1, host: '公网地址:29990', priority: 2 },
{ _id: 2, host: '公网地址:29980', priority: 1 },
{ _id: 3, host: '公网地址:29970', arbiterOnly: true },
]
})

Docker / Podman 建立MongoDB 副本集群Docker / Podman 建立MongoDB 副本集群
完成
Docker / Podman 建立MongoDB 副本集群

Podman下部署

Podman下部署与Docker类似,只是在执行build.sh时选Podman为容器。然后在启动容器时使用下面的命令:

podman-compose -f mongo.yaml -t identity up -d

其他命令与Docker部署一样
Docker / Podman 建立MongoDB 副本集群Docker / Podman 建立MongoDB 副本集群Docker / Podman 建立MongoDB 副本集群Docker / Podman 建立MongoDB 副本集群

上一篇:[Linux] docker-compose环境下mongoDB4.4.2副本集搭建


下一篇:<二>docker 安装mongodb