基于Docker swarm快速搭建集群环境

152 阅读4分钟

通过集群来管理应用会比直接使用单节点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 查看服务状态

到这里访问集群中任一节点都可找到服务了.