Docker学习系列|Docker学习十(Docker Swarm)

一、Swarm介绍
Swarm 是 Docker 官方推出的容器集群管理工具,最大的优势之一就是原生支持 Docker API,原来的 Docker 用户可以很方便地将服务迁移到 Swarm 中来。
Swarm 还内置了对 Docker 网络插件的支持,因此用户可以很方便地部署需要跨主机通信的容器集群。
除此之外,Swarm还有以下优点:

  • 分布式: Swarm 使用Raft(一种分布式一致性协议)协议来做集群间数据一致性保障,使用多个容器节点组成管理集群,从而避免单点故障。
  • 安全: Swarm 使用 TLS 双向认证来确保节点之间通信的安全,它可以利用双向 TLS 进行节点之间的身份认证,角色授权和加密传输,并且可以自动执行证书的颁发和更换。
  • 简单: Swarm 的操作非常简单,并且除 Docker 外基本无其他外部依赖,而且从 Docker 1.12 版本后, Swarm 直接被内置到了 Docker 中,可以说真正做到了开箱即用。
1. Swarm 的架构 Swarm 的架构整体分为管理节点(Manager Nodes)和工作节点(Worker Nodes):
  • 管理节点: 管理节点负责接受用户的请求,用户的请求中包含用户定义的容器运行状态描述,然后 Swarm 负责调度和管理容器,并且努力达到用户所期望的状态。
  • 工作节点: 工作节点运行执行器(Executor),负责执行具体的容器管理任务(Task),例如容器的启动、停止、删除等操作。
Docker学习系列|Docker学习十(Docker Swarm)
文章图片
2. 核心概念 a. Swarm 集群 一组被 Swarm 统一管理和调度的节点,被 Swarm纳管的节点可以是物理机或者虚拟机。其中一部分节点作为管理节点,负责集群状态的管理和协调,另一部分作为工作节点,负责执行具体的任务来管理容器,实现用户服务的启停等功能。
b. 节点 Swarm 集群中的每一台物理机或者虚拟机称为节点。节点按照工作职责分为管理节点和工作节点,管理节点由于需要使用 Raft 协议来协商节点状态,生产环境中通常建议将管理节点的数量设置为奇数个,一般为 3 个、5 个或 7 个。
c. 服务 服务是为了支持容器编排所提出的概念,它是一系列复杂容器环境互相协作的统称。一个服务的声明通常包含容器的启动方式、启动的副本数、环境变量、存储、配置、网络等一系列配置,用户通过声明一个服务,将它交给 Swarm,Swarm 负责将用户声明的服务实现。
服务分为全局服务(global services)和副本服务(replicated services):
  • 全局服务:每个工作节点上都会运行一个任务,类似于 Kubernetes 中的 Daemonset。
  • 副本服务:按照指定的副本数在整个集群中调度运行。
d. 任务 集群中的最小调度单位,它包含一个真正运行中的 Docker 容器。当管理节点根据服务中声明的副本数将任务调度到节点时,任务则开始在该节点启动和运行,当节点出现异常时,任务会运行失败。此时调度器会把失败的任务重新调度到其他正常的节点上正常运行,以确保运行中的容器副本数满足用户所期望的副本数。
e. 服务外部访问 由于容器的 IP 只能在集群内部访问到,而且容器又是用后马上销毁,这样容器的 IP 也会动态变化,因此容器集群内部的服务想要被集群外部的用户访问到,服务必须要映射到主机上的固定端口。
Swarm 使用入口负载均衡(ingress load balancing)的模式将服务暴露在主机上,该模式下,每一个服务会被分配一个公开端口(PublishedPort),你可以指定使用某个未被占用的公开端口,也可以让 Swarm 自动分配一个。
Swarm 集群的公开端口可以从集群内的任意节点上访问到,当请求达到集群中的一个节点时,如果该节点没有要请求的服务,则会将请求转发到实际运行该服务的节点上,从而响应用户的请求。
二、搭建Swarm 集群
【Docker学习系列|Docker学习十(Docker Swarm)】前提条件:
  • Docker 版本大于 1.12,推荐使用最新稳定版 Docker;
  • 主机需要开放一些端口(TCP:2377 UDP:4789 TCP 和 UDP:7946)。
  • 生产环境中推荐使用至少三个 manager 作为管理节点
1. 初始化集群 为了简化,这里仅是有一个manager管理节点
# 初始化 Swarm集群 docker swarm init --advertise-addr Swarm initialized: current node (1ehtnlcf3emncktgjzpoux5ga) is now a manager.To add a worker to this swarm, run the following command:docker swarm join --token SWMTKN-1-1kal5b1iozbfmnnhx3kjfd3y6yqcjjjpcftrlg69pm2g8hw5vx-8j4l0t2is9ok9jwwc3tovtxbp 192.168.31.100:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.# advertise-addr 一般用于主机有多块网卡的情况,如果你的主机只有一块网卡,可以忽略此参数 # 打印信息中,提示了如何把一台主机加入集群成为工作节点

2. 加入工作节点
# 复制初始化集群时,提示的加入工作节点命令,分别在工作节点上执行 $ docker swarm join --token SWMTKN-1-1kal5b1iozbfmnnhx3kjfd3y6yqcjjjpcftrlg69pm2g8hw5vx-8j4l0t2is9ok9jwwc3tovtxbp 192.168.31.100:2377 This node joined a swarm as a worker.# 如果是生产环境,可以使用docker swarm join-token manager命令来查看如何加入管理节点 $ docker swarm join-to ken manager To add a manager to this swarm, run the following command:docker swarm join --token SWMTKN-1-1kal5b1iozbfmnnhx3kjfd3y6yqcjjjpcftrlg69pm2g8hw5vx-8fq89jxo2axwggryvom5a337t 192.168.31.100:2377# 复制 Swarm 输出的结果即可加入管理节点到集群中

3. 节点查看
# 查看当前节点的状态 $ ]# docker node ls IDHOSTNAMESTATUSAVAILABILITYMANAGER STATUSENGINE VERSION 1ehtnlcf3emncktgjzpoux5ga *swarm-managerReadyActiveLeader19.03.12 pn7gdm847sfzydqhcv3vma97y *swarm-node1ReadyActive19.03.12 4dtc9pw5quyjs5yf25ccgr8uh *swarm-node2ReadyActive19.03.12 est7ww3gngna4u7td22g9m2k5 *swarm-node3ReadyActive19.03.12 # 当前集群包含 1 个管理节点,3 个工作节点

三、使用 Swarm
1. 通过 docker service 命令创建服务
# 创建服务 $ docker service create --replicas 1 --name hello-world nginx 24f9ng83m9sq4ml3e92k4g5by overall progress: 1 out of 1 tasks 1/1: running[==================================================>] verify: Service converged# 查看已经启动的服务 $ docker service ls IDNAMEMODEREPLICASIMAGEPORTS 24f9ng83m9sqhello-worldreplicated1/1nginx:latest# 删除服务 $ docker service rm hello-world hello-world

更多的docker service命令的相关操作,可以参考这里。
2. 通过 docker stack 命令创建服务 修改前述章节提到的docker-compose 的模板文件,添加了deploy 指令,并且指定使用副本服务(replicated)的方式启动两个 WordPress 实例
version: '3'services: mysql: image: mysql:5.7 volumes: - mysql_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: mywordpress MYSQL_USER: mywordpress MYSQL_PASSWORD: mywordpresswordpress: depends_on: - mysql image: wordpress:php7.4 deploy: mode: replicated replicas: 2 ports: - "8080:80" restart: always environment: WORDPRESS_DB_HOST: mysql:3306 WORDPRESS_DB_USER: mywordpress WORDPRESS_DB_PASSWORD: mywordpress WORDPRESS_DB_NAME: mywordpress volumes: mysql_data: {}

在 /tmp 目下新建 docker-compose.yml 文件,并且写入以上的内容。使用以下命令启动服务:
$ docker stack deploy -c docker-compose.yml wordpress Ignoring unsupported options: restartCreating network wordpress_default Creating service wordpress_mysql Creating service wordpress_wordpress

以上命令执行后,将会启动两个服务:
  • MySQL服务,默认启动一个副本
  • WordPress服务,根据compose模板的定义启动了两个副本
# 查看启动的服务: $ docker service ls IDNAMEMODEREPLICASIMAGEPORTS v8i0pzb4e3tcwordpress_mysqlreplicated1/1mysql:5.7 96m8xfyeqzr5wordpress_wordpressreplicated2/2wordpress:php7.4*:8080-> 80/tcp

    推荐阅读