前言
有时需要在本地模拟多节点集群环境,通常我们会创建虚拟机作为独立的节点,但是常用的工具如VMware或Virtualbox都是基于GUI操作的:下载OS镜像、配置虚拟机、再进入多个虚拟机内安装软件,一系列操作下来比较繁琐耗时。Ubuntu推出了一个叫multipass的工具,可以基于命令行创建、配置、管理虚拟机,这使得快速、自动化地创建虚拟机成为可能。
本文探索使用multipass工具在本地快速搭建docker swarm集群环境。
核心步骤
安装multipass
-
mac环境安装multipass
bashbrew install multipass
其它安装方式及multipass的使用手册请查阅官网。
创建虚拟机
-
创建manager节点,规格为1cpu,500M内存,5G磁盘
bashmultipass 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磁盘
bashmultipass 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'
上述命令包含两个操作:
- 依赖
multipass exec
命令可以直接在manager和worker节点虚拟机内执行用户指定命令。 - 使用脚本安装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节点检查集群状态
bashubuntu@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
输出结果如下: