整体目标
项目背景
领导给到了我一个客户,客户商业模式为成本制作,成本核算。其中涉及到大量涉密数据,且与我们现有产品几乎没有兼容点(我们是一套低代码的框架,客户有很多业务二开)
测试环境给到了我6台业务机器,起初其中4台作为业务服务器,一台作为中间件,一台作为mysql。
6台机器均使用私有云部署,配置均为4c8G。
技术选型
直白的讲,物理器部署资源有限。
框架选型
开源框架:选型是ruoyi微服务框架,原因:开源免费,明星star项目,社区活跃,技术相对主流,自己也熟悉。
技术架构图
这是官方的架构图
系统架构图
这是我结合我们的系统 画的整体系统架构图
部署选型
部署方式:因为微服务框架和有限的物理机,我必然是选择集群部署的。市面上相对主流的集群部署毋庸置疑是k8s,但是作为一个之前只是后端的开发人员,在没有人指导的情况下,且有期返时间内,部署生产环境集群着实有点为难了。
K8S与docker swarm的横向对比
比较维度 | Docker Swarm | Kubernetes (k8s) |
---|---|---|
优点 | 简单易用 | 功能强大 |
与 Docker 集成紧密 | 高度扩展性 | |
快速部署 | 广泛社区支持 | |
轻量级 | 多云支持 | |
缺点 | 功能相对有限 | 学习曲线陡峭 |
扩展性差 | 资源消耗大 | |
社区和生态较少 | 部署复杂 | |
适用场景 | 中小型项目 | 大规模项目 |
简单应用 | 复杂应用 | |
初学者 | 跨云部署 | |
学习成本 | 低 | 高 |
快速上手 | 深入掌握需要时间 | |
拓展性 | 低 | 高 |
有限插件和工具 | 丰富的插件和工具 | |
社区完善度 | 较小 | 庞大 |
支持较少 | 丰富的第三方支持 |
额外提一句:现实中,我们往往以结果为导向。虽然k8s不管是从扩展性,社区活跃度都远远超过docker swarm,但奈何学习成本高,我对于初学者不够友好(PS:国内好多站点被封了,之前用kubeadm部署,刷机后又没有资源站点了)。
学习东西是一个渐进的过程,阶段性的交付和成功,会给自己带来快乐。而一下子上来最难的,只能带来无穷的挫败和自我怀疑,最终陷入无限期的搁置(PS:难度因人而异)
docker swarm 介绍
Docker Swarm 是 Docker 提供的原生容器编排工具。它允许用户将多个 Docker 主机组合在一起,形成一个虚拟的 Docker 集群,并在这个集群上管理和部署容器。Swarm 使得用户可以通过熟悉的 Docker 命令和工具管理大规模的 Docker 容器部署。
部署方式就是一个master节点,其他worker节点加入。管理的最小单位是service,可以使用类似docker-compose的文件进行管理service。同时有多个stack,进行一组service的管理。
部署架构图
这是整体多机网络部署架构图
基于Redhat构建docker、docker-compose
repo配置
配置文件如下:
# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client. You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the #mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#
[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
#failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/BaseOS/$basearch/os/
http://mirrors.aliyuncs.com/centos/$releasever/BaseOS/$basearch/os/
http://mirrors.cloud.aliyuncs.com/centos/$releasever/BaseOS/$basearch/os/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
#failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/os/
http://mirrors.aliyuncs.com/centos/$releasever/extras/$basearch/os/
http://mirrors.cloud.aliyuncs.com/centos/$releasever/extras/$basearch/os/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus - mirrors.aliyun.com
#failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/os/
http://mirrors.aliyuncs.com/centos/$releasever/centosplus/$basearch/os/
http://mirrors.cloud.aliyuncs.com/centos/$releasever/centosplus/$basearch/os/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
[PowerTools]
name=CentOS-$releasever - PowerTools - mirrors.aliyun.com
#failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/PowerTools/$basearch/os/
http://mirrors.aliyuncs.com/centos/$releasever/PowerTools/$basearch/os/
http://mirrors.cloud.aliyuncs.com/centos/$releasever/PowerTools/$basearch/os/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
[AppStream]
name=CentOS-$releasever - AppStream - mirrors.aliyun.com
#failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/AppStream/$basearch/os/
http://mirrors.aliyuncs.com/centos/$releasever/AppStream/$basearch/os/
http://mirrors.cloud.aliyuncs.com/centos/$releasever/AppStream/$basearch/os/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-stable-debuginfo]
name=Docker CE Stable - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/debug-$basearch/stable
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-stable-source]
name=Docker CE Stable - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/source/stable
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-test]
name=Docker CE Test - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/$basearch/test
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-test-debuginfo]
name=Docker CE Test - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/debug-$basearch/test
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-test-source]
name=Docker CE Test - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/source/test
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-nightly]
name=Docker CE Nightly - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/$basearch/nightly
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-nightly-debuginfo]
name=Docker CE Nightly - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/debug-$basearch/nightly
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
[docker-ce-nightly-source]
name=Docker CE Nightly - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/$releasever/source/nightly
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/rhel/gpg
redhat因为客户买的没有注册 所以他的资源文件是空的
阿里云镜像
这个因为一些image在国外,配置一下阿里云镜像会拉取快很多
具体路径 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
按照上面的配置就可以
部署操作
docker
sudo yum install -y yum-utils
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
docker-compose
sudo curl -L “https://github.com/docker/compose/releases/download/v2.x.x/docker-compose- ( u n a m e − s ) − (uname -s)- (uname−s)−(uname -m)” -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker swarm 初始化
docker swarm init
正常情况下,会出现token,如果你没有记录,也可以在manage节点
docker swarm join-token worker
查看对应的swarm的manage的token
然后再worker节点上 直接直接join就可以了
然后整体的一个node结构如下
这里我还对hostname做了修改
overlay 网络构建
十分重要
docker network create --driver overlay --subnet=10.10.0.0/24 --gateway=10.10.0.1 sangfor-network
docker中的网络是最为复杂的,同时因为我是跨机之间的网络通讯,这里使用了overlay的配置
然后再整个stack配置文件中,我使用了external: true,使用外部网络
网络查看
正常来说 当你构建完成一个service的构建之后,你要查看这个网络
docker network inspect sangfor-network
这里面会体现出你的container和对应的ip
需要注意是,当你的使用overlay网络的时候,如果你的某台woker机器上并没有service,那么这个overlay网络是不显示的
同时需要明确的是,查看网络中的container 只有当前机器的container才会显示
yml配置优先网段
需要明确的是,docker container内的网卡是有很多个的,他是哪个可以用就用哪个
所以这里需要结合程序的修改,就是这个preferred-networks,我写了10.10.0网段
通过这种方式,使得container的ip优先使用这个10.10.0网段
docker-stack部署
这里直接贴我两个的stack文件吧
docker-stack-basic.yml
version : '3.8'
services:
cloud-mysql:
image: mysql:5.7
ports:
- "3306:3306"
volumes:
- /data/cloud/mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
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',
'--default-authentication-plugin=mysql_native_password'
]
environment:
MYSQL_DATABASE: 'cloud_business'
MYSQL_ROOT_PASSWORD: 'yourpassword'
TZ: 'Asia/Shanghai'
networks:
- sangfor-network
deploy:
placement:
constraints:
- node.labels.mysql == true
cloud-redis:
container_name: cloud-redis
image: redis
build:
context: ./redis
ports:
- "6379:6379"
volumes:
- ./redis/conf/redis.conf:/home/ruoyi/redis/redis.conf
- ./redis/data:/data
command: redis-server /home/ruoyi/redis/redis.conf
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
deploy:
placement:
constraints:
- node.labels.middle == true
networks:
sangfor-network:
external: true
docker-stack-sangfor.yml
version : '3.8'
services:
cloud-portainer:
image: portainer/portainer-ce:latest
environment:
- TZ=Asia/Shanghai
volumes:
- ./portainer/data/:/data
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "9000:9000"
deploy:
placement:
constraints:
- node.labels.portainer == true
resources:
limits:
cpus: '0.50'
memory: 500M
networks:
- sangfor-network
cloud-nacos:
image: nacos/nacos-server
build:
context: ./nacos
environment:
- MODE=standalone
- TZ=Asia/Shanghai
volumes:
- ./nacos/logs/:/home/nacos/logs
- ./nacos/conf/application.properties:/home/nacos/conf/application.properties
- /etc/localtime:/etc/localtime:ro
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/v1/console/health/liveness"]
interval: 30s
timeout: 10s
retries: 5
networks:
- sangfor-network
deploy:
placement:
constraints:
- node.labels.middle == true
cloud-nginx:
image: nginx:1.0
ports:
- "80:80"
volumes:
- ./nginx/html/dist:/home/cloud/projects/cloud-ui
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/conf.d:/etc/nginx/conf.d
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
deploy:
placement:
constraints:
- node.labels.master == true
cloud-gateway:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_gateway:1.0
ports:
- "8080:8080"
environment:
TZ: Asia/Shanghai
deploy:
placement:
constraints:
- node.labels.master == true
networks:
- sangfor-network
cloud-auth:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_auth:1.0
ports:
- "9200:9200"
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
cloud-modules-system:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_system:1.0
ports:
- "9201:9201"
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
cloud-modules-gen:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_gen:1.0
ports:
- "9202:9202"
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
cloud-modules-job:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_job:1.0
ports:
- "9203:9203"
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
cloud-modules-file:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_file:1.0
ports:
- "9300:9300"
environment:
- TZ=Asia/Shanghai
volumes:
- ./cloud/uploadPath:/home/cloud/uploadPath
networks:
- sangfor-network
cloud-visual-monitor:
image: registry.cn-hangzhou.aliyuncs.com/sangfor_authine/cloud_monitor:1.0
ports:
- "9100:9100"
environment:
- TZ=Asia/Shanghai
networks:
- sangfor-network
networks:
sangfor-network:
external: true
label标签固定
这里可以看到有些service我是固定在某些机器上的,当然前提是你要给你的机器打标签
标签这么打就行了
docker node update --label-add work_node3=true work_node3
我这边打标签分为几种常见场景
1.外部异构系统需要公用redis和mysql
2.portainer 需要在master节点上监控
3.nacos配置我是固定ip的(这里面应该是可以直接使用service名称代替ip的)
端口开放
有些端口需要对外开放,docker swarm中部分port也要打开
开放端口如下
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
image托管
我这里偷懒了 我不想搭建harbor了
我直接把我的阿里云镜像仓库贡献出来了
这些相关的操作文档还是很多的
portainer可视化构建
portainer的构建方式在之前的stack中有
他的最大意义在于可视化的操作,降低scale和查看日志都比较方便
贴几张图
这里面service和stack他会自动抓取的
对于容器也可以做一些调配
查看nacos 内网ip
这个很重要,之前我一直跨机服务的时候 调度不通
查到最后是我的内网nacos ip注册的有问题,这也是前面网络声明网段和我使用preferred-networks的原因
记得在服务列表里面查看自己的ip
异常情况与排查思路
遇到了太多了卡点和异常了,我现在只记得一些关键卡点和排查思路了
Overlay网络问题
最一开始部署的时候,redis和mysql其实使用docker-compose部署的,然后发现我业务内部调用mysql网络不通。
我不服气,我把swarm集群中的网络改成了外部可以访问 增加了–attachable,但最后发现不行。
还是要放在一个网络里面,所以最后我把之前docker-compose build的mysql和redis 切换为stack部署了(切换代价很小,因为都做了挂载,数据不会丢失)
服务无法调度问题
通俗的讲就是我服务到了nginx,做完转发进入gateway 调不通auth权限。
第一反应其实也是网路问题,最后排查思路是 进入到gateway的容器内部
docker exec -it a927a4a68b2d /bin/bash
然后curl auth服务
这就是ping的通的
但是真实调研的时候 因为使用的是fegin
他们用的是这个serviceName
这里面的service名称 要等于nacos的名称
然后域名访问如下:
这样服务就基本没啥问题了
naocs 配置
这个完全是我因为我不太熟悉导致的问题
这个yml配置里面 就是cloud-auth-dev配置
naocs配置中心里面配置保持一致就可以‘