专栏名称: 分布式实验室
最专业的Docker文章,最权威的Docker新闻。关注容器生态圈的发展。
目录
相关文章推荐
51好读  ›  专栏  ›  分布式实验室

某股份制商业银行定制化PaaS介绍

分布式实验室  · 公众号  · 后端  · 2017-05-07 08:10

正文

某股份制商业银行的PaaS平台是由Wise2C与Rancher合作,基于Rancher做的定制化开发。基于业务场景和银行业的特殊需求,同时为了兼顾能够实现对以后Rancher版本的平滑升级,我们在Rancher之上做了一层逻辑抽象。


1. 软件架构与部署方案


整体软件架构如下图所示:



顶层的DCOS作为统一的管理平台,可以通过PaaS以及IaaS提供的API实现对云平台的集中管控。左侧蓝色部分是原生Rancher,DCOS与红色定制化部分通过API来访问Rancher。由于未对Rancher做任何改动,可以做到对Rancher版本大于1.2的平滑升级。


红色部分为定制化逻辑抽象部分,归纳起来可以按照功能职责大致分为以下微服务(后面会详细介绍):


  • 鉴权认证


  • 资源管理


  • 应用编排


  • 弹性伸缩


  • 日志收集


  • 监控告警


  • 镜像仓库


这些微服务在部署时按照Rancher将infrastructure stack部署到环境中的思路,使用一个独立的Rancher环境来部署这些微服务,部署拓扑结构如下图所示:




图中每一个虚线框对应Rancher中的一个环境;“扩展ENV”这个环境直接使用Rancher server的主机作为Agent,上面运行定制化的微服务。其他环境分别对应到某个租户的特定网络,单个网络内部流量不使用Rancher原生的overlay,而采用Wise2C实现的扁平化网络,网络之间流量由外部防火墙控制。


2. 角色与权限模型


PaaS平台的角色与权限模型沿用了Rancher的一部分概念,又引入了自己的内容。主要差异在于两方面:


  1. PaaS平台引入了对镜像仓库的管理,这在Rancher中是没有的;即角色的权限,除包含操作Rancher外,还能够操作镜像仓库。镜像仓库与PaaS的权限模型是一致的;


  2. 另外,客户引入了租户的概念,这点与Rancher中不同,租户是可以跨越多个Rancher的环境的;


Rancher权限模型


  • 平台管理员:


    拥有整个Rancher平台的所有权限;


  • 环境用户:


    Owner,拥有环境的所有权限;

    Member,拥有除对环境内部用户授权外的所有权限;

    Restricted User,拥有环境内部除对用户授权以及操作基础资源外的所有权限;

    Read Only,拥有环境内部资源的只读权限。


PaaS平台权限模型


  • 平台管理员:


    等同于Rancher的平台管理员权限再加上对镜像仓库管理的所有权限;


  • 租户内部角色:


    租户管理员,拥有管理租户资源以及对租户内部用户进行授权的所有权限,再加上对镜像仓库管理的所有权限。

    高级成员,在PaaS平台内拥有对租户内用户授权以及操作基础资源外的所有权限,在镜像仓库内,拥有对镜像仓库设置镜像同步规则、创建、删除镜像仓库Namespace、改变镜像状态等权限。

    受限成员,在PaaS平台内拥有对租户内用户授权以及操作基础资源外的所有权限,在镜像仓库所属Namespace内,拥有上传、下载镜像的权限。

    Read Only,在PaaS平台内,拥有查看租户类资源的权限,在镜像仓库所属Namespace内,拥有查看镜像仓库资源的权限。


具体映射关系如下图所示:



鉴权部分的软件设计如下所示:



所有对PaaS访问的API请求均经由API proxy做鉴权控制之后代理到系统内部具体的微服务上。PaaS不直接参与租户的增删查改,API proxy通过与PaaS外部的Keystone通信来获取用户角色以及租户信息。


3. 资源管理


网络部分


  1. 由于金融行业对网络安全性方面的要求比较苛刻,而Rancher所能够提供的均是基于某个环境内部的overlay网络。Overlay必然会导致很多报文无法被安全设备透明的过滤,这是行业内无法接受的;因此,必须采用扁平网络。


  2. 处于安全的考虑,会出现同一个stack内部的多个service需要分别部署到不同的网络分区的需求,采用当前Rancher的managed网络显然无法满足需求;因此,必须支持多网络。


对于扁平网络的支持,我在之前的文章(在Rancher 1.2中实现基于CNI的扁平网络)中有详细的介绍,主要是使用ebtable直接在linux bridge上对流量做控制,从而避免使用overlay;这样,外部安全设备能够透明的看到各个容器之间的流量。



对于多网络的支持,我们是通过在Rancher之上实现一层抽象逻辑来实现的。整个模型演变为一个网络映射为Rancher的一个环境(环境内部运行一个扁平网络)。这部分主要涉及对平台中所有网络的管理,以及维护租户与网络之间的映射关系。


下面举一个例子来描述该流程:



平台管理员在PaaS上创建一个网络,指定网络的参数(子网掩码、网关、所属安全域、所属隔离域等),这些数据会保存到数据库;


平台管理员根据需要为租户分配第一个网络;此时,抽象层需要真正在Rancher上创建出网络所对应的环境;以及创建监控、日志、以及定制化系统所需的system级别的应用堆栈;


当平台管理员为租户分配第二个以上的网络时,抽象层还需要将该Rancher环境与租户其他网络对应的Rancher环境之间建立env link关系,否则跨Rancher环境的应用堆栈各service之间无法使用Rancher DNS进行互访。


存储部分


客户PaaS在存储部分最终选定NFS作为其存储方案,前期也有讨论过使用ceph等,这部分我在之前的文章(探讨容器中使用块存储)中也有专门分析过为什么不选用那种方案。


由于单个租户可以拥有多个网络(也就是多个Rancher环境),而在Rancher中Rancher-NFS driver所创建volume是基于环境层面的。为了能够将该volume映射到租户层面,我们在抽象层中做了这层映射操作。


具体流程如下


平台管理员在PaaS中指定参数创建出一个NFS server;同网络一样,此时只是将数据保存到数据库;


平台管理员为租户分配NFS server,此时抽象层真正操作租户网络所对应的多个Rancher环境,在逐个环境内添加用于提供Rancher-NFS driver的system stack;


假设租户内用户创建、删除、更新volume;同上,抽象层需要在逐个租户网络对应的Rancher环境内操作volume。


之所以要这样抽象的原因在于客户存在跨网络部署应用栈的需求,因此,存储必须基于租户的粒度,实现跨Rancher环境共享。除此之外,对NFS server的管理方面,客户方面也有自己特殊的要求:


物理存储是按照性能分等级的,同一个租户应该可以同时拥有金牌、银牌、铜牌的NFS server。基于业务的级别,可以为不同级别的微服务指定使用不同等级的NFS server。


因此,与当前Rancher对存储的使用方式不同体现在:同一个租户可以关联多个NFS server,租户内用户在创建volume的时候,可以指定NFS server。


4. 应用编排


在应用编排方面,基于金融行业的特殊安全需求,客户要求应用堆栈能够基于微服务的安全等级来跨网络部署同一个应用堆栈,即应用堆栈中的多个微服务可能跨域多个不同网络。


为了实现跨网络部署微服务,除了对基础资源(网络和存储)模型进行抽象之外,整个应用堆栈的部署流程也需要做相应的调整;


另外,对应用堆栈的描述不再使用rancher的catalog,而是基于一套开源的Tosca模板标准;这样做的目的是方便与OpenStack以及其他平台贯通,方面以后使用同一个模板来描述整个IaaS和PaaS的编排情况;


对应用堆栈以及内部微服务的更新,要求提供统一的接口,均通过下发新的Tosca模板更新应用栈的方式来实现。


在解决应用堆栈的跨网络(Rancher环境)部署以及基于Tosca的编排方面,我们在抽象层中操作流程如下:


接受用户输入的Tosca模板,然后交由translator模块做模板语法的check以及翻译,最终输出能够分别部署到各个Rancher环境的rancher-compose文件以及其他附加信息;


orchestration模块需要对translator的返回信息进行资源层面的检查,比如是否该租户拥有应用堆栈部署所需的网络(Rancher环境)等;


基于Translator的返回信息,按照各个网络之间微服务的依赖关系,决定各个rancher-compose的部署先后顺序,然后开始往网络中(Rancher环境中)部署没有存在依赖的rancher-compose;


基于Rancher环境中应用堆栈的部署情况,按照依赖顺序,逐个部署后续的rancher-compose;


在确保当前应用堆栈在所有Rancher环境中的rancher-compose都部署完成后,将该应用栈的弹性伸缩规则下发到弹性伸缩模块。



5. 弹性伸缩


自动弹性伸缩是客户基于其业务场景而定制化的需求,大致如下:


首先弹性伸缩的策略是基于时间段的,即按照一天为周期,可以设置在一天的某个时间段内采用哪一种弹性伸缩策略;


弹性伸缩的策略包括三种:


  1. 基于微服务下所有容器的CPU利用率的平均值;


  2. 基于微服务下所有容器的内存使用率的平均值;


  3. 基于时间段,只要进入该时间区间,直接将容器数量伸或缩为某个最大或者最小值;在从该时间区间离去时,恢复容器数;


支持对某个微服务的弹性伸缩策略使能和去使能;


在对CPU和内存的监测时,又有如下规则:


  1. 可设置监控指标的上下阈值;


  2. 可设定时长,持续超过指定时长,容器数量增加或减少;


  3. 可设定触发伸缩行为时,单次容器数量增减值;


  4. 可设定弹性伸缩可调节的容器数最大值和最小值;


  5. 可配置弹性伸缩动作之后再触发的时间间隔;


对弹性伸缩功能的实现根据策略的类型不同大致分为两种:


  1. 基于时间的策略,该策略主要是对当前时间与策略时间区间做匹配,一旦发现进入到基于时间的策略的时间区间就基于微服务的索引,找到并更改目标微服务的容器数量;


  2. 基于内存和CPU利用率的策略本身并不监测CPU和内存信息,而是依赖于监控模块。在应用编排侧添加或更新了某个微服务的弹性伸缩策略后,弹性伸缩模块会将对这个微服务的弹性伸缩策略转换为监控告警策略下发到监控模块;同时,监听来自监控告警模块的告警信息。当收到告警时,弹性伸缩就从自己维护的映射表中找到是具体触发该告警的微服务,然后基于一系列规则来决定是否伸缩微服务的容器数量以及一次调整多少个。



由于弹性伸缩策略被设定于各个时间区间内,必然需要维护众多的定时器。一旦规则被设定后,就相当于为微服务定义好了一个周期为24小时,基于时间的状态机。当微服务数量较多时,如何保障既管理好这些状态机、定时器,又能不消耗掉太多的系统资源是软件设计的难点。


另外,由于各个运行实例都运行着独立的状态机,如何做好弹性伸缩的高可用(冗余)又能够保障冗余部分的数据同步,也是值得深入思考的问题。


6. 日志收集


客户PaaS对日志的收集主要按照日志的来源可分为三种类型:


  1. 主机日志收集;


  2. 容器日志收集;


  3. 应用日志收集;



对于主机和容器的日志收集相对比较简单,主要通过对指定目录的文件内容进行收集,然后将收集到的日志信息进行格式化后统一发送到kafka集群;


对于应用的日志收集相对较复杂,既要不对业务容器产生侵入又要保障能够收集到及时的日志。我们是通过在Tosca模板中定义某个微服务的log_files来指定应用日志在容器中的路径以及扩展名的。



当容器被调度到某台主机上时,该主机上的日志收集模块就会基于容器标签得知该容器内的应用日志目录,通过分析容器的详情可以获取到该容器内日志目录所映射到主机上的路径,从而将对容器内应用日志的收集,转换为对主机上特定文件内容的收集。具体的收集方式是采用logstash,通过程序自动修改logstach的配置文件来添加日志来源。


将所有日志收集到kafka之后,客户再采用第三方的日志分析工具来对日志做特定的过滤、分析、搜索和多维度的展现。


7. 监控告警


客户的监控需求大致如下:


租户宿主机集群的资源使用情况和运行状况,具体包括:


  1. 租户集群的容器宿主机数量和总体资源使用情况


  2. 租户集群中不同网络区域、等保区域等细分范围的容器宿主机数量和资源使用情况


  3. 集群总体容器数量、容器在集群各容器宿主机节点的运行和分布情况


  4. 每个容器宿主机节点的资源使用情况、运行容器列表


应用(包含Stack和Service)监控数据,监控数据包括应用容器列表(容器IP、所在宿主机)、应用运行情况(健康情况、资源占用)等。


每个容器所使用CPU、内存、网络、存储、标签、端口号等信息进行监控,提供Restful API。


事件等信息写入事件审计数据库;同时支持配置事件告警规则,当激活事件告警功能后,根据事先设定的告警规则,从事件审计数据库中读取和过滤信息,转换成syslog格式,再将告警信息通过消息队列发送到PaaS平台外部。



该部分的实现主要使用bosun平台, 容器方面从cAdvisor中采集监控数据,主机方面是直接读取主机实时信息,对Rancher的审计日志,主要通过读取Rancher的数据库来实现。所有的监控数据汇集到bosun之后,通过对bosun做一层封装,一方面用于按照自定义的格式设置告警规则、另一方面实现bosun对接Active MQ将监控信息发送到消息队列,从而对接第三方监控大数据平台。


8. 镜像仓库


镜像仓库分为测试仓库和生成仓库,这两个仓库均实现了与PaaS平台的权限模型对接,实现单点登录以及统一的鉴权控制。


另外值得提的是,客户对镜像从测试仓库到生产仓库的同步的流程划分为手动和自动,具体如下:


  • 镜像在被提交到测试仓库后,默认为“开发中”状态;


  • 开发完镜像后,受限用户通过外部协同管理平台来通知高级用户将镜像从测试仓库同步到生产仓库;


  • 高级用户登录测试仓库后,可以修改镜像同步规则;在正式同步之前,高级用户可以修改镜像的“待同步”状态为“开发中”;


  • 如果在生产仓库中已存在对应的Namespace,且高级用户勾选了自动同步,测试仓库会在同步周期超时时同步镜像并将“待同步”镜像状态改为“同步中”。如果同步成功,状态自动更新为“已同步”;否则为“待同步”;


  • 如果在生产仓库中已存在对应的Namespace,且高级用户勾选了手动同步,需要高级用户在测试仓库中手动点击“同步”按钮来同步镜像到生产仓库;如果同步成功,状态自动更新为“已同步”;否则为“待同步”。


Q&A


Q:弹性这块,扩容好说,缩的话有个问题,就是还有用户请求在这个容器上,怎么办?

A:在该项目中我们并未对这种情况做特殊处理,但是在我们另外的产品中,已经考虑到了该问题。正确的方法应该是基于ingress设置一个销毁容器的宽限时间,即:在这段时间内,不允许新流量导入即将销毁的容器,这些容器在该宽限时间到期后,自动销毁。


Q:对弹性伸缩部分请教一下:您分享的弹性伸缩的场景业务周期性很明显,所以基于时间区间触发采取不同的伸缩操作,如果业务周期性不明显,伸缩机制能处理吗?如何处理?

A:在当前项目中,客户明确要求按照1天为周期。在我们自己的PaaS产品线中,弹性伸缩可以调整周期(比如:星期、月份等),另外,还可以不按照时间周期,直接基于CPU、内存或者某一个可监控项。你可以理解为只要能够被监控的监控项,都可以作为弹性伸缩的依据。


Q:我目前关注的是日志这块,怎么才能把日志集中在一起,能不能说的具体点?

A:我们是将日志收集后,统一发送到kafka集群,你可以理解为拷贝一份集中存储到kafka集群。这里的集中不是什么难点,难点在于对日志的收集,涉及三个层面:主机、容器、应用。我们的方式是在各台主机上部署容器化后的logstash,然后通过程序修改其配置模板,从而收集不同目录的日志。而这些目录就分别对应着主机日志、容器日志映射到主机的目录、以及应用日志映射到主机的目录。


Q:根据日志标签获得应用日志目录,请问容器标签具体是什么格式的,采集日志信息中包含节点信息,容器信息,应用信息等跟平台、应用相关的元数据字段吗?

A:这里的日志标签是可以自定义的,相当于主机上的daemon程序会监听该主机上容器的创建、销毁等event,一旦发现容器创建,就去check其标签,是否有自定义的“日志目录信息”,“日志文件扩展名信息”。这些日志目录都有对应的volume挂载到宿主机上,因此通过分析容器的inspect信息,就能够找到日志目录映射到宿主机的目录。而你提到的节点信息,这些是每个宿主机上的日志收集的服务容器在启动的时候就定义好的,所有由它收集并发送出去的日志,都会有该宿主机的标签。


Q:关于日志收集的时间取值问题,是日志收集点的本地时间还是系统时间,具体如何保持一致?NTP?

A:是日志收集点的本地时间,具体通过NTP,但是要注意,需要保障容器时间与宿主机时间(时区)要保持一致。


Q:弹性伸缩另一个问题,如果不是周期性弹性伸缩是否考虑避免短期脉冲现象引起的不必要的弹性伸缩操作?

A:所以在弹性伸缩的规则里面有一个参数为:“retrigger time” 也可以把它理解为一个安全的时间片,再一次伸缩动作之后,必须要等待这个时间片结束之后才会再次触发弹性伸缩行为。否则不予响应。



3 天烧脑式Kubernetes训练营


本次培训内容包括:Kubernetes概述、架构、日志和监控,部署、自动驾驶、服务发现、网络方案等核心机制分析,Kubernetes调度工作原理、资源管理及源码分析等,点击识别下方二维码即可查看具体培训内容。



点击阅读原文链接可直接报名。