Docker Swarm简介:

Docker Swarm是Docker的本地集群。它将Docker主机池变成单个虚拟Docker主机。由于Docker Swarm提供标准的Docker API,所有已经与Docker守护进程通信的工具都可以使用Swarm以透明地扩展到多个主机。

Docker - Swarm:

2014年底,Docker公司着手设计了一组容器的解决方案:MachineSwarmCompose。在这个方案中,Machine是用于主流虚拟机和云平台快速搭建和创建 Docker环境的工具,支持在创建的节点上自动部署Swarm。当时的Swarm是一款整合跨节点网络的集群式容器运维管理服务,它利用 Docker守护进程的 API ,将多节点的计算资源进行汇总,并将目标设置为Swarm服务的 IP 和端口,使得可以像操作单个节点的Docker 服务一样来操作整个容器集群。这种方式有先天性的局限性,比如在单节点 Docker中并没有为服务高可用而设计的副本集和负载均衡等概念,也不存在服务网络管理和跨节点数据存储的问题。

Docker - SwarmKit:

2016年2月,Docker公司启动了 SwarmKit项目,这个项目与 Swarm 相似,SwarmKit 从一开始就重新设计了一套独立的API和模型体系,并且采用了独立的客户端命令行工具: swarmctl,同时,Swarmkit将过去 Swarm所依赖的外部集群一致性存储组件 Etcd 的核心部分内置到了软件中,这样的结果是让使用者失去了极大的选择自由,却大大简化了集群的部署过程。

真正使得 SwarmKit项目为大家所熟知的事件是 Docker1.12版本开始提供一个一键创建容器集群的命令docker swarm,在这个后来被称之为 Swarm Mode的功能背后,正是 SwarmKit的功劳,DockerSwarmKit的核心模块内嵌在了 Docker后台的服务中。

SwarmKit的优点:

SwarmKit是一个用于协调任何规模分布式系统的工具包。它包括用于节点发现的基元,基于木筏的共识,任务调度等等。

其主要好处是:

  • 分布式SwarmKit使用Raft一致性算法来协调并且不依赖单个故障点来执行决策。
  • 安全:节点通信和Swarm中的成员身份是安全的。SwarmKit使用相互TLS进行节点身份验证角色授权传输加密,自动执行证书颁发和轮换。
  • 简单SwarmKit操作简单,并将基础设施依赖性降到最低。它不需要外部数据库来操作。

项目地址:https://github.com/docker/swarmkit

Docker - Swarm Mode:

Swarm Mode并非是一种特别的运行模式,而是 Docker 中的一组与集群相关的功能的统称。Swarm Mode所创建的集群 ,本质上就是 SwarmKit的集群,二者在代码上实现是同样的事物。相比于 Swarm Mode这个名称,SwarmKit一词更具有识别性,因此社区中有时候会用 SwarmKit集群来指代 Swarm Mode所创建的集群,以便于与过去的经典 Swarm集群划清界限。

如果您使用的是1.12.0之前的Docker版本,则可以使用独立群集,但我们建议您进行更新。

功能亮点:

  • 与Docker Engine集成的集群管理:使用Docker Engine CLI创建一群Docker引擎,您可以在其中部署应用程序服务。您不需要额外的编排软件来创建或管理群。
  • 分散式设计:Docker Engine在部署时不需要处理节点角色之间的差异,而是在运行时处理任何专业化。您可以使用Docker Engine部署这两种节点,管理员和工作人员。这意味着您可以从单个磁盘映像构建整个群集。
  • 声明式服务模型:Docker Engine使用声明式方法让您在应用程序堆栈中定义各种服务的所需状态。例如,您可能会描述一个由带有消息队列服务和数据库后端的Web前端服务组成的应用程序。
  • 缩放:对于每个服务,您可以声明要运行的任务数量。当您向上或向下缩放时,swarm管理器会通过添加或删除任务来自动调整以保持所需的状态。
  • 期望的状态协调:swarm manager节点持续监视集群状态,并协调实际状态与表达期望状态之间的任何差异。例如,如果您设置了一个服务来运行容器的10个副本以及承载其中两个副本崩溃的工作计算机,则该管理器会创建两个新副本来替换发生崩溃的副本。 swarm manager将新副本分配给正在运行且可用的工作人员。
  • 多主机联网:您可以为您的服务指定覆盖网络。 swarm管理器在初始化或更新应用程序时自动为覆盖网络上的容器分配地址。
  • 服务发现:Swarm管理器节点为swarm中的每个服务分配一个唯一的DNS名称并负载平衡正在运行的容器。您可以通过群集中嵌入的DNS服务器查询群集中运行的每个容器。
  • 负载平衡:您可以将服务的端口暴露给外部负载平衡器。在群集内部,您可以指定如何在节点之间分发服务容器。
  • 默认情况下为安全:群中的每个节点都强制进行TLS相互认证和加密,以保护其自身与所有其他节点之间的通信。您可以选择使用自定义根证书或来自自定义根CA的证书。
  • 滚动更新:在推出时,您可以逐步将服务更新应用于节点。 swarm管理器允许您控制服务部署到不同节点集之间的延迟。如果出现任何问题,您可以将任务回滚到以前版本的服务。

关系对比图:

对比图

Docker Swarm使用:

Swarm Mode CLI:

Swarm Mode 命令一览:

  • swarm init :初始化一个群
  • swarm join :以 nodemanager 的身份加入到集群中
  • service create :创建一个新的服务
  • service inspect :显示一项或多项服务的详细信息
  • service ls :列出服务
  • service rm :删除一项或多项服务
  • service scale :扩展一个或多个复制服务
  • service ps :列出一项或多项服务的任务
  • service update :更新服务

创建一个三节点的Swarm集群:

Vagrantfile:

用于构建集群的 Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 1.6.0"

boxes = [
    {
        :name => "swarm-manager",
        :eth1 => "192.168.10.11",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "swarm-worker1",
        :eth1 => "192.168.10.12",
        :mem => "1024",
        :cpu => "1"
    },
    {
        :name => "swarm-worker2",
        :eth1 => "192.168.10.13",
        :mem => "1024",
        :cpu => "1"
    }
]

Vagrant.configure(2) do |config|

  config.vm.box = "centos/7"

  boxes.each do |opts|
      config.vm.define opts[:name] do |config|
        config.vm.hostname = opts[:name]
        config.vm.provider "vmware_fusion" do |v|
          v.vmx["memsize"] = opts[:mem]
          v.vmx["numvcpus"] = opts[:cpu]
        end

        config.vm.provider "virtualbox" do |v|
          v.customize ["modifyvm", :id, "--memory", opts[:mem]]
          v.customize ["modifyvm", :id, "--cpus", opts[:cpu]]
        end

        config.vm.network :private_network, ip: opts[:eth1]
      end
  end

  config.vm.synced_folder "./share", "/home/vagrant/share"
  config.vm.provision "shell", privileged: true, path: "./setup.sh"

end

构建集群时所运行的脚本:

#/bin/sh

# install some tools
sudo yum install -y git vim gcc glibc-static telnet bridge-utils

# install docker
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh

# start docker service
sudo groupadd docker
sudo gpasswd -a vagrant docker
sudo systemctl start docker

rm -rf get-docker.sh

检查环境:

Vagrant构建完成之后,分别登陆到虚拟机中:

vagrant ssh swarm-manager
vagrant ssh swarm-worker1
vagrant ssh swarm-worker2

然后检查一下各个主机之间的网络是否能够正常通信,Docker环境是否正常,与宿主机的文件共享是否可用等等。

构建集群:

在Manager节点上初始化集群:
➜  swarm vagrant ssh swarm-manager
[vagrant@swarm-manager ~]$ docker swarm init --advertise-addr=192.168.10.11
Swarm initialized: current node (z79giyqd1mkutnlshuucoqwn0) is now a manager.

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

    docker swarm join --token SWMTKN-1-0asyz8unumzj8qbardoxo4wkh03wizp3stapr9kux9yiiufvnu-7daydi586pedk0unlkowcwr02 192.168.10.11:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
将Worker1节点加入集群:
➜  swarm vagrant ssh swarm-worker1
[vagrant@swarm-worker1 ~]$ docker swarm join --token SWMTKN-1-0asyz8unumzj8qbardoxo4wkh03wizp3stapr9kux9yiiufvnu-7daydi586pedk0unlkowcwr02 192.168.10.11:2377
This node joined a swarm as a worker.
将Worker2节点加入集群:
➜  swarm vagrant ssh swarm-worker2
[vagrant@swarm-worker2 ~]$ docker swarm join --token SWMTKN-1-0asyz8unumzj8qbardoxo4wkh03wizp3stapr9kux9yiiufvnu-7daydi586pedk0unlkowcwr02 192.168.10.11:2377
This node joined a swarm as a worker.
在Manager中查看集群信息:
[vagrant@swarm-manager ~]$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
z79giyqd1mkutnlshuucoqwn0 *   swarm-manager       Ready               Active              Leader              18.05.0-ce
w9gz1cmu756ydzlas0u2uhkpm     swarm-worker1       Ready               Active                                  18.05.0-ce
ajeyxpm0mn058vgn741n3hd4w     swarm-worker2       Ready               Active                                  18.05.0-ce

可以看出现在的集群中有一个 Manager节点和两个 Worker节点。

Docker Service实践:

Docker Service是一种声明式的、可扩展的、负载均衡的应用。Docker Service是面向用户的应用,而Docker Swarm是面向IT的节点集群。

Docker Service的运行往往是在Docker Swarm的基础之上的。

Docker Service CLI:

命令 说明
docker service create 创建一个新的服务
docker service inspect 显示一个或多个服务的详细信息
docker service logs 获取服务或任务的日志
docker service ls 列出服务信息
docker service ps 列出一个或多个服务的任务
docker service rm 删除一个或多个服务
docker service rollback 回滚原服务的配置
docker service scale 扩展服务
docker service update 更新服务

Service的创建与扩展:

创建一个服务:

[vagrant@swarm-manager ~]$ docker service create  --name bbox busybox sh -c "while true;do sleep 3600;done"

查看创建的服务:

[vagrant@swarm-manager ~]$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
5rtehf1xpr0y        bbox                replicated          1/1                 busybox:latest

replicated: 指服务可以进行水平扩展。

查看服务的任务信息:

[vagrant@swarm-manager ~]$ docker service ps bbox
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
z5hdgkdnc90v        bbox.1              busybox:latest      swarm-manager       Running             Running 12 minutes ago

对服务进行扩展:

使用 docker service scale命令来对服务进行扩展:

[vagrant@swarm-manager ~]$ docker service scale bbox=5
bbox scaled to 5
overall progress: 5 out of 5 tasks
1/5: running   [==================================================>]
2/5: running   [==================================================>]
3/5: running   [==================================================>]
4/5: running   [==================================================>]
5/5: running   [==================================================>]
verify: Service converged

扩展完成后,列出服务的详细信息:

[vagrant@swarm-manager ~]$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
5rtehf1xpr0y        bbox                replicated          5/5                 busybox:latest

会发现 REPLICAS由最开始的 1/1已经变成了 5/5,分子的 5指的是Service的状态是否已经ready,分母的 5指的是ServiceScale的数量。如果集群中的容器发生故障,REPLICAS也会发生变化。

容器在集群中的分布:

[vagrant@swarm-manager ~]$ docker service ps bbox
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
z5hdgkdnc90v        bbox.1              busybox:latest      swarm-manager       Running             Running 21 minutes ago
yv6nvn6j5d6u        bbox.2              busybox:latest      swarm-worker1       Running             Running 4 minutes ago
ls8smm681z4s        bbox.3              busybox:latest      swarm-worker2       Running             Running 4 minutes ago
4a6l5ll5ympp        bbox.4              busybox:latest      swarm-worker2       Running             Running 4 minutes ago
ir8mg63x9klx        bbox.5              busybox:latest      swarm-manager       Running             Running 4 minutes ago

可以看出五个容器是分别部署在集群中的三个节上的。

灾害与恢复:

在运行过程中某个集群中的某个容器停掉了,那么Swarm会在另外一个节点中再次复制一个容器,以保证scale的数量。

[vagrant@swarm-manager ~]$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
5rtehf1xpr0y        bbox                replicated          5/5                 busybox:latest
[vagrant@swarm-manager ~]$ docker service ps bbox
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
z5hdgkdnc90v        bbox.1              busybox:latest      swarm-manager       Running             Running 43 minutes ago
yv6nvn6j5d6u        bbox.2              busybox:latest      swarm-worker1       Running             Running 26 minutes ago
ls8smm681z4s        bbox.3              busybox:latest      swarm-worker2       Running             Running 26 minutes ago
4a6l5ll5ympp        bbox.4              busybox:latest      swarm-worker2       Running             Running 26 minutes ago
ir8mg63x9klx        bbox.5              busybox:latest      swarm-manager       Running             Running 26 minutes ago

进入到Worker1中,删除掉这个容器:

➜  swarm vagrant ssh swarm-worker1
Last login: Sat Jun 23 12:27:06 2018 from 10.0.2.2
[vagrant@swarm-worker1 ~]$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
17693f72e4f1        busybox:latest      "sh -c 'while true;d…"   28 minutes ago      Up 28 minutes                           bbox.2.yv6nvn6j5d6u1z9dnqb1ij318
[vagrant@swarm-worker1 ~]$ docker rm -f 17693f72e4f1
17693f72e4f1

删除完成后再次查看容器:

[vagrant@swarm-manager ~]$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
5rtehf1xpr0y        bbox                replicated          4/5                busybox:latest

会发现 REPLICAS中的数量已经发生了变化。

[vagrant@swarm-manager ~]$ docker serviceps bboxx
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE               ERROR                         PORTS
z5hdgkdnc90v        bbox.1              busybox:latest      swarm-manager       Running             Running about an hour ago
scdoihn28kig        bbox.2              busybox:latest      swarm-worker1       Running             Running 34 seconds ago
yv6nvn6j5d6u         \_ bbox.2          busybox:latest      swarm-worker1       Shutdown            Failed 40 seconds ago       "task: non-zero exit (137)"
ls8smm681z4s        bbox.3              busybox:latest      swarm-worker2       Running             Running 29 minutes ago
4a6l5ll5ympp        bbox.4              busybox:latest      swarm-worker2       Running             Running 29 minutes ago
ir8mg63x9klx        bbox.5              busybox:latest      swarm-manager       Running             Running 30 minutes ago

可以看出 worker1 上有一个容器的状态为shutdown但是 又在 worker1 启动了一个容器,所以当前使用scale扩展的数量还是保持在5个。

[vagrant@swarm-manager ~]$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
5rtehf1xpr0y        bbox                replicated          5/5                 busybox:latest

参考资料: