Docker Swarm 之 节点(Node)

摘要

Docker Swarm 简介

  • Docker Swarm 是 Docker 官方提供的一个集群管理工具,基于 Docker Swarm 可以快速实现 Docker 集群的管理。

  • 从 Docker v1.12 版本开始,Docker Swarm 已经包含在 Docker Engine 中,不需要单独安装。

  • Docker Swarm 具有服务编排、服务负载均衡、服务升级和服务失败迁移等功能。

  • Docker Swarm 集群中的节点分为两种类型:管理节点(Manager Node)和工作节点(Worker Node),管理节点负责集群的管理,工作节点负责运行容器。

  • 以下是 Docker Swarm 中 管理节点(Manager Node) 和 工作节点(Worker Node) 的对比

特性/功能 管理节点(Manager Node) 工作节点(Worker Node)
角色 负责集群管理和决策 执行分配的服务任务
是否参与服务运行 可以运行服务任务,也可以只做管理(可配置) 仅运行服务任务,不参与管理决策
集群状态维护 维护整个 Swarm 的状态(使用 Raft 协议) 不维护集群状态
调度任务 决定将服务任务分配给哪个节点 不负责调度,只执行接收到的任务
管理命令处理 接收并处理 Swarm 管理命令(如创建服务、扩缩容等) 不处理管理命令
数据一致性 需要保持一致性(至少 3 个管理节点形成高可用) 不涉及一致性
资源要求 相对较高,需要承担管理和协调开销 相对较低,专注于运行容器
可用性要求 通常配置奇数个(3、5、7…)以保障高可用 可根据需要自由扩展或缩减
节点加入方式 通过 manager token 加入 Swarm 通过 worker token 加入 Swarm
故障影响 多个管理节点故障可能影响整个 Swarm 的控制能力 部分工作节点故障通常不会影响 Swarm 的管理能力
  • manager 节点通常配置为奇数个,默认创建集群的节点就是 manager 节点,并且是 manager 节点中的的 Leader 节点。Leader 节点负责管理集群,Leader 节点在集群中只能有一个。当 Leader 节点故障时,Swarm 会自动从其它 manager 节点中选举出一个新的 Leader 节点。

  • worker 节点是运行容器的节点,不参与机器的管理和调度,不支持执行任何和集群管理相关的操作。

  • 默认情况下,manager 节点也会参与接收运行容器的任务,但是可以通过设置来指定 manager 节点不参与接收任务。

  • manager 节点和 worker 节点可以通过“升级”和“降级”相互转换。

搭建Swarm集群

  • 本教程需要五台安装了Docker且能够通过网络通信的 Linux 主机,这些主机可以是物理机、虚拟机、Amazon EC2 实例,也可以以其他方式托管。

  • 其中三台机器是管理节点(称为manager1,manager2,manager3),另外两台是工作节点(worker1和worker2)。

IP 地址 HostName 角色类型
10.211.55.10 manager1 管理节点
10.211.55.11 manager2 管理节点
10.211.55.12 manager3 管理节点
10.211.55.13 worker1 工作节点
10.211.55.14 worker2 工作节点
  • 所有主机上必须开启如下端口,以确保Docker Swarm 集群正常通信:

端口号 协议 用途说明
2377 TCP 管理器节点之间通信(管理指令和加入集群)
7946 TCP/UDP 节点发现和通信(集群内部发现机制)
4789 UDP 覆盖网络流量(VXLAN,用于容器间网络)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 开放 Swarm 管理节点通信端口
sudo firewall-cmd --permanent --add-port=2377/tcp

# 节点发现(cluster communication)
sudo firewall-cmd --permanent --add-port=7946/tcp
sudo firewall-cmd --permanent --add-port=7946/udp

# overlay 网络流量(容器间通信)
sudo firewall-cmd --permanent --add-port=4789/udp

# 应用更改
sudo firewall-cmd --reload

# 查看防火墙状态
sudo firewall-cmd --list-all
  • 所有主机必须时间一致

1
2
3
4
5
6
7
8
# 同步系统时间
sudo systemctl restart chronyd
chronyc tracking
# 同步后系统时间显示为 UTC,而不是中国时区(CST/Asia/Shanghai)
# 设置时区为中国上海时间(CST)
sudo timedatectl set-timezone Asia/Shanghai
# 查看时间和时区
timedatectl

创建集群

  • 在 manager1 节点上执行如下命令来创建一个新的swarm集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 查看当前docker的swarm模式是否开启
docker info | grep "Swarm"
## 输出, inactive 表示没有开启swarm集群
Swarm: inactive

# 集群初始化
# docker swarm init --advertise-addr <MANAGER-IP>
docker swarm init --advertise-addr 10.211.55.10
## 参数说明
# --advertise-addr:指定当前节点的IP地址,用于集群中其他节点发现当前节点,端口默认2377
# 这个参数是可选的,如果节点上存在多个网卡,则需要指定当前节点的IP地址
## 输出
# swarm 初始化成功,当前节点成为 manager node,并自动成为集群的leader
Swarm initialized: current node (kp2zerd28xgz5mmglnje0jp22) is now a manager.
# 将一个worker node加入集群请运行下面的命令
To add a worker to this swarm, run the following command:
# 这个token不需要记住,可以通过命令 `docker swarm join-token worker` 获取
docker swarm join --token SWMTKN-1-256y3fmlkr5u76a5lor7jsboox2eztl954djhnuoj4p2x7dem4-0izbgc1xv73qulz31szmxnk3y 10.211.55.10:2377
# 添加一个manager node需要执行下面的命令获取 manager token
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

# 再次查看当前docker的swarm模式是否开启
docker info | grep Swarm
## 输出
Swarm: active

# 若要查看更为详细的信息,可以直接查看 Swarm 中的信息,也可以使用如下命令查看主要信息,此时集群中只有一个节点,并且是manager节点
docker info --format '{{json .Swarm}}' | jq '{LocalNodeState,NodeID,NodeAddr,RemoteManagers,Nodes,Nodes,Managers,ControlAvailable}' | yq -P
## 输出
LocalNodeState: active # 节点状态
NodeID: kp2zerd28xgz5mmglnje0jp22 # 节点ID
NodeAddr: 10.211.55.10 # 节点IP
RemoteManagers: [ # 节点管理节点信息
- NodeID: kp2zerd28xgz5mmglnje0jp22 # 节点管理节点ID
Addr: 10.211.55.10:2377 # 节点管理节点地址
Nodes: 1 # 节点数量
Managers: 1 # 管理节点数量
ControlAvailable: true # 是否有控制节点

安装 yq 工具

  • yq 是 yaml 的命令行处理工具,具体参考yq
1
2
3
4
5
6
7
8
# 下载 yq 最新版本
VERSION=v4.45.4
ARCH=amd64
wget https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_linux_${ARCH} -O /usr/local/bin/yq
# 添加执行权限
chmod +x /usr/local/bin/yq
# 验证安装
yq --version

添加 manager 节点

  • 获取 manager 节点的 token

1
2
3
4
5
6
# 在 manager1 上运行
docker swarm join-token manager
## 输出结果
To add a manager to this swarm, run the following command:

docker swarm join --token SWMTKN-1-256y3fmlkr5u76a5lor7jsboox2eztl954djhnuoj4p2x7dem4-byc8ygc6hdoyzna0in1btp9yu 10.211.55.10:2377
  • 将 manager2 和 manager3 加入 swarm 集群

1
2
3
4
5
6
7
# 分别在 manager2 和 manager3 上运行如下命令,
docker swarm join \
--token SWMTKN-1-256y3fmlkr5u76a5lor7jsboox2eztl954djhnuoj4p2x7dem4-byc8ygc6hdoyzna0in1btp9yu \
10.211.55.10:2377
## 如果机器上有多块网卡也需要指定ip: 如 --advertise-addr 10.211.55.11
## 运行结果
This node joined a swarm as a manager.

添加 worker 节点

  • 获取 worker 节点的 token

1
2
3
4
5
6
# 在 manager1 上运行
docker swarm join-token worker
## 输出结果
To add a worker to this swarm, run the following command:

docker swarm join --token SWMTKN-1-256y3fmlkr5u76a5lor7jsboox2eztl954djhnuoj4p2x7dem4-0izbgc1xv73qulz31szmxnk3y 10.211.55.10:2377
  • 将 worker1 和 worker2 加入 swarm 集群

1
2
3
4
5
6
7
# 分别在 worker1 和 worker2 上运行如下命令,
docker swarm join \
--token SWMTKN-1-256y3fmlkr5u76a5lor7jsboox2eztl954djhnuoj4p2x7dem4-0izbgc1xv73qulz31szmxnk3y \
10.211.55.10:2377
## 如果机器上有多块网卡也需要指定ip: 如 --advertise-addr 10.211.55.13
## 运行结果
This node joined a swarm as a worker.

查看集群状态

  • 在 manager1 上执行如下命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker info --format '{{json .Swarm}}' | jq '{LocalNodeState,NodeID,NodeAddr,RemoteManagers,Nodes,Nodes,Managers,ControlAvailable}' | yq -P
## 结果
LocalNodeState: active
NodeID: kp2zerd28xgz5mmglnje0jp22
NodeAddr: 10.211.55.10
RemoteManagers:
- NodeID: oymi74epagdqeprah7s81tsa2
Addr: 10.211.55.11:2377
- NodeID: r7388xl84nczjtnf53pwh7hla
Addr: 10.211.55.12:2377
- NodeID: kp2zerd28xgz5mmglnje0jp22
Addr: 10.211.55.10:2377
Nodes: 5
Managers: 3
ControlAvailable: true

查看集群内节点信息

  • 在 任意 manager 节点上运行如下命令

1
2
3
4
5
6
7
8
9
# 在 manager1 上运行,列出所有节点信息,只有 manager 节点支持 node 相关命令
docker node ls
## 运行结果
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
kp2zerd28xgz5mmglnje0jp22 * manager1 Ready Active Leader 26.1.3
oymi74epagdqeprah7s81tsa2 manager2 Ready Active Reachable 26.1.3
r7388xl84nczjtnf53pwh7hla manager3 Ready Active Reachable 26.1.3
v31visfparkcsr9hswkb6v09u worker1 Ready Active 26.1.3
lsxj50x8ftqw8etvz5y37xc5q worker2 Ready Active 26.1.3
字段名 示例值 中文含义
ID kp2zerd28xgz5mmglnje0jp22 节点的唯一 ID(在 swarm 集群中自动生成的唯一标识符)
HOSTNAME manager1 节点的主机名(即加入 swarm 集群时该节点的 hostname
STATUS Ready 节点的状态:
Ready:节点正常运行中
Down:节点离线或无法通信
Paused:暂停
Drain:排空,正在迁移任务
AVAILABILITY Active 节点的可用性设置:
Active:节点可以调度任务(默认)
Pause:暂停调度新任务
Drain:迁移任务并不再调度
MANAGER STATUS Leader / Reachable / 空 仅适用于管理节点:
Leader:当前 swarm 的主节点(负责协调)
Reachable:集群中可通信的管理节点
• 空:表示这是一个工作节点(非管理节点)
ENGINE VERSION 26.1.3 Docker 引擎的版本号(即该节点上运行的 Docker 版本)

docker swarm集群管理

命令 中文含义
ca 显示和轮换 Swarm 的根证书(CA)
init 初始化一个新的 Swarm 集群
join 将当前节点加入到 Swarm 中,作为工作节点或管理节点
join-token 管理用于加入 Swarm 的令牌(查看或重新生成)
leave 当前节点离开 Swarm 集群
unlock 解锁被加密的 Swarm(用于恢复 Manager 节点)
unlock-key 管理 Swarm 的解锁密钥(查看、备份等)
update 更新 Swarm 集群的全局配置(如加密、日志等)
  • docker swarm init: 初始化 Swarm 集群(只在首次创建时使用)

1
docker swarm init --advertise-addr 10.211.55.10
  • docker swarm join-token: 生成加入集群的令牌

1
2
3
4
# 生成 worker 节点的令牌
docker swarm join-token worker
# 生成 manager 节点的令牌
docker swarm join-token manager
  • docker swarm join: 加入 Swarm 集群(在已有 Swarm 集群中加入节点时使用)

1
docker swarm join --token <token> 10.211.55.10:2377
  • docker swarm leave: 使当前节点离开 Swarm 集群(从 Swarm 集群中移除节点时使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# worker 节点离开集群
docker swarm leave
# manager 节点必须先降级为 worker节点,或者加上 --force 强制离开
docker swarm leave --force
# 如果Leader节点离开集群,那么集群中的其它Manager节点,会重新选举一个新的Leader节点
# 集群中至少需要一个Manager节点,否则无法运行服务
# 节点离开swarm集群后,在 docker node ls中仍然可以看到,比如将 worker2 节点从集群中移除,其状态变为 down
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
kp2zerd28xgz5mmglnje0jp22 * manager1 Ready Active Leader 26.1.3
oymi74epagdqeprah7s81tsa2 manager2 Ready Active Reachable 26.1.3
r7388xl84nczjtnf53pwh7hla manager3 Ready Active Reachable 26.1.3
v31visfparkcsr9hswkb6v09u worker1 Ready Active 26.1.3
lsxj50x8ftqw8etvz5y37xc5q worker2 Down Active 26.1.3
# 如需彻底删除需要运行
docker node rm worker2
  • docker swarm update: 更新 Swarm 集群配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 开启Swarm集群锁定,只针对manager节点,manager节点重启后需要解锁才能恢复,下面的密钥不需要记住,通过`docker swarm unlock-key`命令查看
docker swarm update --autolock=true
## 输出
Swarm updated.
To unlock a swarm manager after it restarts, run the `docker swarm unlock`
command and provide the following key:

SWMKEY-1-X74/FGf+SkUkJEWtYok6ZFgCDAdwt3CQpOvLPT5lra4

Please remember to store this key in a password manager, since without it you
will not be able to restart the manager.

# 关闭Swarm集群锁定
docker swarm update --autolock=false
  • docker swarm unlock-key: 获取Swarm集群的解锁密钥,该命令可以判断Swarm集群是否被锁定

1
2
3
4
# 获取Swarm集群的解锁密钥
docker swarm unlock-key
# 轮换Swarm集群的解锁密钥
docker swarm unlock-key --rotate
  • docker swarm unlock: 手动解锁当前 manager 节点,使其在启用 autolock 时恢复功能

1
2
3
4
5
6
7
8
9
10
# 如果Swarm集群设置为锁定,则重启manager2上的docker服务后将无法运行node管理命令
systemctl restart docker
# 查看节点列表
docker node ls
## 输出
Error response from daemon: Swarm is encrypted and needs to be unlocked before it can be used. Please use "docker swarm unlock" to unlock it.
# 需要先解锁才可以运行节点管理命令
docker swarm unlock
## 会提示输入解锁密钥,解锁后就恢复正常了
Please enter unlock key:

docker node节点管理

  • 节点管理相关命令,只能在 管理节点 上执行

命令 中文含义
demote 将一个或多个管理节点降级为工作节点
inspect 显示一个或多个节点的详细信息
ls 列出 swarm 集群中的所有节点
promote 将一个或多个工作节点提升为管理节点
ps 查看一个或多个节点上正在运行的任务(默认当前节点)
rm 从 swarm 集群中移除一个或多个节点
update 更新节点的元数据(如标签、可用性等)
  • docker node ls: 列出 swarm 集群中的所有节点

1
docker node ls
  • docker node inspect <node_id>/<hostname>: 查看指定节点的详细信息

1
docker node inspect --pretty manager1
  • docker node update <options> <node_id>/<hostname>: 更新节点的元数据

1
2
3
4
5
6
# 设置节点为不可用
docker node update --availability drain manager1
# 添加标签
docker node update --label-add foo=bar manager1
# 删除标签
docker node update --label-rm foo manager1
  • docker node demote <node_id>/<hostname>: 将管理节点降级为工作节点

1
docker node demote manager1
  • docker note promote <node_id>/<hostname>: 将工作节点升级为管理节点

1
docker node promote worker1
  • docker node rm <node_id>/<hostname>: 从 swarm 集群中移除一个节点

1
docker node rm manager1

节点管理常见情况

如何正确的删除一个节点

  • 1.如果是 manager 节点,先将 manager 节点降级为 worker 节点

1
docker node demote manager1
  • 2.退出集群

1
2
# 在要退出集群的节点上执行
docker swarm leave
  • 3.删除节点

1
docker node rm manager1

节点被退群或删除后,其上运行的service会怎样?

  • 用一个示例来说明,先在 manager1 节点上创建一个 service

1
2
3
4
5
6
# --replicas 10 表示启动 10 个 nginx 容器,swarm集群有5个节点,所以启动10个nginx容器,每个节点会启动2个nginx容器
docker service create \
--name my-nginx \
--publish 8080:80 \
--replicas 10 \
nginx:latest
  • 查看service状态

1
2
3
4
5
6
7
8
9
10
11
12
13
docker service ps my-nginx
## 输出结果,可以看到每个节点上都启动了2个nginx容器
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
fciheo523fb3 my-nginx.1 nginx:latest manager2 Running Running about a minute ago
t9agioefr316 my-nginx.2 nginx:latest manager2 Running Running about a minute ago
moitlj50nunh my-nginx.3 nginx:latest manager3 Running Running 2 minutes ago
x07voc2qth5q my-nginx.4 nginx:latest manager1 Running Running about a minute ago
p8khdhngz0xm my-nginx.5 nginx:latest manager3 Running Running 2 minutes ago
i6mieuodbrtg my-nginx.6 nginx:latest worker2 Running Running about a minute ago
2yohffzzsrrl my-nginx.7 nginx:latest worker1 Running Running 2 minutes ago
f3lusxoflqn2 my-nginx.8 nginx:latest worker2 Running Running about a minute ago
xovzfmzsjlet my-nginx.9 nginx:latest worker1 Running Running 2 minutes ago
ndrz827kpu2k my-nginx.10 nginx:latest manager1 Running Running about a minute ago
  • 这时将 worker2 从集群中退群

1
2
3
4
5
6
7
8
9
10
# 在worker2节点执行
docker swarm leave
# 在manager节点查看集群节点
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
kp2zerd28xgz5mmglnje0jp22 * manager1 Ready Active Leader 26.1.3
oymi74epagdqeprah7s81tsa2 manager2 Ready Active Reachable 26.1.3
r7388xl84nczjtnf53pwh7hla manager3 Ready Active Reachable 26.1.3
v31visfparkcsr9hswkb6v09u worker1 Ready Active 26.1.3
x87lfn4pzorahpr9zehv9ag3f worker2 Down Active 26.1.3
  • 再次查看service状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker service ps my-nginx
# 输出,可以看到worker2节点上的容器已经被关闭,新的容器在其它节点上启动了,保证了service中的容器数量
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
fciheo523fb3 my-nginx.1 nginx:latest manager2 Running Running 6 minutes ago
t9agioefr316 my-nginx.2 nginx:latest manager2 Running Running 6 minutes ago
moitlj50nunh my-nginx.3 nginx:latest manager3 Running Running 6 minutes ago
x07voc2qth5q my-nginx.4 nginx:latest manager1 Running Running 6 minutes ago
p8khdhngz0xm my-nginx.5 nginx:latest manager3 Running Running 6 minutes ago
uz7wam5ul4aa my-nginx.6 nginx:latest manager2 Running Running 43 seconds ago
i6mieuodbrtg \_ my-nginx.6 nginx:latest worker2 Shutdown Running 6 minutes ago
2yohffzzsrrl my-nginx.7 nginx:latest worker1 Running Running 6 minutes ago
34km8mzg3xat my-nginx.8 nginx:latest manager3 Running Running 43 seconds ago
f3lusxoflqn2 \_ my-nginx.8 nginx:latest worker2 Shutdown Running 6 minutes ago
xovzfmzsjlet my-nginx.9 nginx:latest worker1 Running Running 6 minutes ago
ndrz827kpu2k my-nginx.10 nginx:latest manager1 Running Running 6 minutes ago
  • 如果不退群直接删除节点呢?这次我们直接删除 worker1 节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 删除 worker1 节点
docker node rm worker1
# 输出,提示 worker1 节点不是 down 状态,不能删除
# Error response from daemon: rpc error: code = FailedPrecondition desc = node v31visfparkcsr9hswkb6v09u is not down and can't be removed

# 接着我们强制删除
docker node rm -f worker1
# 查看节点列表
docker node ls
# 输出,可以看到worker1节点已经删除了
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
kp2zerd28xgz5mmglnje0jp22 * manager1 Ready Active Leader 26.1.3
oymi74epagdqeprah7s81tsa2 manager2 Ready Active Reachable 26.1.3
r7388xl84nczjtnf53pwh7hla manager3 Ready Active Reachable 26.1.3
x87lfn4pzorahpr9zehv9ag3f worker2 Down Active 26.1.3

# 再次查看service状态
docker service ps my-nginx
## 输出,可以看到worker1(因为worker1节点已经被删除,所以这里只会显示节点ID:v31visfparkcsr9hswkb6v09u)节点上的容器已经被关闭,新的容器在其它节点上启动了,保证了service中的容器数量
docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
fciheo523fb3 my-nginx.1 nginx:latest manager2 Running Running 12 minutes ago
t9agioefr316 my-nginx.2 nginx:latest manager2 Running Running 12 minutes ago
moitlj50nunh my-nginx.3 nginx:latest manager3 Running Running 12 minutes ago
x07voc2qth5q my-nginx.4 nginx:latest manager1 Running Running 12 minutes ago
p8khdhngz0xm my-nginx.5 nginx:latest manager3 Running Running 12 minutes ago
uz7wam5ul4aa my-nginx.6 nginx:latest manager2 Running Running 6 minutes ago
i6mieuodbrtg \_ my-nginx.6 nginx:latest worker2 Shutdown Running 12 minutes ago
3t4qvpvrzpg3 my-nginx.7 nginx:latest manager1 Running Running about a minute ago
2yohffzzsrrl \_ my-nginx.7 nginx:latest v31visfparkcsr9hswkb6v09u Shutdown Orphaned about a minute ago
34km8mzg3xat my-nginx.8 nginx:latest manager3 Running Running 6 minutes ago
f3lusxoflqn2 \_ my-nginx.8 nginx:latest worker2 Shutdown Running 12 minutes ago
4w5zfpfye3t8 my-nginx.9 nginx:latest manager1 Running Running about a minute ago
xovzfmzsjlet \_ my-nginx.9 nginx:latest v31visfparkcsr9hswkb6v09u Shutdown Orphaned about a minute ago
ndrz827kpu2k my-nginx.10 nginx:latest manager1 Running Running 12 minutes ago

节点被退群或删除后是否可以重新加入集群

  • 节点被退群或删除后,可以通过 docker swarm join 命令重新加入集群

  • 若节点是被强制删除,而没有退群,则重新加入集群时需要先通过 docker swarm leave 命令退群后再加入集群

如果Swarm集群设置为锁定,则重启manager节点后无法提供集群服务的解决方法

1
2
3
4
5
6
7
8
9
10
11
12
13
# 这里重启一个manager节点的docker服务
systemctl restart docker
# 查看节点列表
docker node ls
## 输出
Error response from daemon: Swarm is encrypted and needs to be unlocked before it can be used. Please use "docker swarm unlock" to unlock it.
# 需要先解锁才可以运行节点管理命令
docker swarm unlock
## 会提示输入解锁密钥,解锁后就恢复正常了
Please enter unlock key:
## 如果忘记了密钥,可以在其它manager节点通过如下命令查看
docker swarm unlock-key
# 如果所有manager节点都重启了,你又没有记录解锁密钥,那么恭喜你,只能重新创建swarm集群了

Swarm 集群锁定功能的作用及使用场景

  • 作用

✅ 作用 📋 说明
加密保护管理密钥 管理器节点之间的数据(如 Raft 日志)虽然默认加密,但密钥保存在内存中。启用锁定功能后,密钥在节点重启时不会自动加载,必须手动提供解锁密钥才能恢复。
防止节点被非法重启后加入集群 如果攻击者获得了管理节点的物理访问权限(如重启、磁盘克隆等),锁定功能可以防止其自动控制或重新加入 Swarm 集群。
  • 场景

场景类型 具体描述
✅ 适合场景 对安全性要求高的生产环境
部署在不可信或共享物理环境中
云服务器、数据中心有专人运维管理解锁过程
希望防止物理/远程入侵者恢复管理器角色的公司
❌ 不适合场景 需要自动化部署或重启的 CI/CD 系统
测试环境或开发集群
无人值守、要求高可用自动恢复的部署系统
  • 总结

项目 是否推荐
安全性 ✅ 强烈推荐启用(尤其在生产环境)
自动化 ❌ 不推荐(增加人工干预步骤)
解锁方式 解锁命令 + unlock key
unlock key 丢失后果 可能需要重建 Swarm(除非提前备份)

docker swarm ca 是做什么用的?

  • docker swarm ca 命令是用来 管理 Swarm 集群中的根证书颁发机构(CA) 的工具。具体功能包括:

子命令/参数 说明
docker swarm ca 查看当前 Swarm 的根 CA 公钥(PEM 格式)
docker swarm ca --rotate 轮换根 CA,用于安全更新
  • Swarm 中的证书是干什么用的?

用途 说明
✅ 节点身份验证 每个节点加入集群时,都会收到一个由根 CA 签发的 TLS 证书,用于证明它的身份。
🔐 通信加密 节点之间(Manager ↔ Worker)的通信通过 TLS 进行加密。
🔄 自动轮换 Docker 会自动为每个节点签发短期证书(默认有效期 90 天)并定期自动轮换。
  • Swarm 在后台自动管理证书,所以你不需要手动处理它们。不过,你可以在每个节点上找到它们的位置:

1
2
3
4
5
6
cd /var/lib/docker/swarm/certificates
tree
.
├── swarm-node.crt # 节点证书
├── swarm-node.key # 节点密钥
└── swarm-root-ca.crt # 根CA证书

只让 Manager 做管理,不运行服务

  • 节点的AVAILABILITY有三种:activepausedrain

状态 说明
active 可调度,Swarm 可以在此节点上运行服务任务(默认)
pause 暂停调度,不会分配新任务,但保留已有任务
drain 排空模式,不可调度,Swarm 会将该节点上的任务迁移到其他节点,新的任务将不会分配到此节点
  • 如果你希望 Swarm Manager 节点仅参与管理工作,而不运行服务任务(task),你可以通过 设置节点的可调度状态为“不可调度” 来实现这一目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 设置 manager1 节点为“不可调度”,即 排空模式
docker node update --availability drain manager1
# 查看节点状态
docker node ls
## 输出,manager1 节点状态变为 排空
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
kp2zerd28xgz5mmglnje0jp22 * manager1 Ready Drain Reachable 26.1.3
oymi74epagdqeprah7s81tsa2 manager2 Ready Active Reachable 26.1.3
r7388xl84nczjtnf53pwh7hla manager3 Ready Active Leader 26.1.3
xkww4853bbdgv7bv8771xibob worker1 Ready Active 26.1.3
hvzkh3ip5ef8gx973z1ywahbu worker2 Ready Active 26.1.3
# 查看服务状态
docker service ps my-nginx
## 输出,可以看到 manager1 节点上的任务已经关闭,并且在其它节点上运行了任务。
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
23m03nj54mzo my-nginx.1 nginx:latest worker2 Running Running 35 seconds ago
9xi83bnh4fus my-nginx.2 nginx:latest worker2 Running Running 35 seconds ago
wos8tbk449lk my-nginx.3 nginx:latest manager2 Running Running 28 seconds ago
uosmuh6bvwm0 \_ my-nginx.3 nginx:latest manager1 Shutdown Shutdown 7 seconds ago
yeqhqc3f735y my-nginx.4 nginx:latest manager2 Running Running about a minute ago
g8rduix7s74v my-nginx.5 nginx:latest worker2 Running Running less than a second ago
wuxilgpv9f50 \_ my-nginx.5 nginx:latest manager1 Shutdown Shutdown 7 seconds ago
3bxtn9boit28 my-nginx.6 nginx:latest manager3 Running Running 28 seconds ago
57kdggaf8sag my-nginx.7 nginx:latest manager2 Running Running about a minute ago
uugi506p74s8 my-nginx.8 nginx:latest worker1 Running Running 28 seconds ago
yifwpqjnts9l my-nginx.9 nginx:latest worker1 Running Running 28 seconds ago
yv4p6su7aom5 my-nginx.10 nginx:latest manager3 Running Running 28 seconds ago

# 恢复运行任务能力
docker node update --availability active manager1

# 停止接收新的任务但保留运行中的任务
docker node update --availability pause manager1