15、Docker swarm-2-安装与存储

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
  • 同步一下时间服务器

    bash 复制代码
    yum -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"
          }
      ]
相关推荐
fyakm7 小时前
Linux文件搜索:grep、find命令实战应用(附案例)
linux·运维·服务器
wanhengidc9 小时前
云手机存在的意义是什么
运维·服务器·arm开发·安全·智能手机
snow@li10 小时前
运维:部署Jenkins
运维·jenkins
Wang's Blog11 小时前
Nestjs框架: 微服务容器化部署与网络通信解决方案
docker·微服务·云原生·架构·nestjs
脚踏实地的大梦想家11 小时前
【Docker】P2 Docker 命令:从Nginx部署到镜像分享的全流程指南
java·nginx·docker
大海绵啤酒肚11 小时前
OpenStack虚拟化平台之T版搭建部署
linux·运维·云计算·openstack
极限实验室13 小时前
使用 Docker Compose 轻松实现 INFINI Console 离线部署与持久化管理
docker·devops
The Chosen One98513 小时前
【Linux】Linux权限讲解 :写给文件的一封情书
linux·运维·服务器
天地之于壹炁兮14 小时前
Docker革命:软件开发的集装箱时代
docker·容器·eureka