1、创建集群

初始化集群

docker swarm init

加入集群

# 生成工作节点命令
docker swarm join-token worker

# 生成管理节点命令,所有管理节点需要开放 2377 端口
docker swarm join-token manager

# 加入集群
docker swarm join xxxx

2、负载均衡

docker swarm 集群默认实现负载均衡,轮询访问服务的不同副本,但需要注意开放对应的端口即可

1、创建集群并加入

docker swarm init

docker swarm join ...

2、创建服务

docker service create -p 80:80 --name my-nginx --replicas 2 nginx

3、修改nginx主页

vim index.html

image-20230626113755591

4、测试访问,轮询算法的负载均衡,通过命令行的方式访问,如果通过浏览器访问,可能是因为缓存问题,不会有轮询效果

image-20230626113824037

注意:如果通过管理节点的ip无法访问,或者不会负载均衡时,应该时端口开放问题,要让 swarm mode routing mesh 生效的话, 在初始化swarm集群前必须开放7946tcp/udp端口, 4789udp端口

firewall-cmd --permanent --zone=public --add-port=7946/tcp
firewall-cmd --permanent --zone=public --add-port=7946/udp
firewall-cmd --permanent --zone=public --add-port=4789/udp

# 重启防火墙
firewall-cmd --reload

3、灰度发布

这是用于更新服务的方式,用新的系统镜像进行更新

1、拉取另外的镜像,用于更新替代 nginx

docker pull httpd

2、进行更新

# 参数含义解释:
# –image 指定要更新的镜像
# –update-parallelism 指定最大同步更新的任务数
# –update-delay 指定更新间隔
docker service update --image httpd --update-delay 5s  --update-parallelism 5 my-nginx

image-20230626144421895

更新完成,将所有的镜像都替换为 httpd,只有将所有服务更新完成之后才会访问到新的内容

image-20230626144524347

4、监测工具

# 拉取镜像
docker pull dockersamples/visualizer

# 启动服务
docker service create \
--name=viz \
--publish=8080:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer

image-20230626143521755

5、docker stack

1、与 docker-compose 一样,编写对应的 docker-compose.ymldockerfile 文件,上传对应的 jar 包,但是需要注意每一台服务器上都需要上传对应的文件,java 项目配置文件中的数据库 ip 地址直接填写下方的服务名称 xj-mysql 即可

docker-compose.yml

version : '3.8'
services:
  xj-mysql:
    container_name: xj-mysql
    image: mysql:5.7
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/conf:/etc/mysql/conf.d
      - ./mysql/logs:/logs
      - ./mysql/data:/var/lib/mysql
    command: [
          'mysqld',
          '--innodb-buffer-pool-size=80M',
          '--character-set-server=utf8mb4',
          '--collation-server=utf8mb4_unicode_ci',
          '--default-time-zone=+8:00',
          '--lower-case-table-names=1'
        ]
    environment:
      MYSQL_DATABASE: 'shanwei_dfdj_backend'
      MYSQL_ROOT_PASSWORD: 'aW0gr1EPMrYV'
  xj-system:
    container_name: xj-system
    image: docker_xj-system
    ports:
      - "9200:9200"
    depends_on:
      - xj-mysql
    deploy:
      replicas: 2

dockerfile

# 基础镜像
FROM  openjdk:8-jre

# 挂载目录
VOLUME /home/xiaojiang
# 创建目录
RUN mkdir -p /home/xiaojiang
# 指定路径
WORKDIR /home/xiaojiang
# 复制jar文件到路径
COPY ./jar/*.jar /home/xiaojiang/system.jar
CMD ["---spring.profiles.active=test"]
# 启动网关服务
ENTRYPOINT ["java", "-jar", "system.jar"]

2、只能在 docker-compose.yml 文件中定义对应容器的副本,通过 replicas 属性

3、在启动之前需要在各个服务器上 pull 或者 创建好对应的镜像,不能像 docker-compose 一样边创建边启动,并且集群中的每个节点都需要用户这个镜像,所以建议将镜像先打包上传到 dockerHub 上,然后再每个节点拉取镜像,确保所有镜像是一致的

# 拉取镜像
docker pull xxx

# 构建镜像
docker build -f dockerfile -t 镜像名:[tag] [文件路径]

# 在主节点上启动服务
docker stack deploy -c docker-compose.yml my-stack-service

image-20230626172826006

4、更新服务,直接使用 deploy 就是灰度发布

docker stack deploy -c docker-compose.yml my-stack-service

image-20230626174932430

总结:使用 docker stack 的时候需要提前将需要的镜像都拉取下来,并构建好对应的系统镜像,上传到 dockerhub 上,每个节点都需要重新拉取最新的系统镜像,然后再执行更新命令