百亿级数据处理量的弹性调度容器平台
七牛云数据处理团队的容器技术实践经验
一、数据处理业务场景
首先介绍一下七牛数据处理业务的背景。七牛云目前平台上有超过 50 万家企业客户,图片超过 2000 亿张,累积超过 10 亿小时的视频。 用户把这些图片和视频存储在七牛上后会有一些数据处理方面的需求,如缩放、裁剪、水印等。
这些文件持续在线且数据种类多样,如果用户把这些文件在自己的基板上处理好后再上传到七牛,是非常不合算的事情。而七牛最先提供基于存储的数据处理功能方便用户去做数据处理,这些数据处理通常放在企业的客户端或服务器端来操作,对接上七牛云存储的数据处理接口后,即可对图片和音频进行丰富的实时转码功能,转码生成的新规格文件放在七牛提供的缓存层供 App 调用,不用占用存储空间,对企业来说不仅成本大大降低,还可提高开发效率。
下图为一个图片裁剪的数据处理示例:
七牛的文件处理程序简称 FOP(File Operation),不同的文件处理操作使用不同的 FOP。用户只需上传一个原文件就可以通过使用七牛的数据处理功能得到各种样式丰富的文件。下图为文件从上传存储到处理到分发的流程图:
二、海量数据处理平台的挑战
七牛云的海量数据成就了 Dora 十分强大的数据处理能力,目前七牛的数据处理服务已经日处理数近百亿次。面对这样海量的数据处理请求,原有的数据处理平台也面临着新的挑战:
- 日均请求量百亿级,CPU 密集型计算
目前系统每天有近百亿的数据处理请求量,拥有近千台的计算集群,整个存量、增量都非常大。而数据处理集群中绝大部分的机器都是用来跑图片、音视频转码的,这些都是 CPU 密集型的计算,这意味着后台需要很多台机器,而且 CPU 的核数越多越好。在年底数据处理平台可能会在目前近千台的计算集群基础上翻好几倍,需要有快速物理扩展和高效智能管理的能力。 - 服务器负载不均衡,资源利用率不高
实时在线处理的业务处理时间短,但是量大,需要大量的实例来应对高并发的情况。而异步处理的业务处理时间长,也需要分配足够的资源来。当实时业务并不繁忙而异步处理业务增长时,并不能使用分配给实时业务的资源, 这种静态资源分配机制带来的分配不合理问题,导致服务器负载不均衡,资源利用率不高。 - 突发流量不可测量, 大量冗余资源
在新接入用户并不能完全正确的预测请求量,原来的模式是通过快速扩容机器并验证上线,需要一定的处理时间,对于这种非计划内的请求量需要准备大量的冗余资源来应对突发流量。 - 集群负载过重,不能自动按需扩展
个别用户突增数据处理请求时导致集群负载压力过大,CPU 处理变慢, 请求时间变长,请求任务堆积,影响其他业务,并不能在现有的资源基础上进行快速扩展,也不能根据实际的业务压力进行按需自动扩展集群实例。 - 用户自定义应用(UFOP)质量及规模未知
七牛除了提供官方的数据处理服务,也支持客户将自定义数据处理模块部署到七牛云存储的就近计算环境,避免远程读写数据的性能开销和流量成本,满足用户多方位的数据处理需求。但是各种 UFOP 运行在同一个平台上就可能会存在部分 UFOP 的质量问题或请求量过大而分配的资源不足导致影响平台上其他服务的正常运行。
三、自研容器调度系统介绍
为了解决以上问题,七牛基于资源管理系统 Mesos 自主研发了一套容器调度框架(DoraFramework),通过容器技术打造了易扩展、易部署、高自由度的数据处理平台 Dora。整体架构图如下所示:
各组件介绍:
- Mesos:由 ZooKeeper、Mesos Master、Mesos Agent 构成了基础的 Mesos 数据中心操作系统,可以统一管理机房中的所有物理机,负责资源层面的调度,是二层调度系统最基础的运行环境 。
- DoraFramework:业务层调度框架,通过 DoraFramework 使用 Mesos 管理所有的物理机资源,完成业务进程的调度与管理。
- Consul:包含服务发现,健康检查和 KV 存储功能的一个开源集群管理系统,DoraFramework 调度系统使用 Consul 的服务发现和健康检查机制提供基础的服务发现功能,使用 KV 存储功能来存储 DoraFramework 的 metadata。
- Prometheus:一个开源的监控系统,实现机器级别,容器级别及业务系统级别的监控。
- Pandora: 七牛的内部的日志控制管理系统,负责生产环境所有日志的汇聚及处理。
在这个架构中,我们选择通过容器技术实现跨机器实现弹性的实时调度。调度框架可以根据具体的业务负载情况动态的调度容器的个数, 很好的解决了静态配置导致的资源利用率不高的问题 。而容器秒启的特性也解决了当有大量突发请示进入,可以快速启动服务的问题。在网络方面,由于 UFOP 是用户部署运行的服务,并不知道用户是否有开启其他的端口使用,所以使用的是 Bridge 模式,需要对外使用端口的都需要通过 NAT 进行暴露,这样服务内部使用了什么端口并不会对外界环境造成影响 ,对平台环境做了非常好的安全隔离。
数据处理平台的调度系统我们选择的是 Mesos 自研容器调度框架(DoraFramework)。选择 Mesos 做为资源管理系统一个是因为 Mesos 的相对其他的容器调度系统更成熟,Kubernetes 是 2015 才发布可生产环境运行的版本,Docker Swarm 则是 2016 年才发布,这两个产品的生产实践在调研时基本还没什么大型生产实践经验,而 Mesos 则已有七八年的历史,且资源管理方面已经在如苹果,Twitter 等大型公司得到生产实践,稳定性比较好。
第二个是因为 Mesos 支持调度成千上万的节点,以七牛目前已经达到近千台物理机的规模,且每年都在大幅度增长的情况,Meoso 这种支持超大规模调度的资源管理框架更合适七牛的业务发展。
第三是因为 Mesos 的简单性,开放性及可扩展性,Mesos 是一个开源的分布式弹性资源管理系统,整个 Mesos 系统采用了双层调度框架:第一层由 Mesos 收集整个数据中心的资源信息,再将资源分配给框架;第二层由框架自己的调度器将资源分配给自己内部的任务。Mesos 自身只做资源层的管理,这种简单性带来的则是稳定性。而容器的调度框架则可以使用开源框架如 Marathon/chronos 或自主研发。Kubernetes 虽然功能很丰富,但是也比较复杂,组件及概念都比较多,并且缺乏开放性和可扩展性,只能使用它提供的调度功能,而不能根据自身业务的情况定制调度框架,会造成对 Kubernetes 过于依赖的情况。
为什么不选择 Mesos 的核心框架 Marathon 而选择自研,出于三方面的考虑:
1. Marathon 有些方面不支持我们期望的使用姿势,比如不太好无缝对接服务发现;
2. Marathon 采用 Scala 开发,出了问题不好排查,也不方便我们做二次开发;
3. 如果选用 Marathon 的话,我们上面还是要再做一层对 Marathon 的包装才能作为 Dora 的调度服务,这样模块就会变多,部署运维会复杂。
DoraFramework 是七牛使用 Go 语言自研的容器调度框架。DoraFramework 实现了 Mesos 两层调度中业务进程的调度,是 Dora 调度系统中的核心组件,通过与 Mesos 和 Consul 组件之间的交互, 对外提供 API 接口。架构图如下:
DoraFramework 主要功能介绍:
- 自动化应用的部署
- 服务注册与发现
- 弹性调度容器数量
- 负载均衡
- 支持在指定机器上增加或减少实例
- 支持高可用
- 应用的版本和升级管理
- 支持获取实例的状态及日志数据
- 支持业务级别的监控
- 支持实例的故障修复
DoraFramework 与 Marathon 调度架构的对比:
- DoraFramework 调度系统的服务注册与发现使用 Consul 实现, Consul 是用于实现分布式系统的服务发现与配置,支持跨数据中心的内部服务或外部服务的发现, 对外提供 DNS 接口,而 Marathon-lb 并不支持跨数据中心的服务发现。
- Marathon 是通过 Marathon-lb 所在节点的 servicePort 服务端口或 VHOST 来发现服务 ,要求网络模式必须为 Bridge。因为 Marathon-lb 还负责负载均衡的功能,在大型的业务环境下,如果 Marathon-lb 出现异常,则会影响框架正确的服务发现。
- Dora 调度系统可以做更精确的弹性调度。因为它不仅支持做资源使用层面的监控,还支持做业务级别的监控,在对实例进行调度时就可以根据实际的业务压力进行调度。
- Dora 调度系统内的负载均衡组件是通过从 Consul 中获取到所有的可用实例的地址进行负载分发,并可以根据每个实例的业务负载情况进行更精确的分发。而 Marathon-lb 并没有业务层的监控数据。
- Consul 提供系统级和应用级健康检查,可以通过配置文件及 HTTP API 两种方式来定义健康检查,并支持 TCP、HTTP、Script、Docker 和 Timeto Live(TTL)五种方式做 Check。Marathon 的默认的 Health Checks 只检查 Mesos 中的任务状态,当任务为 running 时,就被认为是 health 状态,这样不能做应用级的健康检查。Marathon 通过 REST API 可以查看应用的健康状态, 但只支持 TCP、HTTP 和 Command 三种方式。
- Dora 调度系统提供的监控栈在业务进程运行过程会汇总采集业务运行状况指标,如请求次数,请求延时等信息,业务进程对外暴露一个标准的 http 监控接口,监控接口的数据产出符合 Prometheus 监控数据格式。Prometheus 通过配置 Consul 作为服务发现地址,会从 Consul 中获取需要收集监控数据的业务进程列表,从业务进程暴露的 http 监控接口 pull 监控数据。
我们使用 Consul 做注册中心,实现服务的注册与发现。Consul 自带 key/value 存储,可通过 DNS 接口做服务发现,且具体健康检查的功能,并支持跨数据中心的服务发现。API Gateway 可以通过 Consul 提供的 DNS 接口查询到服务所有的可用实例的列表信息,并将请求进行转发。
- 服务的自动注册和撤销
新增微服务实例时,采取的原则是等待实例为运行状态后将实例的访问地址注册到 Consul Client 的 Service Registration,并配置这个服务的健康检查,再将数据同步到 Consul Server 的服务注册表中。
对于减少实例时,采取的原则是先将实例从 Consul Server 的服务注册表中删除,等待冷却时间之后,再从通过调度系统将这个实例销毁。从而完成服务的自动注册和撤销。 - 服务发现
外在系统想访问服务时,可通过服务名称从 Consul Server 提供的 DNS 接口查询到当前服务在 Consul Server 中注册的所有健康实例的访问地址, 再将请求发送给实例。
四、海量数据处理平台实践
我们生产环境的配置管理采用的是 Ansible,Ansible 默认使用 SSH 进行远程连接,无需在被管节点上安装附加软件,可以批量系统配置、批量部署、批量运行命令等,非常适合七牛的大规模 IT 环境。而 Playbooks 是一种简单的配置管理系统与多机器部署系统的基础,使用非常简单,且具有可读性,非常适合于复杂应用的部署。我们通过 Ansible 可以实现数据处理平台的一键式安装和删除,新增和删除节点,还包括对组件版本的升级及回退,以及生产环境的批量配置修改等操作,简化了复杂的运维配置管理工作。
在实践中,选择一台主机做为中控机,安装 Ansible,再配置这台中控机与所有远程主机的 SSH 互信,再在中控机上配置 Playbook 文件,即可对多台主机进行批量操作。对于简单的操作,可执行如下命令:
$ansible-playbook main.yml -i hosts
在 main.yml 里编辑所有需要做的操作,在 hosts 文件里写入所有需求操作的主机 IP 地址,即可完成对 hosts 文件里所有主机的批量操作。而对于复杂的操作,则可通过编写 Playbook 进行配置。roles 里存放不同的角色任务,比如 Mesos Master 上执行的任务和 Mesos Agent 上执行的任务不同,则可放在不同的 roles 里,也可以把 Mesos、Zookeeper、Consul 放的不同的 roles 里。tasks 里则是 role 里具体执行的任务,handlers 则是 tasks 里触发执行的任务。template 则是模板文件,比如我们需要个性 Consul 的默认配置文件,可以修改后的配置文件放在这个目录下,在执行时用这个文件替换默认的配置文件。
在监控方面,数据处理平台拥有完整的监控体系,包括了主机监控,容器监控,服务监控,流量监控,日志监控。主机和容器的监控主要通过 Prometheus 的各种 Exporter 来做,采集到包括 CPU、内存、网络以及磁盘的实时使用情况,服务监控和流量监控则通过七牛自己的监控程序进行监控,可以监控到服务的状态、存活性、句柄数、及所有处理命令的请求数、失败数等。日志监控则是通过七牛内部的日志平台 Pandora 系统进行监控,包括收集系统日志,容器日志和业务进程日志。通过修改开源的文件收集器 Filebeat 的 output,将采集到的日志全部传送到七牛内部的日志监控系统 Pandora 进行日志监控。
监控数据显示如下:
以上就是七牛云数据处理平台基于容器技术实践的情况。目前七牛的数据处理平台具备零运维、高可用、高性能的数据处理服务能力,可让用户轻松应对图片、音视频及其他各类数据的实时、异步处理场景。七牛的数据处理业务系统不仅可以处理来自七牛云存储的数据处理请求,也支持来自非七牛云存储的数据处理请求,还可以直接处理来自七牛云分发 Fusion 的数据处理请求,用来提高 CDN 中间源数据的处理速度。而数据处理平台 Dora 则是一个开放的平台,不仅可以运行七牛自己的数据处理服务,也支持运行用户自定义的数据处理服务,并具备丰富的运维管理功能,可以使用户从繁杂的运维管理和架构设计中脱离出来,从而专注于实现数据处理单元。 七牛数据处理平台的业务支撑能力如下:
Q&A
Q:请问管理系统是基于什么开发的?这个系统会开源吗?
A:Dora 的调度框架是基本 Go 语言开发的。目前不会开源,但提供私有部署。
Q:刚开始看 Mesos 框架实现,请问自定义的 Scheduler 中如何调用自定义的 executor?
A:Schesuler 跟 executor 这个都是按照 Mesos 最新的 V1 版的 HTTP API 去做的,这个没有不兼容的问题,只是 Mesos Go 版本的 SDK 有些老旧,更新也比较缓慢,这个地方我们自己根据需要做了些更改。
Q:请问目前 Consul 集群是多大规模呢?有没有考虑 Consul 扩展的性能瓶颈呢?
A:Consul 是在每个 slave 节点上会有一个 Consul 的 Agent ,我们一个机房有 200 多台专门用于数据处理的机器,所以 Consul 的集群规模也就这么大,单机房。对我们当前来说不存在瓶颈,因为我们对 Consul 的使用的场景相对单一简单:作为 Metadata 的可靠存储,Metadata 的更新其实并不是很频繁,这个我们参考过别人做过的一些性能测试和我们自己的一些测试,性能是满足需求的。另外一个功能就是服务发现与实例的健康检查,健康检查是由运行在每个机器上的 Consul Agent 负责的,均摊到每个机器上,其实单个机器上的实例数不会特别的多,所以这部分也没有太大的压力。当然了,这个也是跟业务规模相关的,假定哪天 Consul 的扩展性成我们的问题了,也说明我们的业务量特别特别的大了,我们也是很期望这一天到来的。
Q:Dora 是否可以支持 MySQL 的自动伸缩扩容?
A:Dora 系统的应用场景还是运行一些数据处理命令这类无状态的服务。MySQL 这类系统不适合直接跑在 Dora 这个里面,如果期望 MySQL 跑在 Mesos 上面的话,需要自己实现一个专门针对 MySQL 的调度器,因为 MySQL 实例的扩缩容,实例故障的修复都有 MySQL 自身特定的需求。我们公司 MySQL 这类有状态服务的容器化是由公司另一个容器平台实现的。MySQL 的用的是 Percona XtraDB Cluster 方案,我们利用另一个容器平台的 API 写了一个 Percona XtraDB Cluster 的调度器,把 Percona XtraDB Cluster 的大部分运维操作在容器平台上自动化了。
Q:你们的 Ansible host 文件是动态生成的嘛?代码推送也是通过 Ansible 嘛?新增删除节点,以及回滚等操作是如何实现的?
A:最开始实践的时候不是动态生成的,其实我们是可以从 Consul 中获取到当前集群里面的节点和节点的一些简单的配置信息,后面有考虑从 Consul 里面拿节点信息,动态生成用于 Ansible 灰度的 host 文件。代码推送也是使用的 Ansible,如果能和外网连接的机器,也可以使用 GitHub。因为我们的 Playbook 的角色是通过组件区分的,新增删除节点只需要修改 Host 文件,把相应的节点加入安装或删除相应的组件。如回滚操作:
$ ansible-playbook rollback.yml -i hosts -e "hosts_env=XXX app_env=XXX version_env=XXX"
参数说明:
- hosts_env:表示要回滚的主机组,如 Master
- app_env:表示要回滚的组件,如 ZooKeeper
- xxx_version:表示要回滚组件的版本号,如 v1.0.1.20160918
Q:Dora的调度策略是怎么样的?可否简单介绍一下。
A:首先保证同一种数据处理命令的实例尽量均匀分散在不同的机器上,然后再是保证均衡每个机器上的负载。
Q:Prometheus 目前是单机的,数据量大了怎么办?Prometheus 的监控数据是存在 InfluxDB 吗?
A:目前我们是按业务拆分 server,数据量可以支撑。我们没有使用 InfluxDB,还是用的原生的 LevelDB。
Q:这么大文件量,你们在存储技术方面有什么特别的处理吗?怎么实现高性能和海量存储之间均衡?
A:七牛云存储的设计目标是针对海量小文件的存储,所以它对文件系统的第一个改变也是去关系,也就是去目录结构(有目录意味着有父子关系)。所以七牛云存储不是文件系统,而是键值存储,或对象存储。我们每个大文件都是切割成小文件存储下来的,元信息单独存放在数据库中,用户请求的时候通过业务层合并处理后返回。因此理论上磁盘只存储小文件,大文件存储和读取的性能主要在于文件切割和合并。
本文作者: 陈爱珍@七牛云布道师,更多云行业技术洞见请访问七牛云博客。