Deploy Cluster System with Docker Swarm and Docker Machine | 使用 Docker Swarm 和 Docker Machine 部署集群

Albert Wang / 2023-10-03 / 400 Words/has been Read   Times


这篇博客主要介绍怎么用一台电脑和 Docker 来搭建出一个可以随意扩容服务的集群。因为我的宿主机是 win10 系统,所以我先装了一台 ubuntu18.04 版本的虚拟机。

准备工作 #

在开始我们下面的操作之前需要先准备一下环境,

  • 首先我们需要用到的工具是 Docker Machine,Docker Machine 是一个用于简化 Docker 主机(Docker Host)创建、管理和配置的命令行工具。它的主要目标是让用户能够在本地开发环境中或云中轻松创建和管理多个 Docker 主机,而无需深入了解底层虚拟化技术或云提供商的特定配置。你需要确保事先已经安装了这个软件,如果没有的话可以运行下面的命令安装,
base=https://github.com/docker/machine/releases/download/v0.16.2 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
sudo install /tmp/docker-machine /usr/local/bin/docker-machine

image-20231004013754348

  • 另外需要安装 VirtualBox,官网是 https://www.virtualbox.org/ 。这里我们选择的是 linux ubuntu 18.04。

  • 最后需要确保开启了嵌套虚拟化,如果没有开启的话执行创建节点会报下面的错误

image-20231004014525583

virtualBox 开启是在设置的系统设置里,勾选启动PAE/NX和启用嵌套 VT-x/AMD-V.

image-20231004023507036

启用嵌套 VT-x/AMD-V 如果没有办法勾选的话可以在 CMD 里使用下面的命令开启。先 cd 到 virtualBox 的安装目录,我的是 D:\sys\virtualBox\virtualBox。然后 VBoxManage.exe list vms 查看有哪些虚拟机,最后用 VBoxManage.exe modifyvm “name” –nested-hw-virt on 打开指定虚拟机的选项。

D:\sys\virtualBox\virtualBox>VBoxManage.exe list vms
"Ubuntu18.04" {7f39fcd6-f8f2-4e49-b68b-77e1d11fcde2}

VBoxManage.exe modifyvm "Ubuntu18.04" --nested-hw-virt on

创建多个虚拟机 #

下面使用 Docker Machine 创建多个虚拟机,每个虚拟机将运行 Docker 引擎。以下是一个示例命令,创建三个虚拟机:

docker-machine create --driver virtualbox --virtualbox-hostonly-cidr "192.168.56.1/24" node1
docker-machine create --driver virtualbox --virtualbox-hostonly-cidr "192.168.56.1/24" node2
docker-machine create --driver virtualbox --virtualbox-hostonly-cidr "192.168.56.1/24" node3

上面的命令中我们指定了网段是 “192.168.56.1/24”,这是因为在 Linux、Mac OS 和带有 VirtualBox >= 6.1.28 的 Oracle Solaris 上,默认情况下,主机网络只允许 192.68.56.0/21 范围内的 IP 地址。然而 docker-machine 指定创建(VBoxManage hostonlyif ipconfig vboxnet0 —ip192.168.99.1 —netmask 255.255.255.0)192.168.99.1/24 的网段,这就会导致创建失败,报错信息如下图

image-20231004025034935

当我们执行上面三条命令都成功之后可以用 docker-machine ls 看到 docker-machine 管理的三台虚拟机

image-20231004035951487

创建 Swarm 集群: #

现在我们已经有了三台服务器,在开始我们后面的操作之前我们先介绍一下 Swarm 中节点的角色信息。Docker Swarm 中有两种主要类型的节点角色:manager 节点和 worker 节点。这些节点在 Swarm 集群中扮演不同的角色和职责:

  1. Manager 节点
    • Leader Manager: 在 Swarm 集群中只有一个 leader manager,负责集群管理、任务调度、控制平面操作等。Leader manager 由 Raft 一致性算法选举产生,确保高可用性。
    • Manager: Swarm 集群可以有多个 manager 节点,但只有一个 leader。Manager 负责与 Docker CLI 交互、集群管理、服务创建、配置变更、授权等操作。Manager 节点具有与 worker 节点相同的功能,并且可以运行服务容器。
  2. Worker 节点
    • Worker: Worker 节点是运行服务容器的节点。它们接受来自 manager 节点的任务分配,并负责在节点上运行服务。Worker 节点不参与 Swarm 集群的管理或决策。

这些节点角色组合在一起,形成了 Docker Swarm 集群。Manager 节点用于集群管理、任务调度和控制平面操作,而 worker 节点用于运行应用程序服务容器。在高可用性集群中,可以有多个 manager 节点以确保容错性和可用性,但只有一个是 leader。

img

下面在其中一个虚拟机上初始化 Docker Swarm 集群,这里我们选择的是 node1,并且选择它作为 Swarm Manager:

docker-machine ssh node1
docker swarm init --advertise-addr <MANAGER_IP>

<MANAGER_IP> 是 node1 虚拟机的 IP 地址。执行上述命令后我们将获得一个命令用于加入其他节点到 Swarm 集群,如下图所示。

image-20231004040140850

然后我们加入其他虚拟机到 Swarm 集群,在其他虚拟机上执行 Swarm Manager 给出的加入命令。在 node2 和 node3 上执行类似以下命令:

docker-machine ssh node2
docker swarm join --token <TOKEN> <MANAGER_IP>:2377

< TOKEN > 是 Swarm Manager 给出的令牌,<MANAGER_IP> 是 Swarm Manager 的 IP 地址。执行结果如下图所示

image-20231004040332519

然后我们用 docker node ls 可以看到集群中节点的状态信息,可以看到目前有三台机器,其中 ndoe1 是 manager 和 leader,node2 和 ndoe3 是 worker。

image-20231004040901563

部署服务到 Swarm 集群 #

我们已经搭建好了集群,下一步就是给这个集群中添加业务。这里我们用我练习 docker 官网教程时的一个镜像作为例子来说明,这是一个类似备忘录的 Node.js web 项目,源代码可以用下面的命令获取。

git clone https://github.com/docker/getting-started-app.git

image-20231004052707954

首先下面的命令拉取镜像,在三台服务器上都执行这个命令。

docker pull albertwang1/getting-started:latest

image-20231004053514362

完成之后执行下面的命令创建服务

docker service create --name getting-started \
--replicas 2 \
--publish published=3000,target=3000 \
albertwang1/getting-started:latest

上述命令将创建一个名为 getting-started 的服务,创建我们宿主机的 3000 端口和容器 3000 端口的映射,使用我们刚刚拉取的镜像,并创建 2 个副本。然后使用下面的命令查看服务的状态

docker service ls
docker service ps

image-20231004060758396

我们可以看到这个服务被分配在了node1 和 node2上面,然后我们到 ndoe2 和 ndoe3 上去看可以发现已经有一个 albertwang1/getting-started:latest 的容器跑起来了,

image-20231004061030451

image-20231004061046253

这个时候我们访问 manager 节点的 ip:3000 就可以使用这个服务了,如下图所示

image-20231004061305270

如果我们访问 worker 节点的网址仍然可以使用这个服务

image-20231004061412511

到这里我们已经成功部署了集群的服务。但是很显然,我们现在的集群是存在着很大的问题的。因为我们只有一个 manager 节点。假如 manager 挂掉了,那整个集群也就瘫痪了。所以我们可以设置多个节点的角色为 manager,然后这些 manager 通过选举选出一个任期内的 leader。因为一致性方面采用的是 Raft 算法,所以推荐的 manager 数量是奇数个。如果你对 Raft 算法的细节感兴趣的话可以去MIT 6.824 的公开课里查找更多的细节。

我们下面再做一个实验,那就是停止 node3 的服务,然后把 ndoe3 的角色改为 manager。

我们先在 node3 上执行 docker swarm leave 让 node3 脱离集群,然后在 node1 上执行 docker swarm join-token manager 可以获得升为管理节点的令牌。

image-20231004064441688

接着在 node3 上执行这个令牌命令就可以设置 node3 的状态为 manager

image-20231004064613399

参考:

  • https://nowtime.cc/virtual-box/1584.html
  • Docker技术入门与实战(第3版)杨保华,戴王剑,曹亚仑 著

Last modified on 2023-10-03