1. 程式人生 > 資料庫 >Docker / Podman 建立MongoDB 副本叢集

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

在這裡插入圖片描述

登入目標機器,執行指令碼

ssh 目標機器
./build.sh

在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述

建立相關目錄

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-compse啟動mongo例項

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

在這裡插入圖片描述

進入容器【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 },
]
})

在這裡插入圖片描述在這裡插入圖片描述
完成
在這裡插入圖片描述

Podman下部署

Podman下部署與Docker類似,只是在執行build.sh時選Podman為容器。然後在啟動容器時使用下面的命令:

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

其他命令與Docker部署一樣
在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述