锤子两年前登陆墨尔本时,完全是DevOps小白。面试REA的时候,被问到什么是Continuous Delivery(持续交付),锤子诚恳地表示“不知道”。面试官不依不饶,“不知道不要紧,你想想怎么样才能做到Continuous Delivery?” 锤子回顾了一下自己维护项目时的噩梦,斟酌着用词说:“这需要好多自动化的工具支持,怎么测试,怎么接入不同的网络,怎么部署不同的环境,还有数据库的data migration和回滚,个顶个的都是痛点。”
之前锤子所做过的系统都是Monolith(单体)架构,所以,每次需要重启生产环境时,真得一而再,再而三地确认。所以当REA的同事给我讲解我们的微服务架构,和怎么做Continuous Delivery时,我问:“那最坏的情况就是重启系统了?”这个同事说:“不,重启系统是正常情况。”由此,锤子开始慢慢了解REA强大的DevOps。
在介绍REA的DevOps之前,还是简单说说我们使用的微服务架构。
微服务有时被人诟病违背了DRY原则,但是Monolith架构下各种服务间的强耦合对于扩展部署都很痛苦,所以Don’t repeat yourself 诚然不错,微服务架构下,定义好边界之后(APIs),每个微服务独立存在,独立部署且可扩展,即使有一些简单的复制粘贴,其带来的灵活性也是Monolith架构不具备的。
在REA内部,为了保证某种程度的一致性,我们的微服务都需要遵循12 Factor:
不过不管微服务设计得如何精良,当一个“小而美”的团队(5-6名开发人员)需要同时开发维护生产环境中10个以上的微服务时,服务运行和管理上的额外复杂性使得全自动构建和部署变得不可或缺,更进一步,最好使用Continuous Delivery来解决这些问题,而DevOps为真正的Continuous Delivery提供了必要的支持。
那DevOps究竟是什么?DevOps就是更好的优化开发(DEV)、测试(QA)、运维(OPS)的流程,开发运维一体化,通过高度自动化工具与流程来使得软件构建、测试、发布更加快捷、频繁和可靠。
下面这张图(图片来源什么是 DevOps?)就是DevOps的日常。
既然DevOps不是新工具,不是新团队,不是新角色,也不是大量知识,而且DevOps的伟大实践来自于许多不同的领域,并且在IT组织内执行,为了提升IT的性能,那下面就让锤子讲讲REA的DevOps实践,首先自然从最贴近我们程序猿的全工具链开始。
REA实际使用到的全工具链包括:
工具链看起来并不复杂,那么有了工具链,所有的问题就迎刃而解了吗?答案自然是否定的。
怎么样自动化所有流程?怎样为REA超过40个组管理AWS的账号?怎么为AWS里的测试环境和生产环境配置VPC?怎样把微服务部署到不同的环境?监控的策略怎么样实施,怎么样在不同的组之间协调?所有的几百个微服务,一旦某些微服务除了问题怎么办等等。这些都需要工具链切切实实的落地。
REA DevOps工具链的实施过程中,分层协作不但厘清不同部门的责任,也让所有开发人员参与到Operation工作中,让DevOps融入每个IT人员的日常。
REA DevOps不同层面的问题由不同的组负责,如下图。
不同的Squads(REA引入了Spotify模式)使用DevOps工具链来开发和维护自己的微服务。详情会在下面一节进行介绍。
Delivery Engineering团队,顾名思义,就是为了让程序猿们更快更好地发布应用,主要职责是工具的开发和管理。包括创建Docker Registry,准备好已经安装了必要库的baked Docker image,有了这些基准的Docker Images,开发团队在为自己的微服务构建Docker Image的时可以有效节省时间,还能规避各种库版本不一致的问题。Delivery Engineering还需要为不同部门配置Buildkite,Buildkite的Agents部署在AWS的EC2中,根据需要连接的环境,多个Agents分布在不同的VPC。
最值得一提的是Delivery Engineering开发的rea-shipper。
以我们一个实际的service charge-central为例,登陆到EC2 instance之后,可以看到正在运行的几个container。
Global Infrastructure & Architecture 团队负责基础设施建设,管理维护并开发相应的工具,包括网络、数据中心、AWS账号的管理、Splunk的集成等。比如,去年悉尼大雨,Amazon的机房被水淹了,澳洲大批网站受到影响,也包括我们公司的一小部分,当时苦了GIA team的人了。
所以全工具链的配置和开发是Global Infrastructure & Architecture 和Delivery Engineering的职责,而作为程序猿的锤子,则是工具链的使用者。下面就说说程序猿所参与的DevOps日常。
前面提到过代码库使用github企业版,采用github flow。
微服务需要的部署脚本和AWS Cloudformation的信息,提供给不同监控工具的接口,fried Docker image 定义等,也都是代码的一部分,需要开发人员完成。
构建和部署就以Buildkite为例子,这是一个微服务的buildkite脚本。
这个流程里代码检查和单元测试自动化起来很容易,那么怎么做整合测试?REA基于Ian Robinson提出的用消费者驱动的契约进行面向服务开发的模式开发了 开源的Pact 测试框架,用轻量级的契约测试来代替厚重的集成测试。Pact在消费端用单元测试的形式(更轻)来生成 pact 契约,服务端通过验证契约来保证两者稳定集成。一旦有一端契约未经协商发生改变,那么Pact测试就会失败。
构建成功之后,会把微服务打包成Docker Image然后上传到Docker Registry。我们会选择在Delivery Engineering提供的基准Docker Image之上来打包,这是一个微服务的Dockerfile的例子:
用这种方式,在buildkite上打包并上传到Docker Registry的时间小于三分钟。
部署时,脚本会调用rea-shipper。不同的环境下,Buildkite会选择不同的Agent进行部署:Test 环境的non-prod-corp:default和Prod环境的prod-corp:default。部署的时间通常10分钟以内,下面是一个微服务部署到test(6分1秒)和prod(5分43秒)的时间,图中能够看到Cloudformation更新的步骤。
尽管是全自动的部署,考虑到生产环境的重要性,我们还是选择谨慎地Block,需要某个开发人员手动触发。触发的时间没有特别的规定,只是在我们的kanban中,deploy是最后一步,这意味着只有真正部署到生产环境,这个卡片才算完成。如果部署过程中出现失败,rea-shipper不会切换运行中的ASG(Auto Scalling Group),业务并不会受到影响。如果部署的新版本发现bug需要紧急回滚,可以很容易地根据Docker Image的版本找到相应的Image进行部署。
日常的运维如下图所示:
需要处理的问题一般有两种:
我们Tribe有5个Squad,除了有超过30个microservice之外,还有跟不同系统的接口,如果不能组织好,开发人员每天必定会被各种问题打扰。所以如图所示,Tribe级别有Dingo(工作时间)或者Owl(非工作时间)作为接口人,负责处理和分发问题到Squad级别的Squid。Dingo,Owl和Squid是团队的开发人员轮岗。
本文介绍了REA DevOps的实践,包括工具链,工具链的分层协作以及使用中的流程。再来对比一下Gene Kim的3个方法:流程,反馈和持续学习,这3个方法是DevOps的主要部分,提供一种路标来理解和执行DevOps。锤子能够看到的是在REA DevOps实践中,每个开发人员都参与到流程的不断优化中,让流程变得更顺畅和快速;通过不同方式可视化监控和反馈,以达到更快的反馈路径;开放全代码库给所有开发人员,鼓励程序猿持续学习和改进等等。
以上种种,推荐阅读我们公司同事的文章来更深入的了解REA的文化。Scaling On-Call: from 10 Ops to 100 Devs,讲述了怎么从这样的状态:
到达下面的状态:
这种变化并不是技术改进带来的,而是源于持续学习的企业文化。而这,正是DevOps最需要的。
原文作者:虎头锤,2015年4月登陆澳洲之后,入职REA Group
Original url: Access
Created at: 2018-11-06 10:50:51
Category: default
Tags: none
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论