Docker swarm-2
本章要点:docker-swarm集群安装部署,docker swarm volume使用
参考文档:Docker Swarm 全面总结,Docker Swarm介绍,Docker之Swarm详细讲解,Swarm 集群管理,compose 多主机网络共享 overlay,纳米ai, 接上章
Swarm 集群部署
基础环境准备
- 
环境准备
IP 主机名 系统 内核 架构 10.4.50.130 manager130 centos7 3.10.0-1127 x86_64 10.4.50.139 node139 centos7 3.10.0-1127 x86_64 10.4.50.161 node161 centos7 3.10.0-1127 x86_64  - 
修改主机名
bash# 10.4.50.130 执行 ]# hostnamectl set-hostname manager130 # 10.4.50.139 执行 ]# hostnamectl set-hostname node139 # 10.4.50.167 执行 ]# hostnamectl set-hostname node167 - 
添加hosts
bash# 三台都加一下 cat >> /etc/hosts << EOF 10.4.50.130 manager130 10.4.50.139 node139 10.4.50.167 node161 EOF - 
同步一下时间服务器
bashyum -y install ntpdate ntpdate ntp1.aliyun.com # 如果时间不一致,在加入节点时会提示以下异常 Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid: current time 2025-10-29T09:32:09+08:00 is before 2025-10-29T07:34:00Z - 
设置防火墙
端口 说明 2377/tcp 管理端口 7946/tcp/udp 节点间通信端口 4789/udp overlay 网络端口 bash# 全节点, 测试环境可以stop ~]# firewall-cmd --zone=public --add-port=2377/tcp --permanent ~]# firewall-cmd --zone=public --add-port=7946/tcp --permanent ~]# firewall-cmd --zone=public --add-port=7946/udp --permanent ~]# firewall-cmd --zone=public --add-port=4789/udp --permanent # 重新加载生效 ~]# firewall-cmd --reload # 查看 ~]# firewall-cmd --list-ports # selinux 关闭 ~]# setenforce 0 
集群配置
- 
创建swarm集群
bash# 创建集群 ~]# docker swarm init --advertise-addr=10.4.50.130 # 服务器初始会自动加入swarm集群, 同时也会给出一个唯一token值,后续节点加入会用到. # --advertise-addr 参数表示其它 swarm 中的 worker 节点使用此ip地址与 manager 联系
bash# 如果忘了token 也可以用提示的命令进行查看 ~]# docker swarm join-token manager- 
如果想删除
bash# 这里的leave就是在集群中删除节点,-f参数强制删除,执行完在重新执行OK ~]# docker swarm leave -f - 
查看集群想关信息
bash# 集群主节点 ~]# docker info [root@manager130 ~]# docker info Client: Docker Engine - Community Version: 26.1.4 Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc.) Version: v0.14.1 Path: /usr/libexec/docker/cli-plugins/docker-buildx compose: Docker Compose (Docker Inc.) Version: v2.27.0 Path: /usr/libexec/docker/cli-plugins/docker-compose Server: Storage Driver: overlay2 Swarm: active NodeID: lptzlefacgceb16moa9c3ay3x Is Manager: true ClusterID: jthxgdgiuhc8j7j4az9zxfwyu Managers: 1 Nodes: 2 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 Node Address: 10.4.50.130 Manager Addresses: 10.4.50.130:2377 # 为了对比, 这里直接先拉出节点部分描述信息 # 139、docker info Swarm: active NodeID: ottqbgjip0wgp6md372klhn76 Is Manager: false Node Address: 10.4.50.139 Manager Addresses: 10.4.50.130:2377 # 167、docker info Swarm: active NodeID: jggun3821zhi3odkv0a1z94k8 Is Manager: false Node Address: 10.4.50.167 Manager Addresses: 10.4.50.130:2377 
 - 
 - 
添加 node 节点主机到 Swarm 集群
- 
加入节点
bash# 如果忘了token 也可以用提示的命令进行查看 ~]# docker swarm join-token manager <-- 主节点上查询 # 139 跟 161 上都执行 ~]# docker swarm join --token SWMTKN-1-1k8zohbti5pynhwj1j3fqco9nlx61czwxjvbrab9ifxnnsm966-0yrfl9po2at7m6a32chuzmis2 10.4.50.130:2377 This node joined a swarm as a worker. - 
查看节点加入信息
bash~]# docker node ls
- 
AVAILABILITY 的三种状态:
- Active: 调度器能够安排任务到该节点。
 - Pause: 调度器不能够安排任务到该节点,但是已经存在的任务会继续运行。
 - Drain: 调度器不能够安排任务到该节点,而且会停止已存在的任务,并将这些任务分配到其他 Active 状态的节点。
 
 - 
改变节点的可用性(availability)
bash~]# docker node update --help 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") # master节点上执行 ~]# docker node update --availability drain 节点名
当node139的状态改为drain后,那么该节点就不会接受task任务分发,就算之前已经接受的任务也会转移到别的节点上
 - 
MANAGER STATUS 的三种状态:
- Leader: 为群体做出所有群管理和编排决策的主要管理者节点。
 - Reachable: 如果 Leader 节点变为不可用,该节点有资格被选举为新的 Leader。
 - Unavailable: 该节点不能和其他 Manager 节点产生任何联系,这种情况下,应该添加一个新的 Manager 节点到集群,或者将一个 Worker 节点提升为 Manager 节点。
 
 - 
升级/降级节点,示例
- 
升级
bash~]# docker node promote node139 # 升级为节点侯选者 Node node139 promoted to a manager in the swarm. # 此时我们再去查看 docker info --> 139上查看 Swarm: active NodeID: ottqbgjip0wgp6md372klhn76 Is Manager: true ClusterID: xzv8uujn592j7hqhdwnzvy0zy Managers: 2 Nodes: 3 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: 10.4.50.139 Manager Addresses: 10.4.50.130:2377 10.4.50.139:2377 # 查看 docker info --> 130上查看,除了NodeID、地址改变其它一样 NodeID: md4wxe8qlgjg7ll6kwapyees3 Is Manager: true ClusterID: xzv8uujn592j7hqhdwnzvy0zy Node Address: 10.4.50.130 Manager Addresses: 10.4.50.130:2377 10.4.50.139:2377
 - 
降级
bash~]# docker node demote node139 Manager node139 demoted in the swarm. 
 - 
 
 - 
 
 - 
 
服务部署
- 
创建网络
bash~]# docker network create -d overlay mytest1 5ofnc745p5zk98h74jprdx6gs ~]# docker network ls | grep mytest 5ofnc745p5zk mytest1 overlay swarm - 
部署服务
bash# 创建一个名叫my1的服务 镜像nginx.1.28.0, 网络加入mytest1 映射端口9999 ~]# docker service create --network mytest1 --replicas=1 --name=my1 -p 9999:9999 nginx.1.28.0 # 需要注意的是: 如果镜像是自己build的,需要手动将镜像发布到各节点,也可以用自建仓库直接指定 # 如果不能获取到该镜像则会提示异常。 mrajpx4c5evn \_ my1.1 nginx.1.28.0:latest node139 Shutdown Rejected 43 seconds ago "No such image: nginx.1.28.0:l..." ~]# docker service create --network=mytest1 --name=my1 --replicas=1 -p 9999:9999 nginx:1.28.0 ..... i71aexhnnuwuv526ncof2jj6d overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service i71aexhnnuwuv526ncof2jj6d converged ~]# curl http://127.0.0.1:9999 <--- 访问正常 <div> hello world </div> - 
查询 Swarm 中服务的信息 - ⚠️: 都是在管理节点上操作
- 
查看容器运行在哪个节点之上
bash~]# docker service ps my1
 - 
查看swarm运行的容器列表
bash~]# docker service ls
 - 
查询 Swarm 中服务的信息
bash# 以字典的形式打印出来,打印更为详细 ~]# docker service inspect my1 # 格式化为可读的格式 ~]# docker service inspect --pretty my1 ID: i71aexhnnuwuv526ncof2jj6d Name: my1 Service Mode: Replicated Replicas: 1 Placement: UpdateConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Update order: stop-first RollbackConfig: Parallelism: 1 On failure: pause Monitoring Period: 5s Max failure ratio: 0 Rollback order: stop-first ContainerSpec: Image: nginx:1.28.0 Init: false Resources: Networks: mytest1 Endpoint Mode: vip Ports: PublishedPort = 9999 Protocol = tcp TargetPort = 9999 PublishMode = ingress - 
扩容容器
bash~]# docker service scale my1=4 my1 scaled to 4 overall progress: 4 out of 4 tasks 1/4: running [==================================================>] 2/4: running [==================================================>] 3/4: running [==================================================>] 4/4: running [==================================================>] verify: Service my1 converged # 查看扩容容器 ~]# docker service ps my1 # 访问容器,在哪台就直接用哪个ip访问即可 ~]# curl http://10.4.50.130:9999 <div> hello world </div> ~]# curl http://10.4.50.139:9999 <div> hello world </div> ~]# curl http://10.4.50.167:9999 <div> hello world </div>
 - 
缩容容器
bash~]# docker service scale my1=1 # 缩减之后,哪怕容器不在 130之后也可以直接访问 以类vip的方式
 
 - 
 - 
将主节点降级测试一下
 - 
测试
bash# 先将139设置为 侯选人 ~]# docker node promote node139 Node node139 promoted to a manager in the swarm. # 在将130降一级 ~]# docker node demote manager130 Manager manager130 demoted in the swarm. # 此时 130 就无法在查看node管理操作了 ~]# docker node ls Error response from daemon: This node is not a swarm manager ~]# docker node ls ~]# docker service ps my1 ~]# curl http://ip:端口
 
Swarm 中使用 Volume
存储卷-5-需要用到index.jsp, 先总结一下,主节点创建存储卷,其它节点在 service create 之后会自动创建volume,但文件不会共享, 建议用个存储给它串起来
- 
参数说明
挂载类型 关键参数示例 适用场景 注意事项 volume(命名卷) type=volume,src=myvol,dst=/app,volume-driver=local服务间共享数据、持久化存储 需先创建卷( docker volume create)或自动创建bind(绑定挂载) type=bind,src=/host/path,dst=/app,readonly主机目录直接映射到容器 主机路径必须存在,否则报错 tmpfs(临时存储) type=tmpfs,dst=/tmp,tmpfs-size=100m临时数据(如缓存) 数据仅存于内存,容器销毁后丢失  - 
示例- volume挂载方式 - 本地文件,多容器间适合用
- 
创建一个名为myv2的存储卷
bash# 创建一个名为myv2的存储卷, <---主节点上创建 ~]# docker volume create myv2 # 此时记得查看 从节点即work节点 myv2是不存在的 [root@node139 ~]# docker volume inspect myv2 [ { "CreatedAt": "2025-10-29T17:18:08+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/myv2/_data", "Name": "myv2", "Options": null, "Scope": "local" } ] - 
创建容器
bash~]# docker service create --replicas=3 --mount type=volume,src=myv2,dst=/usr/local/tomcat/webapps/ -p 8889:8080 --name myt2 tomcat:8.5.100 --replicas=3 # 搞三个容器 --mount,type=volume,src=创建的存储卷,dst=目录容器挂载的目录 -p 宿主机端口:容器端口 # 默认是Spread模式,每台节点上会跑一个
 - 
访问测试一下
bash# 我这台139创建了ROOT/index.jsp, 代码可以看第5节最下面 ~]# curl http://127.0.0.1:8889/index.jsp ... <div class="hostname">error: f1a394cff068: f1a394cff068: Name or service not known</div> # 此时我们其它节点是没有创建volume的,此时在看一下 # 167、130上都自动生成了 ~]# docker volume ls DRIVER VOLUME NAME local myv2 # 但文件它是不会同时复制的,直接访问 vip139,由于负载机制有一点成功性能打开,挂载点还是要串起来 
 - 
 - 
示例 - bind(绑定挂载),主机目录直接映射到容器
- 
创建容器
bash~]# mkdir /root/tomcat <-- 还是仅主节点创建, 用于测试 ~]# docker service create --replicas=3 --mount type=bind,src=/root/tomcat,dst=/usr/local/tomcat/webapps -p 9999:8080 --name=file3 tomcat:8.5.100 --replicas=3 # 搞三个容器 --mount,type=bind,src=创建的存储卷,dst=目录容器挂载的目录 -p 宿主机端口:容器端口 # 这里跟 craete 存储卷不同, 如果本地没有,它连建都建连不起来 # 可以通过 docker service ps file3 查看, 因为本地没有创建,只会有139创建成功 - 
第二次继续,我们先手动将目录文件创建起来,
bash# 三台都有, 假装它用了存储(nfs,ftp)之类的 ~]# ls /root/tomcat/ROOT/index.jsp ~]# docker service create --replicas=3 --mount type=bind,src=/root/tomcat,dst=/usr/local/tomcat/webapps -p 10000:8080 --name=file4 tomcat:8.5.100 # 通过 docker service ps file4 查看 - 
测试一下
bash# 访问三次,试试水。 ~]# curl http://10.4.50.139:10000/index.jsp hostname=23da9de8eeeb: 23da9de8eeeb ~]# curl http://10.4.50.139:10000/index.jsp hostname=b988c025e438: b988c025e438 ~]# curl http://10.4.50.139:10000/index.jsp hostname=dd6f9876df30: dd6f9876df30 
 - 
 - 
示例- volume挂载方式 - nfs, 与bind一样, 只是本机生效,如果想使用得用 docker stack,待研究
- 
创建nfs挂载点
bash# 需要先手动把全部节点创建一下. ~]# docker volume create --driver local --opt type=nfs --opt o=addr=10.4.50.139 --opt device=:/opt/volumetest/volume/ swv1 ~]# docker volume inspect swv1 --> worker节点上看 [ { "CreatedAt": "2025-10-30T14:28:59+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/swv1/_data", "Name": "swv1", "Options": null, "Scope": "local" } ] 
 -