Docker Swarm 服务部署,轻松实现负载均衡

  1. 初始化集群
  2. 服务部署
  3. 副本控制
  4. 负载均衡
  5. 滚动更新和归滚
  6. 节点管理
  7. 网络管理
  8. 存储管理
  9. 服务发现
  10. Ingress
  11. 其他命令
  12. Docker Swarm是 Docker 官方推出的容器编排工具,旨在解决 Docker Compose 单机使用的局限性,满足大规模分布式环境中高效、可靠、管理容器化应用的需求。
  13. 标准化和生态整合:Docker Swarm和Docker紧密集成,提供Docker CLI一致的使用,用户可用使用熟悉的Docker命令管理Swarm集群,降低了学习成本。
  14. 资源优化和负载均衡:Docker Swarm自动调度容器,根据定义的服务和策略优化资源利用,提供内置负载均衡,实现水平扩展和性能均衡。
  15. 集群化和高可用性:Docker Swarm可以实现容器在多台主机上建立集群部署,提高应用容错性和高可用性,内置恢复机制可以确保服务始终可用。
  16. 容器化管理需求:Docker Swarm提供自动化、集中化的管理,简化容器部署、扩容、缩容、更新、健康检查等操作,解决了手动管理的复杂性。

演示代码存于gitee.com/ft/docker-s... ,包含app代码,构建各版本镜像Dockerfile、compose-nginx.yaml(包含nginx proxy_pass配置文件)、compose.yaml等,可以克隆本地进行练习使用。

今天更新有点晚,由于内容有点多,花费时间有些久。各位见谅。

Docker Swarm与Docker Compose使用相同的docker-compose.yaml配置,在其上增加的Docker Swarm的独有功能。Docker Swarm不支持build属性,可以将构建好的镜像push到Docker Hub或私有仓库。如果仅在管理节点构建好镜像,未推送到所有节点可访问的公共仓库,当调度到工作节点时,无法拉取到镜像,服务将无法启动成功。

以下使用 1 个主节点(192.168.31.23)和 1 个工作节点(192.168.31.21),演示如何创建集群、加入集群、启动 Docker Swarm 服务、实现负载均衡以及通过标签实现亲和性。

使用Docker Swarm,可以进行如下操作:

1. 初始化集群

使用 Docker Swarm 初始化一个集群,包括设置管理节点(Manager)和工作节点(Worker)。通过运行 docker swarm init 命令创建一个 Swarm 集群:

csharp 复制代码
➜  ~ docker swarm init
Swarm initialized: current node (hq2zqriske8co4x2b5g2hncvx) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-6cg4dd01sppqhw2deo5h9inxzxho9gzvuarnh7euje2kpts1id-61dilhm0249oihe0wnu2g6xr0 192.168.31.23:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

运行此命令后,会生成一个令牌,使用这个令牌将其他服务器添加到 Swarm 集群中作为工作节点。直接在工作节点运行 docker swarm join --token ... 命令:

csharp 复制代码
➜  ~ docker swarm join --token SWMTKN-1-6cg4dd01sppqhw2deo5h9inxzxho9gzvuarnh7euje2kpts1id-61dilhm0249oihe0wnu2g6xr0 192.168.31.23:2377
This node joined a swarm as a worker.

此时,消息提示节点已作为工作节点加入 Swarm 集群。通过 docker node ls 命令查看集群中的节点:

bash 复制代码
➜  ~ docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
mquy418xgmsgh5jbrehyhbh0z     debian01   Ready     Active                          26.0.0
hq2zqriske8co4x2b5g2hncvx *   debian03   Ready     Active         Leader           26.0.1

2. 服务部署

定义并部署服务,每个服务可以包含多个容器实例。为部署一个服务,使用 Docker Compose 文件,如以下示例所示的 compose.yaml 文件:

yaml 复制代码
version: '3'
services:
  web:
    image: nginx:1.25
    ports:
      - "80:80"

使用 docker stack deploy 命令部署 Compose 文件中定义的服务:

arduino 复制代码
docker stack deploy -c compose.yaml hello

这将在集群中部署一个名为 "web" 的服务,使用 Nginx 镜像,并将主机的 80 端口映射到容器的 80 端口。使用 curl localhost:80 进行测试。

3. 副本控制

为服务设定所需的副本数(Replicas),Swarm 将自动确保指定数量的容器实例始终保持运行。使用以下命令设置服务的副本数:

ini 复制代码
docker service scale hello=2

输出如下:

ini 复制代码
➜  ~ docker service scale hello_web=2
hello_web scaled to 2
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service hello_web converged

将 "hello_web" 服务的副本数设置为 2,Swarm 将自动启动或停止容器实例以满足指定的副本数。等待一段时间,让 Swarm 自动调节到设置的副本数。通过 curl 192.168.31.21curl 192.168.31.23 访问节点 IP 地址,发现都可以看到 Nginx 默认页面,表明 Docker Swarm 已按要求的副本数成功部署。

4. 负载均衡

Swarm 内置了负载均衡机制,可以自动为服务分配虚拟 IP(VIP)或使用 DNS 轮询(DNS Round-Robin)方式,将外部客户端的请求分发到服务的不同实例。通过 docker service create 命令创建一个具有负载均衡的服务。当 endpoint_mode 设置为 vip 时,Docker Swarm 会为服务分配一个虚拟 IP(VIP)地址。客户端通过这个 VIP 地址访问服务,Swarm 内部则使用 IPVS 或 iptables 等技术将请求透明地分发到服务的各个容器实例上。

修改之前的 compose.yaml 文件,使用 dockerswarmdemo-app:latest 替换 Nginx,该镜像是使用 Go 编写的 demo,用于获取服务器 IP:

yaml 复制代码
version: '3.8'
services:
  app:
    image: dockerswarmdemo-app:latest
    ports:
      - 3003:3003
    deploy:
      mode: replicated
      replicas: 2
      endpoint_mode: vip

使用 docker stack deploy -c compose.yaml hellogo 命令部署,稍等片刻,Docker Swarm 将根据 compose.yaml 的设定启动 2 个副本。查看容器列表:

bash 复制代码
➜  DockerSwarmDemo git:(main) docker ps
CONTAINER ID   IMAGE                        COMMAND                  CREATED          STATUS                    PORTS                                       NAMES
64447d6d52af   dockerswarmdemo-app:latest   "/bin/sh -c ./app"       10 minutes ago   Up 10 minutes             3003/tcp                                    hellogo3_app.1.i2gyvwhveas9awuwgk7y96h0a
36f947e42095   dockerswarmdemo-app:latest   "/bin/sh -c ./app"       12 minutes ago   Up 12 minutes             3003/tcp                                    hellogo3_app.2.qnfunvio51beb2lh0cvb93pht

使用 docker service inspect 获取 Docker Swarm 为 hellogo_app 分配的 VIP IP:

yaml 复制代码
➜  DockerSwarmDemo git:(main) docker service inspect --format '{{range $p := .Endpoint.VirtualIPs}}{{println $p.Addr}}{{end}}' hellogo_app
10.0.0.46/24
10.0.4.2/24

进入其中一个容器的 shell:

bash 复制代码
➜  DockerSwarmDemo git:(main)  docker exec -it hellogo3_app.1.i2gyvwhveas9awuwgk7y96h0a sh
/app # apk add curl
/app # curl 10.0.4.2:3003
{"server_ip":"10.0.4.15"}/app #
/app # curl 10.0.4.2:3003
{"server_ip":"10.0.4.4"}/app #
/app # curl 10.0.4.2:3003
{"server_ip":"10.0.4.15"}/app #
/app # curl 10.0.4.2:3003
{"server_ip":"10.0.4.4"}/app #
/app # curl 10.0.4.2:3003
{"server_ip":"10.0.4.15"}/app

结果显示,每次访问的服务器 IP 在 10.0.4.15 和 10.0.4.4 之间轮询。

5. 滚动更新和回滚

轻松进行服务版本升级,支持滚动更新策略(如分批更新、延迟时间等),并在出现问题时快速回滚到先前版本。

➜  ~ docker images
REPOSITORY                  TAG                IMAGE ID       CREATED          SIZE
dockerswarmdemo-app         v2                 640c0a108907   6 minutes ago    18.1MB
dockerswarmdemo-app         v1                 483a682ee82a   7 minutes ago    18.1MB

滚动更新

使用docker service update命令来更新服务

sql 复制代码
docker service update --image <新镜像> <服务名称>

将出发滚动更新,并将服务的容器副本逐步更新为指定镜像,在不停止服务的情况下进行更新。

sql 复制代码
➜  DockerSwarmDemo git:(main) docker service update --image dockerswarmdemo-app:v2 hellogo_app
image dockerswarmdemo-app:v2 could not be accessed on a registry to record
its digest. Each node will access dockerswarmdemo-app:v2 independently,
possibly leading to different nodes running different
versions of the image.

hellogo_app
overall progress: 1 out of 2 tasks
1/2: running   [==================================================>]
2/2: preparing [=================================>                 ]

回滚

dockerswarmdemo-app 镜像构建两个版本。首先使用 docker stack deploy -c compose.yaml hellogo 启动 v1 版本的服务。接着更新 compose.yaml 中的镜像版本为 v2,并再次运行 docker stack deploy -c compose.yaml hellogo 更新现有服务版本为 v2。

当前运行的服务版本

v1

v2  * 当前运行中的版本

使用命令docker service rollback hellogo_app将回滚到前一个版本`,即为v1版本。

sql 复制代码
➜  DockerSwarmDemo git:(main) docker service ls
ID             NAME          MODE         REPLICAS   IMAGE                    PORTS
1fwuf3nfi8ef   hellogo_app   replicated   1/2        dockerswarmdemo-app:v2   *:3003->3003/tcp
➜  DockerSwarmDemo git:(main) docker service rollback hellogo_app
hellogo_app
rollback: manually requested rollback
overall progress: rolling back update: 0 out of 2 tasks                                                                 1/2:
2/2: preparing [=================================>                 ]
service rollback paused: update paused due to failure or early termination of task wv0y6sptgahkwuiewx4v5oues
➜  DockerSwarmDemo git:(main) docker service ls
ID             NAME          MODE         REPLICAS   IMAGE                    PORTS
1fwuf3nfi8ef   hellogo_app   replicated   2/2        dockerswarmdemo-app:v1   *:3003->3003/tcp

当前运行的服务版本

v1 * 当前运行中的版本

v2

6. 节点管理

添加或移除节点、查看节点状态、设置节点约束与亲和性规则,以控制服务在特定节点上的分布。

csharp 复制代码
docker swarm join  // 加入节点
docker node rm <node-name|node-id>  // 移除节点
docker node ls  // 查看节点状态
docker node update --label-add [key=value] <node-name|node-id>  // 设置节点标签,用于运行指定部署时,为服务指定节点标签,指定服务我们指定节点运行

    deploy:
      mode: replicated
      replicas: 1
      endpoint_mode: vip
      placement:
        constraints: # 添加条件约束
          - node.labels.role==web

7. 网络管理

创建和管理覆盖网络(Overlay Networks),实现跨节点的容器间通信,以及为服务提供统一的网络命名空间。

可以通过命令overlay查看,使用Docker Swarm启动的服务使用的驱动为overlay类型。

sql 复制代码
➜  ~ docker network ls
NETWORK ID     NAME                  DRIVER    SCOPE
js0c41lnvw7e   hellogo_default       overlay   swarm

8. 存储管理

配置持久化存储卷(Volumes),确保服务数据在容器迁移或重启时得以保留。在集群中最好使用网络存储,NFS(Network File System)、ceph及者云厂商提供的相关存储类产品。

9. 服务发现

内置的服务发现机制允许服务间通过服务名进行互相访问,无需关心具体的 IP 地址和端口变化。

例如 :使用Nginx反向代理hellogo_app服务。

我们不需要知道hellogo_app服务的IP,在没启动服务前,我们也不知道,在Nginx中添加配置即可代理到后端,hellogo_app运行了2个副本。Nginx即默认为我们实现了负载均衡。

arduino 复制代码
 location / {
        proxy_pass http://hellogo_app:3003/;
 }

hellogo_app会替换为实际hellogo_app服务的IP地址。

10. Ingress

Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

只启动hellogo_app,创建副本数2

lua 复制代码
docker service create \
  --name hellogo_app \
  --replicas 2 \
  --publish mode=ingress,target=3003 \
  dockerswarmdemo-app:latest

使用docker service create命令,创建服务名hellogo_app,副本数2个,用 Ingress 模式将服务内部的端口 3003 发布到外部。外部访问端口由 Swarm 自动分配,并通过 Ingress 网络进行负载均衡。使用镜像dockerswarmdemo-app:latest

css 复制代码
docker service inspect --format '{{ .Endpoint.Ports }}' hellogo_app
[{ tcp 3003 30000 ingress}]

可以看到我们容器内部的端口为3003,外部访问的端口为30000。

csharp 复制代码
➜  ~ curl http://192.168.31.21:30000/
{"server_ip":"10.0.0.21"}#
➜  ~ curl http://192.168.31.21:30000/
{"server_ip":"10.0.0.20"}#
➜  ~ curl http://192.168.31.21:30000/
{"server_ip":"10.0.0.21"}#
➜  ~ curl http://192.168.31.21:30000/
{"server_ip":"10.0.0.20"}#

使用任何节点IP+PORT都可以访问,提供curl访问可以看出,每次IP会在2个副本之间进行轮询访问。

11. 其他命令

docker swarm leave 工作节点执行,将离开Docker Swarm集群。

docker swarm leave --force只有 一个管理节点执行,将失去Docker Swarm集群管理能力。Docker Swarm相关都会停止、断开。

docker service ls 查看Docker Swarm集群中服务,包含ID、名称、模式、副本数、镜像名称、端口映射。

docker service rm <Service ID|Service Name> 删除指定服务。

docker service logs <Service ID|Service Name> 输出指定服务日志。

docker service inspect <Service ID|Service Name> 显示服务详细信息,可使用-f筛选指定内容。

docker service scale <Service Name>=副本数量 缩容或扩容一个服务。

docker create 根据命令参数创建一个服务,可以使用docker service create --help了解。

docker update 根据命令参数更新一个服务,可以使用docker service update --help了解。

docker service rollback 命令用于将服务回滚到之前的一个版本。

docker swarm join-token <worker|manager> 命令获取的相应类型(Worker或Manager)的令牌。

Docker Swarm 是 Docker 官方推出的容器编排解决方案,旨在应对大规模分布式环境下的容器管理挑战,通过提供标准化的接口、强大的资源调度、高可用集群架构以及便捷的容器生命周期管理,极大地简化了容器化应用的部署、扩展和维护过程。

读完后,忍不住要加个关注!不是我吹,但你会后悔没关注的!

相关推荐
雪域迷影8 小时前
PostgreSQL Docker Error – 5432: 地址已被占用
数据库·docker·postgresql
福大大架构师每日一题9 小时前
22.1 k8s不同role级别的服务发现
容器·kubernetes·服务发现
莹雨潇潇9 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
tangdou36909865510 小时前
1分钟搞懂K8S中的NodeSelector
云原生·容器·kubernetes
tangdou36909865513 小时前
Docker系列-5种方案超详细讲解docker数据存储持久化(volume,bind mounts,NFS等)
docker·容器
later_rql13 小时前
k8s-集群部署1
云原生·容器·kubernetes
漫无目的行走的月亮16 小时前
在Docker中运行微服务注册中心Eureka
docker
大G哥18 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
大道归简19 小时前
Docker 命令从入门到入门:从 Windows 到容器的完美类比
windows·docker·容器
zeruns80219 小时前
如何搭建自己的域名邮箱服务器?Poste.io邮箱服务器搭建教程,Linux+Docker搭建邮件服务器的教程
linux·运维·服务器·docker·网站