Docker Swarm
学习来源:
Swarm 简介
Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。

docker swarm:管理集群
# 初始化一个swarm
docker swarm init [OPTIONS]
# 选项:
--advertise-addr string # 发布的地址(格式:<ip|interface>[:port])
--force-new-cluster # 强制从当前状态创建一个新的集群(去除本地之外的所有管理器身份)
--cert-expiry duration # 节点证书有效期(ns|us|ms|s|m|h)(默认为2160h0m0s)
--data-path-addr string # 用于数据路径通信的地址或接口(格式: <ip|interface>)
--data-path-port uint32 # 用于数据路径流量的端口号(1024 - 49151)。如果没有值,则默认端口号4789
--dispatcher-heartbeat duration # 调度程序的心跳周期(ns|us|ms|s|m|h)(默认为5s)
--listen-addr node-addr # 监听地址(格式: <ip|interface>[:port]) (默认 0.0.0.0:2377)
# 查看加入节点到集群的命令及令牌(token)
docker swarm join-token [OPTIONS] (worker|manager)
# 选项:
-q, --quiet # 只显示令牌
--rotate # 使旧令牌无效并生成新令牌
# 查看加入工作节点到集群的命令及令牌
docker swarm join-token worker
# 查看加入管理节点到集群的命令及令牌
docker swarm join-token manager
# 将节点加入swarm集群,作为一个manager或worker
docker swarm join [OPTIONS] HOST:PORT
# 选项:
--advertise-addr string # 发布的地址 (格式: <ip|interface>[:port])
--availability string # 节点的可用性 ("active"|"pause"|"drain") (default "active")
--data-path-addr string # 用于数据路径通信的地址或接口 (格式: <ip|interface>)
--listen-addr node-addr # 监听地址 (格式: <ip|interface>[:port]) (default 0.0.0.0:2377)
--token string # 进入的swarm集群的令牌
# 主动退出集群,让节点处于down状态(在需要退出Swarm集群的节点主机上执行命令)
docker swarm leave [OPTIONS]
# 选项:
-f, --force # 强制。Manager若要退出 Swarm 集群,需要加上强制选项
## 移除一个work-node节点主机的完整步骤:
# 1.在管理节点上操作,清空work-node节点的容器。id 可以使用命令 docker node ls 查看
docker node update --availability drain [id]
# 2.在work-node节点主机上操作,退出集群
docker swarm leave
# 3,在管理节点上操作,删除work-node节点
docker node rm [id]
# 若想解散整个集群,则需先移除所有work-node节点主机,然后所有管理节点也退出集群
# 更新 swarm 集群的配置
docker swarm update [OPTIONS]
# 选项:
--autolock # 更改管理器自动锁定设置(true|false)
--cert-expiry duration # 节点证书有效期(ns|us|ms|s|m|h)(默认为2160h0m0s)
--dispatcher-heartbeat duration # 调度程序心跳周期(ns|us|ms|s|m|h)(默认为5s)
docker node:管理swarm集群节点
# 查看集群中的节点
docker node ls
#选项:
-f, --filter filter # 根据所提供的条件过滤输出。(格式:key=value)
# 目前支持的过滤器是:id, label, name, membership[=accepted|pending]
# , role[manager|worker]
-q, --quiet # 只显示id
# 查看运行的一个或多个及节点任务数,默认当前节点
docker node ps [OPTIONS] [NODE...]
#选项:
-f, --filter filter # 根据所提供的条件过滤输出
-q, --quiet # 只显示id
# 将worker角色升级为manager
docker node promote NODE [NODE...]
# 将manager角色降级为worker
docker node demote NODE [NODE...]
# 查看节点的详细信息,默认json格式
docker node inspect 主机名
# 查看节点信息平铺格式
docker node inspect --pretty 主机名
# 从swarm中删除一个节点
docker node rm 主机名
# 从swarm中强制删除一个节点
docker node rm -f 主机名
# 更新一个节点
docker node update [options] 主机名
# 选项
--label-add list # 添加节点标签(key=value)
--label-rm list # 删除节点标签
--role string # 更改节点角色 ("worker"|"manager")
--availability active/pause/drain # 设置节点的状态
# active 正常
# pause 暂停。调度程序不向节点分配新任务,但是现有任务仍然保持运行
# drain 排除自身work任务。调度程序不向节点分配新任务,且会关闭任何现有任务并在可用节点上安排它们
docker service:服务管理
# 列出服务列表
docker service ls
# 列出服务任务信息
docker service ps [OPTIONS] SERVICE [SERVICE...]
# 选项:
--no-trunc # 显示完整的信息
-f, --filter filter # 根据所提供的条件过滤输出。过滤只运行的任务信息:"desired-state=running"
-q, --quiet # 只显示任务id
# 查看服务内输出
docker service logs [OPTIONS] SERVICE|TASK
# 选项:
--details # 显示提供给日志的额外细节
-f, --follow # 跟踪日志输出
--since string # 显示自时间戳 (2013-01-02T13:23:37Z) 或相对时间戳 (42m for 42 minutes) 以来的日志
-n, --tail string # 从日志末尾显示的行数(默认为“all”)
-t, --timestamps # 显示时间戳
# 更新服务的相关配置
docker service update [options] 服务名
# 选项
--args "指令" # 容器加入指令
--image IMAGE # 更新服务容器镜像
--rollback # 回滚服务容器版本
--network-add 网络名 # 添加容器网络
--network-rm 网络名 # 删除容器网络
--reserve-cpu int # 更新分配的cpu
--reserve-memory bytes # 更新分配的内存(示例:512m)
--publish-add 暴露端口:容器端口 # 映射容器端口到主机
--publish-rm 暴露端口:容器端口 # 移除暴露端口
--endpoint-mode dnsrr # 修改负载均衡模式为dnsrr
--force # 强制重启服务
--config-rm 配置文件名称 # 删除配置文件
--constraint-add list # 新增一个约束
--constraint-rm list # 移除一个约束
--placement-pref-add pref # 新增一个偏好
--placement-pref-rm pref # 移除一个偏好
--config-add 配置文件名,target=/../容器内配置文件名 # 添加新的配置文件到容器内
# 查看服务详细信息,默认json格式
docker service inspect [OPTIONS] 服务名 [SERVICE...]
# 查看服务信息平铺形式
docker service inspect --pretty 服务名
# 删除服务
docker service rm [OPTIONS] 服务名 [SERVICE...]
# 缩容扩容服务容器副本数量
docker service scale 服务名=副本数 [SERVICE=REPLICAS...]
# 创建一个服务。一般搭建好 Swarm 集群后,使用 docker stack 部署应用,此处仅作了解
docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]
# 选项:
--name string # 指定容器名称
--replicas int # 指定副本数
--network 网络名 # 添加网络组
--mode string # 服务模式(复制或全局)(replicated | global)
--reserve-cpu int # 预留的cpu
--reserve-memory bytes # 预留的内存(512m)
--limit-cpu int # 限制CPU
--limit-memory bytes # 限制内存(512m)
-l, --label list # 服务的标签(key=value)
--container-label list # 容器标签(key=value)
-p, --publish 暴露端口:容器端口 # 映射容器端口到主机
-e, --env MYVAR=myvalue # 配置环境变量
-w, --workdir string # 指定工作目录(示例:/tmp)
-restart-condition string # 满足条件时重新启动(no | always | on-failure | unless-stopped)
--restart-delay duration # 重新启动尝试之间的延迟 (ns/us/ms/s/m/h)
--restart-max-attempts int # 放弃前的最大重启次数
--restart-window duration # 用于评估重启策略的窗口 (ns/us/ms/s/m/h)
--stop-grace-period duration # 强制杀死容器前的等待时间 (ns/us/ms/s/m/h)
--update-delay duration # 更新之间的延迟(ns/us/ms/s/m/h)(默认 0s)
--update-failure-action string # 更新失败的操作("pause"停止|"continue"继续)(默认pause)
--update-max-failure-ratio float # 更新期间容忍的失败率
--update-monitor duration # 每次任务更新后监控失败的持续时间(ns/us/ms/s/m/h)(默认 0s)
--update-parallelism int # 同时更新的最大任务数(0表示一次更新全部任务)(默认为1)
--endpoint-mode string # 负载均衡模式(vip or dnsrr) (默认 "vip")
--rollback-monitor 20s # 每次容器与容器之间的回滚时间间隔
--rollback-max-failure-ratio .数值 # 回滚故障率如果小于百分比允许运行(“.2”为%20)
--mount type=volume,src=volume名称,dst=容器目录 # 创建volume类型数据卷
--mount type=bind,src=宿主目录,dst=容器目录 # 创建bind读写目录挂载
--mount type=bind,src=宿主目录,dst=容器目录,readonly # 创建bind只读目录挂载
--config source=docker配置文件,target=配置文件路径 # 创建docker配置文件到容器本地目录
docker secret:管理敏感数据存储
# 查看敏感数据卷列表
$ docker secret ls
# 显示一个或多个敏感数据卷的详细信息
$ docker secret inspect [OPTIONS] SECRET [SECRET...]
# 选项
--pretty # 易读的格式打印信息
# 从文件或标准输入创建一个敏感数据卷作为内容
$ docker secret create [OPTIONS] SECRET [file|-]
# 选项
-d, --driver string # 指定驱动
-l, --label list # 指定标签
--template-driver string # 指定模板驱动程序
# 移除一个或多个敏感数据卷
$ docker secret rm SECRET [SECRET...]
# 别名:rm, remove
docker config:管理配置文件
# 查看已创建配置文件
docker config ls [OPTIONS]
# 选项:
-f, --filter filter # 根据所提供的条件过滤输出
-q, --quiet # 只显示id
# 查看配置详细信息
docker config inspect 配置文件名
# 删除配置
docker config rm CONFIG [CONFIG...]
# 创建配置文件
docker config create 配置文件名 本地配置文件
# 示例:新建配置文件并添加新配置文件到服务
# 1.创建配置文件
docker config create nginx2_config nginx2.conf
# 2.删除旧配置文件
docker service update --config-rm ce_nginx_config 服务名
# 3.添加新配置文件到服务
docker service update --config-add src=nginx2_config,target=/etc/nginx/nginx.conf ce_nginx
docker network: 网络信息
# 查看集群网络列表
docker network ls
# 将容器连接到集群网络中
$ docker network connect [OPTIONS] NETWORK CONTAINER
# 选项
--alias strings # 为容器添加网络范围的别名
--driver-opt string · # 指定网络驱动程序
--ip string # 指定IPv4地址(如172.30.100.104)
--ip6 string # 指定IPv6地址(例如,2001:db8::33)
--link list # 添加到另一个容器的链接
--link-local-ip string # 为容器添加一个链接本地地址
# 示例
docker network connect mynet nginx
# 断开一个容器与集群网络的连接
$ docker network disconnect [OPTIONS] NETWORK CONTAINER
# 选项
-f, --force # 强制容器从网络断开连接
# 显示一个或多个集群网络的详细信息
$ docker network inspect [OPTIONS] NETWORK [NETWORK...]
# 选项
-f, --format string # 使用给定的Go模板格式化输出
-v, --verbose # 输出详细的诊断信息
# 创建一个集群网络
$ docker network create [OPTIONS] NETWORK
# 选项
--attachable # 准许手动容器连接
--aux-address map # 网络驱动使用的辅助IPv4或IPv6地址(默认映射[])
--config-from string # 要从其中复制配置的网络
--config-only # 创建仅配置网络
-d, --driver string # 管理网络的驱动程序(默认为“"bridge”)。选项:bridge、overlay、macvlan
--gateway strings # 指定IPv4或IPv6主子网网关。示例:172.20.0.1
--ingress # 创建群路由-网格网络
--internal # 限制外部访问网络
--ip-range strings # 从子范围分配容器ip
--ipam-driver string # IP管理驱动(默认为“default”)
--ipam-opt map # 设置IPAM驱动程序的特定选项(默认map[])
--ipv6 # 启用IPv6网络
--label list # 在网络中设置元数据
-o, --opt map # 设置驱动程序特定选项(默认map[])
--scope string # 控制网络的范围
--subnet strings # 指定一个CIDR格式的网段。示例:172.20.0.0/24
# 示例:
docker network create -d overlay --attachable apps_net
# 移除所有未使用的集群网络
$ docker network prune [OPTIONS]
# 选项
--filter filter # 提供过滤值(e.g. 'until=<timestamp>')
-f, --force # 强制,没有提示确认
# 删除一个或多个集群网络
$ docker network rm NETWORK [NETWORK...]
# 别名:rm, remove
开始配置
环境准备
1、修改主机名 2、配置IP地址 3、关闭防火墙和SELINUX安全模式 4、配置系统YUM源和Docker镜像源 5、更新系统(yum update -y) 6、安装好docker环境
初始化集群
docker swarm init --advertise-addr 192.168.65.148
root@chenjx12-0:~# docker swarm init --advertise-addr 192.168.65.148
Swarm initialized: current node (1e0chr8bpn27vlq9g056zy7a2) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-10u0nu575ou6thien8kscddxebzsnatljdytcas3n9sgin5jog-9cu9j19pfitelu1oap7rgdlub 192.168.65.148:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
root@chenjx12-0:~# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-10u0nu575ou6thien8kscddxebzsnatljdytcas3n9sgin5jog-ejpgz6tdq0xsm3c6qjrstq299 192.168.65.148:2377
让其他节点加入集群
root@chenjx12-0:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
1e0chr8bpn27vlq9g056zy7a2 * chenjx12-0 Ready Active Leader 27.3.1
jb55cgd88n5tl2ybdokhznq1t chenjx12-1 Ready Active 27.3.1
oav94gisk9wm4mfuqvzpfhqzh chenjx12-2 Ready Active 27.3.1
g6vxdk2myltc9i9lwx1zr3s4i chenjx12-3 Ready Active 27.3.1
查看详细情况
root@chenjx12-0:~# docker info
Client: Docker Engine - Community
Version: 27.3.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.17.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.29.7
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 27.3.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: active
NodeID: 1e0chr8bpn27vlq9g056zy7a2
Is Manager: true
ClusterID: ye2nnvev8mzdyv0g56ee0ka6w
Managers: 1
Nodes: 4
Data Path Port: 4789
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.65.148
Manager Addresses:
192.168.65.148:2377
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
runc version: v1.1.14-0-g2c9f560
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.1.0-26-amd64
Operating System: Debian GNU/Linux 12 (bookworm)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 1.887GiB
Name: chenjx12-0
ID: 8d684424-29b4-4611-8a59-d4ce19b0f9da
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
查看网络信息
root@chenjx12-0:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
a162d4d5a77e bridge bridge local
1f622764003c docker_gwbridge bridge local
8f11bd442416 host host local
d8isx3sccunf ingress overlay swarm
3b8eea1a0902 none null local
root@chenjx12-0:~# docker network inspect d8isx3sccunf
[
{
"Name": "ingress",
"Id": "d8isx3sccunf33xeb63c1v21x",
"Created": "2024-10-28T19:50:32.014998441+08:00",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.0.0/24",
"Gateway": "10.0.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": true,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"ingress-sbox": {
"Name": "ingress-endpoint",
"EndpointID": "f2dd609d5bc4ba0cb7206b7e4bdc3cd1ba232d727841b693805eecd1b591f7b9",
"MacAddress": "02:42:0a:00:00:02",
"IPv4Address": "10.0.0.2/24",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.driver.overlay.vxlanid_list": "4096"
},
"Labels": {},
"Peers": [
{
"Name": "b4947f7ebf00",
"IP": "192.168.65.148"
},
{
"Name": "bac21fa67653",
"IP": "192.168.65.154"
},
{
"Name": "d6c037335dd0",
"IP": "192.168.65.155"
},
{
"Name": "3b5f5c73c94c",
"IP": "192.168.65.152"
}
]
}
]
更换节点的角色(manager – worker)
root@chenjx12-0:~# docker node update -h
Flag shorthand -h has been deprecated, use --help
Usage: docker node update [OPTIONS] NODE
Update a node
Options:
--availability string Availability of the node ("active", "pause", "drain")
--label-add list Add or update a node label ("key=value")
--label-rm list Remove a node label if exists
--role string Role of the node ("worker", "manager")
root@chenjx12-0:~# docker node update --role manager chenjx12-1
chenjx12-1
root@chenjx12-0:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
1e0chr8bpn27vlq9g056zy7a2 * chenjx12-0 Ready Active Leader 27.3.1
jb55cgd88n5tl2ybdokhznq1t chenjx12-1 Ready Active Reachable 27.3.1
oav94gisk9wm4mfuqvzpfhqzh chenjx12-2 Ready Active 27.3.1
g6vxdk2myltc9i9lwx1zr3s4i chenjx12-3 Ready Active 27.3.1
root@chenjx12-0:~# docker node update --role worker chenjx12-1
chenjx12-1
root@chenjx12-0:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
1e0chr8bpn27vlq9g056zy7a2 * chenjx12-0 Ready Active Leader 27.3.1
jb55cgd88n5tl2ybdokhznq1t chenjx12-1 Ready Active 27.3.1
oav94gisk9wm4mfuqvzpfhqzh chenjx12-2 Ready Active 27.3.1
g6vxdk2myltc9i9lwx1zr3s4i chenjx12-3 Ready Active 27.3.1
节点退出集群
在3号节点上使用命令,回到0号节点发现3号节点下线了(down)
root@chenjx12-0:~# docker swarm leave -h
Flag shorthand -h has been deprecated, use --help
Usage: docker swarm leave [OPTIONS]
Leave the swarm
Options:
-f, --force Force this node to leave the swarm, ignoring warnings
root@chenjx12-3:~# docker swarm leave -f
Node left the swarm.
root@chenjx12-0:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
1e0chr8bpn27vlq9g056zy7a2 * chenjx12-0 Ready Active Leader 27.3.1
jb55cgd88n5tl2ybdokhznq1t chenjx12-1 Ready Active 27.3.1
oav94gisk9wm4mfuqvzpfhqzh chenjx12-2 Ready Active 27.3.1
g6vxdk2myltc9i9lwx1zr3s4i chenjx12-3 Down Active 27.3.1
删除节点
docker node rm [id]
注意,删除节点无法删除manager管理节点,需要先--role worker,才能rm
服务部署
查看help
root@chenjx12-0:~# docker service
Usage: docker service COMMAND
Manage Swarm services
Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services
update Update a service
Run 'docker service COMMAND --help' for more information on a command.
先在leader上pull一个nginx
root@chenjx12-0:/etc/docker# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a480a496ba95: Pull complete
f3ace1b8ce45: Pull complete
11d6fdd0e8a7: Pull complete
f1091da6fd5c: Pull complete
40eea07b53d8: Pull complete
6476794e50f4: Pull complete
70850b3ec6b2: Pull complete
Digest: sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
使用service命令启动Nginx
root@chenjx12-0:~# docker service create -p 8888:80 --name xybdiy-nginx nginx
qvx9t2qskhr8g0r1i7y5f9ub9
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service qvx9t2qskhr8g0r1i7y5f9ub9 converged
使用docker services创建服务,具有扩缩容,滚动更新
查看服务
root@chenjx12-0:~# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
qvx9t2qskhr8 xybdiy-nginx replicated 1/1 nginx:latest *:8888->80/tcp
root@chenjx12-0:~# docker service ps xybdiy-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7jzyf300ygqh xybdiy-nginx.1 nginx:latest chenjx12-1 Running Running about a minute ago
root@chenjx12-0:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@chenjx12-1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1efdebcefcd0 nginx:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 80/tcp xybdiy-nginx.1.7jzyf300ygqhnj8zfukkjmrtp
root@chenjx12-0:~# docker service inspect xybdiy-nginx
[
{
"ID": "qvx9t2qskhr8g0r1i7y5f9ub9",
"Version": {
"Index": 76
},
"CreatedAt": "2024-10-28T13:46:32.118348646Z",
"UpdatedAt": "2024-10-28T13:46:32.127340473Z",
"Spec": {
"Name": "xybdiy-nginx",
"Labels": {},
"TaskTemplate": {
"ContainerSpec": {
"Image": "nginx:latest@sha256:28402db69fec7c17e179ea87882667f1e054391138f77ffaf0c3eb388efc3ffb",
"Init": false,
"StopGracePeriod": 10000000000,
"DNSConfig": {},
"Isolation": "default"
},
"Resources": {
"Limits": {},
"Reservations": {}
},
"RestartPolicy": {
"Condition": "any",
"Delay": 5000000000,
"MaxAttempts": 0
},
"Placement": {
"Platforms": [
{
"Architecture": "amd64",
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"Architecture": "arm64",
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"Architecture": "386",
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"Architecture": "mips64le",
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"Architecture": "ppc64le",
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
},
{
"Architecture": "s390x",
"OS": "linux"
},
{
"Architecture": "unknown",
"OS": "unknown"
}
]
},
"ForceUpdate": 0,
"Runtime": "container"
},
"Mode": {
"Replicated": {
"Replicas": 1
}
},
"UpdateConfig": {
"Parallelism": 1,
"FailureAction": "pause",
"Monitor": 5000000000,
"MaxFailureRatio": 0,
"Order": "stop-first"
},
"RollbackConfig": {
"Parallelism": 1,
"FailureAction": "pause",
"Monitor": 5000000000,
"MaxFailureRatio": 0,
"Order": "stop-first"
},
"EndpointSpec": {
"Mode": "vip",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 80,
"PublishedPort": 8888,
"PublishMode": "ingress"
}
]
}
},
"Endpoint": {
"Spec": {
"Mode": "vip",
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 80,
"PublishedPort": 8888,
"PublishMode": "ingress"
}
]
},
"Ports": [
{
"Protocol": "tcp",
"TargetPort": 80,
"PublishedPort": 8888,
"PublishMode": "ingress"
}
],
"VirtualIPs": [
{
"NetworkID": "d8isx3sccunf33xeb63c1v21x",
"Addr": "10.0.0.5/24"
}
]
}
}
]
可以看到该服务被部署到1号节点上,0节点本地docker ps是没有的,而1节点下出现了该服务
多个部署,动态扩容
root@chenjx12-0:~# docker service update --replicas 2 xybdiy-nginx
xybdiy-nginx
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service xybdiy-nginx converged
由于第一个服务前面已经部署在1号节点上了,所以这次只需要再部署一个
root@chenjx12-0:~# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
qvx9t2qskhr8 xybdiy-nginx replicated 2/2 nginx:latest *:8888->80/tcp
root@chenjx12-0:~# docker service ps xybdiy-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
7jzyf300ygqh xybdiy-nginx.1 nginx:latest chenjx12-1 Running Running 9 minutes ago
i5m1yshi8p8o xybdiy-nginx.2 nginx:latest chenjx12-0 Running Running 2 minutes ago
可以看到这次部署到了0号和1号两个节点上,但是注意啊:
1号节点本身是worker,用来运行和部署服务是没问题的
但是0号节点原来是manager呀,甚至还是leader
所以,再次查看节点信息会发现:
root@chenjx12-0:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
1e0chr8bpn27vlq9g056zy7a2 * chenjx12-0 Ready Active Reachable 27.3.1
jb55cgd88n5tl2ybdokhznq1t chenjx12-1 Ready Active 27.3.1
oav94gisk9wm4mfuqvzpfhqzh chenjx12-2 Ready Active 27.3.1
u6x1nn2xjqsfchbtlegne7swf chenjx12-3 Ready Active Leader 27.3.1
leader被转移到另一个manager节点(3号)上了
在Docker Swarm集群中,如果当前的leader节点变得不可用或者其资源不足以运行新的任务,leadership(领导权)会自动转移到另一个manager节点上。这是Swarm集群的高可用特性之一。
在您描述的场景中,如果有一个manager节点被部署了nginx服务,并且这个manager节点恰好是当前的leader,以下情况可能会发生:
- 如果该manager节点只是被分配了nginx服务,并且它仍然能够处理manager节点的职责,那么它仍然可以保持leader的角色。
- 如果部署nginx服务导致该manager节点过载,或者由于某些原因它变得不可用(比如网络问题、硬件故障等),Swarm集群会检测到这个问题,并进行以下操作:
- 集群中的其他manager节点会通过raft协议选举出一个新的leader。
- leadership将从当前不可用的manager节点转移到新的leader节点上。
为了确保Swarm集群的稳定性和高可用性,通常建议将manager节点专用于管理任务,而不要在它们上面运行worker任务。这样可以确保manager节点有足够的资源来处理集群管理和决策任务,即使在节点故障的情况下也能保持集群的稳定运行。
如果您确实需要在manager节点上运行服务,可以通过以下策略来降低风险:
- 限制在manager节点上运行的服务数量,确保它们不会消耗过多资源。
- 使用资源限制和预留,确保manager节点有足够的资源来执行其管理职责。
如果我们需要保持manager节点不要运行服务,专心管理worker,并且避免leader转移,我们可以使用下面的命令
docker service create \
--name my_nginx \
--constraint 'node.role != manager' \
nginx
如果我们要更具体一点,限制它不会部署在某个节点上:
使用节点ip限制
docker service create \
--name my_nginx \
--constraint 'node.id != node_id' \
nginx
使用节点名称限制
docker service create \
--name my_nginx \
--constraint 'node.hostname != node_name' \
nginx
虽然看上去是只部署在了0号和1号节点,但是实际上你访问集群中任意一个ip的8888端口都能够看到nginx页面
这就是swarm集群的负载均衡
故障
前面可以知道,虽然我部署只在两个服务器上但是我访问集群中任意一个ip都能得到服务
那如果我某个,或者多个服务器挂了呢
首先,我把所有的(两个)manager挂了
得到的结果是:访问剩下两个worker节点的ip均能得到服务,但是manager不行
我把一个manager和一个woker挂了
得到的结果是:还是能访问到,但是挂了的不行
并且最后的manager报错:
root@chenjx12-3:~# docker node 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.
把两个worker都挂掉
结果是:也是仅存活的两个才能访问,但是使用
docker node ls指令不会报错了
所有就引出了我们swarm集群的节点管理规则:
Docker Swarm集群节点规划
为了利用 swarm 模式的容错功能,可以根据组织的高可用性要求实现奇数个节点。 当有多个管理中心时,可以从一个管理中心节点的故障中恢复,而无需停机。
- 三个管理器群可以容忍最多损失一个管理器。
- 五个管理器群最多可以同时丢失两个管理器节点。
- 七个管理器群最多可以同时丢失三个管理器节点。
- 九个管理器群最多可以同时丢失四个管理器节点。
- Docker 建议一个群最多有七个管理器节点。 (添加更多管理器并不意味着可伸缩性或性能的提高。一般来说,情况恰恰相反。)