概述
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