如何设计一条稳定的应用交付流程?|云效工程师指北

简介: 如何设计一条稳定的应用交付流程?为持续交付的过程提供了规范化的可能,也为了引入了让人不时埋首于配置文件的小山里的麻烦。我们不妨从一次略有波折、稍显隐患的集成部署案例开始,看看如何着手设计一条更为稳定的应用交付流程。

大家好,我叫王泊,负责云效应用交付AppStack的开发。把应用部署到各个环境、一步步进行集成测试,最终发布到生产环境,是程序员工作中必不可少的组成部分;而云原生技术引入的容器化、IaC(基础设施即代码,Infrastructure as Code)等等技术与理念,为持续交付的过程提供了规范化的可能,但也引入了让人不时埋首于配置文件的小山里的麻烦。我们不妨从一次略有波折、稍显隐患的集成部署案例开始,看看如何着手设计一条更为稳定的应用交付流程。

640 (1).png

一次波折的部署

许多个迭代后,面对陪风扇一起嘎吱嘎吱转着的流水线,程序员阿伟会回忆起把系统部署到预发环境、提交最后一轮验收,然后被打回来的那个并不遥远的下午。当时他有一个酷炫的Java SpringBoot应用要上线,实现了酷炫的“在不同部署环境下、发送带环境路由标签的业务消息”的接口:

1.png

日常环境的镜像构建、部署和验收测试一路OK,但是在再次构建部署到预发环境后,阿伟发现消息丢了:预发环境的消费方并没有消费到消息。经过一系列不管黑屏白屏康到bug就是好屏的排查,发现问题起源于在预发环境使用的SpringBoot配置文件application-staging.yaml中漏配了routing.env属性,应用启动时使用了缺省配置application.yaml中的兜底值,导致消息tag打错。

具体的问题倒是解决了,不过多少会留下点顾虑:以后写配置项的时候,免不了翻来覆去diff一下,是不是漏了什么,会不会导致各个环境里的产物有微妙的结构差异引发bug……

旧交付方式的潜在问题

仍然以SpringBoot应用为例,一部分开发者将应用从传统的虚机部署迁移到Kubernetes上的容器化部署时,会使用类似下面的思路:

640 (2).png

框架提供了为不同环境编写不同application.yaml配置文件的机制,用以达到环境差异化部署的效果。我们不难构陷出小故事的主人公阿伟也使用了类似的思路:

● 使用application.yaml提供所有环境的共性(和一部分兜底)配置;
● 各环境的差异化配置由单独的application-xxx.yaml给出,覆盖兜底配置;各差异化配置不作特别的规范要求,允许属性取值不同,也允许引入某个环境特有的属性值;
● 为不同环境的镜像编写不同的Dockerfiles, 环境配置方面的差异主要在于启动应用时指定的参数不同。

一个典型的工程目录看起来像是这样:

640 (3).png

看起来很规整,但其实也引入了一些问题:

● 环境差异化配置需要靠人工核对来减少错漏,编写application.yaml这类基准配置的时候也需要慎重考虑提供什么样的兜底值,一旦有差错则排查成本相对高;
● Dockerfile往往没有很大的差异,但构建出来的产物是和具体环境强绑定的,没办法复用;多次编译可能因为某些隐患(最典型的比如依赖版本不严格)导致不同环境下的交付内容并不一致,有引入bug、招致线上问题的风险。
  ○ 比如在日常环境下完成构建后,某个(可能是间接)依赖的快照包被更新了(可能是不规范的快照包更新,也可能是安全包之类选择倾向于让接入方无感升级而使用快照版本当作release);此后部署到预发环境时,构建引用了新版本的依赖包,导致日常环境下的测试验收结论可信度下降。

单应用逐环境晋级方案的考量

吃一堑长一智,我们不妨帮阿伟的应用发布方案列出下面的考量:

● 产物对环境中立:环境差异化配置在部署时注入,一份镜像可以用于所有环境的部署。
● 环境配置统一:所有环境使用同样格式的配置模板和差异化的值注入,避免“兜底+覆盖”引入的配置模板差别。

具体来说,在“日常-预发-生产”的整条集成发布流程中,使用的镜像和编排只有一份;镜像中的SpringBoot应用里,也只使用application.yaml,不再引入其他差异化配置。

这样做看起来限制了一些灵活性,但核心考虑在于:通常情况下很难规范配置文件和编排的具体格式;一旦存在“一份配置兜底+多份差异化调整”的情况,理解应用代码逻辑和部署细节的成本会变高,维护、验证应用逻辑所需理解的内容也随配置文件的增加而线性增长。即使是应用的设计者或是owner,也难免随着时过境迁而忘记一些细节(“我当时为什么要加这个环境变量来着”),更不用提中途加入进行功能迭代的其他开发人员了。

640 (4).png

实际部署到Kubernetes集群中时,环境变量通过编排中容器的环境变量注入。接下来需要统一Deployment编排——如果为不同的环境使用多份编排文件,仍然会引入无意义的重复。这里我们可以使用Helm chart的形式,诸如镜像、环境变量等等在构建部署时才能决定的差异化配置,都可以通过values配置进行注入:

640 (5).png

需要定制化的部分,则是CICD系统中动态生成Values.yaml配置的脚本。这部分的复杂性相对容易控制,具体的实现则根据使用的CICD工具不同而略有差异,我们将会在后文中看到一个概略的示例。

方案改造例

现在可以回到阿伟的服务上进行改造了。

Step 1: 统一application.yaml和Dockerfile

首先我们要压缩服务中的SpringBoot application yaml配置,只留下一份:

2.png

这里使用了占位符${DEPLOY_ENV},要求环境变量提供routing.env的值。

Dockerfile则可以去掉所有环境差异化的环境变量定义、统一为一份配置,并假定环境变量都已经正确注入。

Step 2: 编写Helm chart

从创建一份空的helm chart开始:

3.png

接下来,可以把原先的编排文件按照helm模板的格式简单改写,放置到cool-service-chart/templates/目录下。以Deployment为例:

4.png

我们使用.Values.image这一helm占位符将镜像注入容器。环境变量注入的方式则有多种——变量较少的情况下可以在pod template中直接定义name和value;不过如果考虑到更长远的扩展性,也可以采用关注点分离的方式,单独定义一份ConfigMap用于定义环境变量;这样做的好处,则是添加环境变量的开发者无需理解Deployment的具体结构,甚至只需要理解“往ConfigMap的数据定义里写一个键值对就能实现环境变量注入”就可以了。

基于这些考虑,我们定义容器使用下面的ConfigMap提供键值对、注入环境变量:

5.png

Chart里的模板编写完成后,记得推送到一个git库里,方便后面使用。

Step 3: 编写Values.yaml生成脚本

在准备好Helm chart的静态模板部分之后,需要为CICD工具编写部署时生成Values.yaml的脚本。我们不妨假设阿伟的团队选择使用Jenkins建设CICD流水线:

6.png

这里我们主要关注chart-complete.sh,它需要完成如下的任务:

● 从git仓库克隆chart库的主干;
● 从环境变量中,生成values.yaml.

7.png

如果已经搭建了helm仓库,这里也可以选择把生成好的chart推到仓库。

总结

在单一应用逐环境晋级部署的过程中,往往会涉及到针对环境定制的差异化配置;为了避免Dockerfile、配置文件等冗余带来的治理成本及bug隐患,我们可以利用云原生IaC的优势,基于统一的制品和编排定义,将环境的差异化配置项延迟到部署时注入。这样,在各个环境中所部署的代码是完全一致的,提高了集成的可信程度及测试效率。

当然,从头搭建CICD体系往往也需要一定的试错;云效应用交付AppStack提供了符合前述实践的编排管理、环境治理和差异化配置能力,可以通过集成云效流水线Flow,快速搭建出整条晋级流程,欢迎大家尝试。若有收获,就点个赞吧!

点击下方链接,免费体验应用交付平台 AppStack。

https://www.aliyun.com/product/yunxiao/appstack?channel=yy_practice

lQLPDhtDba1KT2_NBDjNB4CwgwE-eOLUK_gCPyXeUECTAA_1920_1080.png

相关实践学习
流水线运行出错排查难?AI帮您智能排查
本实验将带您体验云效流水线Flow的智能排查能力,只需短短1-2分钟,即可体验AI智能排查建议。
ALPD云架构师系列 - 云原生DevOps36计
如何把握和运用云原生技术,撬动新技术红利,实现持续、安全、高效和高质量的应用交付,并提升业务的连续性和稳定性,这是云原生时代持续交付共同面对的机会和挑战。本课程由阿里云开发者学堂和阿里云云效共同出品,是ALPD方法学云架构师系列的核心课程之一,适合架构师、企业工程效能负责人、对DevOps感兴趣的研发、测试、运维。 课程目标 前沿技术:了解云原生下DevOps的正确姿势,享受云原生带来的技术红利 系统知识:全局视角看软件研发生命周期,系统学习DevOps实践技能 课程大纲: 云原生开发和交付:云研发时代软件交付的挑战与云原生工程实践 云原生开发、运行基础设施:无差别的开发、运行环境 自动部署:构建可靠高效的应用发布体系 持续交付:建立团队协同交付的流程和流水线 质量守护:构建和维护测试和质量守护体系 安全保障:打造可信交付的安全保障体系 建立持续反馈和持续改进闭环
相关文章
|
7月前
|
传感器 人工智能 监控
通义灵码智能体模式在企业级开发中的应用:以云效DevOps自动化流程为例
通义灵码智能体模式具备语义理解、任务闭环与环境感知能力,结合云效DevOps实现CI/CD异常修复、测试覆盖与配置合规检查,大幅提升研发效率与质量。
362 0
|
4月前
|
运维 Kubernetes 测试技术
应用多、交付快,研发运维怎么管?看云效+SAE 如何一站式破局
通过在云效中创建 SAE 服务连接并关联集群,团队可将应用环境直接部署到 SAE,实现从代码提交、镜像构建到 SAE 部署的自动化流水线。该集成打通了研发与运维的壁垒,特别适用于应用数量多、团队规模大、交付节奏快的组织,助力企业实现敏捷、可靠的持续交付。
|
弹性计算 监控 JavaScript
云效Flow:打造高效、稳定的CI/CD流程实战指南
【10月更文挑战第7天】本文介绍了“云效Flow”这一CI/CD工具,通过实际案例展示了其在Node.js项目中的应用,包括自动化构建、测试及部署流程。云效Flow支持多种开发语言与框架,集成第三方服务,提供详尽的新手引导,简化了CI/CD流程的搭建,提升了开发效率与软件质量,特别适合初创团队和大型企业使用。
540 4
|
7月前
|
Cloud Native Java Devops
Java 学习路线之环境搭建微服务项目实战及 DevOps 流程实操内容解析
这是一份结合最新技术的Java学习路线,涵盖环境搭建、微服务项目实战及DevOps流程。内容包括2025年版开发环境配置(如SDKMAN管理JDK、)、Gradle构建工具使用、微服务图书管理系统实战(Spring Boot 3.3 + Spring Cloud 2025.0)、云原生部署)、AI融合实践(OpenAI集成)以及性能优化与监控(JFR/Micrometer/Sleuth)。通过每日实践、代码审查和技术分享,帮助你掌握现代企业级开发技能,实现云原生应用的独立开发与部署。资源地址:[点击下载](https://pan.quark.cn/s/14fcf913bae6)。
547 0
|
运维 监控 Devops
图解 DevOps 流程,7 大关键步骤总结,非常详细!
本文详解 DevOps 流程的 7 大关键步骤,快速掌握 DevOps 的核心实践。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
图解 DevOps 流程,7 大关键步骤总结,非常详细!
|
运维 Devops 测试技术
自动化运维的魔法——打造高效的DevOps流程
【10月更文挑战第28天】在数字化浪潮不断推进的今天,企业对运维效率的追求如同古人探索魔法一般充满好奇与渴望。本文将带你走进自动化运维的世界,揭秘如何通过DevOps实践,实现从代码到部署的无缝连接,提升企业的IT运营效能。我们将一起探索自动化工具的选择与配置,以及如何构建一个既能快速响应业务需求,又能保障系统稳定性的高效流程。
|
监控 Devops jenkins
自动化部署与监控:打造高效的DevOps流程
【10月更文挑战第24天】在追求快速迭代和持续交付的软件开发时代,DevOps成为提升团队效率的关键。本文深入探讨如何构建一个高效的DevOps流程,包括自动化部署、监控和故障排除等关键环节。通过实际案例,我们将学习如何利用工具简化运维任务,确保系统稳定运行,并快速响应生产问题。
413 2
|
存储 网络安全 开发工具
快速认识和上手云效代码管理应用
要体验云效代码托管Codeup的本地命令行操作和SSH克隆/提交,请先安装Git并配置SSH公钥。登录Codeup后,新建代码库并设置相关信息。可从其他平台导入代码。提交代码支持网页和本地客户端两种方式。库管理员可邀请成员协作,并按需设置角色。此外,Codeup内置代码检测服务,支持自动触发扫描。功能开发完成后,可通过合并请求进行代码评审,确保编码质量。
700 1
|
运维 监控 Devops
DevOps实践:构建高效运维流程
【9月更文挑战第3天】在当今快节奏的技术环境中,高效的运维流程是企业成功的关键。本文旨在揭示如何通过DevOps实践,构建一个既灵活又高效的运维体系。我们将深入探讨自动化工具、持续集成与持续部署(CI/CD)策略以及监控和日志管理的最佳实践,以实现运维工作的优化。文章将用简洁明了的语言,结合生动的比喻,带领读者走进DevOps的世界,学习如何将理论应用到实际工作中去。
|
敏捷开发 缓存 前端开发
阿里云云效产品使用合集之前端打包时npm安装卡住一般是什么导致的
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。