传统金融企业的 Docker 实践

编者按:随着 Docker 技术的风行,容器云的概念也逐渐被人们所熟知。为了解决平安传统的应用交付耗时长的问题,基于 Docker 的容器云—Padis 经过开发、测试到生产,出现在人们的视野当中。Padis 解决了中间件的标准化问题,大大缩短了交付时长。下面是对王耀武先生在 ArchSummit 全球架构师峰会七牛云专场上,关于平安容器云平台 Padis 演讲内容的整理。




屏幕快照 2016-08-04 上午10.03.29


王耀武


2008 年首次参加工作,2010 年加入平安科技基础架构,从此被打上了中间件烙印,4 年时间从不知道中间件是什么,到成长为中间件专家。经历了平安的多个重大项目和改革。2014 年开始「不务正业」,做 Docker 在平台的落地,组建团队,搭建快速部署平台 Padis。



基于 Docker 的容器云—Padis


目前市面上基于容器云的产品有很多,对于平安而言,则是基于 Docker 的 Padis 平台。所谓 Padis,全称是 PingAn Distribution ——平安分布式平台。Padis 基于 Docker,实现了平安内部的一个分布式平台。它的实现采用了 Mesos+Marathon(下面简称MM) 框架,可以完成应用程序的快速创建、运行、快速缩容扩容以及故障自愈的功能;平台上实现了独立 IP,可以实现任何集群与外部的或者传统的 IP 的通讯;平台负载均衡的方式很多,可以根据容器的动态变化(容器的增删)做动态调整;平台内还有独立的域名解析,可以做到 CMDB 和性能监控的动态更新。


Padis 的「成长」主要历经以下几个阶段:



  1. 开发环境 Docker 单机版

  2. 测试环境 Padis 上线

  3. 生产环境 Padis 上线

  4. Padis 承接平安金管家(原平安人寿App) 系统群


下面是对每个阶段的详细叙述。


开发环境 Docker 单机版


平安传统的交付过程耗时很长。从需求发起,到资源申请,到中间件交互,这些过程往返很多,会耗费大量的人力和时间。而交付流程长,人力支配不足等原因,会导致交付质量的下降。为了解决交付所面临的这一系列难题,Docker 就成为了一种最初的尝试方式。Docker 包含三方面内容(图 1):仓库、镜像、容器。仓库这方面需要改进的不多,重点放在镜像上面。 2014 年单机版的 Docker 上线,第一版的 Padis 将 Docker 镜像集成到 OS。图1


第一版的 Padis 基于 Docker 和 Docker UI 。 当时的 Docker UI 改了很多的东西(图 2),原本的 Docker UI 不带仓库管理,也没有镜像下载和镜像提升的功能, 而更改后的 Docker UI,不仅添加了 Commit 镜像功能,还增加了仓库管理功能,同时也支持定向搜索下拉或上传。图2


图 2


第一版的 Padis 出来时,着手的重点就是定制化的镜像。平安的业务系统非常多,中间件用的东西又比较标准化,所以定制化的主要方向就是标准的中间件怎么去配,才能放到镜像里形成一个标准的东西,这个问题解决了,那么当开发环境的镜像可用时,该镜像放入生产后依旧可用。此时,将应用包或中间件打包起来后就可以快速启动服务;如果要对这个环境进行复制,将原来环境进行拷贝就可以。这样一来,交付就可以做到分钟级别或者是秒级别。


但是,怎么将中间件打到标准镜像中,这又是一个问题。一个容器是有限制的,如果什么东西都打进去,日志会越写越多,容器容量就会爆,容器默认大小只有 10G。金融行业的日志,它必须要落地、必须要存储,有一些需要排查的问题如果没有日志就会很不方便,因此日志一定要保留。而把应用都打到里面去,开始时不会出现太大的问题,但是随着第一个版本的发行,就出现一个让人很不爽的问题:要对镜像作调整,可是无需对应用的独立镜像进行更新。所以必须要将应用包和日志全部挪走,只留下 OS 和 中间件固定配置和介质,才可行。


因为需要根据一些用户需求做调整,所以这个版本的 Padis 出来后在平安内部做了推广并进行反馈收集。对所收集的信息进行整合,发现单机版的 Docker 存在很多缺陷:一是没有集群,不能解决跨 Host 之间的通讯功能;二是没有健康检查机制,容器应用故障无法自愈;三是没有监控和统计信息,资源使用不可控;四是熟悉 Docker 命令的人不多,要去推广使用很困难。公司中各种不同部门的人很多,每个部门的关注重点不一样,当一个部门里的人根本不了解这是什么的时候,是没有办法使用 Docker 的,因此必须做到界面化。所以后续又做了相应的调整,对于用户一定要镜像透明,并把 Docker 做成集群模式。


对于集群模式的选择则做了两个选项,下面先简单介绍一下这两种框架选项。图3


图 3


其一是 k8S(图 3 ),它基于 Go 语言开发,并且底层基于 CentOS。如果选用这个框架,首先在 Go 语言的学习成本上会耗费很多精力,再者,平安的底层基本是基于 Red Hat Linux ,所以要将 Red Hat Linux 和 CentOS 之间做转换又是一个很复杂的问题。鉴于这两个原因,最后选用了 MM 框架,MM 框架解决了这两个问题。


图4图 4


MM 框架(图 4)结构简单,并且是基于 Java 开发,开发人员占比很多,选用 MM 框架,不仅在上面可以做很多的二次开发和接口,底层也可以选用 Red Hat Linux。这些最基本的问题 MM 都可以解决。而服务器资源池化、容器应用关联、故障自愈、资源隔离、事件驱动也是 MM 框架可以解决的问题。


利用 Mesos 可以实现资源池化,包括对后台的资源进行配置、管理。容器应用关联,可以实现容器的动态伸缩。Marathon 框架本身会提供故障自愈这个功能,平安经常会做一个静态的页面,当使用 HTTP 协议访问该页面时,会返回一个设定好的字符串, 如果不是这个字符串,则会被认为是访问异常,此时就会将原有容器删除,之后进行重启。资源隔离是基于 Mesos 的资源管理所做的,在后台物理机或者是虚拟机上打上标签,当进行资源分配时,不同的资源自然就会落到其所对应的不同的服务器上。平安有很多保险公司,而监管的要求是必须进行物理隔离,因此要进行资源隔离。对于事件驱动而言,在 Marathon 做容器的任何起停时,都会同时在Marathon 有 event 生成,可将自身的 API sever 注册到 Marathon 的 上 ,之后监听所有的 event ,根据返回的所有 event 进行解析,并做一些相应的任务下发。

集群模式的选择确定了,接下来就是如何解决跨 Host 之间的通讯功能问题。平安存在一些历史性的遗留问题,一是容器没有独立的 IP,无法与容器集群外面的服务器进行通讯,当时采用的解决方案是做独立 IP;二是由于没有 IP,所以也不存在 DNS ,这样就无法实现跨安全区域,平安的域名很多都是通过 DNS 做负载的,所以 DNS 不可或缺;其次是负载均衡和共享存储的问题。下面是就独立 IP 和 DNS 的解决方案详述。图5


图 5


首先是关于独立 IP 的几个问题(图5):


EJB 逻辑,共享存储,传统的共享存储使用的是 Nas,Nas 则基本上都需要用到独立 IP 做二层进行对接 。

组播与 HA,不论两个容器在不在同一个物理机上,都要保证它们之间的组播相通。

要与传统环境对接,因为不能将所有系统都搬到平台上面来。要与传统环境进行对接,必须与平台外的服务器应用做通信,这就需要独立 IP 。

用户操作习惯,用户需要登录主机查看日志,配置等相关信息。因此不仅要在物理机上登录,也需要在容器上登录,所以独立 IP 也发挥了很大的作用。图6.1


图 6.1图6.2


图 6.2图6.3


图 6.3


什么是 EJB 逻辑?EJB 当中存在一个 Cluster 的概念(图 6.1),假设 Cluster 中有三台服务器,2.1 、2.2 、2.3 ,三台服务器上都做了容器,当 Container 端对他们进行访问时,首先都会通过 T3 地址来调用(这里没有域名,所以选用的是 IP,在三个 IP 里随机取一个,这里取 192.168.2.1)。首先,会发出 EJB Create Request 请求(图 6.1),之后 2.1 会返回一个集群信息 Return Stub message (图 6.2)给 Client,并告诉 Client 这个集群中间有哪些服务器,之后 Client 这边会再发出 EJB Channle Create 的请求(图 6.3), 此时不管集群中有多少服务器,都会建立 EJB 长连接。


图7


图 7


在 Padis 平台的初始版本中,没有独立 IP,容器与外面通信是基于端口 Mapping 的方式实现,这样EJB 逻辑就会如上图(图 7)。这样就出现了一个问题,假设容器里的地址是私网 IP:172.17.0.2(外部不可见),而宿主主机的 IP 是 192.168.2.2,当请求发到这里时,因为 172 的 IP 对外不可见,所以只能够连接到 192(物理机)的 IP ,再通过对物理机进行端口 Mapping 的方式来获取 172 的 IP (这是在组播通的情况下,会返回 172 的 IP )。可是,即便是获取了 172 的 IP 地址,依旧是不能与外部建立连接的,因为 172 的 IP 对外是不可见的,所以导致容器也不能进行连接,因此要求它必须有独立的 IP 。这里有一点要强调,Docker 不支持 overlay。


图8


图 8


图 8 是平安对 Padis Network 的一个简单描述。图左侧的 API Server(基于 Python) 主要包括 Message Center 和 Network,Message Center 会注册到 MM 框架当中,接收 Marathon 框架的所有 event ,用来进行分析处理,右侧从上到下依次是 MM 框架、计算节点(物理机中装了 Openvswitch,在上面起容器)、自己设计的网关服务器(基于 Linux 服务器上和 Iptables 实现)。 整个过程如图 8 所示,Message Center 收到 event 消息后,获取容器创建,删除,重启等动作的 event,通过基于 Ansible 搭建的任务分发平台把相应的动作下发到响应的服务器上。


图9图 9


图 9 是 Docker 宿主主机实现的简单示意图。首先所有的物理机/虚拟机(用 trunk 实现了物理机里面跑所有 VLAN 的容器)的物理网卡都要通过 Openvswitch 加入到 ovs0 中,启动容器后用Pipework 给容器指定一个 IP、网关、VLAN,这样就可以实现 WEB 通信。宿主主机的 IP 是 10.30.1.11 (第一版用的是双网卡,其中 eth0 是管理网卡,eth1 是宿主主机的网卡,容器启动后会和它进行 mapping),在这里必须记住要给容器加路由,否则会由于Marathon自身的故障自愈功能,导致不可访问。当然,此时也可指定相关命令,自动下发的对容器里的路由进行调整。


在这些里面,IP 是一个很重要的概念,所以,接下来介绍一下 Padis 平台的 IP 管理。


对于 Padis 的 IP 管理有以下几点:



  1. IP 地址池可以在用户创建资源池时,动态的生成网段信息。

  2. 网段生成时,可以自动在 Gateway 上配置网关和 VLAN 信息(生产环境取消了 Gateway )

  3. IP 状态设置增加为三种:预留、已分配和未分配。

  4. 故障自愈是指,容器和 IP 本来是绑定在一起的,但是,将容器删除后该 IP 也会随之删除。

  5. 一个容器一个 IP,共享存储走三层路由。


图10


图 10


刚刚上面讲的是对 IP 的诉求,下面介绍平安关于 DNS 的需求。


平安的 DNS 安全区域架构主要分三种(图 10):WEB 层(做展示,WEB || 提供给内部员工使用,DMZ 给公网或者合作伙伴使用)、SF 层(应用逻辑层) 、DB 层。在三层架构时 ,DMZ 上要求做双向的 NAT ,即在 DMZ 上所看到 SF 的 IP 地址不是真实的,在 SF 上看到 DMZ 的 IP 地址也不是真实的。 做分布式协调的时候,也会存在这样的问题,跨安全区域时,因为做了 NAT,你所看到的地址,并不是真实,可以进行访问的地址。这样一来,在对外提供服务时,你需要去给人家提供 IP 地址,才能让人家进入,这样会导致用户体验非常不好。 对于应用层,会经常出现跨域的问题,所以域名是必须要有,且必须要一致,还有就是平安内部会有一些应用需求,比如要做单点登录( SSO ) ,它是基于域名做的,所以也要求系统必须有域名。


对于 LB( Load balancing ),根据收集到的需求和历史经验做以下分析:一是软件负载均衡,对金融公司来说,负载均衡的要求是非常稳定的,不能出事,软件负载均衡的可靠性和性能不好,所以不被认可;硬件负载均衡的性能肯定是要高于软件负载均衡的,可是也存在相应的问题,硬件负载均衡的成本相对很高,部分系统的用户量没有必要用硬件负载均衡。


针对 LB 的这 几种情况,平安提出了三套方案:



  • 软件负载均衡 HAProxy

    基于容器,在容器上面搭建一个 HAProxy。


优点:可以实现基本功能、新版的可以做应用路由(可以根据不同规则,向不同应用上分发路由)、动态更新配置(通过 API 更改配置文件然后进行 Reload)。


缺点:高并发能力比较弱、SSL 卸载能力差。



  • 软件负载均衡 Lvs+Nginx LVS+Ospf 调度机自由伸缩,自由扩展(最大 8 台,受限于网络设备允许的等价路由数目);一个 LVS 后端可以搭建多个 Nginx。


优点:并发能力比较高、可以很轻易的完成动态配置更新、SSL 卸载能力好( LVS 可以搭建多个 Nginx,Nginx 多了,卸载能力自然有所提升)。


缺点:后端 Nginx 发生频繁变化时(例如由 10 个变成 20 个),当进行等价路由算法时,此时便会发生路由抖动。



  • 硬件负载均衡 LTM

    做了自动化配置开发、做了动态接口配置。


缺点:本身扩展能力不好、成本高。


测试环境 Padis 上线图11


图 11


图 11 是基于以上问题,搭建出来的一个测试环境框架。首先提供给用户看的是 Portal(基于 JS 写的),下面的 API 是基于 python 写的。接下来是 MM 框架,Log 是日志云,Log 旁边是认证模块和硬件负载均衡 LTM 。 图中红色那块就是仓库,开发环境时所用的镜像全部在仓库里面,镜像中包括用户认证配置、基础环境的调优等等,仓库下面是存储,存储主要用 Nas。现在的容器支持虚拟机和物理机的运维理念与开发不同,节点越少越好,这样故障点也会越少,所以平台的主要计算节点大部分是物理机。最后,在网络模块( Network )上设置了 Gateway 。


图12图 12


图 12 是一个逻辑示意图。首先从 Potal 进入,调用 API 创建网段或者应用 ,API 分为认证、DNS、Traffic( LB )、Network 、Cache 这几个模块,当时的想法是将数据库也一同打包进来,但是由于平安的库太大(动辄几个 T ),所以就放弃了这样的想法。 Padis API 可以进行用户认证、DNS 的增删改。从图 12 可见,所有模块彼此相互独立,所有系统都是通过 Portal 进来,并发送请求到 API,API 根据不同的请求做相应的操作,所有的操作会直接发送给Marathon框架,Marathon 框架也会根据事件再给 API 相应的反馈,API 同时也会根据反馈结果再做相应的操作。


生产环境 Padis 上线


与测试环境相比,对生产环境的要求是很高的。对于生产环境,主要做了以下几点改造:



  1. 测试环境的性能达不到要求,稳定性有问题,于是取消 Gateway Server ,生产环境中 全部改用网络设备。

  2. CMDB,测试环境是自己独立的,生产的要与传统的 CMDB 对接,数据需要写入传统的 CMDB 里面去,所以需要开发 CMDB 接口,进行数据导入。

  3. 监控告警。需要搭建 Zabbix 监控平台,对接传统的监控平台。

  4. 性能数据收集。在做故障分析时,都是基于对性能数据的分析,然后得出结果,并且要根据性能数据, 对容量进行判断,比如是否要做一些动态的扩容缩容(关于扩容缩容最初的想法是做成自动化的,但存在的问题是,如果做成自动化,当别人攻击时,后台资源则不一定能扛住)。

  5. DNS 改造。对接生产网络的 DNS,实现动态更新 DNS(在这个地方专门写一个 DNS 模块,跟平安的 DNS 对接,内部的 DNS 会做一个节点,在上面做单独配置,所有的配置更新都在里面做)。

  6. 日志存储。测试环境用的是 Ceph,没有用到本地磁盘,把所有空余的物理磁盘做了一个Ceph,但测试时用的 Ceph 是不成熟的,所以改成了 NAS,同时将日志接入到日志云里进行分析、处理和归档。


图13图 13


经过以上几点改造,生产环境框架就变成如图 13 这样(添加了 CMDB 模块)。


Padis 承接平安金融管家系统群


平安 Padis 在今年上半年的时候承接了平安金融管家(原平安人寿)系统群,当时系统群所运用的平台,就是 Padis 平台。


传统环境的搭建,从 0 到上线最快 3 天,可是 Padis 却完成了系统从 0 到上线只用 5 分钟这个过程,当中还包括所有的调试环节。Padis 当时做了一个互联网出口,还有一个 LVS + Ospf 的改造,并且同时由 50 路 Nginx 和多路 LVS 提供服务。因为当时所有的配置都是标准化的,只需将包上传,之后立马就能使用,所以耗时短。那也是 Padis 在生产环境的第一次亮相,经过这一次之后,总结出了一个经验:隔离集团和其他系统的相互影响,不能因为搞活动而影响系统的正常运行。