前端应用部署 k8s 的平滑发布问题
背景
在前端资源的发布中,有一个重要的诉求就是实现非覆盖式发布(也称为增量式发布),这是因为在新老版本切换的过程中,有时候需要访问旧版本的资源,如果采用覆盖式发布,那么在请求旧版本资源时就会出现 404 的异常。
目前我们在进行前端应用的 k8s 部署时就遇到了类似问题,由于我们采用的是覆盖式更新,部署镜像只保留最新发布的资源,而旧版本资源丢失了,导致会出现加载不到资源的情况出现。例如,前端资源很多时候有懒加载的优化策略做法,也就是用户会在老版本的时候切换模块,懒加载老版本一些对应的 css,js 资源,那么只保留最新资源的部署方式就会导致 UI 页面出现异常。
解决方案
其实上述问题,最本质的是要保留以前的历史发布资源,避免在新旧版本切换过程中导致的访问不到资源的情况出现。在没有使用 k8s 部署之前,我们采用的是 EC2 部署方式(云平台的机器实例),将前端资源推送到指定目录下(旧资源并不删除),只要磁盘不出现问题,就可以保证新老版本切换的平稳。
使用了 k8s 部署后,每次部署都会新生成 pod 保存最新资源,而包含旧版本资源的旧 pod 会立即被替换,导致无法平滑切换新老版本。
为此,我们讨论了三种解决方案来实现保留旧版本资源的问题。
方案 1 给 pod 挂载存储卷
这个方案的思路是将底层存储卷看作是磁盘,只要 pod 挂载存储卷的目录不变,那么历史版本的资源也将继续保留。使用这个方案相当于将前端应用当作了有状态应用进行处理,需要使用 opertator 进行调度,同时也需要保证底层存储卷的稳定性。
方案 1 需要我们对当前部署调度架构做比较大的修改,而且目前我们使用的 chubaoFS 并不稳定,加上把前端应用作为有状态应用会引入额外的复杂性,不利于跟其他无状态应用做统一调度,因此,并不适合我们采用。
方案 2 镜像包含旧版本资源
这个方案的思路是每次构建新镜像时将历史版本资源包含在内,这样部署时自然就会包含历史资源,不需要做额外的处理。这个思路确实 naive,也能解决问题,但主要的问题在于将会给镜像构建逻辑引入复杂性,而且从实践看,最新镜像中包含历史镜像内容,非常的不优雅。
因为本质上这就是一个资源合并的问题,把历史资源直接打入镜像并不是一个好的解决方案,因此我们也没有采用。
方案 3 历史版本资源单独存储,部署时合并最新版本
这个方案的思路是历史版本资源单独存储(比如云平台存储 s3),镜像构建逻辑保持不变,只需要修改启动脚本逻辑,将新旧版本资源合并后再启动即可,如下图所示:
这个方案的优点是不需要对现有构建/部署/调度架构做调整,只需要修改前端应用部署脚本,因此我们最终采用这个方案解决前端资源平滑发布的问题。
总结
本文针对前端资源在 k8s 发布中存在的平滑发布问题,提出了三个解决方案,并分析了其优缺点,最后采用的历史资源独立存储,使用发布脚本做资源合并的方案,希望对大家有所借鉴。
版权声明: 本文为 InfoQ 作者【小江】的原创文章。
原文链接:【http://xie.infoq.cn/article/224dcb9644db13e4808ba901e】。文章转载请联系作者。
评论