中国人寿研发中心高级架构师 张青南
从 2017 年起,中国人寿正式开始利用容器技术搭建 PaaS 平台“稻客云”,结合持续集成/持续交付技术,实现了研发全流程自动化及对应用容器的全面管理,至 2019 年,“稻客云”已支持中国人寿 15 个关键系统的生产运行,管理应用容器 4800 多个。容器技术的应用促进了中国人寿整个研发流程的优化和可管控,软件的迭代周期大大缩短,并且以容器部署的方式承载了应用,实现弹性伸缩,应用快速构建部署。本文将介绍中国人寿基于容器构建 PaaS 平台的实践。
2017 年初,中国人寿容器云建设开始启动,6 月完成了研发测试云和生产云的搭建。搭建完成后,开始大面积推广研发测试云,生产云依然处在试运行阶段。2017 年年底,我们在研发环境上个迁移了 54 个系统,几乎所有 Java 类系统都在云上进行开发和测试。
2018 年 6 月,生产云上线了第一个真正意义上的关键业务系统——大健康平台,一个完全基于云原生开发的系统。其后,我们陆续在生产云上线了其他的关键业务系统。2019 年初,部分中国人寿的分公司开始使用中国人寿 PaaS 平台。
截至目前,中国人寿有 174 台服务器,绝大部分是中高端的刀片机,托管了 600 多个微服务,运行了 4000 多个容器,有 15 个关键业务系统在生产云上运行。中国人寿新一代核心业务系统中的保全平台已经完全上云,综合查询、批作业等业务模块也在 7 月份上线到生产云。另外,中国人寿面向客户的寿险 APP 和面向营销员的 E 店系统的部分微服务也运行在云上。同时,中国人寿的统一用户系统也运行在云上。
过去两年多的时间里,中国人寿 PaaS 云一直稳定运行,主要是因为 Rancher 比较稳定,且我们在部署和运维上做了很多稳定性相关的保障。
本文的内容分为三部分,一是中国人寿为什么要建设 PaaS 平台,二是我们是怎么建设 PaaS 平台,最后是我们如何利用 PaaS 平台。
为何建设 PaaS 平台?
中国人寿建设 PaaS 平台的目标很简单,就是一句话“为了更好地使用资源”。大家都应该知道,字越少,事儿越大。一句话的目标听来宽泛,我们需要分解它,以便于更好地理解。
首先,什么是资源?我们觉得以下三类内容是我们需要考虑的:一是“环境”,程序需要运行起来,就需要使用 CPU、内存、磁盘操作系统,这些程序运行起来的需要的最基本的资源就是环境;光有环境你的程序可能还是无法运行,大部分系统的运行还需要依赖中间件,比如 web 中间件、数据库、缓存服务等,这些是你需要的“技术依赖”;有了这些,你的程序可以运行起来了,但不一定能处理业务。比如我们开发一个出单服务,这可能需要依赖保单服务、支付服务,这些是你的“业务依赖”。
上述三个就是我们需要解决的资源问题,一是环境资源,二是技术依赖,三是业务依赖。
理解了什么是资源,我们再去看什么是“更好地使用”。我们认为它包括两个方面的内容,一是对人来说,能够更便利地使用资源,最好能达到像使用水电一样,想用的时候就打开,想用多少就用多少,用完了就关上。二是对应用来说,能更有效地利用资源,以达到节约资源和降低成本的目的。过去需要花 10 份的资源才能做成的事情,现在用 5 份资源就能完成。
用一句话总结中国人寿的 PaaS 平台,就是:基于“容器技术”和“自动化技术”为“人”和“应用”提供服务,解决“更好地使用资源”问题的“云平台”。
首先,这句话里包含了两大关键技术:“容器技术”和“自动化技术”。
我们先来说说以 Docker 为代表的容器技术。为什么中国人寿要用 Docker 容器技术搭建 PaaS 平台,而非使用传统的虚拟化技术呢?
在这个项目启动之前,中国人寿已经大量地使用基于 VMware 的虚拟化技术了。那么,在搭建 PaaS 平台的时候,为什么我们不用 VMware 搭 PaaS,而是用容器来进行搭建呢?主要有两个原因。一是容器的“轻”,这个“轻”体现在各个方面。举个例子,容器是基于进程的资源管理,所有运行的容器共享一个宿主机上的资源,它是抢占式的。虚拟机像是切蛋糕,你把资源分配给它,无论它是否使用,它始终都会占用这个资源,其他人无法使用。容器要比虚机模式节省非常多的资源,我们在后面会用一组数据说明这个问题。
第二个原因也非常重要:容器是以应用为中心的,容器一旦启用,启动的是一个应用;而虚机是以环境为中心的 ,当你启动虚机的时候,它为你提供的是一个操作系统。二者之间区别很大。中国人寿 PaaS 平台的建设以应用为中心。诚然 PaaS 译为 Platform as a Service,但我一直将它当作是 APP as a Service 去考虑这一问题。
中国人寿使用 Rancher 进行容器调度,目前用的是 Rancher 1.6 版本。2017 年我们开始搭建中国人寿 PaaS 云平台的时候,Rancher 还是 1.0 的版本。
我们选择 Rancher 主要有三方面的原因:
第一,Rancher 足够简单,这个非常重要,Rancher 的概念模型沿用的是 Swarm 的概念,上面是应用栈,底下是一组 Service 即微服务,这个概念与中国人寿“以应用为中心”的概念非常吻合,拿来即用,我们很喜欢这个概念。
第二,Rancher 功能足够,不复杂,但足够。作为一个金融企业的 IT 部门,我们不需要那些花里胡哨的、没用的功能,Rancher 产品本身使用简单,但提供的功能又能满足我们的需求,这样很好。
第三个原因也非常关键,就是稳定,我们从 Rancher 1.0 版本一直使用到现在的 1.6 版本。在 Rancher1.5 之后,Rancher 基本上没有过多功能上的变化,一直在完善功能和应用性,后面的几个版本都非常稳定,我们从 1.4 版本开始上生产云,现在用的是 1.6 的版本。
说完了容器技术,接下来讲第二个关键技术,以 Jenkins 为中心的自动化技术。
中国人寿的自动化技术主要用于持续集成和持续交付,我们重点谈一下持续集成。
我们认为,容器技术使持续集成技术格外强大。在容器技术之前,持续集成指的是,当代码发生变化,触发 Jenkins 上的一个 Job,将程序编译打包后,发布到一个固定环境的固定中间件上,让它跑起来,你所能做的就是能让代码的变动触发程序的变化。而有了容器技术之后,你就能做到当环境变化后,通过触发持续集成搭建新的环境;当中间件依赖变化后,通过触发持续集成构建新的中间件;当业务应用架构变化后,例如从一个应用变成了十个应用,还是可以通过触发持续集成拉起一套全新的应用体系。这点非常关键,因为我们刚才说了,我们想解决的问题是环境依赖、技术依赖和业务依赖,现在通过容器技术,通过 docker-compose 文件结合持续集成,我们基本可以做到自动获取任何资源了。这是第一个关键点。
第二个关键点是持续集成使容器技术在中国人寿这样的企业广泛推广,它大幅降低了技术人员的使用门槛。中国人寿有各种产品、不同的团队,并不是所有的开发人员都有意愿去学习和掌握什么是 PaaS、什么是 Docker、什么是镜像、怎样做部署。但我们又希望所有人都能把容器用起来,那该怎么做呢?在公司内部推广的时候,每一个需要对接进来的系统,我们都会让 PaaS 团队为这个系统实现持续集成。持续集成将代码编译、构建镜像、镜像更新、应用商店等等全部自动化。如此一来,对研发项目组、对开发人员而言,他的工作没有发生任何大变化,只需更新代码即可,PaaS 的使用均由持续集成自动化执行。
我们的服务对象包括两类,一类是“人”,一类是“应用”。我们希望为“人”即项目经理、开发人员、运维人员提供研发运营模式上的革新,对“应用”提供微服务架构、无服务器架构等架构模式上的革新。
中国人寿 PaaS 平台旨在解决“是否更好地使用资源”的问题。我们如何判断是否更好地使用资源呢?我们可以将它量化为三项,即:是不是省时了、是不是省事了、是不是省钱了。
中国人寿有一组数据,它并非整个平台的使用成果,而是中国人寿的一个分公司在平台迁移前后的数据成果,我们将过去部署在虚机上的服务器和部署在云上进行了前后对比。
上图是平台的资源使用情况和效率提升情况。资源之所以节省,是因为容器基于争抢资源的模式,能极大避免虚机时代资源占用浪费的问题。效率的提升,则是由于持续集成极大地提升了研发及资源获取的效率。在中国人寿,我们申请设备需要走流程进行审批,这个过程会花费大量的时间,现在可以通过持续集成实现“自管理”,开发人员在需要资源时,通过触发持续集成自动获取资源。
如何建设 PaaS 平台?
上图是我们在 2017 年立项时画的,这张简单的图指导了中国人寿两年左右的 PaaS 平台建设工作。
我们认为,中国人寿需要有一款自己的 PaaS 产品,我们要基于这个产品搭建两朵云,一朵是开发测试云,一朵是生产云。两朵云有不一样的定位。开发测试云解决的是资源利用率、管理成本和研发效率等问题,生产云主要解决微服务托管、快速部署、交付一致性、弹性伸缩等问题。
两朵云对应用的要求也不一样。对于开发测试云而言,所有你能搬上开发测试云的应用,我都能帮你做容器化和自动化,你享受开发测试环境带来的种种优点即可。但对于生产云,我们有更高的要求,生产云的应用必须是云原生的应用,必须做好微服务化改造,技术人员自身还必须知道如何利用云上的优点。所以两朵云对应用的要求是不一样的。
我们在开发测试云上做了持续集成,通过持续交付打通两朵云,两种云结合为 DevOps 夯实了基础。
上图是我们对产品的定位,主要关注四个部分:第一部分是通过 Rancher 进行容器管理;第二部分通过 Harbor 进行镜像管理;第三部分是通过 Git 进行应用商店管理;最后一部分是是基于 Jenkins 搭建 CI/CD,开发运维一体化。
这四部分明确之后,我们通过中国人寿的稻客云门户集中管理底层云生态,再通过稻客云门户对接用户管理,统一权限、统一用户,进行界面上的集成,让用户在一个界面上完成所有事情,以及实现监控、日志等功能。
除此之外,稻客云门户还可以实现两个比较有意思的功能,一是多租户,一是快速部署。Rancher 1.6 版本里没有基于用户层面的多租户隔离,它基于环境进行隔离,所以如果一个环境上很多用户,上层运行的应用能互相看到,和我们理解的多租户隔离有所区别,所以中国人寿自行开发了多租户隔离功能。
快速部署是一个将发布流程极简化的功能,它屏蔽了持续集成以及 PaaS、Docker 的过程。我们先前有个情况,分公司的同事希望运行自己的应用,但又不想关注 PaaS、Docker、容器包括持续集成等技术。为了解决这个问题,我们开发了一个界面,让分公司选好应用程序,点击上传,再点击启动,我们在容器上运行应用程序,再将容器 IP 返回去,就完成一次快速部署。
中国人寿在北京和上海各有一个数据中心,在上海和北京各部署了一套生产云,开发测试云只部署在北京。每朵云的管控节点均为独立部署,每个管控节点托管很多个不同的环境。当中有一个关键点,即环境的划分。一个环境里托管的主机越多,共享的应用就越多,从而规模效益越好,资源利用率也越高。但这样会使隔离性降低,当系统出现问题时,运维难度将呈几何级上升。
因此,在开发测试环境中,我们追求尽量扩大规模效益,在开发测试环境划分了 5 个大环境,所有机器部署在五个大环境当中,大家混合使用,资源利用率很高。但在生产环境中,我们非常谨慎,一个关键系统独占一个环境。正如我先前所说的:两朵云的定位不同,想解决的问题也是不同的。
如何利用 PaaS 平台?
前文曾经提到,中国人寿 PaaS 平台的服务对象一类是“人”,一类是“应用”。“人”指的是项目经理、研发人员、运营人员,“应用”指的是微服务框架和无服务架构的支持。
对于项目经理而言,我们希望为他提供的变革是自服务。过去,项目经理的主要职责是找各种能够提供资源的对象,获取开发所需的资源。现在,我们希望对他进行变革,利用 PaaS 平台,让他通过平台、应用商店、持续集成实现自助服务,提升项目经理获取资源的效率。
对于开发人员而言,我们希望达到自动化。刚才前面几位嘉宾在分享的时候,提到了开发人员专注于业务逻辑开发。我们认为开发人员要做的最基本的事情是开发代码、提交代码、测试、查看,开发人员只需要做这几件事情,剩下的活动比如编译、构建、部署、测试等完全通过持续集成、自动化脚本来实现。
我们通过持续交付,为运维人员提供软件交付上的变革。我们在开发环境专门找了一台开发交付机部署 Jenkins,这台机器打通了跳板区的镜像仓库,为每一个在云上提交的项目实现交付任务。交付任务完成后,我们将 Jenkins 上的用户权限提交给应用的应用经理及应用团队。当应用团队需要交付时,先将代码提交到交付机器上,再在 Jenkins 上执行交付任务,交付的 Jenkins 会抓取代码,打包编译、构建镜像,将发布镜像推到跳板区的镜像仓库,再由生产的运维同事在应用商店里选取应用,点击部署,一键部署后将整个应用从 Rancher 上拽起来。
文初提到中国人寿 PaaS 云平台上线的第一个业务应用——大健康平台,拥有 45 个微服务,运行 200 多个应用容器。因为大健康平台是第一个上线的业务应用,我们对它进行了测试,从开始交付到运维人员现场部署一共花了 8 分钟。假如我们手工按传统的方式去部署,200 多个应用预计要花 2 周的时间。
中国人寿 PaaS 平台的微服务主要有三个场景。第一个场景是应用完全微服务化,全部应用均跑在容器上。我们为这个应用拽取两个应用栈,让它能实现蓝绿发布与灰度部署,这两个栈是一样的,栈里面的微服务通过服务名进行通信,这一功能由 Rancher 实现。对外提供服务则是在 Rancher 界面上配置一个内部代理,将内部代理固定到主机,在 PaaS 环境外配置一个外部代理,指向两个栈的内部代理。
第二个场景就是部分应用容器化,一个应用在进行微服务改造后,一半跑在传统环境上,另外一半跑在云上。这种情况建议引入两个关键组件,应用网关和服务发展中心。
里面有非常关键的一点,我们使用的是 Rancher 1.6 提供的扁平网络模式。在这种模式下,每个容器均拿到一个真实的 IP,在它们的 IP 及 PaaS 环境外部,公司其他设施 IP 互通。这样设置之后,假设应用拆分出三个微服务,均部署在云上,三个微服务都注册到服务注册发现中心,微服务和过去的传统应用之间的通信直接通过 IP,通过服务注册发现中心即可直接互通。云外面的应用需要访问微服务或者是传统应用,通过上面的应用网关即可访问。
最后一种模式非常简单,它可能不是微服务,就只是一个普通应用,需求是要在云上进行扩容。例如,我有一个业务几月几日开始,将产生大量访问,我需要扩容,怎么办?这是最简单的一个场景,我们把应用容器化之后,作为服务在 PaaS 进行部署,上层部署一个内部代理,将外部的负载指向两边即可。
评论