吕健|Microservices 场景下的持续部署

Posted 中生代技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了吕健|Microservices 场景下的持续部署相关的知识,希望对你有一定的参考价值。

内容简介

近两年作者在海外交付中参与   microservices   下的团队,为客户提升   Finance   系统的扩展性。 作者所在团队,3   对开发(pair   programming,   2     dev     pair)为客户支撑着   11     services,持续部署流水线(CD   pipeline)是其中必不可少的一个技术实践。本次分享作者将从实践的角度分享   microservices   架构下的持续部署(CD)。 内容概述
  1. 1. microservice   概述:简要介绍   microservice   架构下的挑战

  2. 2. 持续部署实践:这里会提到『Build   Pipeline   as   Code』,『Infrastructure   as   Code』等概念。

  3. 3. 持续部署了之后呢?   这里会介绍   CD   结合团队的敏捷开发流程的实践经验。

microservices 概述

当提到   microservice   的时候,我们通常会从下图开始:

吕健|Microservices 场景下的持续部署

为了从业务和技术方面得到更好的扩展能力,我们将单一架构的系统(Monolithic   architecture),拆分成若干的微服务(Microservices   architecture),这种拆分是架构演进的一个过程。 在整个拆分过程中,对团队的组织架构,数据的管理方式,部署监控技术方面都带来极大的挑战。 持续部署(简称   CD)是   microservices   架构中一个必备的实践之一。本文将介绍基于Docker     CD   方式。

部署方面带来的挑战

吕健|Microservices 场景下的持续部署

单一架构下(Monolithic),我们的系统   Code   base   可以在一个项目中,这个系统采用一个持续集成(简称:CI)   pipeline,并且此时我们也可以采用持续集成(简称:CD)pipeline,最终将系统持续部署到生产环境中。 在这种情况下,每当系统引入一个改变的时候,CI,CD   pipe   line   都会执行一次。例如:
  • - 10   mins   Unit   Test
  • - 2   hours   Acceptance   Test
  • - 15   mins   package
  • - 20   mins   deployment
上面列举的例子并不算坏,更庞大的系统可能会需要更多的时间。 当我们将   Monolithic   系统拆分成多个   micro   services   时,并且将每个   services   进行独立部署。每当系统引入一个改变的时候(code   change),它只会影响个别   service,我们只需要部署发生改变的部署,从新运行一个   service     CI,CD   pipeline:
  • - 1   mins   Unit   Test
  • - 1   mins   Integration   test
  • - 5   mins   package
  • - 5   mins   deployment
这种拆分之后,更符合我们对解耦的追求: 『当代码引入一个改变的时候,它应该影响的改动最小』 此时所提到的改变涉及整个开发流程,从代码到部署的影响做到了最小。 拆分   services   之后的代价是,每个   service   都需要独立部署,我们需要为每个   service   搭建   CD   pipeline。   microservices   场景下,不同的   service   按照需求可能会采用不同的技术栈。并且在每次新建   service   时,配套的日志,监控,报警系统也需要进行配置。 这个对   CD   提出了很大的挑战。

持续部署方面的实践

当我们谈持续部署的时候,此时也会包括持续集成。持续部署的整个过程会从代码   push     master   开始:

吕健|Microservices 场景下的持续部署

我们采用   Docker   来解决技术栈差异的问题,DevOps   创建部署工具将部署,监控,报警等配置模板化。 实践:
  • - 使用   Docker   构建和发布   service
  • - 采用   Docker   Compose   运行测试
  • - 使用   Docker   进行部署
准则:
  • - Build   pipe   line   as   Code
  • - Infrastructure   as   Code(base   on   AWS)
  • - 共享构建脚本

使用   Docker   构建和发布   service

吕健|Microservices 场景下的持续部署

  • - 使用   Docker   构建   service,service     docker   image   的方式发布
  • - 将   docker   发布到   docker   registry
  • - 从   docker   registry     pull   docker   image   进行部署

使用   Docker   Compose   运行测试

吕健|Microservices 场景下的持续部署

可以将多个   docker   image   进行组合。有些   service   需要访问数据,我们可以通过   docker   compose     service   image     database   image   组合在一起。 组合之后,我们可以采用   docker   compose   运行持续集成。 下面这个实例展示如何进行这种组合:

Build   pipeline   as   Code

吕健|Microservices 场景下的持续部署

通常我们使用     或者     来搭建   CI/CD   pipeline,每次创建   pipeline   需要进行大量的手工配置,此时很难自动化   CI   服务器配置。 Build   pipeline   as   Code,即使用代码来描述   pipeline,这样做可以带来非常好的可读性和重用性。我们可以很容易的做到   CI   服务器配置。 今年团队将所有   pipeline     Bamboo   迁移到了   。在   BuildKite   上可以使用如下代码描述上图的   pipeline:

Infrastructure   as   Code

吕健|Microservices 场景下的持续部署

如果我们要发布一个基于   HTTP   协议的   REST-ful   API   service,我们需要   service   准备如下基础设施(Infrastructure):
  • - 可部署的机器
  • - 机器的   IP   和网络配置
  • - 设备硬件监控服务(GPU,Memory   等)
  • - 负载均衡(Load   Balancer)
  • - DNS
  • - AutoScaling   (services   自动伸缩服务)
  • - Splunk   日志收集
  • - NewRelic   性能监控
  • - Sentry.io     PagerDuty   报警
这些基础设施的搭建和配置我们希望将其模板化,自动化。我们才用代码描述基础设施,DevOps   提供工具模板化基础设施的描述。 实践:
  • - 采用   AWS   云服务进行部署
  • - 采用   AWS   CloudFormation   描述和创建资源
  • - 将对资源操作的脚本进行   source   control
准则:
  • - 对资源的描述和操作应该在   git  
  • - 在所有环境中采用相同的部署流程
  • - 使用   ssh   等手动操作资源的方式,只能用于测试环境和做一些   debug。

共享构建脚本

吕健|Microservices 场景下的持续部署

在为多个   services   搭建   CD   pipeline   之后,我们将   CD   pipeline   归纳为三部:
  1. 1. 运行测试
  2. 2. 构建发布   docker   image
  3. 3. 部署
分别为这三步提取出   shell   scripts:
  1. 1. test.sh
  2. 2. docker-tag.sh
  3. 3. deploy   <test|prod>

之后为上述脚本创建   git   repository,并且将其以   git   submodule   的方式引入各个项目。 持续部署了之后呢?

  CD   pipeline   服务团队的工作流程

我们搭建好   CD   pipeline,需要让它在团队的敏捷开发流程中发挥为威力:

吕健|Microservices 场景下的持续部署

团队职责:
  • - 团队主要分为   BA,Developer(简称   Dev),Tech   Lead(简称TL)
  • - BA   负责分析业务,并在故事墙上创建   Story
  • - Dev   负责开发,QA,运维(跨能型团队)
  • - Tech   Lead   负责技术
工作流程:
  1. 1. Dev     Backlog   中拿卡进行分析,分析完成后跟   BA,TL一起   kickoff   确定需求、技术实现。
  2. 2. kickoff   之后,   Dev     repository   上创建   Pull   Request(简称   PR)   开始工作。此时在   PR   上的每一次   git   push   会触发   PR     pipeline,此时在   CI   机器上只会运行单元测试和集成测试。
  3. 3. Dev   开发完成后,其他   Dev     PR   进行   Review,Review   通过之后将   PR   merge     master   分支,此时会   trigger   master   分支上的   pipeline,将最新代码自动部署到   test   环境。
  4. 4. 部署   test   环境成功后,Dev   基于   test   环境进行   QA。
  5. 5. QA   完成后向   BA,   TL     showcase   进行   user   acceptance   test。
  6. 6. 通过   user   acceptance   test   之后,在   BuildKite   上点击部署到   production   按钮完成发布。

按照以上流程,团队可以快速从   CI/CD   pipeline   上得到反馈,高度自动化的   CD   pipeline   可以让团队做到按照   Story   进行   service   发布。 Summary

Microsservices   在业务和技术的扩展性方面带来了极大的便利,同时在组织和技术层面带来的极大的挑战。 由于在架构的演进过程中,会有很多新服务产生,持续部署是技术层面的挑战之一,追求极致的自动化,可以让团队从基础设施抽离出来,关注与产生业务价值的功能实现。

Q&A Q1:你们的docker是用什么来管理的?k8s,swarm   还是其他什么?

A1:   K8S,   Swarm   都没使用,对这两个服务我也只是听说过。   每个独立的   service   Docker   image   会单独运行在   AWS   EC   2   Instance。管理一般也都是围绕   EC   2   Instance   来做。关于     Docker   Images   仓库,采用自建的   Docker   Registry   服务来   push     pull   docker   image。 ================ Q2:如何做跨语言的服务集成 A2:     我们做过   Ruby     Node.js   的集成。服务器间通信采用   HTTP   协议,JSON   作为传输格式,   JSON   基于   hyper   media   link   的实现之一   HAL       如何解决   service   之间的约定,我们采用   Consumer   Driven   Contract   的方式,使用单元测试代替集成测试,这部分实现采用   Pact   ================ Q3:service的粒度如何确定 A3:   这是一个非常好的问题,也是很难回答的问题。     我个人觉得   microservices   中最难回答的两个问题是: 1.   什么拆分出一个   service? 2.   怎么拆分?(也就是拆分多细,系统边界如何确定) service   粒度如何确定,一句话来回答(TL;DR):『采用领域驱动设计(DDD)的方式拆分』。 更长版本,我们项目是为客户解决已运行10年以上财务生态系统的拆分问题。也就是老系统改造,也是我觉得最适合实施   micro   services   的场景。老系统存在很多痛点,并且需求较为稳定。 那么如何拆: 1.   需要引入业务专家,技术专家,相关利益人一起分析业务场景,系统构成确定领域语言对业务进行建模。 2.   将以前以业务切分系统的思路转为按照数据模型切分的思路。 3.   每个类数据模型可以划分多种子模型来辅助主数据模型。 4.   service   的粒度一般以数据模型的粒度来确认。 还有一些按照非功能性需求来切分的原则,比如实施   CQRS   的时候,将读写拆成两部分,采用   Even   Sourcing   解决分布式系统数据状态同步的问题。 ================ Q4:为什么没有考虑gocd,gocd可是first   class的CI/CD工具 A4:     好问题,这个我需要找   ThoughtWorks   负责   GoCD   的同时聊聊销售问题。BTW,我个人还没机会使用过   GoCD ================ Q5:目前发现从esb     soa转microservice,原本进程内的调用关系变成了网络调用,一次rpc变成了几次或者几十次rpc,同等条件下性能损失严重。这个问题如何得到解决? A5:     好问题,性能问题也是被同事问得最多的问题。关于性能问题我没遇见过高并发的场景,当时对于降低   services   依赖,控制网络请求我们是有一些解决方案。 1.   所有   services   基本都部署在同一个网络,比如   AWS   的网络上,可以讲起想想成内部局网,HTTP   call   带来的性能损耗目前为止还算可以接受。

2.   从系统设计的角度讲,与其降低HTTP请求的消耗时间,不如减少HTTP   请求的发送次数。从系统设计上考虑,大部数据模型都是   immutable   (不可变得),在系统系统间我们将数据缓存,减少   HTTP   请求的次数。(全文完)



扩展阅读




中生代技术下期分享预告


以上是关于吕健|Microservices 场景下的持续部署的主要内容,如果未能解决你的问题,请参考以下文章

持续部署Microservices的实践和准则

微服务架构(Microservices Architecture)介绍

基于Docker环境下的Jenkins搭建及使用

State of the Art in Microservices

负载均衡续:万亿流量场景下的负载均衡实践

自动化运维|云原生架构下的产品自动化发布快速部署和持续交付实战之路