本地快速部署docker swarm集群

前言

有时需要在本地模拟多节点集群环境,通常我们会创建虚拟机作为独立的节点,但是常用的工具如VMware或Virtualbox都是基于GUI操作的:下载OS镜像、配置虚拟机、再进入多个虚拟机内安装软件,一系列操作下来比较繁琐耗时。Ubuntu推出了一个叫multipass的工具,可以基于命令行创建、配置、管理虚拟机,这使得快速、自动化地创建虚拟机成为可能。

本文探索使用multipass工具在本地快速搭建docker swarm集群环境。

核心步骤

安装multipass

  • mac环境安装multipass

    bash 复制代码
    brew install multipass

    其它安装方式及multipass的使用手册请查阅官网

创建虚拟机

  • 创建manager节点,规格为1cpu,500M内存,5G磁盘

    bash 复制代码
    multipass launch --name manager --cpus 1 --memory 512M --disk 5G

    命令执行成功后查看vm信息:

    bash 复制代码
    ➜ ~ multipass info manager
    Name:           manager
    State:          Running
    IPv4:           192.168.64.13
    Release:        Ubuntu 22.04.3 LTS
    Image hash:     2461b36d86ac (Ubuntu 22.04 LTS)
    CPU(s):         1
    Load:           0.28 0.17 0.07
    Disk usage:     1.4GiB out of 4.8GiB
    Memory usage:   120.5MiB out of 448.3MiB
    Mounts:         --

    同时mac上多了一个虚拟机进程

    Multipass uses Hyper-V on Windows, QEMU and HyperKit on macOS and LXD on Linux for minimal overhead and the fastest possible start time

  • 创建worker节点,规格为2cpu,1G内存,10G磁盘

    bash 复制代码
    multipass launch --name worker --cpus 2 --memory 1G --disk 10G

为虚拟机安装docker

bash 复制代码
# 为manager节点安装docker
multipass exec manager -- sh -c 'wget -qO- https://get.docker.com | sh && sudo usermod -aG docker $USER'
# 为worker节点安装docker
multipass exec worker -- sh -c 'wget -qO- https://get.docker.com | sh && sudo usermod -aG docker $USER'

上述命令包含两个操作:

  1. 依赖multipass exec命令可以直接在manager和worker节点虚拟机内执行用户指定命令。
  2. 使用脚本安装docker,并将当前用户加入docker用户组。

配置docker swarm集群

  • 登录manager节点,初始化docker swarm集群

    bash 复制代码
    # 登录manager节点
    ➜ ~ multipass shell manager
    # 初始化docker swarm集群
    ubuntu@manager:~$ docker swarm init
    Swarm initialized: current node (qrj2ed06u9u8hv1q42naant7u) is now a manager.
    
    To add a worker to this swarm, run the following command:
    
        docker swarm join --token SWMTKN-1-0rbktjge30ppw1o62wt9ruju7ff7neuq5y109f6i3vxxgq8myt-4fdu3c2bku48ray80pxbhiv0m 192.168.64.13:2377
    
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
  • 登录worker节点,将worker节点加入swarm集群

    bash 复制代码
    # 登录worker节点
    ➜ ~ multipass shell worker
    # 将worker节点加入docker swarm集群
    ubuntu@worker:~$ docker swarm join --token SWMTKN-1-0rbktjge30ppw1o62wt9ruju7ff7neuq5y109f6i3vxxgq8myt-4fdu3c2bku48ray80pxbhiv0m 192.168.64.13:2377
    This node joined a swarm as a worker.
  • 在manager节点检查集群状态

    bash 复制代码
    ubuntu@manager:~$ docker node ls
    ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
    qrj2ed06u9u8hv1q42naant7u *   manager     Ready     Active         Leader           24.0.6
    7di8oseqxypswdayrrzth9ivq     worker     Ready     Active                          24.0.6

脚本一键部署

上面我们部署了1manager + 1worker规格的最简单集群,为了模拟更真实的集群环境我们通常需要部署更多的节点,为了减少重复手工操作,使用shell脚本将上述步骤自动化。

  • 创建一个名为docker-swarm-init.sh的脚本

    bash 复制代码
    #!/bin/bash
    
    log() {
    	# 使用蓝色打印关键日志
    	pattern="\033[34m>> $1\033[0m\n"
    	shift
    	args="$@"
    	printf "$pattern" $args
    }
    
    # 默认配置
    manager_nums=1
    manager_cpus=1
    manager_memory=512M
    manager_disk=5G
    
    worker_nums=1
    worker_cpus=2
    worker_memory=2G
    worker_disk=10G
    
    # 解析参数
    OPTIONS=m:w:
    LONGOPTIONS=manager-nums:,worker-nums:,manager-cpus:,manager-memory:,manager-disk:,worker-cpus:,worker-memory:,worker-disk:
    args=$(getopt -o "$OPTIONS" -l "$LONGOPTIONS" --name "$0" -- "$@")
    ## 检查解析结果是否出错
    if [ $? -ne 0 ]; then
    	exit 1
    fi
    ## 重新设置命令行参数
    eval set -- "$args"
    
    while true; do
    	case "$1" in
    	-m | --manager-nums)
    		manager_nums=$2
    		shift
    		;;
    	--manager-cpus)
    		manager_cpus=$2
    		shift
    		;;
    	--manager-memory)
    		manager_memory=$2
    		shift
    		;;
    	--manager-disk)
    		manager_disk=$2
    		shift
    		;;
    	-w | --worker-nums)
    		worker_nums=$2
    		shift
    		;;
    	--worker-cpus)
    		worker_cpus=$2
    		shift
    		;;
    	--worker-memory)
    		worker_memory=$2
    		shift
    		;;
    	--worker-disk)
    		worker_disk=$2
    		shift
    		;;
    	--)
    		shift
    		break
    		;;
    	*)
    		echo "Invalid option: $1"
    		exit 1
    		;;
    	esac
    	shift
    done
    
    log "start building clusters, expected %s managers[cpus: %s, memory: %s, disk: %s], and %s workers[cpus: %s, memory: %s, disk: %s]" $manager_nums $manager_cpus $manager_memory $manager_disk $worker_nums $worker_cpus $worker_memory $worker_disk
    
    # 创建vm实例
    create_vm() {
    	type=$1
    	instance_name=$2
    	case "$type" in
    	manager)
    		multipass launch --name $instance_name --cpus $manager_cpus --memory $manager_memory --disk $manager_disk
    		;;
    	worker)
    		multipass launch --name $instance_name --cpus $worker_cpus --memory $worker_memory --disk $worker_disk
    		;;
    	*)
    		log "Invalid vm type: $type"
    		exit 1
    		;;
    	esac
    	log "vm $instance_name created"
    }
    manager_vms=()
    worker_vms=()
    ## 创建manager vms
    for ((i = 1; i <= $manager_nums; i++)); do
    	instance_name=manager$i
    	manager_vms[$i]=$instance_name
    	create_vm "manager" $instance_name &
    done
    ## 创建worker vms
    for ((i = 1; i <= worker_nums; i++)); do
    	instance_name=worker$i
    	worker_vms[$i]=$instance_name
    	create_vm "worker" $instance_name &
    done
    wait
    
    # 安装docker
    install_docker() {
    	instance_name=$1
    	multipass exec $instance_name -- sh -c 'wget -qO- https://get.docker.com | sh > /dev/null 2>&1 && sudo usermod -aG docker $USER'
    	log "docker installed on $instance_name"
    }
    all_vms=("${manager_vms[@]}" "${worker_vms[@]}")
    for instance_name in "${all_vms[@]}"; do
    	install_docker $instance_name &
    done
    wait
    
    # 配置swarm集群
    leader="${manager_vms[@]:0:1}"
    ## 初始化leader
    multipass exec $leader -- docker swarm init
    log "docker swarm init at $leader"
    manager_join_script=$(multipass exec $leader -- sh -c 'docker swarm join-token manager | sed -e "1d;/^$/d"')
    worker_join_script=$(multipass exec $leader -- sh -c 'docker swarm join-token worker | sed -e "1d;/^$/d"')
    ## join as manager
    for instance_name in "${manager_vms[@]}"; do
    	if [ "$instance_name" != "$leader" ]; then
    		multipass exec $instance_name -- $manager_join_script
    		log "$instance_name joined swarm as mananger"
    	fi
    done
    ## join as worker
    for instance_name in "${worker_vms[@]}"; do
    	multipass exec $instance_name -- $worker_join_script
    	log "$instance_name joined swarm as worker"
    done
    ## show nodes
    log "docker swarm cluster create success"
    multipass exec $leader -- docker node ls

    mac上执行时需要使用gnu-getopt命令,否则参数解析会异常:1. 安装命令:brew install gnu-getopt 2. 将/usr/local/opt/gnu-getopt/bin加入PATH路径下

  • 执行脚本,创建一个3manager+3worker规格的swarm集群

    bash 复制代码
    ./docker-swarm-init.sh -m 3 -w 3

    输出结果如下:

相关推荐
为什么不问问神奇的海螺呢丶23 分钟前
n9e categraf docker 监控配置
运维·docker·容器
青树寒鸦25 分钟前
wsl的docker备份mongo和迁移
运维·mongodb·docker·容器
hopsky3 小时前
Docker Desktop 报 500
运维·docker·容器
曦云沐3 小时前
一键部署ROS2开发环境!Docker run命令详解与实战
docker·容器·ros2
H Journey3 小时前
Docker swarm 集群搭建实战
运维·docker·容器
江湖有缘4 小时前
Docker环境下使用RustScan端口扫描工具教程
运维·docker·容器
70asunflower4 小时前
镜像仓库(Image Registries)详解
linux·docker·容器
青树寒鸦4 小时前
wsl的docker备份redis和迁移
redis·docker·容器
岩屿4 小时前
Ubuntu下安装Docker并部署.NET API(二)
运维·docker·容器·.net
hopsky4 小时前
限制 Docker Desktop 的资源使用
运维·docker·容器