本文系云原生应用最佳实践杭州站活动演讲稿整理。杭州站活动邀请了 Apache APISIX 项目 VP 温铭、又拍云平台开发部高级工程师莫红波、蚂蚁金服技术专家王发康、有赞中间件开发工程师张超,分享云原生落地应用的经验心得,如下是莫红波《微服务架构下 CI/CD 如何落地》分享内容。html
莫红波,又拍云平台开发部高级工程师,目前专一于容器及虚拟化技术在又拍云的私有云实践,主要负责又拍云容器云的设计和开发工做。web
你们好,今天分享的主题是《微服务架构下 CI/CD 如何落地》,围绕如下两部分展开:数据库
或许你们对于互联网公司的共同印象是 996,对于我我的而言,互联网公司还有另外一个特色,那就是常常须要拥抱变化。在互联网公司,新产品上线、下线、调整,这都是很屡见不鲜的事情。在这种状况下,一个好的松耦合的架构就显得尤其重要。安全
恰好我最近就有遇到这个问题,我在作的项目,帐号这块是对标 GitHub 的注册制帐号机制的。本来的需求是用户注册咱们的平台,注册完成后能够建立一个属于本身的团队,并将其余人拉入本身的团队。可是当咱们作完这部份内容后发现,客户仍是更偏好「帐号+子帐号」的模式,公司一个总的帐号,全部员工单独开子帐号进行关联。这让咱们已经作好的项目变得很是尴尬,须要当即拥抱变化,须要根据最新的需求进行调整。这时,我就发现拥有一套松耦合的架构的重要性,好比帐号这一部分,若是把它单独拎出来,作好足够的抽象,提供必要的对外接口,可能会更加灵活,扩展性更加好。服务器
那怎样拥有一套松耦合的架构?有什么好的方案呢?在我看来有两个,一个是几年前出现的 SOA,即将服务进行单独化,将每一块都进行拆分;另外一个就是最近几年火热的微服务了。我认为,微服务跟 SOA 实际上是一回事,只不过微服务比 SOA 拆分粒度更细,功能也更小。网络
在调研微服务过程当中,不少人会有疑问:“咱们是一个很小的团队,小团队适不适合上微服务呢?”。由于上微服务就意味着一个服务可能就会被拆分红 10 个、20 个甚至更多个的服务,这就让小团队不得不去考虑本身的测试、部署、更新成本是否是会翻不少倍。架构
那么我对于“小团队适不适合上微服务”这个问题的答案是什么呢?我认为是彻底能够上的,不过你须要注意一点:作好自动化,能交给自动化来实现的,就不要人工介入了。app
在聊如何作自动化集成测试(CI)以前,我先和你们谈一谈从单体如何到微服务,服务是如何拆分的,以及微服务的测试通常是怎么作的。微服务
如上图所示,咱们能够看到图左边是一个单体服务,右边则是通过微服务拆解后的。咱们能够看到它有 4 个特色:单元测试
咱们都知道,若是须要一个服务可以稳定运行,那测试确定是少不了的。而就像咱们微服务化有一套理论同样,微服务测试也拥有属于本身的金字塔理论:最底层是单元测试,成本相对较低,像咱们在 API 认证部分作的签名校验模块,它通常不须要依赖其余东西,所以测试效率也比较高;第二层是集成测试,这一层你就必需要依赖一些第三方的服务模块或者组件,好比咱们通常会用到数据库的测试,就属于集成测试的范畴;第三层是 e2e 测试,它会模拟客户端的行为来进行测试,你们也许都接触过这类测试,像K8S 就有一个 e2e 测试,当你去申请 CNCF 的一致性认证时,就须要经过官方提供的 e2e 测试;最上层是 UI 测试,好比对于页面的点击调整是否符合预期,这部分咱们如今作的比较弱,还处在人工模式下,但咱们也在努力将它更新成自动化。
从这个微服务测试金字塔咱们能够看到,越靠近底层成本越低,你只须要几行代码就能完成,效率也很是高。同时越底层它对于三方或组件的依赖也越低,自动化也就越简单。到这里可能就有人想问:“既然越底层的成本越低,那咱们能不能只跑单元测试?”在解答这个问题前,你们先看下面这张图。
这两扇窗户,每一扇单独存在的时候都是无缺的窗户,能够正常开合。可是两个都安装到墙上后就没有办法正常开合。这就是咱们不能只跑单元测试的缘由了,不跑集成测试就没法发现一些问题。同理不跑单元测试也会有一些没法发现的问题,因此咱们在跑测试的时候,集成测试和单元测试,一项都不能少。
那具体实践的时候要如何作呢,我推荐你们分红两步来进行:
GitLab/CI
自动化集成环境这块目前已经有不少的开源方案了,好比常见的 Jenkins,还有 GitLab。咱们选择的是 GitLab,或者说是选择了 GitLab/CI,选择它的缘由有如下几点:
GitLab WorkFlow
既然咱们选择使用了 GitLab,那咱们内部就会严格遵照 GitLab 的 WorkFlow。WorkFlow 主要分为两个部分。
第一部分是面向代码仓库。代码仓库中,咱们通常会有三类分支,第一类分支是 master 分支,通常只会有一个,咱们会定义 master 分支,并基于这个分支进行线上版本的发布。第二类分支是 develop 分支,通常也只会有一个,develop 分支是从 master 分支中 checkout 出来的,功能比 master 领先,包含一些已经完成功能开发,可是尚未发布的功能。第三类分支是 feature 分支,特性分支,通常会有不少个,新功能都会在这个分支上进行开发,每每一个功能对应一个 feature 分支。最后一类是 hotfix 分支,这个就比较常见了,线上发布后,若是发现了一个须要紧急修复的bug,这时你就能够在 master 分支上 checkout 出来一个 hotfix 分支,把代码改掉。不过进行这个操做时你须要注意,master 分支和 develop 分支都须要进行该 commit 合并,不然就不能算完成了 bug 修复。
第二部分与 CI/CD 有关。以咱们的流程举例,研发的同窗提交代码到 GitLab 仓库,以后 GitLab 会触发事先约定好的 CI 的 pipeline 进行测试和构建。等待测试和构建成功后再进行 code review 的确认,确认无误后会合并到 develop 分支并最终合并到 master 分支进行发布。这就是 GitLabCI 的一个配置,总结来看能够划分为下图的四个阶段。
下图是配置文件对应的 pipeline 的展现,你们能够看一下。
其实到目前为止的方案,已是微服务没有大热前的完备方案了。若是你想要将方案运用到微服务的集成测试里,你还须要作一些变形,不妨参考下图中所示的又拍云如今使用的整套流程。
从图中能够看到,咱们目前使用的整套流程相比标准的其实有作一些小的变形,变形主要集中在中间的集成测试环境这一块,咱们将每一个服务器都部署在了集成环境内,使集成环境变成一个准发布环境。具体流程是,当咱们的建立 projectA 后,由它来 push 代码,完成后触发 CI,也就是在 GitLab runner 上进行测试。
在跑测试的过程当中,由于 A 服务须要调用 B 和 C 服务,因此经过 API 去请求集成环境中的对应服务。若是测试完成后没有问题,则合并到主线。再经过在 master 分支打 tag 的方式来触发容器构建并推送到 Harbor 镜像仓库。最后咱们会作一个线上 release。这个就是咱们的大体流程了。
那么接下来咱们来具体看一下变形中会遇到的问题。
服务发现
在微服务场景下的变形中遇到了不少问题,我以为其中值得注意的是“服务发现”。好比咱们如今有这样一个场景,A 服务在跑测试时须要依赖 B 服务和 C 服务,面对这个需求,在没有引入 Kubernetes 以前,咱们能够经过使用一台共用机器,将服务都布置到这台机器上,并在测试代码里写死 IP 地址,让每一次测试都在这个环境内跑。但这个方法会有下面四个没法忽视的问题:
所以咱们引用了 Kubernetes Service 的方案进行优化。
Kubernetes Service 的流程你们能够大概看一下。咱们先定义一个 Service, 咱们这边建立的 ClusterIP 类型的,定义了暴露端口 8000,目标端口 8000,协议是 TCP,标签选择器是 app=holdon。经过这种方式,咱们能够把一组相同功能的服务,绑定在同一个 Service 下。在 Kubernetes 集群内,定义好 Service 后,会提供内部的 DNS 解析,你能够经过一个固定的域名访问指定的 Service。这样当在跑测试的时候就能够经过这个域名加对应端口,调用到对应服务了。
持续交付
持续交付(英语:Continuous Delivery,缩写为 CD)。每一个项⽬都要有⼀个 Dockerfile,提供了服务运⾏所需的环境,以及服务对应的软件包。当须要发版本的时候,咱们会在主线上打上⼀个 tag,触发镜像构建,而后推送到 Harbor 镜像仓库。其中,这个 tag 也会对应到镜像的版本号。
上图是咱们的 CD 流程你们能够参考看一下。须要提一下的是,咱们引用 Harbor 的缘由是由于它相对官方的 Registry 更安全。你们应该都知道,官方的 Registry 自己不带权限校验,当你公司内部使用的时候,这个问题会致使你的镜像有被其余部门的人覆盖掉的可能性,因此咱们引入了 Harbor。但这里也有一个问题,使用同一个 tag 去推依然会被覆盖的状况。不过好歹作到了小组和小组之间、部门和部门之间的隔离。
持续部署
持续部署(英语:Continuous deployment,缩写为 CD),目前这块,在实践过程当中,咱们是只针对集成测试环境,线上更新仍是走常规的流程。给项⽬增长⼀个 k8s-deploy.yaml 的⽂件,⾥⾯包含了服务相关的配置、部署⽅式、访问⽅式等等,等待镜像构建完成后,apply 该⽂件就能够了 。
回顾
如今咱们再回到服务变形的流程图来看一下,当咱们有 A、B、C 三个服务,且 A 服务在测试时须要调用集成环境内的 B 服务与 C 服务时,能够经过 K8S 提供的内部域名进行访问。等待整块测试跑完后,咱们在主线上打 tag,让 CI 去帮执行 image build 构建镜像并推送到 Harbor 仓库。
其中涉及到的准发布环境,能够经过 kubectl apply 的方式进行部署。因为线上环境更复杂,推荐你们经过自研的容器云平台来进行操做,咱们就是这么处理的,经过云平台发布,功能更加全面安全,更加符合线上部署的流程。
最后,跟你们分享下最近正在作的项目的状况。从 2019 年 12月 开始到如今,咱们天天基本保持在一个较高的 commit 数上,而这其中一共进行了大约 4500 次的测试。想象下,若是没有这套自动化持续集成环境,测试须要怎么来进行,须要投入人力资源。
点击阅读可直接跳转,获取现场分享视频、下载 PPT。