docker 用主机dns docker swarm dns 详解_docker


Docker从v1.12.0后开始集成swarm mode(swarmkit),关于swarm的所有操作可以直接使用docker swarm 命令来完成。Docker Swarm是docker原生的用于管理docker集群的工具,目前的功能主要有:

  • Docker集群的管理,包括集群的创建,manager,worker节点的加入/删除;
  • 服务的管理,包括service的创建删除,scale等;
  • 跨主机的网络管理(覆盖网络,overlay network);
  • 服务发现(内建DNS服务,服务可以通过dns发现);
  • 服务负载均衡(Load Balancing)。

Swarm mode 主要概念

swarm是什么?

swarm由多台运行在swarm模式(swarm mode)的Docker主机组成,它们之中有管理者(manager,起管理和委派任务的功能)和工作者(worker,负责运行swarm服务)。其中的Docker主机可以是manager或worker或同时担任两种角色。创建服务(service)时需要定义它的理想状态(optimal status,副本数量,可访问到的资源,对外开放的端口等)。Docker会负责维持该理想状态。例如当某一worker节点因某些原因变得不可用时,Docker会将这个节点的任务(task)调度分配到其他节点上。任务是一个运行中的容器,它是swarm服务的一部分,并且由swarm manager进行管理,对应独立模式(standalone)下的容器(container)。

swarm服务相比与独立模式容器的主要优势在于你可以随意修改服务的配置(网络,存储卷等)而不用手动重启服务。Docker会更新配置,停掉配置已过时的任务并创建符合预期配置的新任务。

当Docker处在swarm模式时,你依旧可以在该Docker主机上运行独立模式的容器。这两者的主要区别就是swarm服务只能由swarm manager来管理,独立模式的容器可以由Docker守护进程随意启停。

节点(Nodes)

一个节点(node)是一个加入到swarm中的Docker engine实例。可以看作是一个Docker节点。可以在一台物理机器或云机器上运行多个节点,但是在生产环境我们通常还是会把节点分散到多个物理机器上。

要将应用部署到swarm,我们需要提交一个服务(service)定义到manager节点上。manager节点负责把被称作任务的工作单元分发到worker节点上。manager节点还负责执行调度和集群管理工作来维持swarm的正常运行。在所有的manager节点中会有一个领导(leader)节点来执行编排任务。

worker节点 接受并执行从manager节点分发下来的任务。默认情况下,manager节点也会像worker节点一样执行任务,swarm允许配置manager节点只负责管理。各个worker节点上的代理(agent)负责上报本节点上的任务情况。worker节点会通知manager节点当前分配任务的状态,manager节点以此来维持服务的期望状态。

docker 用主机dns docker swarm dns 详解_网络_02

服务(Service) 和任务( task)

服务是任务的集合。它处于swarm系统结构的中心。创建服务的也就是要指定要使用哪个镜像(image),在容器(container)中执行什么命令(command)。

在副本服务(replicated services)模型中swarm manager会根据我们设置的副本数量来分发对应数量的任务到各个节点中。全局服务(global services)模式下swarm会在集群的每个节点上都运行一个对应任务。

任务是一个Docker容器加上要在该容器中运行的命令。它是swarm作业调度的最小单位。manager节点根据设置的副本数量分发任务。

docker 用主机dns docker swarm dns 详解_docker_03

配置

最小配置要求:

  • 三台安装了Docker的能互相通信的主机
  • Docker Engine 1.12或更高的版本

三台互通的主机

我这里用到了三台网络互通的Ubuntu物理主机。其中一台是manager(manager1),剩下的两台是worker(分别叫worker1worker2)。

  • manager1
  • docker 用主机dns docker swarm dns 详解_运维_04

  • worker1
  • docker 用主机dns docker swarm dns 详解_docker_05

  • worker2
  • docker 用主机dns docker swarm dns 详解_网络_06

由于worker节点根据manager节点的ip进行通信,所以manager节点的ip需要是固定的。网络拓扑如下:

docker 用主机dns docker swarm dns 详解_docker 用主机dns_07

Docker Engine 1.12 或更高的版本

  • manager1
  • docker 用主机dns docker swarm dns 详解_网络_08

  • worker1
  • docker 用主机dns docker swarm dns 详解_运维_09

  • worker2
  • docker 用主机dns docker swarm dns 详解_网络_10

主机的协议和端口

需要满足下面的要求(大部分情况下,机器的默认配置都满足)

  • TCP 2377端口 (manager节点通信用)
  • TCPUDP 7946端口 (节点之间的通信)
  • UDP 4789端口 (覆盖网络通信)

创建swarm

  1. manager1 运行下面的命令:
docker swarm init --advertise-addr <MANAGER-IP>

docker 用主机dns docker swarm dns 详解_docker 用主机dns_11


--advertise-addr 标志配置manager节点的IP地址,这里配置为192.168.110.169。swarm中的其他节点必须能够访问到该IP。

输出结果中有加入到该swarm的命令。

  1. 运行 docker info 命令查看当前swarm的状态:
  2. docker 用主机dns docker swarm dns 详解_docker 用主机dns_12

  3. 运行 docker node ls 命令查看所有节点的状态:
  4. docker 用主机dns docker swarm dns 详解_docker 用主机dns_13

  5. ID旁的 * 表示当前连接上的节点。

向swarm中添加节点

  1. 根据我们上面创建swarm时( docker swarm init )输出的命令来添加worker节点:
$ docker swarm join --token \
 SWMTKN-1-4ytcy7c8a26wnppr212eu0e5hdpd9zq6ds5mb9x6pj2z5n6sbj-az3qexi09pe2p93m9u173dg1j \
 192.168.110.169:2377

docker 用主机dns docker swarm dns 详解_docker 用主机dns_14


如果以上命令遗失了,可以在manager节点上运行下面的命令来重新获取:

$ docker swarm join-token worker

docker 用主机dns docker swarm dns 详解_docker 用主机dns_15


剩下的worker节点是相同的工作。在manager1 节点上运行 docker node ls :

docker 用主机dns docker swarm dns 详解_json_16


MANAGER STATUS 列的Leader标识了当前swarm中的manager节点为Leader。 worker1worker2中的空值表示它们为worker节点。

类似于 docker node ls这样的命令只能在manager节点上运行。

AVAILABILITY 列表示在当前节点上能否分发任务:

  • Active 表示调度者能分配任务到该节点。
  • Pause 表示调度者不能分配新任务到该节点,但是已经存在的任务正常运行。
  • Drain 表示调度者不能分配新任务到该节点,调度者会停掉之前已经存在的任务并调度到其他活跃节点上。

MANAGER STATUS 列:

  • 空值表示该节点为worker节点。
  • Leader 表示该节点为主要的manager节点,并能做swarm调度决策。
  • Reachable 表示该节点是一个加入到调度管理仲裁组的manager节点。如果leader节点变得不可用,该节点有机会被推举为新的leader。
  • Unavailable 表示该节点是一个manager节点,但是它现在不能与其他manager通信。如果一个manager节点变成此状态,你应该要添加一个新的manager节点到该swarm中,或者将一个worker节点提升为manager。

在swarm中部署服务

  1. manager1 节点上运行:
$ docker service create --replicas 1 --name helloworld alpine ping cn.bing.com
  • docker service create 命令用来创建服务;
  • --name 标志表示该服务名为 helloworld;
  • --replicas 标志指定服务期望状态的的副本个数;
  • 参数 alpine ping cn.bing.com 表示服务使用Alpine镜像并在容器中执行 ping cn.bing.com 命令;
  • docker会为每个节点都下载一个alpine镜像.

    对应的worker节点的运行情况:

小技巧: 访问docker国外镜像源很慢的朋友可以为文件 /etc/docker/daemon.json(没有该文件则新建) 添加下面内容:

{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

查看swarm服务情况

manager1 节点上运行 docker service inspect --pretty <SERVICE-ID> 来查看某个服务的详细情况:

docker 用主机dns docker swarm dns 详解_json_17


运行 docker service ps <SERVICE-ID> 来查看哪些节点在运行对应服务:

docker 用主机dns docker swarm dns 详解_网络_18


本例中,在 worker1节点上运行了一个 helloworld 服务上。也有可能在你的manager节点上看到该服务在运行。因为默认情况下,manager节点也能像worker节点一样运行任务。

Swarm 还显示了服务的 DESIRED STATE (期望状态)和 CURRENT STATE(当前状态),我们能以此来确定服务是否按照预期运行。

如果在对应的worker节点上停止manager节点创建的服务,docker会自动创建新的容器来满足DESIRED STATE的要求.

swarm服务动态调整(scaling)

我们可以用 Docker CLI来调整服务的容器个数(也就是调整任务个数)。

运行下面的命令来调整服务的期望状态:

$ docker service scale <SERVICE-ID>=<NUMBER-OF-TASKS>

例如:

$ docker service scale helloworld=5

docker 用主机dns docker swarm dns 详解_docker_19


运行 docker service ps <SERVICE-ID> 来查看更新后的任务列表:

docker 用主机dns docker swarm dns 详解_docker 用主机dns_20


可以看到swarm创建了4个新的任务。这些任务分布在各个节点上,其中两个还运行在我们的manager节点上。在各个节点上运行 docker ps 来查看运行中的容器状态(和独立模式下的Docker一样)。例如,在manager1 节点上:

docker 用主机dns docker swarm dns 详解_docker_21

删除swarm服务

运行 docker service rm helloworld 来删除 helloworld 服务.

docker 用主机dns docker swarm dns 详解_网络_22


运行 docker service inspect <SERVICE-ID> 验证swarm manager已把该服务移除。CLI返回的消息表示该服务已不存在:

docker 用主机dns docker swarm dns 详解_docker 用主机dns_23


删除服务后,对应的容器不会立即删除,Docker需要一点时间(几秒种)清理运行容器:

docker 用主机dns docker swarm dns 详解_网络_24

以上就是docker swarm最小配置的基本步骤, 我们了解了docker swarm的几个重要基本概念(节点,服务,任务等);并且手动创建了一个小的swarm集群,在该集群上进行了服务的动态调整以及服务的删除等操作;可以看到swarm的基本操作都比较简单。