本地快速部署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

    输出结果如下:

相关推荐
java_logo18 分钟前
Docker 部署 MinIO 全指南
运维·windows·mongodb·docker·容器
我狸才不是赔钱货35 分钟前
DevOps:打破开发与运维之间的高墙
运维·vscode·docker·devops
黄雄进1 小时前
Windows使用docker安装milvus的配置文件
windows·docker·milvus
一勺菠萝丶3 小时前
在 macOS 上用 Docker 为 Java 后端 & 常见开发需求搭建完整服务(详尽教程)
java·macos·docker
AI云原生4 小时前
云原生系列Bug修复:Docker镜像无法启动的终极解决方案与排查思路
运维·服务器·python·docker·云原生·容器·bug
tryCbest10 小时前
CentOS部署Docker容器
linux·docker·centos
菠萝炒饭pineapple-boss11 小时前
单机让多docker拥有多ip出口
docker
007php00713 小时前
百度面试题解析:微服务架构、Dubbo、Redis及其一致性问题(一)
redis·百度·docker·微服务·容器·职场和发展·架构
阑梦清川14 小时前
es的docker部署和docker相关的可可视化面板工具介绍
大数据·elasticsearch·docker
我狸才不是赔钱货16 小时前
容器:软件世界的标准集装箱
linux·运维·c++·docker·容器