50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

基于容器服务的持续集成与云端交付(一)- 交付之禅

  • 2017-02-13
  • 本文字数:3732 字

    阅读完需:约 12 分钟

前言

随着微服务架构与容器虚拟化技术的发展,持续集成与持续交付的概念又重新回到了大家的视野,越来越多的公司开始使用持续集成的系统来解决频繁发布带来的质量问题;使用持续交付的工具来实现代码在不同环境上的自动部署。原本有些学院派乌托邦式的思想正被千千万万次的集成与部署证明着它应有的价值。那么究竟是因为什么让持续集成与持续交付这个已经不再年轻的软件开发与交付的思想重新焕发绽放迷人的光彩呢?

传统软件交付之殇

传统软件的开发与交付的周期都很漫长,一款普通的企业软件通常需要十几个开发人员,几个月的时间来完成,从需求的分析、系统的设计、编写测试用例、系统开发、单元测试、组装测试到交付调试。有条不紊的流程与规范像一辆绿皮火车下的枕木,稳定而可靠的保证整个系统缓慢的推进,每一次交付、升级,都需要提供基础的硬件、软件的环境、软件的代码、软件的文档与手册。还记得刚刚迈入软件开发行业的时候,跟随公司的服务团队,驻场交付产品,每一个驻场工程师都按照之前预演过好多遍的流程,对照着系统的部署手册,一步一步的组装硬件,安装软件,稍有差池,就要按照对应的应急预案进行回滚。开始的时候觉得交付像一个神圣的仪式,将用智慧和汗水构建成的软件交付给客户使用,是一种非常荣耀和值得骄傲的事情;后来越来越多次的产品交付让我深深的感觉每一次交付都像分娩一样痛苦,扪心自问是否有简单更舒畅的流程可以将软件交付给客户呢?

传统模式的反思与 CI/CD 概念的提出

通常来讲,一个软件的生命周期分为问题的定义、可行性的分析、系统设计、系统编写、系统测试与调试、系统部署与交付、维护与升级等步骤。在传统软件的生命周期中,更倾向于使用瀑布流的模式来去有条不紊的规范整个流程,每一个阶段都期望遵循“活动 - 结果 - 审核 - 再活动 - 直至正确”的流程来保证系统稳定。整个软件的生命周期就变成了一个很长的二维线性的流程。这也制约了软件的开发迭代与交付的速度,前辈们想了非常多的办法来提高整体的开发速度,比如将一个单体的系统系统设计成为服务化的分布式的子系统,这样可以让一个大型的单体软件的开发变成多个小的独立系统的并行开发;使用组件化的方式组建系统,在不同的系统间复用模块加速开发;通过自动化工具或者脚本进行自动化部署与交付等等。

诚然,这些都解决了软件交付过程中的一些问题与难点,但是这些方式都像西医一样,治标不治本,因为要想快速的交付,首先要明白软件交付过程中遇到的核心问题是什么。总结成两个词“自动”与“可靠”。自动是一个很宽泛的词汇,在软件交付中代表着测试自动化、交付自动化、运维自动化等等,而可靠讲的是每一次交付要保证是当前的交付是稳定的或可回滚到稳定版本的。

为了解决“自动”与“可靠”的问题,敏捷开发鼻祖 Martin Fowler 提出了持续集成与持续交付的概念,它所描述的软件开发,是从原始需求识别到最终产品部署到生产环境这个过程中,需求以小批量形式在团队的各个角色间顺畅流动,能够以较短地周期完成需求的小粒度频繁交付。频繁的交付周期带来了更迅速的对软件的反馈,并且在这个过程中,需求分析、产品的用户体验和交互 设计、开发、测试、运维等角色密切协作,相比于传统的瀑布式软件团队,更少浪费。通过这种小步快跑的方式,将小功能快速迭代、验证、交付,通过自动化的工具,将测试、部署、运维自动化,减少需求在软件生命周期中流动的时间。但是为什么看上去可以奉为圭臬的持续集成与持续交付的思想却在相当长的时间被开发者束之高阁呢?

实现持续集成持续交付的难点

对持续集成持续交付有一些理解与体会的开发者会经常看到类似下面这张图的持续交付流程。

在这张图中我们讲述了一个持续集成与持续交付的流程,从代码的提交、构建与编译、单元测试到部署环境、集成测试与发布。软件交付本身就是一件复杂的事情,不同的产品、不同的架构、不同的业务形态会导致持续集成与持续交付的实现上有非常大的不同。还记得很久以前流行一个关于哲学的笑话,当你问十个哲学家什么是哲学的时候,你会得到十一种答案,因为每个人都有对哲学不同的理解。对于持续交付也一样,Martin Fowler 讲述了一个乌托邦式的软件开发与交付的模式 - 持续集成与持续交付,但是前辈只给了我们先进的思想,并没有给出默认的实现。不同的公司、不同的产品、不同的技术栈、不同的开发与部署形态决定了持续集成与持续交付注定是因人而异的,在大家不断摸索什么样的方式是持续集成与持续交付的最佳实践的过程中。有的人做少了,只实践了其中的一部分,导致基本的交付能力上有缺欠;有的人做多了,引入了更多复杂的流程,导致原本应该提速的交付流程,像穿着名牌高跟鞋参加跨栏一样,怎么也快不起来。

如果将上面的流程具象化一个 LNMP(Linux、Nginx、MySQL、PHP) 的例子,就变成了如下的过程。

我们会发现当整个持续交付的流程流转到了持续交付系统的时候,流程开始和具体的环境与编程框架开始耦合,比如单元测试在这个例子中需要运行 PHPUnit 相关的命令去实现;准备环境需要根据具体的部署环境是 KVM 的虚拟机还是物理机或者是云服务器区别实现;配置环境需要根据具体的编程模型来准备在本例中会通过自动化配管工具例如 Ansible 来验证与准备不同环境中的代码运行时环境;分发代码后的流程在本例中是通过重启 Nginx 实现。其实这就是持续集成与持续交付真正难的部分,它并没有特定的要求规定什么流程该用什么方式做什么,就像大型软件系统的架构设计,只有“法”没有“型”,这也就是为什么程序员有很多,但架构师少的可怜的道理。

归根结底,持续集成与持续交付的难点在于如何屏蔽不同语言、不同框架、不同系统之间的持续集成与持续交付流程的差异性。曾经幻想过是否能有一种方式可以归约软件的交付,而这就是 Martin Fowler 留给我们的课后思考题 - 论如何实现持续集成与持续交付的流程标准化。

新的交付之道——容器标准化交付

容器虚拟化这几年随着 Docker 的推出,也逐渐进入到开发者的视野中。刚刚接触 Docker 的时候,按照学习新知识的习惯,我将 Docker 和虚拟机或者虚拟化进行了等同,认为他们是一个领域的不同实现,通过类比的方式来学习 Docker。但是后来我发现,Docker 的意义不在于解决软件底层的环境定义的问题,更多的是在解决交付的问题。

在上文中我们讨论了为什么持续集成与持续交付对于很多公司来讲是有难度的。而解决这个问题的最理想的办法就是是否有一种方式可以将交付的流程编程一个标准化,这样进行持续集成与持续交付的开发者可以很快的像读说明书一样,一步一步完成自己的持续集成与持续交付流程。

容器给交付带来最大的变革就是标准化。

Dockerfile: 将代码和环境打包成了镜像,将原来系统中分发的最小单元由代码变成了镜像,不同的环境、不同的软件、不同的配置都可以通过 Dockerfile 的配置来实现,标准化了交付的最小单元,让交付的最小单元不再和环境、编程框架耦合。

Docker API: 将软件的生命周期管理从原来的不同框架不同实现变成了统一标准的命令。启动软件变成了 docker run,停止软件变成了 docker stop,重启软件变成了 docker restart。

Docker Compose: 将软件交付的方式进行了标准化,大型的软件是由很多不同的部分组成的,而 Docker Compose 就是将软件之间的关联关系用标准话的方式进行了描述,并通过分发 Docker Comopse 的配置文件即可将软件进行交付。

如上图,我们将刚才的例子用 Docker 的方式进行推演,发现原本和编程框架或者环境耦合的部分现在通过 Docker 进行了标准化,这样不同语言不同框架不同业务场景的开发者就可以快速的时间自己的持续集成与持续交付了。

软件定义交付时代已到来?

云计算的兴起,让越来越多的 IT 基础设施变成虚拟的、软件定义的,比如软件定义存储、软件定义网络等等。通过编程的方式可以将原本的 IT 基础设施进行创建、分配、管理,屏蔽掉了底层的硬件的异构。反过来看云端交付的场景,是否可以变成软件定义的。我们可以通过资源编排(例如阿里云的 Ros 或者 AWS CloudFormation)定义基础的设施;可以通过 Docker 软件定义部署;云资源和容器化的应用都可以用 API 的方式来实现软件定义运维。

软件定义基础设施 + 软件定义部署 + 软件定义运维 = 软件定义交付?这个问题留给大家更多的思考。

阿里云容器服务是阿里云 2015 年 12 月推出的基于容器的 CaaS 产品,集成了阿里云 OSS、ECS、SLB、SLS、VPC、RDS 等多款 IaaS 云产品的能力。容器的交付方式虽然给交付带来了很多的便利,但是还远远不够,阿里云容器服务为微服务、持续交付提供了大量云交付的能力,可以让 Docker 的交付过程更顺畅。在下一篇文章中,我们将讨论下阿里云容器服务提供了什么样的功能特性满足大家的云端交付场景。

个人简介

莫源,阿里云高级研发工程师。在加入阿里巴巴之前,先后在北京天方地圆科技有限公司、微软亚洲研究院任职。现主要负责阿里云容器服务产品的底层服务发现系统、集群管理系统的研发,从事容器的持续交付、持续集成的方案的设计与实现。在云计算、分布式系统、图像识别与虚拟现实方向有多年的开发经验。


感谢木环对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-02-13 16:447998

评论 3 条评论

发布
用户头像
软件交付的核心问题是自动和可靠,想请问下老师:为什么有这个结论呢?这个结论的依据是什么?
2019-06-20 08:26
回复
用户头像
文章的两个过程图是不是顺序放反了?
2019-01-08 00:12
回复
是放反了
2020-03-08 11:41
回复
没有更多了
发现更多内容

实例讲解如何制作Python模式程序

华为云开发者联盟

Python 编程语言 星型程序 Programs 模式程序

Ai特征选择,一篇就够了

泳鱼

Python 人工智能 机器学习 深度学习 AI

滴滴OCE惊喜福利!

滴滴云

Google Material Design 元件库

zhuchuanming

元件库

SpringBoot-技术专题-启动自动装配过程

码界西柚

spring springboot

数据加密:你应该知道的数仓安全

华为云开发者联盟

数据加密 GaussDB(DWS) 数仓安全 透明加密 加密函数

【实战问题】-- 缓存穿透之布隆过滤器(1)

秦怀杂货店

缓存 布隆过滤器 java;

如何阅读 Java 字节码(Byte Code)

Kori Lin

Java JVM bytecode 字节码

深入理解 JavaScript, 从作用域与作用域链开始

koala

JavaScript 大前端

一文归纳Python特征生成方法(全)

泳鱼

Python 机器学习 深度学习

阿里P7大牛手把手教你!美团Android开发工程师岗位职能要求,附赠课程+题库

欢喜学安卓

android 程序员 面试 移动开发

Python OpenCV 图像旋转,取经之旅第 11 天

梦想橡皮擦

3月日更

EGG NETWORK永动金融EFTalk火爆来袭

币圈那点事

一束光的旅程

白洞计划

【JS必知必会】高阶函数详解与实战

koala

JavaScript 面试 大前端

Ai调参炼丹,一篇就够了

泳鱼

Python 机器学习 深度学习 AI

Android开发必须要会!2021大厂Android面试经验,全网疯传

欢喜学安卓

android 程序员 面试 移动开发

WC,误删数据库了,会被开除吗?

Java架构师迁哥

经常被面试官问道的JavaScript数据类型知识你真的懂吗?

koala

JavaScript 面试 大前端

Spark性能调优-Shuffle调优及故障排除篇

五分钟学大数据

spark Spark调优 3月日更

牛链NB系统开发案例源码

系统开发咨询1357O98O718

悖论和直觉

阳龙生

领域驱动设计101 - 绑定模型与实现

luojiahu

领域驱动设计 DDD

4大华为云“安全镖局”秘密法宝揭秘

华为云开发者联盟

态势感知 华为云 企业主机安全 数据安全中心 Web应用防火墙

Apache Ranger安全认证配置

大数据技术指南

大数据 3月日更

2021年GitHub上爆火的999页Java面试宝典终开源

比伯

Java 编程 架构 面试 程序人生

蚂蚁金服三面Java面试题全解析,这也太难了吧

Java架构之路

Java 程序员 架构 面试 编程语言

巩固知识体系!应聘高级Android工程师历程感言,面试建议

欢喜学安卓

android 程序员 面试 移动开发

小鼎量化机器人系统开发详情介绍

系统开发咨询1357O98O718

Java面试必问:一位清华大牛用一个坦克大战讲明白了23种设计模式(视频+源码笔记)

Java架构追梦

Java 架构 面试 设计模式 坦克大战

如何实现一个简易版的 Spring - 如何实现 Setter 注入

mghio

spring 依赖注入

基于容器服务的持续集成与云端交付(一)- 交付之禅_DevOps & 平台工程_莫源_InfoQ精选文章