DevOps,并不那么遥远

2017-11-22

DevOps 最早是在 2009 年被人提出,不过刚开始只是停留在概念上。虽然愿景非常美好,但是真正实施起来非常困难。随着最近几年微服务、容器等技术的兴起,使得企业对 DevOps 的需求更加迫切,实施变得更加容易,DevOps 才逐渐被接受和重视。


什么是 DevOps


DevOps 不是简单地等价于 Dev + Ops,很多人根据这个缩写会产生误解。DevOps 应该是贯穿整个软件生命周期,包括立项、设计、开发、测试、运维等诸多环节。


有人提到 DevOps 的第一反应就是 CI/CD,认为搭建好 CI/CD 流水线就实现了 DevOps。毋庸置疑,CI/CD 是 DevOps 在流程管理方面非常重要的组成部分,没有 CI/CD,DevOps 就无从谈起。通过搭建 CI/CD 流水线,将软件生命周期中最核心的三个环节开发、测试和部署规范化、自动化管理起来,实现持续集成和持续部署,从而提高软件开发效率和迭代速度。



还有些人认为 DevOps 就是将很多工具组织起来,实现自动化。DevOps 虽然强调充分利用工具实现自动化,但是更重要的是通过规范的流程,将整个工具链打通,使各团队间更加高效地协同工作。



因此,DevOps 是一种强调产品管理、软件开发和运营专员间沟通协作的软件开发和交付流程。它包括三个要素:文化,流程和工具,只要将这三个要素落实,就能真正地实践 DevOps。


为什么需要 DevOps


随着技术的飞速发展,人们对软件服务的要求越来越高。软件必须快速地迭代,才能满足市场不断变化的需求。软件功能的上线速度,一定程度上决定了市场的机会和份额。然而,这种快速的迭代和发布,势必会让开发和运维间不可调和的冲突变得更加严峻。微服务将不断地取代传统的巨石应用。以前只需要管理一个软件,微服务化之后可能就需要同时管理几十甚至上百个微服务应用,每个应用都有自己独立的生命周期,同时又依赖于其他服务。传统的软件生命周期管理方式,已经无法满足如此复杂的需求,必须借助 DevOps 实现敏捷开发。


既然 DevOps 能够帮我们高效地管理软件生命周期,提高迭代速度和生产效率,那么企业应该如何推行 DevOps 呢?主要有两种策略:

自下而上

先成立一个 DevOps 团队,尝试和积累 DevOps 经验,并评估取得的成果。一旦这个 DevOps 团队积累了一套科学合理的经验,并通过实践检验过这套经验在所在的企业是行之有效的,就可以把这套经验在部门进行小范围进行推广,并不断地优化和改进这套经验,最终推广和普及到整个企业。这种是比较推荐而且低成本的方式,更加容易取得成功。


自上而下

公司高层必须意识到 DevOps 的意义及其重要性,并有足够的魄力在整个公司强力推行 DevOps,并且已经有一套适合本公司的 DevOps 实践方案,才能在整个公司自上而下地执行起来。由于这种方式需要的先决条件比较多,风险和成本都比较高,所以不被推荐。 


如何实践 DevOps


组建两个披萨团队。两个披萨团队是亚马逊 CEO 杰夫·贝索斯提出的,要控制团队的规模在两个披萨能够吃饱,否则过高的沟通成本,会严重影响项目的进度。


采用 Sprint 控制迭代速度,一般两周作为一个迭代周期比较合适。Sprint 太长,大家前期的积极性不高,绝大部分工作会拖到 Sprint 快结束的时候完成,同时也不能建立快速反馈、快速交付的机制;Sprint 太短,很多功能没有足够的时间开发和测试,导致软件质量没办法保证。在 Sprint 开始的时候,制定好计划,细分任务。Sprint 过程中通过 Scrum 不断地反馈、评估和调整,对于可能存在的导致项目延期的风险,及时解决。Sprint 结束之后,需要开 Retrospective 会议进行回顾和总结,好的经验继续保持,不好的地方及时改进。


每天整个团队在一起开 Scrum,简单地反馈一下自己做的事情和进度,使团队所有人都清楚彼此正在做的事情。如果遇到影响项目进度的风险,及时反馈并讨论解决方案。每个成员必须往全栈工程师的方向努力,提升自己综合能力。DevOps 团队的人数比较少,每个人都要负责比较全面的工作,对日常工作中涉及到的其他领域都要有一定的了解。这样有两个明显的优势:团队组员之间互为 Backup,尽量减少某个人的突发因素,影响到整个项目的进度;大部分工作不依赖别人就能够完成,一定程度上能够减少沟通成本,提高效率。


构建 DevOps 文化


  • 共享精神:整个团队、部门、甚至公司,成为一个利益共同体,共享成功,同时共担责任。在 Retrospective 会议的时候,可以分享成功和失败经验,定期举行知识分享,共同成长,使整个团队的综合实力不断增强。


  • 加强沟通协作:随着软件的要求越来越高,一个系统或软件已经不可能由一个人单独完成,必须涉及到各种不同角色的人来共同完成。那么,其中的沟通和协作就非常重要,往往决定了软件成功与失败。


  • 自动化:一切能够自动化地尽量自动化,最大限度地减少重复劳动,释放人去做更加有创造性的事情。

搭建自动化流程 


自动化软件生命周期的管理,主要可以分为 3 个阶段:


  • CI (Continuous Integration):持续集成
  • 通过 Webhook 或者定时触发器,自动将软件从源代码构建成可以发布的包或者 Docker 镜像。一般包括如下流程:代码检出、单元测试、集成测试、静态代码分析、代码覆盖率检查、构建和推送包或者 Docker 镜像。在这个阶段,可以对各流程的结果进行严格控制,从而保证构建出来的软件的质量。CI 阶段比较强调的是各流程状态、结果的可视化,例如:流水线执行到哪个阶段、该阶段成功或者失败、查看执行日志、测试报告、静态代码分析和代码覆盖率检查结果。

 

  • CD (Continuous Delivery):持续交付
  • 经过在一系列环境中的部署和测试,最终将合格的软件版本发布到生产环境中,真正发挥软件的价值。环境一般包括系统集成测试环境、用户验收测试环境、性能测试环境以及生产环境,根据实际情况,环境的名称不一样,可能叫 Staging 环境、预生产环境等。CD 阶段存在的挑战,主要包括:不同环境对应的配置如何管理;采用何种发布策略,保证线上服务不中断的情况下稳定发布;如果发布失败,如何进行回滚;微服务间如何进行注册和发现。

 

  • CO (Continuous Operation):持续运营
  • 通过平台提供的日志收集、监控告警、自动伸缩、健康检查等功能,保证线上环境的安全、可靠运行,达到我们设定的 SLA(ServiceLevel Agreement)。CO 相对于 CI 和 CD,是比较新的概念,通过对线上系统的监控,达到服务的自治和自愈的目标。它需要完善的平台来支撑,因此运维人员需要向 SRE 的方向发展,最终摆脱“背锅侠”的命运。


如何评估 DevOps 效果


DevOps 的目标是通过定义软件的开发和交付流程来实现软件的价值,因此,可以通过如下指标来衡量 DevOps 效果:


  • 部署频率:能够由原来的几个月或者几周部署一次,缩短到几天甚至几小时部署一次。
  • 部署成功率:追求快速部署的同时,也要保证部署的质量。可能九十九次成功发布带来的收益,都弥补不了一次失败发布带来的损失。
  • 问题修复时间:用户反馈的系统缺陷,多长时间能够被解决。
  • 业务交付时间:市场或者用户提出的需求,多长时间能够被满足。
  • 自动化率:被自动化的工作占所有工作的比率。自动化不仅能提高效率,而且能最大限度地避免人为错误带来的损失。
  • 故障恢复时间:系统出现问题,多长时间能够响应和恢复。    
  • 当 DevOps 遇上 Docker


DevOps 的工具链非常丰富,仅 Jenkins 就提供了 1000 多种插件,基本满足各种各样的需求。在众多工具中,不得不提一下最近几年红的发紫 Docker。Docker 提出的口号是“Build,Ship,Run”,它解决的软件生命周期的这三个阶段,跟 DevOps 中 CI/CD 的目标不谋而合。Docker 技术的出现,能够帮 DevOps 完美地解决如下问题:


  • 环境问题:Docker 能够非常快速、廉价提供环境,这些环境占用的资源非常少,而且用完之后可以立即释放资源。使 DevOps 再也不用为各种构建环境、测试环境发愁了。
  • 环境一致性问题:Docker 镜像包含了软件运行所需要的所有信息,任何时候、任何地方都可以通过同一 Image 快速启动完全相同的的容器。DevOps 过程中,能够彻底摆脱环境不一致问题带来的困扰。
  • 交付物:Docker 提供了简单、标准的统一交付物。Docker Image 作为唯一的交付物,方便、快捷地在流水线的各个阶段间流转,避免了语言、框架、不规范导等因素导致交付物的多样性。
  • 容器生态圈:除了上面 Docker 自身的优势以外,Docker 还带来了一个庞大的容器生态圈。基于这个生态圈提供的容器引擎、编排、镜像仓库、监控等丰富工具,DevOps 实践起来会更加地游刃有余。

 

如果说几年前,DevOps 听上去非常美好,但是离我们非常遥远的话,那么现在是实践 DevOps 的最佳时机。一方面快速的市场变化,迫使我们转向敏捷开发模式;另一方面容器技术的快速发展,又帮我们扫清了 DevOps 的各种障碍。所以,本着精益思想,搭上容器这股热潮,DevOps 就并不那么遥远。


Caicloud 的 DevOps 实践


才云科技作为一家容器初创公司,从创立伊始就积极在内部结合容器技术实践 DevOps。


我们遵循 Scrum 敏捷开发的流程,将整体开发团体按功能模块划分成多个 5-6 人的功能开发小组,制定整体的迭代开发计划,每天组织 Daily Scrum 会议同步开发进度,迭代末期组织干系人评审会议和团队复盘总结,持续优化团队效率,持续提高团队能力。


在软件开发和交付的过程中,我们也尽量采用自动化减少人工干预。我们的软件均采用微服务架构,每款软件由多个独立模块组成,每个模块又由多个微服务容器组成。我们在研发、测试、发布、运维环节尽量使用工具自动化操作,减少人工干预。我们自研了一套 CI/CD 工具—— Cyclone。



首先配置 Cyclone 与 Github 上每一个模块的源码库关联。当开发工程师提交代码到 Github 后,会通过 Webhook 通知到 Cyclone 相关源码变动信息。如果是 Pull Request 事件或其他 Commit 事件,Cyclone 会拉取对应分支源码,挂载到指定容器环境中,进行单元测试、代码扫描、编译可执行文件,输出测试报告反馈到 Github,实现 Continous Integration。


如果是 Tag 事件,Cyclone 还能继续构建可执行文件运行环境的镜像,推送到镜像仓库,并更新 Dev 环境的组件镜像,实现 Continous Delivery。


我们还会另外新建一条任务流水线,可手动或定时更新 Test 环境所有微服务组件,运行自动化集成测试、压力测试。这条流水线每晚定时触发,我们早上来到办公室可查看测试报告,根据报告定位昨天开发产生的问题。当需要发布时,手动触发发布流水线,Cyclone 将更新 Test 环境软件,运行自动化测试。


测试通过后,Slack 通知到测试工程师,等待授权。测试工程师将进一步验证 Test 环境软件,如果不通过则终止本次发布,如果通过则授权流水线继续执行。Cyclone 继续通过 Slack 通知到发布经理,请求发布授权。发布经理确认核对信息后,授权 Cyclone 发布新版本到 Prod 环境。Cyclone 按灰度发布的策略更新 Prod 环境。



新旧版本实例同时在线,外部访问按指定的策略导入到新旧版本服务。Cyclone 自动化测试生产环境新版本服务后再次通知到测试工程师。测试工程师测试验证后给出反馈意见发送到发布经理。发布经理综合测试报告和测试工程师反馈意见决定全量更新到新版本还是回滚旧版本。发布后还要会有一个单独的测试环境执行长时间浸泡测试任务。这样就实现了Continous Deployment。



生产环境升级到新版本后,我们仍将通过工具实时监控软件 CPU 使用率、内存使用率、磁盘用量、IO 速率等等相关指标,并收集日志信息。对相关指标设置报警阈值,当出现警情时通知运维人员处警。当前我们正在针对不同的报警事件设计不同的自动化处警方案,比如内存使用率过高时,弹性伸缩扩展出多个服务均衡负载。我们的方向是向 Continous Operation 迈进。

我们现已对 Cyclone 的部分功能开源

整体软件架构如下:



每个立方体代表一个容器:


  • Cyclone-Server 中 Api-Server 组件提供 Restful API 服务,被调用后需要较长时间处理的任务生成一个待处理事件写入etcd;
  • EventManager 加载 etcd 中未完成事件,监视事件变化,发送新增待处理事件到 WorkerManager 中;
  • WorkerManager 调用 Docker API 启一个 Cyclone-Worker 容器,通过环境变量传入需要处理的事件 ID 等信息;
  • Cyclone-Worker 使用事件 ID 作为 token(有效期2小时)调用 API,拉取事件信息依次启容器执行 integration、prebuild、build、postbuild,完成后反馈事件执行结果,构建过程日志推送到 Log-Server,转存到 Kafka;
  • Log-Server 组件从 Kafka 拉取日志推送给用户;
  • 需要持久化的数据存入 mongo。


目前开源版的 Cyclone 已发布 v0.2 实现了大部分 CI 功能,其他功能也将陆续开放出来。


点击体验,开启谷歌级数字化之旅
立即体验
立即咨询