基于DevOps平台构建自己博客:2-整体架构设计
上一篇介绍了需求和技术选型,这一篇我们会介绍具体的架构设计。这里给大家说明一下,当前这个项目相关的课程,都是按照真实的项目实施顺序进行,在实际的工作当中,虽然会复杂许多,但是技术相关的环节是基本一样的。同时涉及到的工具、工作方法、解决问题的思路,都是这么多年本人工作经验的总结。相信对大家会有一定的帮助。
先回顾我们的需求和技术选型:基于DevOps平台构建自己博客:1-开篇
我们先从博客系统开始,从这个开始的主要原因是我们已经有确定的系统,这样,我们只需要理解其技术栈、编译方式、配置方式、部署方式、运行方式以及系统所需要中间件,就可以知道其基础环境所必须的那些东西。当然,对于一个全新的系统,在目标系统尚未设计开发的情况下,我们的架构设计也依然需要明确这些,至少我们的目标系统的运行环境、技术栈及各方面的限制,如网络、硬件、磁盘、应用系统技术框架(前后端框架)、缓存、MQ、文件系统、数据库、以及其他三方系统等等。
一般来讲,系统架构设计到目标系统的各个方面,能够收集到的信息尽可能的完整且准确。但设计的时候,尽量使用通用的、成熟的解决方案,针对特殊化的场景,在满足用户需求的同时,也需要考虑对应的弊端以及影响面的大小,同时,可以做多个方案的对比,以便更好的权衡其中的利弊。
废话不多说,现在开始我们的整体架构设计!
一、域的划分
一般而言,对于一个生产系统,我们需要对整体网络环境做域的划分,主要原因是出于安全的考虑,域的划分可以很好的制定各域之前的访问规则,这种规则是强制约束的,一般通过防火墙的策略配置及网络划分实现。虽然我只有一台云主机,并且无法配置防火墙的策略,但是,我仍然希望我的网站可以尽量趋近于这种设计。暂时先不管那么多,先设计了再说。如下是我的域划分:
从图中可以看出,我划分了四个域: DMZ域,APP域,DB域和Cache域。
DMZ域:该域支持INBOUND和OUTBOUND的流量,即可以访问外界互联网,也允许外界访问。
APP域:只允许来至DMZ域的INBOUND流量,即只允许DMZ域的访问。
DB域:只允许来至APP域的INBOUND流量,即只允许APP域的访问。
Cache域:只允许来至APP域的INBOUND流量,即只允许APP域的访问。
由域划分可知,整个网站的入口为DMZ域,而DMZ域之外是不可以访问我们的APP域、DB域以及Cache域的,应用层及以下均为内网环境。
域的划分是约定了我们网络的隔离策略,划定了网络区域间的关系,同时,也对区域内的组件提供了部署的依据。比如,后续我们继续增加web应用,就可以放到APP域中,这样,新增的应用就天然的满足本身需要的网络环境,而不必过多的考虑其他放通策略。
二、部署架构
基于一中的域划分,我们就可以考虑我们的部署架构具体的样子了。具体的思考方式就是我们最终要达成的目标是什么?有哪些问题?有哪些现有的资源?有什么样的限制?目标在第一篇的需求已经讲过了,这里再做一下细化,同时,补充一些具体的问题。
1. 中间件
搭建一个可外网访问的博客,博客有自己的应用系统,依赖了中间件,具体中间件有Mysql、Redis。
2. 容器化
由于我只有一台云服务器,所以,要做到更好的隔离,最简单的方式就是使用容器化技术,这里我仅使用了Docker。虽然业界采用K8S+Docker的方式更多,但是K8S本身就需要部署管理集群做支撑,在当前资源有限的情况下,对于一个个人网站,没有其他要求的情况下:如资源动态调度、滚动发布、微服务系统架构支撑、故障自主剔除与恢复等等。K8S本身对于我的需求来说,本身就过于厚重。但是Docker本身的轻量级容器特性,已经可以很好的满足了我的需求。所以,Docker还是需要保留的。
3. 限制及约束
选定容器化后,就会涉及到哪些组件需要做容器化部署,部署后会有哪些问题?最近简单的判别标准就是看我们的域是怎么划分的。通过域划分我们可以知道,Nginx、应用系统、Mysql、Redis都是需要的,这样才能做到隔离。但是容器化后,就会涉及到一些问题。比如:
(1)配置是写在固定的配置文件,还是在容器初始化时就设定好?
(2)需要长时间保留的数据,如Mysql的数据文件如果放到容器里面,则容器删除或重建就会丢失。
(3)应用系统运行时的日志、文章中上传的附件、文章中涉及到的图片等静态资源,如果只保留在容器内,则其他容器访问就相对困难。
(4)容器之间本身是隔离的,但是组件之间是有依赖关系的,所以,也就是容器之间的通讯是必然的,所以,容器间的网络放通也需要处理。
以上这些问题,会在后续的文章中详细告诉大家如何解决。当前,我们需要确定的就是,容器化后这些问题是否有解决方案,答案是有的。针对配置文件、数据文件、静态文件这些,我们只需要在创建容器的时候映射物理机文件系统或本地磁盘即可。针对容器间网络通讯问题,只需要通过link参数放通网络访问即可解决。
4. 宿主机
对于一个涉及多个容器化部署,各种各样的配置的系统,我不希望改个代码就手动的编译或者替换class文件,再传到服务器上。我希望有一套流水线支撑我的编译、部署工作。流水线的问题我们在选型的时候已经说过,使用CODING平台的能力即可实现。部署也是一样,但需要注意的是,需要将我们的云主机授权给DevOps的管理,这个方式是通过平台的添加堡垒机实现的,也就是通过在宿主机上安装Agent,实现DevOps与宿主机的通信与命令执行。所以,我还要在我的云主机上安装一个平台的Agent。
以上这些就是我在做架构设计考虑的一些问题,确定可行性及解决方案之后,我的架构基本就可以形成了,具体参考如下:
由上图可知,我们的系统是部署在腾讯云上,网络接入层是由云厂商提供的能力,我们没有更多的操作空间。下层我们部署了5个Docker实例,分别是资源号:R1~R5,在真实的项目中,除了我们的资源编号,还会附带物理机/宿主机的信息,这样,才能知道,具体哪个组件部署在哪些物理机和哪些虚拟机中。即使是使用K8S管理云上资源,也是需要这些信息的,因为K8S的资源调度策略依然依赖他们。在容器服务群之外,物理机上会有文件存储的映射。由于资源有限,我们没有文件系统或者外挂盘,所以只能拿本地磁盘映射成外挂盘,作为文件系统使用。最后,由于我们想要通过流水线工具实现我们的自动化编译部署,所以,需要在物理机上部署对应的Agent,以便Coding平台的可以在我们的物理机上执行相应的命令。
三、资源清单
下面通过一个表格来梳理下我们的资源清单:
编号 | 名称 | 容量 | 所属域 | 说明 |
---|---|---|---|---|
R1 | nginx | 共享主机配置(CPU:2C, MEMORY: 4G) | DMZ | 代理接收外部请求,统一配置入口、协议以及静态资源加速。 1. 指定端口请求转发到R2和R3 2. 加载宿主机配置文件 3. 加载宿主机证书文件 4. 应用静态资源文件配置 |
R2 | app-web | 共享主机配置(CPU:2C, MEMORY: 4G) | APP | 前端应用,需加载宿主机上指定配置文件。 |
R3 | app-admin | 共享主机配置(CPU:2C, MEMORY: 4G) | APP | 管理应用,需加载宿主机上指定配置文件。 |
R4 | mysql | 共享主机配置(CPU:2C, MEMORY: 4G, DISC: 30G) | DB | 数据库。数据文件需持久化到宿主机硬盘。 |
R5 | Redis | 共享主机配置(CPU:2C, MEMORY: 4G) | Cache | 缓存。仅允许R2和R3访问,不开放对外端口。 |
其实稍微大些的项目中,涉及的资源远比上面的多得多,资源清单的内容也更为详细,资源规模涉及到几个环境,类似DEV、SIT、UAT、PRD、LDR、RDR等等,这里只做简单的示范。资源清单对于项目启动初期,环境搭建起到了至关重要的作用,通过资源清单,项目组可用清楚的知道需要购买哪些资源,资源配置容量是多少,预算花费金额,结合部署架构和网络架构,就可以清楚理解系统搭建后的样子。
在资源清单确定以后,就可以计划购买资源,实施环境搭建,一般会先由DEV,SIT,UAT开始,PRD在最后,如果资源足够且费用不作为主要参考指标的情况,可以安排各个环境的部署架构完全一致,配置上做缩减。但是,大多数的项目并没有完美的资金预算,能够支撑的环境也有限,从资源的角度来讲,一方面可以缩减环境,比如测试环境仅保留UAT,而这个UAT环境承接了DEV和SIT的工作。生产环境仅保留PRD,不再要求系统支持switchover。同时,还可以通过资源共用的方式来节省成本。例如,数据库层面划分不同的DB给到不同的环境、Redis也使用不同DB、MQ使用不同的vhost等等。这些妥协在真实项目里十分常见,用户的资源总是有限,作架构的我们总是想尽量的保证我们的环境齐全、结构一致,这样才能更好的保证整体的统一、交付质量更高、系统整体的能力更强。这里就不再多说环境对于我们项目的重要性了,后续有机会再进行详细的讨论。
至此,我们的架构基本已经可以支撑后续的工作了,欢迎继续观看后续的文章!
- 本文标签: DevOps Coding Spring Boot
- 本文链接: https://www.v8en.com/article/4
- 版权声明: 本文由SIMON原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权