发布系统从0到1
最近的新版发布系统项目的开发基本收尾,趁着热乎劲记录一下思路和心得。
整体思路
目标
同时支持K8S(容器)和VM(虚拟机)两种发布引擎。
流程
按3大阶段划分:配置,构建,发布。
对于业务研发来说,只需要操作构建与发布。
全局视角
下面是项目之初我构思的一个整体架构:
发布系统与应用CMDB隔离为2套系统:
- 发布系统:提供所有发布平台的所有功能
- CMDB:restful api接口,维护公司核心的应用基础信息,供发布系统调用。
下面拆开每个部分简单说一下思路。
设计与实现
CI – 持续构建
发布平台支持php&vm、php&k8s、java&vm、java&k8s等多种应用架构。
这一块的理念就是把要发布的东西打包到一起:
- 对于K8S来说,就是生成镜像,推送到Harbor。
- 对于VM来说,就是生成tar.gz包,推送到对象存储。
设计时要克服的难点在于:
- 不同的技术栈的构建流程不同,比如PHP、JAVA、GO在编译代码方面差异是很大的。
- 同一个技术栈,不同的项目其玩法也各不相同,不同团队还有不同的项目结构和组织风格。
- VM和K8S的构建流程本身就不同。
针对上述问题,我的解决方案如下:
- 不同技术栈的构建流程做区分设计,建立接入标准,推动业务适配。
- VM和K8S构建流程做区分设计。
简单的总结一下,不同的技术栈与运行环境(VM or K8S)分别设计一套构建流程和标准,强约束用户只能按照固定套路玩耍。
以PHP+K8S的构建配置为例,前台表单是定制化设计的,这意味着JAVA+K8S也许就不长这样:
表单之所以长这样,完全是因为PHP+K8S架构的应用的构建流程需要这些信息,一些过于灵活配置的东西就通过一个YAML来表达了,否则前台表单太复杂。
虽然不同架构的表单和构建配置各不相同,但是在数据库中都是一个大JSON字段保存,不同的应用架构对该JSON有对应的实现逻辑。
发布平台会触发Jenkins对应的pipeline完成构建,pipeline是按应用架构划分的,流程均基于Python开发,会完成代码下载、编译、打包/镜像等流程,细节不在此展开。
无论如何,CI阶段的核心设计就是build_order构建订单,最终产物就存放在image_list镜像列表(K8S用)或者package_list包列表(VM用)。
下面是php&k8s构建时的样子:
选择commit以及依赖项目的Commit,最终触发构建就可以得到编译结果了。
CD – 持续发布
这一块的理念就是把CI的产物分发到线上:
- K8S就是deployment部署image
- VM就是ansible playbook部署package
CD阶段的设计基本是通用的,可以适用于所有的技术栈(PHP or JAVA or …)和运行时环境(VM or K8S)
对于K8S来说,我们需要配置好Deployment的YAML模板文件,发布的时候只需要替换image name即可。
对于VM来说,需要配置诸如代码部署到哪个目录,部署到哪些机器,如何重启服务等配置。
这里以K8S的发布配置为例:
当然,具体发布到哪些K8S集群也是需要地方配置的,需要和该应用产生关联,就不展示了。
最终发布就很简单,只需要选镜像并点击发布:
CD阶段的核心设计是publish_order。
发布K8S很容易遇到不一致问题,比如创建了订单,但是推送K8S失败,那么到底以谁的状态为准呢?我的思想就是以K8S为准。
为了实现发布系统和K8S的一致性,我在推送deployment yaml给K8S的时候,在annotations中记录了关联的publish order ID。
这样做的好处是,我只需要调用K8S获取它运行中的deployment yaml,并从中找到publish order ID,然后再去publish_order表中找到对应的发布订单即可。
每个发布订单记录2个重要信息:
- 上一个订单ID是多少?
- 操作类型是什么? 发布 or 回滚。
这里一个重要的设计思想就是:把回滚当作一次发布。
因此,回滚的逻辑是找到当前订单的前一个订单,然后Copy它的内容生成一个新的发布订单,其类型等于回滚,然后推送它的YAML到K8S。
这种回滚即发布的设计,对于VM也同样重要,它可以令你的设计非常简单可靠。
下图是查看POD列表的样子:
RBAC权限
在RBAC中的难题就是权限的作用范围:
- 全局权限
- 具体某个应用下的权限
在我的设计中,权限permission表本身没有额外设计,但是在设计角色Role的时候增加了类型字段,用以区分是全局角色和应用级角色。
整个系统只允许给用户user分配角色,不允许直接分配权限permission。
当我们给用户user分配角色的时候,如果角色是应用级角色,那么需要关联到某个应用ID。
框架提供了检查权限的方法和装饰器,其逻辑是:
如果传入应用ID,则获取user关联在该应用ID下的角色以及关联的全局角色,然后分别获取这些角色的权限,最终检查是否权限充足。
大家有不明白的可以加我微信交流。
最后
整个发布平台还有RBAC,工单等设计,就不一一展开了,希望对即将做类似系统的朋友有所启发。
如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~

1
1