通过集群来管理应用会比直接使用单节点compose编排好管理一些.我之前就是用的某台云服务器承载了不少东西,要做机器间的应用迁移比较麻烦,尤其是降本增效,有了更高性价比的机器,采用swarm来管理,很容易就能实现. 顺便学习一下swarm,写下本篇文章做个记录.
环境准备
先准备两台及以上机器, 云服务ECS实例,或稳定的机器.
然后参考Docker文档安装Docker,或者使用ECS管理台直接扩展安装都行.
Manager节点准备
虽然不同机器间切换Manager/worker比较方便,但还是可以一开始就考虑好,作为manager节点,稳定很重要,所以推荐选择一台ECS机器,保底2核4G 3M往上的带宽吧,具体根据情况来,我用的2核2G3M也能部署使用.
在准备作为Manager的机器上 执行 docker swarm init --advertise-addr <MANAGER-IP>
初始化管理节点,MANAGER-IP是内网还是外网取决于你其他机器是否在同一网络环境内,不在同一环境就选择外网IP,强烈建议在内网环境部署工作节点
执行 docker node ls
来查看集群节点,大概内容会如下所示
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
dnakktsettesttestry * <一般是主机名> Ready Active Leader 27.1.2
其中Leader表示是管理节点
Worker节点准备
接下来要添加一个Worker工作节点来运行任务
首先请确保 manager 节点已打开2377端口
在Manager节点执行 docker swarm join-token worker
来获取加入集群的命令,大致如下:
To add a worker to this swarm, run the following command:
docker swarm join --token <token> <Manager-ip>:2377
复制上述打印的 docker swarm join 完整命令在worker节点上执行,以加入此集群.
加入后此时在Manager节点再执行 docker node ls
, 大概如下:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
dp44rcfsfsfs838b39cfey3 <Worker主机名> Ready Active 23.0.3
dnakktsettesttestry * <Manager主机名> Ready Active Leader 27.1.2
看到这里便说明worker机器已经成功加入manager节点
服务准备
既然现在已经有了Manager及Worker节点,接下来我们就要开始部署服务了,这里我先为特定worker节点添加一个特殊标签,以便在指定机器上部署服务.
在manager上先使用docker node ls
获取目标节点id, 然后执行 docker node update --label-add hostname=<主机名> <节点ID>
指定标签.
假设我们现在需要一个mysql来存储数据,还需要一个MinIO来作为OSS存储资源数据,一个casdoor来管理用户角色与权限,一个Redis来管理缓存数据,接下来创建 /root/base-servies/base-services.yml 文件,内容参考如下:
version: "3"
services:
casdoor:
image: casbin/casdoor:${CASDOOR_IMAGE_VERSION}
container_name: base-service-casdoor
restart: always
volumes:
- ${CASDOOR_VOLUMES_CONF}:/conf
ports:
- ${CASDOOR_PORT_ADDRESS}:8000
deploy:
replicas: 1
placement:
constraints: [node.labels.hostname == <替换为指定的hostname值>]
minio:
image: minio/minio:${MINIO_IMAGE_VERSION}
container_name: base-service-minio
restart: always
command: ["server", "/data", "--console-address", ":${MINIO_PORT_CONSOLE_ADDRESS}", "--address", ":${MINIO_PORT_ADDRESS}"]
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- ${MINIO_VOLUMES_CONF}:/root/.minio
- ${MINIO_VOLUMES_DATA_DIR}:/data
ports:
- ${MINIO_PORT_ADDRESS}:${MINIO_PORT_ADDRESS}
- ${MINIO_PORT_CONSOLE_ADDRESS}:${MINIO_PORT_CONSOLE_ADDRESS}
deploy:
replicas: 1
placement:
constraints: [node.labels.hostname == <替换为指定的hostname值>]
mysql:
container_name: base-service-mysql
image: mysql:${MYSQL_IMAGE_VERSION}
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
volumes:
- ${MYSQL_VOLUMES_CONF_DIR}:/etc/mysql/conf.d
- ${MYSQL_VOLUMES_DATA_DIR}:/var/lib/mysql
ports:
- "${MYSQL_PORT}:3306"
deploy:
replicas: 1
placement:
constraints: [node.labels.hostname == <替换为指定的hostname值>]
redis:
container_name: base-service-redis
image: redis:${REDIS_IMAGE_VERSION}
restart: always
command: [ "redis-server", "/usr/local/etc/redis/redis.conf", "--requirepass", $REDIS_PASSWORD ]
volumes:
- ${REDIS_VOLUMES_CONF}:/usr/local/etc/redis/redis.conf
- ${REDIS_VOLUMES_DATA_DIR}:/data
ports:
- ${REDIS_PORT}:6379
deploy:
replicas: 1
placement:
constraints: [node.labels.hostname == <替换为指定的hostname值>]
然后在 /root/base-servies/.env 创建 .env 文件,配置环境变量参考如下:
# MySQL 配置
# mysql镜像版本
MYSQL_IMAGE_VERSION=8.0.32
# mysql root用户密码
MYSQL_ROOT_PASSWORD=<替换该值>
# mysql 配置挂载卷
MYSQL_VOLUMES_CONF_DIR=<替换该值>
# mysql 数据挂载卷
MYSQL_VOLUMES_DATA_DIR=<替换该值>
# mysql 初始数据库的名称
MYSQL_DATABASE=<替换该值>
# mysql 宿主端口
MYSQL_PORT=<替换该值>
# Redis 配置
# redis镜像版本
REDIS_IMAGE_VERSION=7.0.10-alpine
# redis配置文件
REDIS_VOLUMES_CONF=<替换该值>
# redis持久化挂载卷
REDIS_VOLUMES_DATA_DIR=<替换该值>
# redis 连接密码
REDIS_PASSWORD=<替换该值>
# redis 宿主端口
REDIS_PORT=<替换该值>
# MinIO 对象存储
# minio 镜像版本
MINIO_IMAGE_VERSION=RELEASE.2023-04-13T03-08-07Z
# 登录用户名
MINIO_ROOT_USER=<替换该值>
# 登录用户密码
MINIO_ROOT_PASSWORD=<替换该值>
# minio配置文件
MINIO_VOLUMES_CONF=<替换该值>
# minio持久化挂载卷
MINIO_VOLUMES_DATA_DIR=<替换该值>
# 控制台地址
MINIO_PORT_CONSOLE_ADDRESS=<替换该值>
# 访问地址
MINIO_PORT_ADDRESS=<替换该值>
# Casdoor 用户身份认证系统
CASDOOR_IMAGE_VERSION=v1.623.0
CASDOOR_VOLUMES_CONF=<替换该值>
CASDOOR_PORT_ADDRESS=<替换该值>
新建 /root/base-services/start.sh 文件, 内容参考如下:
#!/bin/sh
set -a
source .env
set +a
docker stack deploy -c base-services.yml base-services
准备就绪后,就可以着手启动服务了,在manager节点 /root/base-services 下执行bash ./start.sh
部署基础应用到集群
部署完成后可以通过 docker stack services base-services
查看服务状态
到这里访问集群中任一节点都可找到服务了.