大家好,我是崔力强,我在云效负责 Flow 流水线的开发工作。近年来,SaaS 化部署状态的产品的私有化部署需要越来越多,比方云效本身就有私有化部署的版本。为了可能无效且高效地同时治理 SaaS 版本和私有化版本的公布过程,云效团队也联合云原生的基础设施和标准化工具(比方 helm)进行了一系列的摸索和实际,并将其中一些通能的能力进行了产品化。本文会从问题自身登程,解说解决问题的思路,及如何通过“DIY”的形式来实现这套思路。最终解说云效 AppStack 产品是如何对这些实际进行产品化,并使其更容易规模化。
SaaS 服务在版本化上的先天不足
软件交付有两种根本场景:面向大版本的交付和面向 SaaS 的降级更新。
通常来讲,提供本地或私有化部署的软件都属于第一种。比方 Jenkins 刚刚公布了 2.319.2 版本,那么这个版本里蕴含了什么样的个性就是明确的。你拿着这个安装包在任何一台机器上都能够从头装置失去这些性能。
而互联网产品很大一部分是 SaaS 化的,即只有一套部署,供所有用户应用。软件的维护者更关怀的并不是我的产品是否能够在任何一个数据中心从头搭建进去,而是如何在现有的这个运行中的零碎上通过更新某个组件或者服务来疾速的交付一个个性。
图 1:SaaS 服务交付和大版本交付的交付节奏
从上述的示意图,能够形象地看到两种交互方式的差别。
面向大版本的交付会明确该版本中蕴含的个性以及交付工夫,版本的公布工夫距离通常比拟长,须要对版本的全新装置以及不同版本之间的降级装置进行详尽的测试。
面向 SaaS 的降级更新,交付的频率比拟高,能够疾速响应市场上的需要,但相应的布局性比拟差。同时因为“可反复装置能力”的优先级要低于“疾速利用已有的服务和能力交付新个性”,因而在架构上可能会逐渐产生简单的依赖,从而进一步地使得全新部署这套服务变的越来越艰难。
然而事实并不是非黑即白的。有可能一套互联网产品在倒退了若干年之后有了进军海内的需要,就须要同时部署海内站,或者须要做私有化部署。此时该怎么办呢?是就义效率全副改成版本化的交付,还是以 SaaS 服务的交付节奏为主?如果是后者,那么每个私有化大版本公布前的几天,团队须要从缭乱的 SaaS 部署中厘清须要将哪些服务的什么版本(比方镜像版本)纳入到这个大版本中,进行版本验证,以及潜在的可能要对代码和配置进行调整。
图 2:同时兼顾 SaaS 服务和大版本交付两种交付形式
假如一个月出一个大版本,那么在上图的 2 月 1 号到 2 月 7 号这七天里都可能产生了什么呢?
- 可能在对焦,大版本里要求的性能是否都实现了,如果没有就要拉分支持续做。
- SaaS 化版本外面的一些性能可能是私有化部署不须要的,这时须要加一些开关使其不可见,须要改代码。
- 在这一个月的迭代里,技术架构产生的调整,删除了一个微服务,又新加了一个微服务,大版本须要做相应的调整。
- 在这一个月的迭代里,利用的配置项也产生了变更,须要在大版本中做相应调整。
其中:
1 和 2 属于版本布局和测试左移的问题。本文临时不聊。
3 和 4 就是能够通过技术来解决的问题了,本文接下来的局部会重点探讨如何高效的解决这两类问题。
对立版本格局
解决上述问题的核心技术就是要有一个对立的版本格局,无论是 SaaS 版本还是大版本都应该应用雷同的版本格局。
在此基础之上,要做到
1、版本应该是一个残缺的零碎形容,蕴含了所有的镜像,配置等所有启动服务所须要的形容。从而可能实现基于某个版本,就能够一键拉起一个新的可用的环境。
2、每个环境有一个基线的概念,也就是和环境的以后运行态保持一致的那个版本。
图 3:版本中蕴含的内容
3、在环境中,每个服务还是能够独立更新的。每一次某个服务在某个环境上(比方服务 A 的生产环境)的公布,只管只批改了零碎中的一个服务,但也应该主动生成整个环境的一个新的版本。
4、每个环境的配置应该集中化起来,而不是在各个服务中别离保护。在服务数量比拟多的状况下,这种形式能够大大地升高版本保护的老本。尤其是在新建环境的场景下,因为配置集中化了,须要批改什么就更加的高深莫测。通常在配置项集中化之后,还会看到另一个益处,那就是反复配置少了,因为一个零碎中的不同服务多多少少都会共用一些配置,如果要独自在服务中保护,就不可避免的呈现反复。
图 4:任何制品和配置的变更都引起大版本的更新
5、对环境的任何变更都应该最终反映在版本中。只有这样能力保障你做的变更,能够原样的在另一个环境,另外一家客户的机房中被正确的执行,比方 DDL 和 DML。
6、所有的日常公布行为,实质上就是针对版本变更这个动作的一些场景化封装。比方对某一个服务做变更,那就能够创立一个独立的 CD 流水线进行镜像构建,创立长期版本,更新环境,将长期版本写入基线。而进行某个配置变更,就是批改基线,而后利用基线到环境。
图 5:围绕版本构建日常构建公布等工作流
围绕 Helm 进行版本治理和构建部署
在不同的基础设施之上,上述的思路能够有不同的实现形式。
而在 K8S 基础设施上,Helm Chart 就是版本格局的不二之选。
Helm 的外围概念包含:
- 一套 K8S 资源文件的组织形式,资源文件中能够应用变量占位符
- 变量管理机制,应用 helm 提供的机制,能够很容易的将整个大版本的变量提取进去放到对立的文件来保护,这就符合了咱们后面提到的需要
- 一个渲染引擎,在运行时,将变量替换到文件中,并进一步利用到集群中
- 一套部署历史治理的机制,比方 update/rollback 等
上面看一个典型的例子:
图 6:基于 Helm 构建版本
得益于 K8S 资源的弱小形容能力,造成一个“版本”的各种组成部分都能够很好的形容,比方:
- 零碎的域名是什么?
- 不同的 URL 应该路由到哪个服务?
- 能够将 Flyway 和相干的 SQL 迁徙脚本打包成一个 Job,来做 DDL。
- 能够将其余的须要对系统进行数据初始化的工作打包成一个 Job。
在此之上,再加上 helm 提供的模板化能力,就能够分明的将对一个环境的形容分为两个局部:
- 不变的局部,也就是那些模板化的资源文件,不同的环境会共用这部分形容。
- 抽取进去的属于某个环境的变量。
因而上图中的蓝色的框内的就是“测试环境”的一个版本。
helm chart 作为版本,能够看到,实质上就是一堆形容文件。这些形容文件能够以目录的模式存在,也能够以 tgz 包的模式存在。因为面向 SaaS 的交付的变更频率会十分高,因而每次打一个 tgz 包就会显得十分的臃肿。所以笔者会采取目录的模式,那么什么是承载目录,并且还能实现版本序列技能力的技术呢,很显然就是 Git 啦。
咱们把下面思路中的那个围绕版本进行一系列研发流动那种图翻译到 Helm 和 Git 上,就是这样:
图 7:围绕 helm chart 构建日常构建公布等工作流
至此,利用现成的一些标准化工具,就实现了一套版本机制,及围绕版本机制的开发流程。
在这套流程下:
- 面向 SaaS 的交付流程,依然十分麻利,且同时会主动的保护好各个环境的基线。
- 因为各个环境都通过 helm chart 中的模板文件“耦合”在了一起,当你批改一个环境时候,天然就须要思考其余环境怎么办,因而一致性也很好的失去了保障。任何时刻,我都能够应用某个环境的基线来重建这个环境。
- 也能够基于一个环境的基线,疾速地创立出另一个环境的基线,只须要简略的批改一下环境的变量文件即可。
一些小细节
- 在理论应用这套计划的时候,其实还是很多小细节,须要缓缓优化。这里就简略列两个:
- 所有的镜像的 tag 蕴含日期和 commitId,在后续定位问题时候,能够通过这些信息疾速的找到对应的代码,进行排查。
在上述的 CD 流水线中更新一个环境之前,确保基线与运行态的一致性,如果不统一,则不进行更新,防止有人批改了基线的代码库,意外的被你捎带上了环境。
规模化的驳回最佳实际
上述计划最大的益处,就是驳回的都是规范的组件,具备很大的灵活性,和可定制性。
但这同时也是这个计划的害处,就是太灵便了,各种最佳实际也须要缓缓摸索和调整。在调整的过程中可能会发现很多相似下面提到的“小细节”,须要进行标准或者封装。如果进行规模化的推广,那么就要求每个团队都有一个很相熟这些工具的共事。如果无奈找到这么多相熟工具的同是,那就能够思考对上述的思路进行产品化,使得大部分的开发人员都能够低成本的 follow 最佳实际。
云效的 AppStack,就着眼解决这个问题,通过白屏化利用编排、版本治理、以及企业级利用编排模板等产品能力帮忙升高开源工具应用门槛,提供了开箱即用的最佳实际。
- 利用编排。即上述的基于 helm 来形容多环境配置的产品化实现。
- 版本和基线。有了版本和基线,就能够疾速地进行回滚和基于某个版本一键拉起环境等操作。
- 集成公布流水线。将上文中提到的常见的日常工作流程和版本联合在一起,防止每个团队别离配置。
点击下方;链接体验云效应用交付平台 AppStack。
https://www.aliyun.com/product/yunxiao/appstack?channel=yy_practice