持续部署(Continuous Deploy)的收益是全面的,体现在运维规范、自动化和团队合作等方面。
一个完整的持续部署系统应该如何建设?本文给一个完整的思路和参考实现。
一、持续部署的收益
先来看一张图,图中的自动化部署系统就是持续部署部分。从环境的角度来说,持续部署需要对不同的环境进行部署,而不同的环境涉及到不同的角色,因此在这个平台之下都能带来自动化的效率收益。其次更重要的是,为了真正意义上的持续部署系统建设,此时需要运维对应用环境进行标准化,比如说服务运行目录、进程属主、配置文件等等。最后最重要的,通过这个平台,把一些运维需要管理的东西统一管理起来,角色、环境、应用、包、配置等等,它在服务故障后的恢复阶段,能够起到快速恢复的作用。
二、持续部署的相关概念
1、持续集成、持续交付、持续部署
a、持续集成(CI)
看看Martin Fowler怎么描述的。“.....一种软件开发时间,即团队的成员经常集成他们的工作,通常每个成员每天至少集成一次---这导致每天发生多次集成。每次集成都通过自动化的构建(包括测试)来验证,从而尽快地发现集成错误。许多团队发现,这个过程会大大减少集成问题,让团队能够更快的开发出一致的软件。”,所以我在上图中把【持续集成】提炼成如上几个部分:持续审查、自动化构建、自动化测试、自动化打包等等。详细见书【持续集成,软件质量改进和风险降低之道】
b、持续交付(Continuous Delivery)
持续交付是一个软件工程方法,目的是为了在一个短周期内频繁实现和交付有价值和可用的软件供用户使用。它和持续集成有什么区别?这个可以到【持续交付:发布可靠软件的系统方法】这本书中找到答案。该书Martin Fowler大师给做了一个很短的序,其中谈到“对于很多团队来说,持续交付方法的基础是持续集成。持续集成使整个开发团队保持同步,消除了集成问题引起的延期。.....但CI只是第一步。软件即使被成功地集成到了代码主干上,也仍旧是没有在生产环境中发挥作用的软件。本书是从CI至“最后一公里”的问题进行详细描述,描述了如何构建部署流水线,才能将已集成的代码转变为已部署到生产环境中的软件”。这段话详细的表达了持续交付和持续集成的不同,对照上图,我们其全流程理解成持续交付=持续集成 持续部署 持续反馈。
c、持续部署(Continuous Deploy)
持续部署这个概念本身不突出,但从多次的经验看到,它对运维带来的收益非常大,并且一般是运维能够独立控制的(和研发、测试合作更好)。持续部署真正的是解决“最后一公里”的问题,这个“一公里”是到测试环境、预发布环境和生成环境等等,而不是绝对的生产环境,对于我来说,所有这些环境的持续部署和更新都是由这个平台来完成的。持续部署,你可以理解是集成完成之后,产生了一个package,如何把这个package部署到不同的环境,并且能够实时的给出部署结果的反馈的过程,就叫持续部署。
2、应用、包、环境、配置文件、用户
在持续部署平台中,涉及到很多概念,这也是我为什么不选择开源的原因。具体的概念如下:
a、应用(Application)
一组提供业务服务(面向用户的)或者功能(面向其他服务进程)的集合,对应到技术层面上,有两种表现形式:一个web服务,比如说war包;一个独立的进程包等等。对于一个九游门户来说,我们可以分解成几个应用:门户_前端应用、门户_后台、门户_管理等等。可以说是运维在业务层面上变更的最小单位,是一个一个独立的包。
b、包(Package)
是个技术术语,可以理解成一组文件的集合,基于某个容器或者独立运行便能提供服务和功能,一个应用对应一个包。比如说刚刚说的门户_前端应用对应的持续集成包就是portal_web,当然持续集成构建出来的时候肯定是版本号的。有一些包是依赖容器运行的,比如说war依赖于tomcat或者resin容器;而有些程序包则是一个独立的程序,比如说jar包或者daemon进程等等。
c、环境(Env)
从软件研发过程来说,可运行的程序必然要经过如下几个阶段或者环境,如开发(dev)、测试(test)、预发布(staging)、生产环境(Prod)等等.这些环境必然对应一组服务器的集合。在一个变更频繁的业务场景下,环境的变化也是必然,对它的管理就更加必要,这是持续部署平台需要重点解决的问题。
d、配置文件
配置文件太特别了,所以必须拿出来,并且这个必须是持续部署阶段解决的问题,否则会影响系统的大面积推广使用。最直观的例子,一个程序连接数据库的配置,在几个环境中必然不同,如何管理这个不同?另外有时候一个配置的变化,如果再走一次持续集成,貌似这个过程也太重了,所以会在持续部署工具中,对包的配置文件直接提供版本管理和变更管理的能力,轻量化这个过程,绝对不能把配置管理过程独立在平台之外。
注意:这个地方的配置文件一定是包的配置文件,OS的配置不在此列.
e、用户和角色
角色和环境相关的,一般就分开发、测试、运维三个角色,这个三个角色对应不同的环境有不同的权限,开发只有开发环境的权限、测试有测试、预发布、生产环境权限、运维只有预发布、生产环境权限,没有测试环境权限等,这样可以把环境的隔离在这个层面上控制起来。这个也可以结合运维的不同阶段,权限的控制也是变化的,在YY,研发可以直接发布程序到生产环境。
总的概念如下图:
三、我为什么不用开源系统
当我们都了解到那么多的管理维度,你就理解我为什么不用开源系统。我理解即使使用开源管理系统,也差不多都是需要重新开发一套,因此在YY和UC(包括腾讯),我都坚持重新做一套,或许是我比较幸运,总是有运维研发支持。主要是因为这里面有一个概念上差别,持续部署不是做一个ssh通道能力的封装,更不是提供一个类rpm的打包能力,而是一个持续发布过程的管理能力。
四、持续部署系统的方法
要完成一个持续部署系统的建设,其实有一些方法论也是可以遵循的,供大家参考一下:
a、必须以运维规范为基础的
应用环境不做任何改变,让系统兼容所有的方案,最后就变成ssh通道能力的封装了。建议大家在考虑持续部署系统建设的时候,把应用的部署模式重新梳理一遍,标准化起来,比如说运行的目录,用户的属主甚至是配置文件等等。
b、用简单的收益来驱动
每次建设这个平台的时候,准则都特别简单:让运维提供平台撤出部署事务,变成审核者,从而完成运维角色的转变;全流程效率提升*倍。
c、强调安全和效率,确保团队之间能找到平衡合作点
用平台来做部署控制有利于发布的安全,因为在平台中可以做发布窗、发布灰度、快速回滚的控制,对于那些还直接登陆服务器做变更的运维或者开发来说,这个平台的安全收益就更大了【携程的事情还记得吧】;关于效率,以前一个发布需要不断的邮件更新状态,这个时候不需要了,把整个发布过程搬到线上,由发布系统控制。但改变了用户发布习惯,许多人会用效率来作为借口,这个就是平台建设应该要去解决的问题,我所接触到的持续部署,最后都提升了效率,让研发、测试们很爽。
d、一开始就强调研发、测试、运维的共同参与
太重要了,顺便还可以尝试一下DevOps。研发、测试和运维的共同参与,第一个可以确保需求不会偏离;第二、太有利于后续的推广了;第三、需要各自能力的补齐,研发可以提供研发能力支持,让运维和测试也提升一下研发能力,测试把持续集成搞好和持续部署对接,运维是收益最大者,负责项目推荐和研发力量主力投入。
五、持续部署系统的建设
1、系统的设计目标
当时把系统的设计目标都简化的表达,如下:
- 提升应用变更效率
- 规范运维,应用的规范化约束,发布流程的规范约束
- 标准化应用元数据管理能力,比如说环境管理、包管理等等
- 提升数据驱动运维能力。
- 基于标准的配置管理,进一步透视化服务架构,构建应用业务拓扑
- 完善服务调度能力
2、系统的功能范围
可以对持续部署系统进行一个功能划分,分成几个功能域:基础功能域、包/配置管理域、拓扑管理域、变更管理域。每个域里面又可以对功能进行二次分解,最终形成下图。
在我们完成具体的功能域之后,其实心中基本上就有了一个功能实现路线图和收益的评估,下图是我在UC成立项目的时候做的一个三阶段规划,供参考。
3、系统的数据模型
相对来说,变更系统的配置模型非常简单,重点是在变更的过程管理,比如说日志记录上,确保后续所有的变更可回溯,如下:
4、系统的实现
4.1 通道的实现
其实持续部署系统的实现上来说,非常简单,重要的是通道的设计,文件通道和命令通道,而文件通道可以转换成命令通道,不做文件推,而是做文件拉取的动作,走http下载的方式。命令通道有三种实现思路:
a、ssh通道。简单直接,在一个纯内网的环境里面,可以完全使用这个方法。在腾讯是走ssh通道的形式。
b、agent通道。无论是puppet、salt或者自研agent差不多都是这类形式。在YY以前用的是自研agent的形式。
c、消息队列通道。把server和agent之间进行服务解耦,把服务之间的关系变成消息队列的发布和订阅关系,在CF中,NATS消息中间件的作用大抵如此。这种方式可以解决集群高可用,大规模集群并发等问题,当前UC参照的是该实现。
4.2 包管理的实现
对于所有的程序包来说,要首先约定包的命名规范,这个是在持续集成过程要解决的,我们当前就是“包名 时间戳”的命名规范。包的统一管理,是要实现包的统一集中管理,建立一个标准一致的包仓库平台,在故障恢复的时候有利于恢复;其次要实现包的多版本管理能力,甚至是实现包版本在研发、测试和生产环境的对应关系,版本管理,有利于升级和回滚,建立对应关系是避免人为出错,把一些测试状态的包部署到现网,进一步做好发布控制;最后建立一个分布式包仓库中心,确保包数据的安全性,真要是出故障,可以通过包管理平台的信息可以快速做应用环境的恢复。
4.3 配置管理的实现
配置文件一直是管理的难点,不同的包部署到不同的环境不同就是配置文件,并且还有一种场景是配置需要独立变更的。以上两种情况,你都不能让用户打多个不同的环境包或者再次打包来解决,轻量、轻量再轻量。之前在YY建设把配置从包里独立出来,放到一个配置管理中实现,最后发现这种方式根本就不是用户想要的。在UC的实践,把配置管理直接整合在持续部署平台中实现,收到的效果奇好,大家都非常依赖配置管理管理的功能。
4.4 变更管理的实现
系统提供部署(升级/回滚)、远程操作和灰度的能力,因为我们目前涉及的机器很少,所以没有提供标准的灰度模板,如果服务器很多一定要做成灰度模板,控制这个发布的进度。远程操作非常有必要,否则有时候对包做一些操作必须要登陆服务器,没法做到D/O在环境层面上的隔离。
总而言之,无论是在腾讯、YY或者UC,对于持续部署系统来说,是可以实现一个系统平台方案兼容所有的发布场景,无论是独立进程还是容器服务等等。以前在腾讯对于CGI容器类的服务都是独立另外一套系统来做的,现在想想没有必要,本质上来说都是把文件发布过去,然后在发布前和发布后动作有点不同而已。