目录

1、什么是Docker Swarm

2、Docker Swarm 基本结构图

3、swarm的几个关键概念

4、Dcoker Swarm 集群部署

4.1、准备工作

4.2、创建Swarm并添加节点

4.2.1、创建Swarm集群

4.2.2、查看集群相关信息

4.2.3、添加节点主机到Swarm集群

4.3、部署服务 

4.4、内容扩展

4.4.1、扩充服务

4.4.2、改变节点node状态

4.5、怎么体现swarm的高可用性

4.6、swarm是怎么的node通信的

4.7、主机之间的开放协议和端口

4.8、克隆

4.9、退群服务

4.10、滚动升级

4.11、swarm查看token命令

5、多服务部署

6、Swarm的调度策略


1、什么是Docker Swarm

Swarm是Docker公司推出的用来管理docker集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/swarm, 它是将一群Docker宿主机变成一个单一的虚拟主机,Swarm使用标准的Docker API接口作为其前端的访问入口,换言之,各种形式的Docker

Client(compose,docker-py等)均可以直接与Swarm通信,甚至Docker本身都可以很容易的与Swarm集成,这大大方便了用户将原本基于单节点的系统移植到Swarm上,同时Swarm内置了对Docker网络插件的支持,用户也很容易的部署跨主机的容器集群服务。

  Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。

从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。

  Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受Docker客户端发来的请求,调度适合的节点来运行容器,这就意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,放Swarm重新恢复运行之后,他会收集重建集群信息。

2、Docker Swarm 基本结构图

docker swarm portainer 配置agent_swarm

在结构图可以看出 Docker Client使用Swarm对 集群(Cluster)进行调度使用。

上图可以看出,Swarm是典型的master-slave结构,通过发现服务来选举manager。manager是中心管理节点,各个node上运行agent接受manager的统一管理,集群会自动通过Raft协议分布式选举出manager节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了DNS的负载均衡和对外部负载均衡机制的集成支持

3、swarm的几个关键概念

1.Swarm

集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm

2.Node

一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。

要将应用程序部署到swarm,请将服务定义提交给管理器节点。管理器节点将称为任务的工作单元分派给工作节点。

Manager节点还执行维护所需群集状态所需的编排和集群管理功能。Manager节点选择单个领导者来执行编排任务。

工作节点接收并执行从管理器节点分派的任务。默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。

3.Service

一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建服务时,你需要指定要使用的容器镜像。

4.Task

任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点

4、Dcoker Swarm 集群部署

机器环境(三台机器,centos系统)

IP:192.168.29.137主机名:manager 担任角色:swarm manager

IP:192.168.29.138 主机名:worker138 担任角色:swarm node

IP:192.168.29.140 主机名:worker140 担任角色:swarm node

若是没有这么多机器可以进行克隆,后边有克隆步骤。另外系统不一样也可以做这个实验,比如可以用centos和Ubuntu混合使用,只要是docker版本一样就行。补充说明:这个实验因为一些原因,138这个IP地址改为了139,但是前边还是没有修改138.

4.1、准备工作

(1)配置hosts文件(可配置可不配置)

[root@manager ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.29.137 manager
192.168.29.138 woker138
192.168.29.132 ubuntu-worker

可以使用使用scp复制到node主机或者直接粘贴

[root@manager ~]# scp /etc/hosts root@192.168.29.137:/etc/hosts
[root@manager ~]# scp /etc/hosts root@192.168.29.140:/etc/hosts

(2)设置防火墙

关闭三台机器上的防火墙。如果开启防火墙,则需要在所有节点的防火墙上依次放行2377/tcp(管理端口)、7946/udp(节点间通信端口)、4789/udp(overlay 网络端口)端口。

[root@manager ~]# systemctl disable firewalld.service # 设置开机不要启动

[root@manager ~]# systemctl stop firewalld.service  # 关闭防火墙

最后要重启一下docker,"service docker restart"

4.2、创建Swarm并添加节点

4.2.1、创建Swarm集群

[root@manager ~]# docker swarm init --advertise-addr 192.168.29.137
Swarm initialized: current node (ztges80xx463woqzho8mh38ry) is now a manager.

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

    docker swarm join --token SWMTKN-1-3dc6q0868anw9f1aeb1b1rej97qs7p7wt2lblhejwjr5yfebfw-18swh7q3tul2clkhh3iaemff2 192.168.29.137:2377

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

# 那个token整段就是添加节点的方式(要保存初始化后token,因为在节点加入时要使用token作为通讯的密钥)

上面命令执行后,该机器自动加入到swarm集群。这个会创建一个集群token,获取全球唯一的 token,作为集群唯一标识。后续将其他节点加入集群都会用到这个token值。
其中,--advertise-addr参数表示其它swarm中的worker节点使用此ip地址与manager联系。命令的输出包含了其它节点如何加入集群的命令。 

若是出现"This node is already part of a swarm"的错误

# 在次执行上面的命令,回报下面的错误
[root@manager ~]# docker swarm init --advertise-addr 192.168.31.43
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
# 解决方法
[root@manager ~]# docker swarm leave -f
这里的leave就是在集群中删除节点,-f参数强制删除,执行完在重新执行OK

4.2.2、查看集群相关信息

[root@manager ~]# docker info
上面的命令执行后 找到Swarm的关键字,就可以看到相关信息了
 
[root@manager ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
3jcmnzjh0e99ipgshk1ykuovd *   manager           Ready               Active              Leader              18.06.0-ce
上面的命令是查看集群中的机器(注意上面node ID旁边那个*号表示现在连接到这个节点上)

4.2.3、添加节点主机到Swarm集群

# 192.168.29.138
[root@worker138 ~]# docker swarm join --token SWMTKN-1-3dc6q0868anw9f1aeb1b1rej97qs7p7wt2lblhejwjr5yfebfw-18swh7q3tul2clkhh3iaemff2 192.168.29.137:2377
This node joined a swarm as a worker.

# 192.168.29.140
root@ubuntu-worker:/home/fmy# docker swarm join --token SWMTKN-1-3dc6q0868anw9f1aeb1b1rej97qs7p7wt2lblhejwjr5yfebfw-18swh7q3tul2clkhh3iaemff2 192.168.29.137:2377
This node joined a swarm as a worker.

再次查看集群的状态

[root@manager ~]# docker node ls
ID                            HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
ztges80xx463woqzho8mh38ry *   manager         Ready     Active         Leader           20.10.14
wmpm7hcyq3xd3blv61y5smnbv     worker138       Ready     Active                          20.10.14
3l65w49j8noy7wi52j4j37bd6     worker140       Ready     Active                          20.10.14

4.3、部署服务 

[root@manager ~]# docker service create --replicas 10 --name  fan-web -p 8089:80 nginx
je4r0ssln7jqeunzk6h1jfd75
overall progress: 10 out of 10 tasks 
1/10: running   
2/10: running   
3/10: running   
4/10: running   
5/10: running   
6/10: running   
7/10: running   
8/10: running   
9/10: running   
10/10: running   
verify: Service converged   
[root@manager ~]# docker service ps fan-web
ID             NAME         IMAGE          NODE        DESIRED STATE   CURRENT STATE                ERROR     PORTS
rjiee3xwmzyx   fan-web.1    nginx:latest   worker140   Running         Running about a minute ago             
8g23xziwpee5   fan-web.2    nginx:latest   manager     Running         Running about a minute ago             
shvf0xu2i7ii   fan-web.3    nginx:latest   worker138   Running         Running about a minute ago             
ydo6089yaeov   fan-web.4    nginx:latest   worker140   Running         Running about a minute ago             
taux4cbtk12m   fan-web.5    nginx:latest   manager     Running         Running about a minute ago             
jqs3jebvc0d5   fan-web.6    nginx:latest   worker138   Running         Running about a minute ago             
5r2eapyjv4l4   fan-web.7    nginx:latest   worker138   Running         Running about a minute ago             
ltr498p57one   fan-web.8    nginx:latest   worker140   Running         Running about a minute ago             
j8w208st3zw0   fan-web.9    nginx:latest   manager     Running         Running about a minute ago             
aqb2tt475o9f   fan-web.10   nginx:latest   manager     Running         Running about a minute ago

注意:不需要提前在节点上下载nginx镜像,这个命令执行后会自动下载这个容器镜像

[访问服务]

[root@manager ~]# ss -anplut|grep 8089
tcp    LISTEN     0      128    [::]:8089               [::]:*                   users:(("dockerd",pid=1212,fd=35))
[root@manager ~]# curl 192.168.29.137:8089  # 访问宿主机的真实IP地址
<!DOCTYPE html>
<html>
<head>
....

4.4、内容扩展

问题:所有worker节点上都没有alpine镜像,worker节点是否会自动pull?

10副本如何分配,manager上是否会分有容器?

# manager
[root@manager my_worldpress]# docker service ls
ID             NAME         MODE         REPLICAS   IMAGE           PORTS
y4cp3k9cdrql   helloworld   replicated   10/10      alpine:latest   
[root@manager my_worldpress]# docker ps
CONTAINER ID   IMAGE           COMMAND             CREATED         STATUS         PORTS     NAMES
6052187f7d25   alpine:latest   "ping docker.com"   5 minutes ago   Up 5 minutes             helloworld.5.rkncniakntcp580wfcptget77
45ee458b5de5   alpine:latest   "ping docker.com"   5 minutes ago   Up 5 minutes             helloworld.4.ws2xg6g0nq6ztptoznxgcsekg
bd9c093b1b0d   alpine:latest   "ping docker.com"   5 minutes ago   Up 5 minutes             helloworld.1.ilxps6mac6ifyfdr46b4ewu4g
40d808403b12   alpine:latest   "ping docker.com"   5 minutes ago   Up 5 minutes             helloworld.7.yzwp7jcomsehng5pobz6a17ke
b2f1c8c934d5   alpine:latest   "ping docker.com"   5 minutes ago   Up 5 minutes             helloworld.6.89rvlqvxrhzrxkie994vyc79u


# worker138
[root@worker138 my_worldpress]# docker ps
CONTAINER ID   IMAGE           COMMAND             CREATED         STATUS         PORTS     NAMES
954f6c5df9b6   alpine:latest   "ping docker.com"   2 minutes ago   Up 2 minutes             helloworld.8.l81ge64jk3w12fnvrdkn4qrwm
56faae5c7fd6   alpine:latest   "ping docker.com"   2 minutes ago   Up 2 minutes             helloworld.10.jadl1232tiwnly0nor44txl95
9537332db34b   alpine:latest   "ping docker.com"   2 minutes ago   Up 2 minutes             helloworld.2.dnk7kg9l6dtctpn44a4l85r6j
3b92d4ea075f   alpine:latest   "ping docker.com"   2 minutes ago   Up 2 minutes             helloworld.9.osizqu5qawdxmx5ei8uz0eis7
38cb4b2a8cbb   alpine:latest   "ping docker.com"   2 minutes ago   Up 2 minutes             helloworld.3.gexgn9bhgmcvq36v533x0n13w

4.4.1、扩充服务

[root@manager ~]# docker service scale fan-web=20  # 服务扩容到20个

4.4.2、改变节点node状态

[root@manager ~]# docker node ls
ID                            HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
ztges80xx463woqzho8mh38ry *   manager         Ready     Active         Leader           20.10.14
k3djhdjmn4eqwg2wizus0ut4h     ubuntu-worker   Ready     Active                          20.10.14
wmpm7hcyq3xd3blv61y5smnbv     worker138       Ready     Active                          20.10.14

[root@manager ~]# docker node update --availability drain ubuntu-worker
ubuntu-worker

[root@manager ~]# docker node ls 
ID                            HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
ztges80xx463woqzho8mh38ry *   manager         Ready     Active         Leader           20.10.14
k3djhdjmn4eqwg2wizus0ut4h     ubuntu-worker   Ready     Drain                           20.10.14
wmpm7hcyq3xd3blv61y5smnbv     worker138       Ready     Active                          20.10.14

4.5、怎么体现swarm的高可用性

只有ready状态的节点,才能够运行服务。若是关掉一个node,那么这个node的服务会转移到别的node里边,保证服务能够继续正常的运行。当再次开启这个node的时候,不会返回旧的服务。

4.6、swarm是怎么的node通信的

通过7946端口

4.7、主机之间的开放协议和端口

以下端口必须可用。在某些系统上,默认情况下这些端口是打开的。

  • TCP端口2377用于群集管理通信,管理端口
  • 传输控制协议UDP端口7946用于节点间的通信,即宿主机之间通信
  • UDP端口4789对于覆盖网络流量,容器的overlay网络使用,即容器之间通信

如果你计划创建一个加密覆盖网络(--opt encrypted),您还需要确保ip协议50 (静电除尘器)允许通行

[root@manager ~]# ss -anplut
Netid  State      Recv-Q Send-Q       Local Address:Port                      Peer Address:Port              
udp    UNCONN     0      0                        *:68                                   *:*                   users:(("dhclient",pid=3012,fd=6))
udp    UNCONN     0      0                127.0.0.1:323                                  *:*                   users:(("chronyd",pid=725,fd=5))
udp    UNCONN     0      0                        *:4789                                 *:*                  
udp    UNCONN     0      0                    [::1]:323                               [::]:*                   users:(("chronyd",pid=725,fd=6))
udp    UNCONN     0      0                     [::]:7946                              [::]:*                   users:(("dockerd",pid=1212,fd=26))
tcp    LISTEN     0      128                      *:22                                   *:*                   users:(("sshd",pid=1019,fd=3))
tcp    LISTEN     0      100              127.0.0.1:25                                   *:*                   users:(("master",pid=1241,fd=13))
tcp    LISTEN     0      128                   [::]:2377                              [::]:*                   users:(("dockerd",pid=1212,fd=20))
tcp    LISTEN     0      128                   [::]:7946                              [::]:*                   users:(("dockerd",pid=1212,fd=25))
tcp    LISTEN     0      128                   [::]:22                                [::]:*                   users:(("sshd",pid=1019,fd=4))
tcp    LISTEN     0      128                   [::]:8089                              [::]:*                   users:(("dockerd",pid=1212,fd=35))
tcp    LISTEN     0      100                  [::1]:25                                [::]:*                   users:(("master",pid=1241,fd=14))

4.8、克隆

docker swarm portainer 配置agent_swarm_02

 

docker swarm portainer 配置agent_swarm_03

 

docker swarm portainer 配置agent_swarm_04

 

docker swarm portainer 配置agent_nginx_05

 

docker swarm portainer 配置agent_Docker_06

4.9、退群服务

[root@manager ~]# docker node ls
ID                            HOSTNAME        STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
ztges80xx463woqzho8mh38ry *   manager         Ready     Active         Leader           20.10.14
k3djhdjmn4eqwg2wizus0ut4h     ubuntu-worker   Down      Drain                           20.10.14
wmpm7hcyq3xd3blv61y5smnbv     worker138       Ready     Active                          20.10.14
3l65w49j8noy7wi52j4j37bd6     worker140       Ready     Active                          20.10.14
[root@manager ~]# docker node rm  ubuntu-worker
ubuntu-worker
[root@manager ~]# docker node ls
ID                            HOSTNAME    STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
ztges80xx463woqzho8mh38ry *   manager     Ready     Active         Leader           20.10.14
wmpm7hcyq3xd3blv61y5smnbv     worker138   Ready     Active                          20.10.14
3l65w49j8noy7wi52j4j37bd6     worker140   Ready     Active                          20.10.14

4.10、滚动升级

先停一个旧版本的nginx容器,马上启动一个新版本的容器,然后交替完成。目的是更加稳定的升级

docker swarm portainer 配置agent_nginx_07

 原来版本

docker swarm portainer 配置agent_nginx_08

 升级服务

docker swarm portainer 配置agent_nginx_09

 过程查看,注意查看主机名

docker swarm portainer 配置agent_docker_10

docker swarm portainer 配置agent_docker_11

4.11、swarm查看token命令

Join tokens是允许一个节点加入集群的密钥。有两种可用的不同的join tokens,一个是用作worker角色,另一个是用作manager角色。在执行swarm join时使用–token来传递token。节点只在它们加入集群时才使用这个token。

常用命令:

  • swarm join-token :可以查看或更换join token。
  • docker swarm join-token worker:查看加入worker的命令。
  • docker swarm join-token manager:查看加入manager的命令
  • docker swarm join-token --rotate worker:重置woker的Token。
  • docker swarm join-token -q worker:仅打印Token。

5、多服务部署

问:上面我们只是对单独的一个nginx服务进行的集群部署,那如果要统一编排多个服务呢?
答:docker 三剑客中有个compose 这个就是对单机进行统一编排的,它的实现是通过docker-compose.yml的文件,这里我们就可以结合compose和swarm进行多服务的编排

温馨提示:

我们这里要部署的服务有三个(nginx服务,visualizer服务,portainer服务) 都是集群 GUI 管理服务

docker service部署的是单个服务,我们可以使用docker stack进行多服务编排部署

1) 编写docker-compose.yml文件

[root@manager swarm]# pwd
/composetest/swarm
[root@manager composetest]# mkdir swarm
[root@manager composetest]# cd swarm/
[root@manager swarm]# cat docker-compose.yml 
version: "3"
services:
  fan-nginx:    # 服务的名字
    image: nginx
    ports:
      - 8888:80
    # deploy,是部署的意思
    deploy:
    # replicated,是复制的意思
      mode: replicated
      relicpas: 10    # 副本的数量
  fan-reids:
    image: reids
    ports:
      - 8379:6379
    deploy:
      mode: replicated
      replicas: 6

2) 通过这个yml文件部署服务

[root@manager swarm]# docker stack deploy -c docker-compose.yml deploy_deamon
Creating network deploy_deamon_default
Creating service deploy_deamon_fan-nginx
Creating service deploy_deamon_fan-reids
[root@manager swarm]# docker stack ls
NAME            SERVICES   ORCHESTRATOR
deploy_deamon   2          Swarm

通过上面的执行过程可以看出这样创建会默认创建一个网络并使用它,名字都是我们给的名字的前缀加上服务名

[查看创建服务]

[root@manager swarm]# docker service ls  # 查看创建服务
ID             NAME                      MODE         REPLICAS   IMAGE          PORTS
8scmppd8s927   deploy_deamon_fan-nginx   replicated   10/10      nginx:latest   *:8888->80/tcp
jpgtqig65pa3   deploy_deamon_fan-reids   replicated   0/6        reids:latest   *:8379->6379/tcp
[root@manager swarm]# docker service ps  deploy_deamon_fan-nginx 
ID             NAME                         IMAGE          NODE        DESIRED STATE   CURRENT STATE           ERROR     PORTS
84zdpsftdtry   deploy_deamon_fan-nginx.1    nginx:latest   manager     Running         Running 2 minutes ago             
jnuhe3h1ouqa   deploy_deamon_fan-nginx.2    nginx:latest   worker138   Running         Running 2 minutes ago             
nhr7dcjtpu1h   deploy_deamon_fan-nginx.3    nginx:latest   worker138   Running         Running 2 minutes ago             
9vcgikzw7m6z   deploy_deamon_fan-nginx.4    nginx:latest   manager     Running         Running 2 minutes ago             
duh56hk8e5pu   deploy_deamon_fan-nginx.5    nginx:latest   worker140   Running         Running 2 minutes ago             
ffoljh2fw0ch   deploy_deamon_fan-nginx.6    nginx:latest   worker140   Running         Running 2 minutes ago             
jfstfwvq0xxd   deploy_deamon_fan-nginx.7    nginx:latest   worker140   Running         Running 2 minutes ago             
e9q0q496s4iw   deploy_deamon_fan-nginx.8    nginx:latest   worker138   Running         Running 2 minutes ago             
58zxtdkl6so7   deploy_deamon_fan-nginx.9    nginx:latest   manager     Running         Running 2 minutes ago             
li0551m63upb   deploy_deamon_fan-nginx.10   nginx:latest   worker138   Running         Running 2 minutes ago

6、Swarm的调度策略

Swarm在调度(scheduler)节点(leader节点)运行容器的时候,会根据指定的策略来计算最适合运行容器的节点,目前支持的策略有:spread, binpack, random.

1)Random

顾名思义,就是随机选择一个Node来运行容器,一般用作调试用,spread和binpack策略会根据各个节点的可用的CPU, RAM以及正在运行的容器的数量来计算应该运行容器的节点。

2)Spread

在同等条件下,Spread策略会选择运行容器最少的那台节点来运行新的容器,binpack策略会选择运行容器最集中的那台机器来运行新的节点。

使用Spread策略会使得容器会均衡的分布在集群中的各个节点上运行,一旦一个节点挂掉了只会损失少部分的容器。

3)Binpack

Binpack策略最大化的避免容器碎片化,就是说binpack策略尽可能的把还未使用的节点留给需要更大空间的容器运行,尽可能的把容器运行在一个节点上面。