相关概念
持续集成:集成构建和测试的反复持续过程
持续交付:在持续集成之后获取外部对软件的反馈再通过持续集成进行优化的过程
持续部署:将可交付产品快速且安全地交付用户使用的一套方法和系统
持续交付价值:
- 在保证交付质量的前提下,加快交付速度,从而更快地得到市场反馈,引领产品方向,最终扩大收益。
- 对 CTO:环境管理,整套标准规范落地,提高跨部门协作效率,快速恢复故障(回滚)
- 对 team leader: 只是传承,专注业务而非工程,平稳节奏持续工作
- 对产品经理:即时体验,熟悉进度质量,产品随时可发布
影响持续交付的因素:
期望组织文化:
紧密配合,集思广益,自我驱动
方案:
- 成立项目管理办公室(但不要把流程变得更加复杂),
- 独立工程效能部门(成本高,小团队不适用)
- 敏捷开发(个人能力要求高)
- 打破流程因素:耗时长,人工,信息报备
架构:
系统架构
- 单体架构:项目编译、回归、部署时间随仓库变大而变长
- SOA 架构:服务拆分利于实施,考虑服务之间的依赖、环境隔离,中间件适配
- 微服务架构:非容器技术的微服务架构与 SOA 基本一致
部署架构
- 同意的部署标准方式
- 发布的编排次序(灰度发布策略,如:金丝雀发布 / 滚动发布)
- markdown markup(服务拉入拉出机制)
- 预热与自检
DevOps:
技术(自动化运维,持续交付,高频部署、Docker)/ 职能 / 文化 / 组织架构
分支策略:
主干开发(trunk based dev)
- 优点:无需分支切换;频繁集成冲突少、效率高
- 缺点:短板效应;借助特性切换会引入新问题
- 适用项目:团队系统设计开发能力强,有特性切换方案,快速迭代
特性分支开发:
-
类别
- git flow:普遍认为 hotfix 和 release 显得多余。适用项目:有预订的发布周期,严格执行发布流程。
- github flow:流程简单易上手,适用项目:随时集成即可发布
- gitlab flow:github flow 基础上衍生出 3 个特性分支
production
,enviroment
,release
, 适用项目:随时准备发布,需要通过不同环境测试,对外发布维护不同版本。
- 优点:不同功能互不干扰,保证主干分支质量
- 缺点:需要即时 merge,每个分支的 CI/CD 环境不同
依赖管理特性:
统一的命名规则,中心仓库,配置文件,本地可解析
代码回滚:
个人分支回滚:
可以用 git reset –hard
集成分支上线前回滚:
可在 gitlab 上找到对应的 merge request,点击 revert
集成分支上线后回滚:
在集成分支头上增加一个 commit,该内容等于回滚后对应的 commit
测试环境:
- 5 大类:开发环境,功能测试环境,验收测试环境,预发布环境,生产环境
- 成本:机器;管理(可用,配置,测试数据);流程(沟通,测试)
-
自描述:
- 定义 ServerSpec(描述文件,服务器的所有身份信息)
- 配置中心(构建时配置,打包时配置,运行时配置)
- 服务自发现(根据服务类型,访问路径等自动生成对应的路由负载均衡配置等)
快速构建测试环境:
- 虚拟机环境:物理机硬件配置,系统与网络,利用工具自动配置环境
- 应用部署流水线:单应用标准化部署,并行,容错:错误中断 / 优先完成
- 环境变更:入口管理 - 约定大于配置,调用链管理 - 自发现,数据库 -SOA 调用链 / 来自生产快速创建;创建和拆分、合并后的环境冲突。
容器:
- 概念:是软件的一个轻量的、独立的、可执行包,包括了执行它所需要的所有内容:代码、运行环境、系统工具、系统库、设置。
- 特性:交付结果一致,交付自动化,交付个性化,交付版本控制
构建提速:
- 升级硬件,搭建私有仓库,使用本地缓存,规范构建流程,善用共建工具
- 持续集成工具:Travis CI,Circle CI,Jenkins CI,Gitlab CI
容器镜像:
DooD
(Docker-outside-of-Docker): 是指通过加载宿主 Docker socket 和程序的方式达成重用宿主镜像的目的。
- 优点:复用镜像共建环境,宿主机只需安装 Docker Daemon
- 缺点:内部环境需与外部一致,Docker Daemon 出问题影响其他容器。
DinD
(Docker in Docker): 在容器中安装一个全新的完整的隔离的 Docker 版本,该容器和外部的 Docker 系统完全隔离。
- 优点:内部是一个完整的镜像构建环境
- 缺点:安全和文件系统问题,构建性能(镜像缓存随容器重启而消失)
容器个性化 & 合规检查:
自定义环境脚本(.pass),平台化环境选项与服务集市,自定义镜像发布
发布流程:
-
单机发布抽象步骤:
- 下载新的版本,不执行覆盖;
- 通知上游调用方,自己现在为暂停服务状态;
- 运行命令 load 变更重启服务;
- 验证服务的健康状况;
- 通知上游调用方,自己服务恢复正常。
- 集群灰度发布:蓝绿发布,滚动发布,金丝雀发布
- 不可变模型(Immutable):任何基础设施的实例一旦创建则只读,如需修改或升级只能创建新实例来替换
灰度发布系统设计:
- 类目:集群,实例,发布日志,发布历史,发布批次,发布操作
-
2 种时态:
- 发布中:展示处理的过程,结果,耗时,当前情况
- 未发布时:显示版本演进路线图,当前各集群,服务器上具体版本的情况
- 3 种结果:成功,失败,中断
-
4 种情况按钮组合(谁发布,谁运行):
- 开始发布
- 中断发布
- 中断或重试发布(局部错误时)
- 中断或继续发布(发布刹车时)
-
5 个发布步骤(演进自上述单机发布抽象步骤)
- markdown:拉出集群
- download:根据版本号下载代码包
- install:停止服务、替换代码、重启服务
- verify:启动、预检、预热
- markup:拉回集群
- 策略:单机单应用优于单机多应用,全量发布优于增量发布,header 附加堡垒标识从而保证堡垒机流量定向
监控:
用户监控:
(可以通过打点收集,或者定期采集日志的方式进行数据收集)
- 端到端监控:访问量,成功率,响应时间,发包回包,地区,运营商,app 版本,网络类型
- 移动端日志:系统崩溃异常
- 设备表现监控:CPU, 内存,温度,卡顿白屏,堆栈分析
- uid 监控:获取一个独立用户的具体情况
网络监控
(通过模拟手段或定期采样进行收集): 公网内网监控
业务监控
(定义正确的指标,实时性):单位时间内的订单预测线
应用监控 / 调用链监控
(可以通过中间件打点采集,也可以通过日志联合分析进行数据采集):收集应用层全量的数据进行分析,要分析的内容包括:调用量、响应时长、错误量等;面向的系统包括:应用、中间件、缓存、数据库、存储等;同时也支持对 JVM 等的监控。
系统监控
(定期采样):基础设施的 CPU、内存、I/O、磁盘、网络连接等作为监控指标。
其他:
代码静态检查;破坏性测试:混沌工程(Chaos Monkey);Mock 与回放
持续交付中的数据:
稳定性指标
统计所有的故障时间(开始、结束、时长),计算过去三个月内这个时间段产生的持续交付平均业务量、业务量与月平均量相比的损失率
性能指标
- push 和 fetch 代码的速度;
- 环境创建和销毁的速度;
- 产生仿真数据的速度;
- 平均编译速度及排队时长;
- 静态检查的速度;
- 自动化测试的耗时;
交付能力成熟度指标
- 与代码管理子系统相关的指标包括:commit 的数量,code review 的拒绝率,并行开发的分支数量。
- 与环境管理子系统相关的指标包括:计算资源的使用率,环境的平均大小。
- 与集成编译子系统相关的指标包括:每日编译数量,编译检查的数据。
- 与测试管理子系统相关的指标包括:单元测试的覆盖率,自动化测试的覆盖率。
- 与发布管理子系统相关的指标包括:周发布数量,回滚比率。
例:移动 App 持续交付
生命周期
代码及依赖管理、项目信息管理、静态代码检查、构建管理、发布管理、运营管理、热修复。
细节:
- 利用发布快车的发布模式,可以有效地管理客户端的版本,保证研发工作按节奏持续向前进展;
- 采用带发布分支的 GitLab Flow 配合发布快车的模型,可以使其做到物理落地;
- 发布快车本身也有一些弊端,比如对 Master 分支的合并,检查不够严格的话,会拖累项目进度,因此我们采用改造构建通道的方式,避免了这个问题的产生;
- 移动 App 的发布,有其独特的流程,通常是先内测,后正式发布;但其流程相对固定,且容易自动化。所以,我的建议是,实现发布的完全自动化,以提高研发效率。
进一步,提升交付效率:
- 利用组件化的思想提升开发效率,但同时也会带来组件依赖及发布的问题;
- 利用扁平化依赖管理的方法解决组件依赖和发布的问题,同时采用二进制交付的方式,进一步提高构建效率;
- 合理利用静态代码扫描、UI 自动化、自动 Monkey 等测试工具和方法,进一步提升测试效率;
- 确保分发的精准性和稳定性,是提升发布效率的有效手段。
参考资料
《持续交付 36 讲》