docker swarm 结合 docker-compose.yml 部署集群
1 )准备 docker-compose.yml的文件, 示例 demo 如下
yml
version: "3"
services:
mysql_c:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
restart: always
ports:
- 3306:3306
volumes:
- /root/mysql/conf.d:/etc/mysql/conf.d
- /root/mysql/data:/var/lib/mysql
goweb1:
image: gowebimg
restart: always
deploy:
replicas: 6 # 副本数量
resources: # 资源
limits: # 配置cpu
cpus: "0.3" # 设置该容器最多只能使用 30% 的 CPU
memory: 500M # 设置该容器最多只能使用 500M内存
restart_policy: # 定义容器重启策略, 用于代替 restart 参数
condition: on-failure # 只有当容器内部应用程序出现问题才会重启
depends_on:
- mysql_c
nginx:
image: nginx
restart: always
ports:
- 80:80
depends_on:
- goweb1
volumes:
- /root/nginx/conf.d/:/etc/nginx/conf.d
deploy:
replicas: 6 #副本数量
resources: #资源
limits: #配置cpu
cpus: "0.3" # 设置该容器最多只能使用 30% 的 CPU
memory: 500M # 设置该容器最多只能使用 500M内存
restart_policy: # 定义容器重启策略, 用于代替 restart 参数
condition: on-failure #只有当容器内部应用程序出现问题才会重启
- 基于 docker-compose可以在一台服务器上创建多个容器
- 想在多台服务器上一次创建多个容器, 需要结合 Swarm
- $
docker stack deploy --compose-file docker-compose.yml swarmName
- swarmName是我们的swarm对应的名称,可以自行随意配置, 比如 goWebSwarm
- $
- 以上配置的问题是 mysql 没有进行集群
- mysql 需要单独搭建集群,这里涉及到主从数据库
- 为了方便起见,直接配置到了 yml 文件里
- 这里mysql的副本数量不能配置多个
- 如果多个,就会运行在多台服务器上,会出现数据异常和不一致的问题
2 )搭建集群
- $
docker swarm init --advertise-addr 192.168.1.10
初始化集群并创建管理节点(当前指定的ip为管理节点)- 填入自己主机的ip
- $
docker swarm join --token SWMTKN-1-52tr219htvsg1volky2tej7pj8bjs2j78q4b6wc9fnt72kkchd-29ohn4mgz191f6oznldvjiw47 192.168.1.10:2377
- 其他主机加入集群
- 根据 yml 文件,这里的集群是 nginx 和 goweb的集群,它们都有6个副本,mysql 服务只有一个副本
3 )部署和验证
- $
docker stack deploy --compose-file docker-compose.yml goWebSwarm
开始部署服务- 调用这个命令的时候,首先创建了网络
- 接着创建3个服务
- 这3个服务使用了同一个网络,默认这三个服务可以直接连通
- $
docker service ls
可查看当前运行起来的服务 - $
docker service ps goWebSwarm
查看当前某个服务 - 通过 docker-compose 部署,可见生成了3个服务,这三个服务,使用了同一个网络
- 这里同样存在之前的,mysql服务启动了,接着goWeb服务也启动,但是mysql服务并没有完全可用的状态
- 可以用之前的脚本解决
- 可以重启 goWeb项目 (或扩容,缩容来重启)
- 可以先单独部署 mysql的集群,之后再部署 goWeb 和 Nginx 服务
- 这种就不属于这里的集群了,mysql集群作为一项单独的集群
- goWeb应用的配置文件也要对应同步修改
4 )配置部署额外的一台Nginx服务器(非集群内)
-
额外的NG服务器,用于做路由和转发到集群内的nginx服务器
-
在集群内的各个主机磁盘上都有 /root/nginx/conf.d/ 目录中都有一个 default.conf 文件
confupstream backend { ip_hash; server goweb1:8080; # 这里是 goweb1 容器服务的host别名 } server { listen 80; server_name localhost; # 你的域名地址 location / { # 设置主机头和客户端真实地址,以便服务器获取客户端真实IP # 禁用缓存 proxy_buffering off; # 反向代理的地址 proxy_pass http://backend; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
- 当访问这个时,nginx将 80 转发到 8080
-
现在,我们要配置nginx的主机,也就是转发到集群内,进行负载均衡的配置
confupstream backend { ip_hash; server 192.168.1.10 weight=1; # 集群内的服务 ip 这里有一台 nginx服务器 server 192.168.1.11 weight=1; server 192.168.1.12 weight=1; server 192.168.1.13 weight=1; } server { listen 80; server_name goweb.xxxx.com; # 你的域名地址 这里本机可以配置 host, 如果在服务器配置 域名解析 add_header backendCode $upstream_status; add_header BackendIP "$upstream_addr;" always; location / { # 设置主机头和客户端真实地址,以便服务器获取客户端真实 IP proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # nginx服务器与被代理服务连接超时时间,代理超时,请求一台超过1s就会转发到其他ip proxy_connect_timeout 1s; # 禁用缓存 proxy_buffering off; # 反向代理的地址 proxy_pass http://backend; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
- 上面用于查看nginx服务器转发节点的配置
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- 加上这个,在浏览器中可以看到转发的服务器,在响应表头,会有一个
BackendIP
的字段
- 启动 nginx 主机
- $
docker run -itd --name nginxweb -p 80:80 -v /root/nginx/conf.d:/etc/nginx/conf.d nginx
- $
5 )整体架构如下
-
第一层 )nginx 服务器接收到请求后转发到集群中的各台主机上
- 这里是最外面的一层 nginx 作为负载均衡
- 这台nginx服务器是一台高性能服务器,只负责转发,没有其他处理任务
-
第二层 )集群里面有各类服务
- nginx goWeb
- goWeb 连接到 mysql 或 mysql集群服务
- nginx goWeb
- 同上
- nginx goWeb
- 同上
- ...
- 这个集群内部的nginx服务会动态负载均衡到各个goWeb服务
- nginx goWeb
-
第三层 )mysql 或 mysql集群
- 目前我们的mysql 只有一台服务,并且配置在compose文件里
-
以上三个层,是我们服务端一般的设计方案,当然上面没用到 mysql 集群
-
以上架构可支持 100W 的访问量 (使用mysql集群)
-
如果需要负载更多, 可把这套架构复制到多个城市地区
- 一般情况下,域名解析只能配置到一台服务器
- 当然,有个动态域名解析,可以支持多台
- 这样就可以根据请求判断转发到那些服务器
关于 Docker Swarm 的 Raft 一致性算法
- Raft:一致性算法,在保证大多数管理节点存活的情况下,集群才能使用
- 所以就要求如果集群的话,manager节点必须 >=3 台
- manager: 管理节点,用于管理工作节点
- 如果是两个台,其中一台宕机,剩余的一台也将不可用,以致整个集群不可用
- 为了利用 swarm 模式的容错特性,Docker 建议您根据组织的高可用性要求实现奇数个节点
- 当您有多个管理器时,您可以从管理器节点的故障中恢复而无需停机
- 一个3管理器群最多可以容忍1名管理器的损失
- 一个5管理器群最多可以同时丢失2个管理器节点
- 一个N管理器集群最多可以容忍丢失 (N - 1) / 2 管理器
- Docker 建议一个Swarm集群最多使用7个管理器节点