docker CE on Linux示例浅析(四)swam群集配置


声明:本文转载自https://my.oschina.net/superwjc/blog/3053478,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

1. 概述

github项目地址:https://github.com/superwujc

尊重原创,欢迎转载,注明出处:https://my.oschina.net/superwjc/blog/3053478

历史系列:

docker CE on Linux示例浅析(一)安装与基本运行

docker CE on Linux示例浅析(二)数据存储与持久化

docker CE on Linux示例浅析(三)镜像与容器管理

    每一个宿主机(包括物理机与虚拟机)通常仅运行一个docker主进程(单宿主机可以配置为运行多个docker主进程,但截至18.09.6版本,这一功能仍处于实验阶段,且存在诸多问题尚未解决,生产环境中应避免以该方式部署)。默认情况下,多个宿主机上的docker主进程之间相互独立,每个docker主进程仅可管理本地容器,称为独立容器( standalone container)模式。docker-ce自1.12版本起引入群集(swarm)模式,实现了docker主进程的集群化管理,包括容器分配,规模伸缩,负载均衡,更新回滚,以及网络设置等功能。

节点(node)

    群集内包含一或多个运行于swarm模式的宿主机,每个宿主机称为一个节点,分为2种角色等级:管理(manager)与工作(worker),具有相同角色的节点可以存在多个。角色可以在群集初始化时分配,或在群集初始化后更改。

    管理节点负责群集管理,包括维持群集状态,调度服务,以及处理swarm模式API调用(包括http请求与命令行接口),工作节点负责执行容器。除退出群集之外,非管理节点无法执行任何与群集、节点、服务相关的操作。默认情况下,管理节点同时也作为工作节点。swarm允许群集内仅存在单个管理节点,但不允许仅存在工作节点而无任一管理节点。

    swarm调度器根据节点的可用性(availability)决定是否为某个节点指派任务,包括:

  • Active:节点期望接受新任务。
  • Pause:节点不期望接受新任务,但现存的任务仍将在当前节点继续运行。
  • Drain:节点不期望接受新任务,现存的任务将被关闭,调度器重新分配相应数量的任务并指派至其他可用节点。

    节点的可用性可以在群集初始化时指定,默认为Active,或在群集初始化后更改。

    群集内包含多个管理节点时,仅其中一个为主管理节点,状态为Leader,其他均为备用管理节点,状态为Reachable。swarm通过Raft Consensus算法提供了管理节点的容错机制,可以实现管理节点在失效配额内的自动选举与切换功能。假设管理节点总数量为N,失效配额为M,则二者之间的关系为M = (N - 1) / 2,M的值向下取整。例如管理节点总数为5或6时,最多允许其中2个同时失效。失效的管理节点数量若在配额范围内,则swarm将在其他管理状态为Reachable的节点内自动选举一个新的主管理节点;若超出配额范围(包括仅存在单个管理节点的情况),则群集功能将不可用,必须手动重建群集以恢复故障。群集内容器的运行状态不受管理节点失效的影响,除非所有节点(包括管理节点与工作节点)在物理层面不可用。

    生产环境中应避免使用单管理节点群集,但管理节点之间执行的状态同步操作会产生额外的网络开销。docker官方推荐管理节点数量应尽量为奇数,且最大值为7,以更好地发挥swarm的容错功能。因此,群集内应至少部署3个管理节点,以提供基本的可用性与容错性。

服务(service)

    服务是swarm群集的主要操作对象,用于定义容器的期望运行状态,包括容器运行所使用的镜像与容器内部执行的命令,以及其他可配置的参数,如环境变量,开放端口,网络模式,系统资源,挂载选项,回滚更新策略等。服务的状态可以在命令行或配置文件中指定,swarm调度器根据服务状态的定义,将任务指派给可用的工作节点。

    服务分为2种运行模式:副本(replicated)与全局(global)。副本模式在所有工作节点中运行指定数量的任务,每个可用的节点上运行的任务数量由调度器分配;全局模式则在每一个可用的工作节点上都运行一个任务,任务的数量依赖于可用节点的数量。某一特定的服务仅可运行于两种模式之一,默认为副本模式。

任务(task)

    任务是swarm群集的原子性调度单元,容器从启动到终止构成对应任务的整个生存周期。容器是任务的实例化,二者之间具有一一对应的关系,而与容器相关的操作由工作节点上的docker主进程完成,因此任务与节点之间同样具有一一对应的关系。

    任务经分配后,具有以下状态,调度器根据这些状态持续监视容器与节点的运行情况:

  • NEW:任务已初始化。
  • PENDING:任务已就绪,等待指派。
  • ASSIGNED:任务已指派至节点。
  • ACCEPTED:任务已被工作节点接受,等待执行。
  • PREPARING:节点正在准备执行任务。
  • STARTING:任务正在启动。
  • RUNNING:任务正在运行。
  • COMPLETE:任务因执行成功而退出。
  • FAILED:任务因执行出错而退出。
  • SHUTDOWN:任务被节点关闭。
  • REJECTED:任务被节点拒绝。
  • ORPHANED:任务已指派,但节点长时间不可达。
  • REMOVE:任务未终止,但与之相关联的服务被移除,或减小规模。

    容器启动失败或因错误而终止时,调度器将分配一个新的任务,并尝试重新运行该容器。由于任务、节点与容器之间的对应关系,同一个任务只能运行在被指派的特定节点上,直到终止,而无法从一个节点转移至另一节点。

示例

    本节以tomcat容器为例,简述群集、服务与任务的基本管理。

环境

  • 宿主机3台:dock_host_0(192.168.9.168/24),dock_host_1(192.168.9.169/24),dock_host_2(192.168.9.170/24),系统与软件环境一致,均为全新最小化安装,单物理网卡,操作系统版本CentOS Linux release 7.6.1810 (Core),内核版本3.10.0-957.12.2.el7.x86_64,关闭selinux与防火墙。docker为默认安装,版本18.09.6,无其他额外设置。
  • 基础镜像为最新版CentOS 7官方镜像。
  • jdk环境以命名卷jdks的方式挂载至容器的/opt/jdks目录。
  • 源码包jdk-8u212-linux-x64.tar.gz与apache-tomcat-8.5.40.tar.gz,位于宿主机的/opt/目录。
  • tomcat环境位于容器的/opt/apps/app_0目录。

初始化群集

    群集的初始化包括创建(docker swarm init)与加入(docker swarm join),二者均开启docker引擎的swarm模式。

1. 创建群集。

docker swarm init命令用于创建群集,并将自身节点设置为主管理角色。

    宿主机docker_host_0创建群集,节点的管理状态为Leader:

[root@docker_host_0 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.168/24
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# uname -r
3.10.0-957.12.2.el7.x86_64
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker -v
Docker version 18.09.6, build 481bc77156
[root@docker_host_0 ~]#
[root@docker_host_0 ~]# docker swarm init
Swarm initialized: current node (5h6m2fspnhtg0lr0x6d481qdr) is now a manager.

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

    docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-434u94ack6bd9gwgxbvf2dqiw 192.168.9.168:2377

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

[root@docker_host_0 ~]#

2. 查看节点属性。

docker node ls命令用于查看群集内的节点属性,包括:
ID:节点ID。
HOSTNAME:节点主机名。
STATUS:节点状态,Ready表示该节点可用,Down表示该节点已退出群集,Unknown表示该节点与管理节点之间的session同步出错。
AVAILABILITY:节点可用性(Active/Pause/Drain)。
MANAGER STATUS:管理状态/角色,Leader表示主管理节点,Reachable表示备用管理节点,为空表示仅为工作节点。
ENGINE VERSION:docker引擎版本。

[root@docker_host_0 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr *   docker_host_0       Ready               Active              Leader              18.09.6
[root@docker_host_0 ~]#

3. 查看群集的加入方式。

docker swarm join-token --rotate manager/worker命令用于查看或设置(--rotate)管理节点/工作节点加入群集时使用的token,输出中包含docker主进程以相应角色加入群集的方式。

[root@docker_host_0 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-381n4jpj6ur4il4k6qo0wifhq 192.168.9.168:2377

[root@docker_host_0 ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-434u94ack6bd9gwgxbvf2dqiw 192.168.9.168:2377

[root@docker_host_0 ~]#

4. 加入群集。

    根据管理节点中docker swarm join-token manager/worker命令的输出,分别将宿主机docker_host_1与docker_host_2以管理/工作角色加入群集。

[root@docker_host_1 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.169/24
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# uname -r
3.10.0-957.12.2.el7.x86_64
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker -v
Docker version 18.09.6, build 481bc77156
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-381n4jpj6ur4il4k6qo0wifhq 192.168.9.168:2377
This node joined a swarm as a manager.
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
cos4ftcikaykcit9m15kqmvlh *   docker_host_1       Ready               Active              Reachable           18.09.6
[root@docker_host_1 ~]#
[root@docker_host_2 ~]# ip addr show eth0 | sed -n '/inet /p' | awk '{print $2}'
192.168.9.170/24
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# uname -r
3.10.0-957.12.2.el7.x86_64
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# docker -v
Docker version 18.09.6, build 481bc77156
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-434u94ack6bd9gwgxbvf2dqiw 192.168.9.168:2377
This node joined a swarm as a worker.
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# docker node ls
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.
[root@docker_host_2 ~]#

5. 设置节点角色。

docker node promote/demote命令用于对指定节点的角色进行升级/降级。
备用管理节点与主管理节点具有相同的群集操作权限。

    提升docker_host_2节点的角色等级:

[root@docker_host_1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
cos4ftcikaykcit9m15kqmvlh *   docker_host_1       Ready               Active              Reachable           18.09.6
rvomnj0q7aari989o3c4t6w02     docker_host_2       Ready               Active                                  18.09.6
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker node promote docker_host_2
Node docker_host_2 promoted to a manager in the swarm.
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
cos4ftcikaykcit9m15kqmvlh *   docker_host_1       Ready               Active              Reachable           18.09.6
rvomnj0q7aari989o3c4t6w02     docker_host_2       Ready               Active              Reachable           18.09.6
[root@docker_host_1 ~]#

docker info命令可以查看群集相关的信息,包括是否开启swarm模式,群集ID,管理节点数,节点总数,管理节点IP,当前节点角色/ID/IP等。

[root@docker_host_1 ~]# docker info
    ...
Swarm: active
 NodeID: cos4ftcikaykcit9m15kqmvlh
 Is Manager: true
 ClusterID: odbfcfeayjogvdn34m3nruq2f
 Managers: 3
 Nodes: 3
 Default Address Pool: 10.0.0.0/8
 SubnetSize: 24
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot Interval: 10000
  Number of Old Snapshots to Retain: 0
  Heartbeat Tick: 1
  Election Tick: 10
 Dispatcher:
  Heartbeat Period: 5 seconds
 CA Configuration:
  Expiry Duration: 3 months
  Force Rotate: 0
 Autolock Managers: false
 Root Rotation In Progress: false
 Node Address: 192.168.9.169
 Manager Addresses:
  192.168.9.168:2377
  192.168.9.169:2377
  192.168.9.170:2377
    ...
[root@docker_host_1 ~]#

    至此,群集内包含3个管理节点,docker_host_0为主管理节点,其余为备用管理节点。

运行全局服务

1. 准备应用镜像。

    在docker_host_0中以dockerfile方式构建镜像,名称为tomcat_app:8.5.40。

    设置tomcat:

server.xml中的pattern字段用于设置默认的访问日志格式,更改为%A:%{local}p %a:%{remote}p,表示本端IP:端口 对端IP:端口,以区分访问来源。

[root@docker_host_0 ~]# cd /opt/
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ls
apache-tomcat-8.5.40.tar.gz  containerd  jdk-8u212-linux-x64.tar.gz
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# tar axf apache-tomcat-8.5.40.tar.gz
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# sed -i 's/pattern="%h %l %u %t/pattern="%A:%{local}p %a:%{remote}p %t/' apache-tomcat-8.5.40/conf/server.xml
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# sed -n '/pattern="%A:%/p' apache-tomcat-8.5.40/conf/server.xml
               pattern="%A:%{local}p %a:%{remote}p %t "%r" %s %b" />
[root@docker_host_0 opt]#

    设置数据卷,用于挂载jdk环境:

[root@docker_host_0 opt]# docker volume create jdks
jdks
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# tar axf jdk-8u212-linux-x64.tar.gz -C /var/lib/docker/volumes/jdks/_data/
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker volume ls
DRIVER              VOLUME NAME
local               jdks
[root@docker_host_0 opt]#

    设置dockerfile:

[root@docker_host_0 opt]# vi dockerfile-for-tomcat
FROM centos:latest
COPY apache-tomcat-8.5.40 /opt/apps/app_0
EXPOSE 8080
ENV JAVA_HOME /opt/jdks/jdk1.8.0_212
WORKDIR /opt/apps/app_0
CMD bin/catalina.sh run
[root@docker_host_0 opt]#

    编译镜像:

[root@docker_host_0 opt]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker build -f dockerfile-for-tomcat -t tomcat_app:8.5.40 .
Sending build context to Docker daemon  219.1MB
Step 1/6 : FROM centos:latest
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475
Status: Downloaded newer image for centos:latest
 ---> 9f38484d220f
Step 2/6 : COPY apache-tomcat-8.5.40 /opt/apps/app_0
 ---> 155b18437d11
Step 3/6 : EXPOSE 8080
 ---> Running in 93fdd5ea8433
Removing intermediate container 93fdd5ea8433
 ---> 1c2487ffdd9b
Step 4/6 : ENV JAVA_HOME /opt/jdks/jdk1.8.0_212
 ---> Running in 2ef953a36a71
Removing intermediate container 2ef953a36a71
 ---> 459c7c25ccc2
Step 5/6 : WORKDIR /opt/apps/app_0
 ---> Running in 8dc1cde1177e
Removing intermediate container 8dc1cde1177e
 ---> 35af515cc94f
Step 6/6 : CMD bin/catalina.sh run
 ---> Running in 6733ba74c3d0
Removing intermediate container 6733ba74c3d0
 ---> 74df48f4f0fc
Successfully built 74df48f4f0fc
Successfully tagged tomcat_app:8.5.40
[root@docker_host_0 opt]#
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat_app          8.5.40              74df48f4f0fc        5 seconds ago       216MB
centos              latest              9f38484d220f        2 months ago        202MB
[root@docker_host_0 opt]#

2. 创建全局服务。

    在节点docker_host_0上,以tomcat_app:8.5.40镜像创建服务(docker service create),模式(--mode)为全局,名称(--name)为webapp_g,挂载(--mount)数据卷,开放端口(-p/--publish)8080:

[root@docker_host_0 opt]# docker service create --name webapp_g --mount type=volume,src=jdks,dst=/opt/jdks --mode global -p 8080:8080 tomcat_app:8.5.40
image tomcat_app:8.5.40 could not be accessed on a registry to record
its digest. Each node will access tomcat_app:8.5.40 independently,
possibly leading to different nodes running different
versions of the image.

kp6qdrzoswljwfmiphh19pogv
overall progress: 1 out of 3 tasks
5h6m2fspnhtg: running
rvomnj0q7aar: No such image: tomcat_app:8.5.40
cos4ftcikayk: No such image: tomcat_app:8.5.40
^COperation continuing in background.
Use `docker service ps kp6qdrzoswljwfmiphh19pogv` to check progress.
[root@docker_host_0 opt]#

3. 查看服务属性。

docker service ls命令用于查看当前群集中运行的服务列表与相关信息,包括:
ID:服务ID。
NAME:服务名称。
MODE:服务运行模式(global/replicated)。
REPLICAS:成功分配的任务数/请求分配的任务数。
IMAGE:镜像名称。
PORTS:开放端口与协议。

[root@docker_host_0 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
kp6qdrzoswlj        webapp_g            global              1/3                 tomcat_app:8.5.40   *:8080->8080/tcp
[root@docker_host_0 opt]#

4. 查看任务属性。

docker service ps命令用于查看指定服务中的任务执行情况,包括:
ID:任务ID。
NAME:任务对应的容器名称。
IMAGE:镜像名称。
NODE:任务指派的节点。
DESIRED STATE:任务的期望状态。
CURRENT STATE:任务的当前状态。
ERROR:错误信息。
PORTS:开放端口。
-f/--filter选项以键值对的方式过滤输出,当前支持的键包括id/name/node/desired-state,分别对应以上参数。

[root@docker_host_0 opt]# docker service ps -f "node=docker_host_0" webapp_g
ID                  NAME                                 IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
ncd0lscuk5ts        webapp_g.5h6m2fspnhtg0lr0x6d481qdr   tomcat_app:8.5.40   docker_host_0       Running             Running about a minute ago
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker service ps -f "node=docker_host_1" webapp_g
ID                  NAME                                     IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR                              PORTS
umkwfusbj5rt        webapp_g.cos4ftcikaykcit9m15kqmvlh       tomcat_app:8.5.40   docker_host_1       Ready               Preparing 3 seconds ago
bp49pjyqh5ku         \_ webapp_g.cos4ftcikaykcit9m15kqmvlh   tomcat_app:8.5.40   docker_host_1       Shutdown            Rejected 3 seconds ago    "No such image: tomcat_app:8.5…"
qepo1tzhcz68         \_ webapp_g.cos4ftcikaykcit9m15kqmvlh   tomcat_app:8.5.40   docker_host_1       Shutdown            Rejected 8 seconds ago    "No such image: tomcat_app:8.5…"
2gg2f0d8d3tk         \_ webapp_g.cos4ftcikaykcit9m15kqmvlh   tomcat_app:8.5.40   docker_host_1       Shutdown            Rejected 15 seconds ago   "No such image: tomcat_app:8.5…"
rc41gutotc64         \_ webapp_g.cos4ftcikaykcit9m15kqmvlh   tomcat_app:8.5.40   docker_host_1       Shutdown            Rejected 21 seconds ago   "No such image: tomcat_app:8.5…"
[root@docker_host_0 opt]#
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker service ps -f "node=docker_host_2" webapp_g
ID                  NAME                                     IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR                              PORTS
k8iyvkp5iv14        webapp_g.rvomnj0q7aari989o3c4t6w02       tomcat_app:8.5.40   docker_host_2       Ready               Rejected 1 second ago     "No such image: tomcat_app:8.5…"
wbxd2787npfl         \_ webapp_g.rvomnj0q7aari989o3c4t6w02   tomcat_app:8.5.40   docker_host_2       Shutdown            Rejected 5 seconds ago    "No such image: tomcat_app:8.5…"
tv7x0fl8qwpe         \_ webapp_g.rvomnj0q7aari989o3c4t6w02   tomcat_app:8.5.40   docker_host_2       Shutdown            Rejected 11 seconds ago   "No such image: tomcat_app:8.5…"
vatre7kv4ggt         \_ webapp_g.rvomnj0q7aari989o3c4t6w02   tomcat_app:8.5.40   docker_host_2       Shutdown            Rejected 16 seconds ago   "No such image: tomcat_app:8.5…"
xge3egwymkmj         \_ webapp_g.rvomnj0q7aari989o3c4t6w02   tomcat_app:8.5.40   docker_host_2       Shutdown            Rejected 22 seconds ago   "No such image: tomcat_app:8.5…"
[root@docker_host_0 opt]#

    全局模式的服务在每一个可用节点上都运行一个任务实例,但docker_host_1与docker_host_2节点的本地与镜像仓库不存在tomcat_app:8.5.40镜像,因此另2个任务实例一直因"No such image"错误而被节点拒绝(任务状态为Rejected),随后分配新的任务再次尝试执行。

    群集服务隐藏了容器的运行细节,对外表现为相同的形式。向任一节点发送请求均可访问,即使指定的容器未运行在该节点,调度器会将传入的连接分配至群集内成功运行的容器。

    docker_host_0节点上的任务成功执行,指定的容器运行且端口已开启:

[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
8330cf1374db        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   4 minutes ago       Up 4 minutes        8080/tcp            webapp_g.5h6m2fspnhtg0lr0x6d481qdr.ncd0lscuk5tsvsdmcqse3vibm
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_0 opt]#

    docker_host_1与docker_host_2节点上的任务未成功执行,但端口依然开启,且可提供访问:

[root@docker_host_1 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.168:8080
200
[root@docker_host_1 ~]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.169:8080
200
[root@docker_host_1 ~]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.170:8080
200
[root@docker_host_1 ~]#
[root@docker_host_2 ~]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.168:8080
200
[root@docker_host_2 ~]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.169:8080
200
[root@docker_host_2 ~]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.170:8080
200
[root@docker_host_2 ~]#

5. 设置节点可用性。

docker swarm init/join命令的--availability选项用于在创建/加入群集时设置节点的可用性,默认为active。

docker node update命令用于设置指定节点的可用性(--availability "active"|"pause"|"drain"),标签(--label-add/--label-rm)与角色(--role "worker"|"manager")

    将docker_host_1节点的可用性更改为pause,docker_host_2节点的可用性更改为drain:

[root@docker_host_1 ~]# docker node update --availability pause docker_host_1
docker_host_1
[root@docker_host_1 ~]# docker node update --availability drain docker_host_2
docker_host_2
[root@docker_host_1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
cos4ftcikaykcit9m15kqmvlh *   docker_host_1       Ready               Pause               Reachable           18.09.6
rvomnj0q7aari989o3c4t6w02     docker_host_2       Ready               Drain               Reachable           18.09.6
[root@docker_host_1 ~]#

    docker_host_1与docker_host_2节点因镜像不存在而拒绝了任务,处于关闭状态,因此将二者的节点可用性更改为pause与drain后,服务请求分配的任务数从3变为1,先前失败的2个任务不再尝试执行,结果为仅docker_host_1节点上运行了1个任务(容器)。

[root@docker_host_0 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
kp6qdrzoswlj        webapp_g            global              1/1                 tomcat_app:8.5.40   *:8080->8080/tcp
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker service ps -f 'desired-state=running' webapp_g
ID                  NAME                                 IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
ncd0lscuk5ts        webapp_g.5h6m2fspnhtg0lr0x6d481qdr   tomcat_app:8.5.40   docker_host_0       Running             Running 40 minutes ago
[root@docker_host_0 opt]#

6. 节点角色降级。

    将docker_host_1与docker_host_2节点的角色降级为非管理节点:

[root@docker_host_0 opt]# docker node demote docker_host_1
Manager docker_host_1 demoted in the swarm.
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker node demote docker_host_2
Manager docker_host_2 demoted in the swarm.
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr *   docker_host_0       Ready               Active              Leader              18.09.6
cos4ftcikaykcit9m15kqmvlh     docker_host_1       Ready               Pause                                   18.09.6
rvomnj0q7aari989o3c4t6w02     docker_host_2       Ready               Drain                                   18.09.6
[root@docker_host_0 opt]#

7. 退出群集。

退出群集是非管理节点有权限执行的唯一群集相关操作,包括docker swarm leave命令与POST /swarm/leave接口,二者效果相同。执行退出操作后,swarm模式随之关闭。

docker守护进程默认监听在本地的UNIX域套接字/var/run/docker.sock。

    docker_host_1节点通过命令行接口退出群集:

[root@docker_host_1 ~]# docker swarm leave
Node left the swarm.
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker info -f '{{.Swarm}}'
{  inactive false  [] 0 0 <nil>}
[root@docker_host_1 ~]#

    docker_host_2节点执行HTTP API退出群集:

[root@docker_host_2 ~]# curl -0 -i -X POST --unix-socket /var/run/docker.sock http:/swarm/leave
HTTP/1.0 200 OK
Api-Version: 1.39
Docker-Experimental: false
Ostype: linux
Server: Docker/18.09.6 (linux)
Date: Fri, 24 May 2019 05:04:55 GMT
Content-Length: 0

[root@docker_host_2 ~]# docker info -f '{{.Swarm}}'
{  inactive false  [] 0 0 <nil>}
[root@docker_host_2 ~]#

    退出群集后,相应节点的信息条目仍然存在,但状态变为Down:

[root@docker_host_0 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr *   docker_host_0       Ready               Active              Leader              18.09.6
cos4ftcikaykcit9m15kqmvlh     docker_host_1       Down                Pause                                   18.09.6
rvomnj0q7aari989o3c4t6w02     docker_host_2       Down                Drain                                   18.09.6
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker info -f '{{.Swarm.Nodes}}'
3
[root@docker_host_0 opt]#

8. 移除节点。

docker node rm命令用于从群集内移除指定节点。

    将docker_host_1与docker_host_2节点从群集内移除:

[root@docker_host_0 opt]# docker node rm docker_host_1
docker_host_1
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker node rm docker_host_2
docker_host_2
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr *   docker_host_0       Ready               Active              Leader              18.09.6
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker info -f '{{.Swarm.Nodes}}'
1
[root@docker_host_0 opt]#

9. 移除服务。

docker service rm命令用于移除指定的服务。

    将webapp_g服务从群集内移除:

[root@docker_host_0 opt]# docker service rm webapp_g
webapp_g
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@docker_host_0 opt]#

    将宿主机docker_host_1与docker_host_2重新以管理角色加入群集:

[root@docker_host_0 opt]# docker swarm join-token --rotate manager
Successfully rotated manager join token.

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

    docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-cav7ypxfv6hzuyz5hq7jvn87l 192.168.9.168:2377

[root@docker_host_0 opt]#
[root@docker_host_1 ~]# docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-cav7ypxfv6hzuyz5hq7jvn87l 192.168.9.168:2377
This node joined a swarm as a manager.
[root@docker_host_1 ~]#
[root@docker_host_1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
upn0vc4vx47224gxaxn6hwec9 *   docker_host_1       Ready               Active              Reachable           18.09.6
[root@docker_host_1 ~]#
[root@docker_host_2 ~]# docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-cav7ypxfv6hzuyz5hq7jvn87l 192.168.9.168:2377
This node joined a swarm as a manager.
[root@docker_host_2 ~]#
[root@docker_host_2 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
upn0vc4vx47224gxaxn6hwec9     docker_host_1       Ready               Active              Reachable           18.09.6
jekdpdzmwcxrdfsxaudzbdp2z *   docker_host_2       Ready               Active              Reachable           18.09.6
[root@docker_host_2 ~]#

    至此,群集内仍保持3个管理节点,docker_host_0为主管理节点。

运行副本服务

1. 导入镜像。

    在docker_host_0节点上将镜像tomcat_app:8.5.40打包,并传输至docker_host_1与docker_host_2节点:

[root@docker_host_0 opt]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat_app          8.5.40              74df48f4f0fc        About an hour ago   216MB
centos              latest              9f38484d220f        2 months ago        202MB
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker image save tomcat_app:8.5.40 -o tomcat_app.tar
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# ll -h tomcat_app.tar
-rw------- 1 root root 214M May 24 05:28 tomcat_app.tar
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# scp tomcat_app.tar root@192.168.9.169:/opt
tomcat_app.tar                                                 100%  214MB  78.5MB/s   00:02
[root@docker_host_0 opt]# scp tomcat_app.tar root@192.168.9.170:/opt
tomcat_app.tar                                                 100%  214MB  96.0MB/s   00:02
[root@docker_host_0 opt]#

    在docker_host_1与docker_host_2节点上分别导入镜像,并设置jdk环境所需的数据卷:

[root@docker_host_1 ~]# cd /opt/
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# ls
containerd  jdk-8u212-linux-x64.tar.gz  tomcat_app.tar
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image load -i tomcat_app.tar
d69483a6face: Loading layer  209.5MB/209.5MB
59eb00de447b: Loading layer  14.39MB/14.39MB
Loaded image: tomcat_app:8.5.40
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat_app          8.5.40              74df48f4f0fc        About an hour ago   216MB
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker volume create jdks
jdks
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# tar axf jdk-8u212-linux-x64.tar.gz -C /var/lib/docker/volumes/jdks/_data/
[root@docker_host_1 opt]#
[root@docker_host_2 ~]# cd /opt/
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# ls
containerd  jdk-8u212-linux-x64.tar.gz  tomcat_app.tar
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker image load -i tomcat_app.tar
d69483a6face: Loading layer  209.5MB/209.5MB
59eb00de447b: Loading layer  14.39MB/14.39MB
Loaded image: tomcat_app:8.5.40
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
tomcat_app          8.5.40              74df48f4f0fc        About an hour ago   216MB
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker volume create jdks
jdks
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# tar axf jdk-8u212-linux-x64.tar.gz -C /var/lib/docker/volumes/jdks/_data/
[root@docker_host_2 opt]#

2. 创建副本服务。

docker service create命令不指定--mode选项,则默认创建副本模式的服务,且数量为1。

    以副本模式执行tomcat_app:8.5.40镜像,数量(--replicas)为3,名称为webapp_d:

[root@docker_host_1 opt]# docker service create --name webapp_d --mount type=volume,src=jdks,dst=/opt/jdks --replicas 3 -p 8080:8080 tomcat_app:8.5.40
image tomcat_app:8.5.40 could not be accessed on a registry to record
its digest. Each node will access tomcat_app:8.5.40 independently,
possibly leading to different nodes running different
versions of the image.

hmhqo34e46m1syf4eoawre3fx
overall progress: 3 out of 3 tasks
1/3: running
2/3: running
3/3: running
verify: Service converged
[root@docker_host_1 opt]#

    任务被平均指派至3个节点并成功运行:

[root@docker_host_1 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
hmhqo34e46m1        webapp_d            replicated          3/3                 tomcat_app:8.5.40   *:8080->8080/tcp
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker service ps webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
e2eynnrned2j        webapp_d.1          tomcat_app:8.5.40   docker_host_1       Running             Running 6 minutes ago
nd8qg74l4t7b        webapp_d.2          tomcat_app:8.5.40   docker_host_2       Running             Running 6 minutes ago
e2ef0oc66sqh        webapp_d.3          tomcat_app:8.5.40   docker_host_0       Running             Running 6 minutes ago
[root@docker_host_1 opt]#

3. 更改节点可用性(pause)。

    将docker_host_2节点的可用性更改为pause:

[root@docker_host_1 opt]# docker node update --availability pause docker_host_2
docker_host_2
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
upn0vc4vx47224gxaxn6hwec9 *   docker_host_1       Ready               Active              Reachable           18.09.6
jekdpdzmwcxrdfsxaudzbdp2z     docker_host_2       Ready               Pause               Reachable           18.09.6
[root@docker_host_1 opt]#

    docker_host_2节点上正在运行的任务仍继续运行:

[root@docker_host_1 opt]# docker service ps webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
e2eynnrned2j        webapp_d.1          tomcat_app:8.5.40   docker_host_1       Running             Running 15 minutes ago
nd8qg74l4t7b        webapp_d.2          tomcat_app:8.5.40   docker_host_2       Running             Running 15 minutes ago
e2ef0oc66sqh        webapp_d.3          tomcat_app:8.5.40   docker_host_0       Running             Running 15 minutes ago
[root@docker_host_1 opt]#

4. 更改副本规模。

docker service scale命令用于更改副本服务的运行数量,参数格式为服务名或ID=值,指定的值为最终运行的副本数量,可以增大或减小。

    将服务的副本数量设置为6: 

[root@docker_host_1 opt]# docker service scale webapp_d=6
webapp_d scaled to 6
overall progress: 6 out of 6 tasks
1/6: running
2/6: running
3/6: running
4/6: running
5/6: running
6/6: running
verify: Service converged
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
hmhqo34e46m1        webapp_d            replicated          6/6                 tomcat_app:8.5.40   *:8080->8080/tcp
[root@docker_host_1 opt]#

    docker_host_2节点的可用性为pause,因此不再接受新的任务,新增的3个任务被指派至另2个节点:

[root@docker_host_1 opt]# docker service ps webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
e2eynnrned2j        webapp_d.1          tomcat_app:8.5.40   docker_host_1       Running             Running 21 minutes ago
nd8qg74l4t7b        webapp_d.2          tomcat_app:8.5.40   docker_host_2       Running             Running 21 minutes ago
e2ef0oc66sqh        webapp_d.3          tomcat_app:8.5.40   docker_host_0       Running             Running 21 minutes ago
67mfqjvqgi7b        webapp_d.4          tomcat_app:8.5.40   docker_host_0       Running             Running 2 minutes ago
qrdqrzm2f6si        webapp_d.5          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
mejk0zee8ovy        webapp_d.6          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
[root@docker_host_1 opt]#

5. 更改节点可用性(drain)。

    将docker_host_2节点的可用性更改为drain:

[root@docker_host_1 opt]# docker node update --availability drain docker_host_2
docker_host_2
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Ready               Active              Leader              18.09.6
upn0vc4vx47224gxaxn6hwec9 *   docker_host_1       Ready               Active              Reachable           18.09.6
jekdpdzmwcxrdfsxaudzbdp2z     docker_host_2       Ready               Drain               Reachable           18.09.6
[root@docker_host_1 opt]#

    副本总数未改变,但docker_host_2节点上先前运行的任务(nd8qg74l4t7b)被关闭,新的任务(tuuq6q1tlcib)被指派至docker_host_0节点,结果为docker_host_0与docker_host_1节点各自运行3个任务:

[root@docker_host_1 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
hmhqo34e46m1        webapp_d            replicated          6/6                 tomcat_app:8.5.40   *:8080->8080/tcp
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker service ps webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
e2eynnrned2j        webapp_d.1          tomcat_app:8.5.40   docker_host_1       Running             Running 28 minutes ago
tuuq6q1tlcib        webapp_d.2          tomcat_app:8.5.40   docker_host_0       Running             Running 13 seconds ago
nd8qg74l4t7b         \_ webapp_d.2      tomcat_app:8.5.40   docker_host_2       Shutdown            Shutdown 15 seconds ago
e2ef0oc66sqh        webapp_d.3          tomcat_app:8.5.40   docker_host_0       Running             Running 28 minutes ago
67mfqjvqgi7b        webapp_d.4          tomcat_app:8.5.40   docker_host_0       Running             Running 9 minutes ago
qrdqrzm2f6si        webapp_d.5          tomcat_app:8.5.40   docker_host_1       Running             Running 9 minutes ago
mejk0zee8ovy        webapp_d.6          tomcat_app:8.5.40   docker_host_1       Running             Running 9 minutes ago
[root@docker_host_1 opt]#

    docker_host_2节点上的容器退出,但端口依然开放,且可对外提供访问:

[root@docker_host_2 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
50187866b04e        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   36 minutes ago      Exited (143) 8 minutes ago                       webapp_d.2.nd8qg74l4t7b2oju7bzs9qsk1
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_2 opt]#
[root@docker_host_1 opt]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.170:8080
200
[root@docker_host_1 opt]#

    至此,群集内依然保持3个管理节点,docker_host_0为主管理节点。

故障恢复

    3个管理节点的失效配额为(3 - 1) / 2 = 1,若失效数量若小于或等于配额,则swarm自动执行选举与切换;若超出配额范围,则须手动强制重建群集(docker swarm init -f/--force)。

    出现故障时,需要查看群集、节点、服务、任务等信息,结合命令行输出与日志对故障原因进行定位。CentOS 7下的docker日志文件默认为/var/log/message,可设置为单独的文件,参考docker CE on Linux示例浅析(一)安装与基本运行

    管理节点的/var/lib/docker/swarm/目录用于保存群集状态与管理日志,可以按备份目录-导入目录-重建群集的步骤执行故障恢复。docker官方建议备份与导入操作在docker主进程停用后执行。

1. 故障模拟。

    将主管理节点docker_host_0中的docker守护进程停止:

[root@docker_host_0 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr *   docker_host_0       Ready               Active              Leader              18.09.6
upn0vc4vx47224gxaxn6hwec9     docker_host_1       Ready               Active              Reachable           18.09.6
jekdpdzmwcxrdfsxaudzbdp2z     docker_host_2       Ready               Drain               Reachable           18.09.6
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# systemctl stop docker
[root@docker_host_0 opt]#

    主管理角色自动切换至docker_host_2节点,群集相关的功能不受影响,但docker_host_0节点的状态先后变为Unknown与Down,管理状态变为Unreachable:

[root@docker_host_1 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Unknown             Active              Unreachable         18.09.6
upn0vc4vx47224gxaxn6hwec9 *   docker_host_1       Ready               Active              Reachable           18.09.6
jekdpdzmwcxrdfsxaudzbdp2z     docker_host_2       Ready               Drain               Leader              18.09.6
[root@docker_host_1 opt]#

    副本数量未改变,但先前运行在docker_host_0节点上的3个任务都被关闭,新分配的任务被指派至docker_host_1节点,结果为docker_host_1节点上运行了6个任务:

[root@docker_host_1 opt]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
hmhqo34e46m1        webapp_d            replicated          6/6                 tomcat_app:8.5.40   *:8080->8080/tcp
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker service ps webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
e2eynnrned2j        webapp_d.1          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
wnrm2ndqjk7r        webapp_d.2          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
tuuq6q1tlcib         \_ webapp_d.2      tomcat_app:8.5.40   docker_host_0       Shutdown            Running 16 minutes ago
nd8qg74l4t7b         \_ webapp_d.2      tomcat_app:8.5.40   docker_host_2       Shutdown            Shutdown 16 minutes ago
xazm6xhtji5d        webapp_d.3          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
e2ef0oc66sqh         \_ webapp_d.3      tomcat_app:8.5.40   docker_host_0       Shutdown            Running 44 minutes ago
oervwdwtj9ei        webapp_d.4          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
67mfqjvqgi7b         \_ webapp_d.4      tomcat_app:8.5.40   docker_host_0       Shutdown            Running 25 minutes ago
qrdqrzm2f6si        webapp_d.5          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
mejk0zee8ovy        webapp_d.6          tomcat_app:8.5.40   docker_host_1       Running             Running 2 minutes ago
[root@docker_host_1 opt]#

    将管理节点docker_host_2中的docker守护进程停止:

[root@docker_host_2 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Down                Active              Unreachable         18.09.6
upn0vc4vx47224gxaxn6hwec9     docker_host_1       Ready               Active              Reachable           18.09.6
jekdpdzmwcxrdfsxaudzbdp2z *   docker_host_2       Ready               Drain               Leader              18.09.6
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# systemctl stop docker
[root@docker_host_2 opt]#

    群集功能不可用,但仍可访问运行中的容器:

[root@docker_host_1 opt]# docker node ls
Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker service ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
[root@docker_host_1 opt]# docker service ps webapp_g
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
[root@docker_host_1 opt]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
da48a25cf5b2        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   13 minutes ago      Up 13 minutes       8080/tcp            webapp_d.4.oervwdwtj9eixi9ye225bfaqu
2cfc8b941397        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   13 minutes ago      Up 13 minutes       8080/tcp            webapp_d.2.wnrm2ndqjk7r6couisn3jhuuv
c419aa6ac995        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   13 minutes ago      Up 13 minutes       8080/tcp            webapp_d.3.xazm6xhtji5dir6xed8gdmmim
577267e59128        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   37 minutes ago      Up 37 minutes       8080/tcp            webapp_d.6.mejk0zee8ovyiukv2yxh88n4s
bfa09130f72f        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   37 minutes ago      Up 37 minutes       8080/tcp            webapp_d.5.qrdqrzm2f6siee5pz7a84p6gi
9c9455285a21        tomcat_app:8.5.40   "/bin/sh -c 'bin/cat…"   About an hour ago   Up About an hour    8080/tcp            webapp_d.1.e2eynnrned2j9732uhf1v0dhi
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# ss -atn | grep 8080
LISTEN     0      128         :::8080                    :::*
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# curl -I -o /dev/null -s -w %{http_code} 192.168.9.169:8080
200

2. 重建群集。

    在docker_host_1节点上手动强制重建群集,并移除失效的docker_host_0与docker_host_2节点:

[root@docker_host_1 opt]# docker swarm init --force-new-cluster
Swarm initialized: current node (upn0vc4vx47224gxaxn6hwec9) is now a manager.

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

    docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-434u94ack6bd9gwgxbvf2dqiw 192.168.9.169:2377

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

[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
5h6m2fspnhtg0lr0x6d481qdr     docker_host_0       Down                Active                                  18.09.6
upn0vc4vx47224gxaxn6hwec9 *   docker_host_1       Ready               Active              Leader              18.09.6
jekdpdzmwcxrdfsxaudzbdp2z     docker_host_2       Unknown             Drain                                   18.09.6
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker node rm docker_host_0
docker_host_0
[root@docker_host_1 opt]# docker node rm docker_host_2
docker_host_2
[root@docker_host_1 opt]#

    由于docker_host_1节点的/var/lib/docker/swarm/目录保存了群集状态数据,因此执行重建后,群集ID与先前一致(odbfcfeayjogvdn34m3nruq2f),表明并未创建新的群集。

[root@docker_host_1 opt]# ll /var/lib/docker/swarm/
total 8
drwxr-xr-x 2 root root  75 May 24 05:10 certificates
-rw------- 1 root root 193 May 24 07:24 docker-state.json
drwx------ 4 root root  55 May 24 05:10 raft
-rw------- 1 root root  69 May 24 07:24 state.json
drwxr-xr-x 2 root root  22 May 24 05:10 worker
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker info -f '{{.Swarm.Cluster.ID}}'
odbfcfeayjogvdn34m3nruq2f
[root@docker_host_1 opt]#
[root@docker_host_1 opt]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-cav7ypxfv6hzuyz5hq7jvn87l 192.168.9.169:2377

[root@docker_host_1 opt]#

    故障节点docker_host_0与docker_host_2强制脱离群集后,以管理角色重新加入:

[root@docker_host_0 opt]# systemctl start docker
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker swarm leave -f
Node left the swarm.
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-cav7ypxfv6hzuyz5hq7jvn87l 192.168.9.169:2377
This node joined a swarm as a manager.
[root@docker_host_0 opt]#
[root@docker_host_0 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
i6jberxzc51hprbtgh94e1nzw *   docker_host_0       Ready               Active              Reachable           18.09.6
upn0vc4vx47224gxaxn6hwec9     docker_host_1       Ready               Active              Leader              18.09.6
[root@docker_host_0 opt]#
[root@docker_host_2 opt]# systemctl start docker
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker swarm leave -f
Node left the swarm.
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker swarm join --token SWMTKN-1-4nsmenxl72484akypkevpirfse35u2ouxusbgemzzkuz0otgyv-cav7ypxfv6hzuyz5hq7jvn87l 192.168.9.169:2377
This node joined a swarm as a manager.
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
i6jberxzc51hprbtgh94e1nzw     docker_host_0       Ready               Active              Reachable           18.09.6
upn0vc4vx47224gxaxn6hwec9     docker_host_1       Ready               Active              Leader              18.09.6
sp544qzpe3ghr4ox6gvdv3ylo *   docker_host_2       Ready               Active              Reachable           18.09.6
[root@docker_host_2 opt]#

    群集恢复后,所有任务全部运行在docker_host_1节点:

[root@docker_host_2 opt]# docker service ps -f 'desired-state=running' webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
m9qad5jldkmf        webapp_d.1          tomcat_app:8.5.40   docker_host_1       Running             Running 22 minutes ago
43ycztehfjft        webapp_d.2          tomcat_app:8.5.40   docker_host_1       Running             Running 22 minutes ago
eu49cks7twj1        webapp_d.3          tomcat_app:8.5.40   docker_host_1       Running             Running 22 minutes ago
pagn85s95a4l        webapp_d.4          tomcat_app:8.5.40   docker_host_1       Running             Running 22 minutes ago
mep9zebz50be        webapp_d.5          tomcat_app:8.5.40   docker_host_1       Running             Running 22 minutes ago
q8cetbu1lgpa        webapp_d.6          tomcat_app:8.5.40   docker_host_1       Running             Running 22 minutes ago
[root@docker_host_2 opt]#

docker service update --force命令用于强制对群集任务进行负载均衡,该操作包括任务的停止与重新分配。

[root@docker_host_2 opt]# docker service update --force webapp_d
webapp_d
overall progress: 6 out of 6 tasks
1/6: running
2/6: running
3/6: running
4/6: running
5/6: running
6/6: running
verify: Service converged
[root@docker_host_2 opt]#
[root@docker_host_2 opt]# docker service ps -f 'desired-state=running' webapp_d
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
pezzriea1ql3        webapp_d.1          tomcat_app:8.5.40   docker_host_0       Running             Running 35 seconds ago
miehr525l161        webapp_d.2          tomcat_app:8.5.40   docker_host_2       Running             Running 22 seconds ago
ivo43js9eolh        webapp_d.3          tomcat_app:8.5.40   docker_host_1       Running             Running 13 seconds ago
ool0tu1tyke3        webapp_d.4          tomcat_app:8.5.40   docker_host_1       Running             Running 18 seconds ago
unysta4y6woe        webapp_d.5          tomcat_app:8.5.40   docker_host_0       Running             Running 26 seconds ago
j63gtlovl0k9        webapp_d.6          tomcat_app:8.5.40   docker_host_2       Running             Running 31 seconds ago
[root@docker_host_2 opt]#

参考

https://docs.docker.com/engine/reference/commandline/dockerd/
https://docs.docker.com/engine/swarm/
https://docs.docker.com/engine/swarm/admin_guide/
https://docs.docker.com/engine/api/v1.39/
https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html

 

本文发表于2019年05月24日 22:00
(c)注:本文转载自https://my.oschina.net/superwjc/blog/3053478,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1689 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1