腾讯万台规模的 Docker 应用实践

阅读数:16834 2015 年 3 月 19 日

话题:QCon腾讯语言 & 开发架构

Docker 提供了一种在安全、可重复的环境中自动部署软件的方式,拉开了基于云计算平台发布产品方式的变革序幕。腾讯内部对 Docker 有着广泛的使用,其基于 Yarn 的代号为 Gaia 的调度平台可以同时兼容 Docker 和非 Docker 类型的应用,并提供高并发任务调度和资源管理,它具有高度可伸缩性和可靠性,能够支持 MR 等离线业务。为了剖析 Docker on Gaia 背后的实现细节,InfoQ 专访了腾讯数据平台部高级工程师罗韩梅,另外作为 QCon 全球软件开发大会的讲师,罗韩梅将会分享题为《Gaia——万台规模的 Docker 应用实战》的演讲。关于 Docker 的交流讨论,也可以加入我们的 QQ 群:124378115。

嘉宾介绍

罗韩梅,腾讯数据平台部高级工程师,任数据中心资源调度组副组长。2009 年加入腾讯,主要从事统一资源管理调度平台的开发和运营,承担过腾讯自研云平台“台风”中 Torca 资源调度子系统的研发,目前主要专注于开源技术、分布式数据仓库、分布式资源调度平台、Docker 等领域。

InfoQ:能否介绍下目前 Gaia 平台的状态?你们什么时候开始使用 Docker 的?有多大的规模?

罗韩梅:Gaia 平台是腾讯数据平台部大数据平台的底层资源管理和调度系统,其上层业务包括离线、实时以及在线 service 服务,如 Hadoop MR、Spark、Storm、Hive 以及腾讯内部的 Lhotse、Hermes、广点通等业务。最大单集群规模达 8800 台、并发资源池个数达 2500 个,服务于腾讯所有事业群。我们是 2014 年 10 月份正式上线 Docker,之所以选择 Docker,一方面是因为 Gaia 本来就一直在使用 cgroups 类型的容器,深知其在共享机器资源、灵活、轻量、易扩展、隔离等方面的重要意义。另一重要原因,是 Gaia 作为一个通用的云操作系统,适合所有类型的业务,但是各个业务的环境依赖是一个比较困扰用户的问题,因此我们引入 Docker 来解决,主要目的还是通过 Docker 来将 Gaia 云平台以更有效的方式呈献给各个业务。

我们使用的 OS 是腾讯内部的 tlinux 1.2 版本,最新版本正在 tlinux2.0 上测试,除了 Docker,也使用了 etcd 用来做服务注册和服务发现。我们的集群都是同时兼容 Docker 应用和非 Docker 类型的应用的,MR 等应用还是使用的 cgroups 类型的容器,其它服务使用的 Docker 容器,目前,大概有 15000 多常驻的 Docker 容器,还有大量业务接入测试中。由于我们原本就是使用的 cgroups 容器,所以换成 Docker 后,性能基本也无损耗,可以满足线上需求。

InfoQ:腾讯是如何把 Yarn 与 Docker 深度结合的?

罗韩梅:在腾讯的场景下,首先一个特点就是,业务总类极大,尤其是离线处理规模很大,因此 Yarn 原生的调度器,效率远远跟不上,因此我们开发了自研调度器 SFair,解决了调度器效率和扩展性问题。另外,腾讯的业务特性多样,因此我们引入了 Docker,虽然 Yarn 支持不同的应用类型可以实现不同的 AM(应用管理器),但是对于绝大多数应用来说,他们并不熟悉 Yarn,实现一个支持容灾、可扩展的完善 AM,困难较大,因此我们抽象了可以使用 Docker 的业务,对其进行封装,实现了统一的 AM,并且对用户透明,而对用户提供的是另一套全新的基本的、易于理解的高级接口。同时,我们为 Docker 业务实现了统一的服务注册和发现机制,并也将其封装在了新接口中。另外,在资源管理方面,我们修改了内存管理机制,引入了磁盘和网络带宽管理。

除了 Yarn 之外,其实我们对 Docker 本身也做了一定的修改和 bug 修复,对于 Registry 等服务也做了优化,保证了其服务的高可靠和性能。

实现方面,我们并没有使用社区提供的 Docker 调度器,我们研发 Gaia 的时候社区还没有相应的调度器,并且我们也有特殊要求,需要同时支持同时支持 Docker 类型应用和非 Docker 类型应用。

InfoQ:你们如何确定哪些业务适合使用 Docker?

罗韩梅:我们认为,Docker 提供了一种在安全、可重复的环境中自动部署软件的方式,拉开了基于云计算平台发布产品方式的变革序幕,因此,其实 Docker 对于 Gaia 来讲,只是一个选择,我们并不主动向业务推广 Docker,而是 Docker on Gaia 的整套方案,所以,我们对于需要共享资源、降低成本,需要支持快速的动态扩容缩容、容灾容错,以及大规模分布式系统尤为建议使用 Docker on Gaia。

InfoQ:能否详细介绍下你们对 Docker 以及 Registry 做了哪些优化?

罗韩梅:对于 Docker,我们主要做了三个方面的优化:首先是 bug 修复,比如 Docker 非 0 退出时 rm 不生效,对于 bindmount 为 true 时 config path 无法清除等 bug。其次是优化 Docker 的资源管理策略,比如内存的 Hardlimit 的管理策略,不但使用户进程容易被 kill,更加造成了资源的浪费,对用户估计自己业务的资源需求也非常高。Gaia 引入了 EMC(Elastic Memory Control)的弹性内存管理机制。最后一个方面是资源管理纬度,Docker 在资源管理纬度方面只有 CPU 和内存两个维度,这对于共享的云环境下需要完善,也是目前相对于虚拟机不足的地方。Gaia 引入磁盘容量管理,网络出入带宽控制以及磁盘 IO 的控制维护。其实不仅仅在 Docker 层做控制,还将会引进调度器,不但实现资源的隔离,还要实现资源的保证。

对于 Registry 的优化,主要有下面几个方面:

  1. 容量问题。开源的 Registry 是单机模式,其容量会受单个机器的限制。我们修改存储 driver,取缔原有的 mount 方式,开发后端存储 driver,直接使用 HDFS,实现了存储的无限容量。
  2. 可靠性和可用性的问题。单机版本的 Docker Registry,其可靠性和可用性都成了最大的问题,我们引入数据平台部的 tPG 系统,实现 Registry server 的无状态化,便于实现服务的高可用性。
  3. 性能问题。将单机版的 Registry 扩展成 Registry 集群,并实现在 Registry server pool 中的负载均衡,提升性能。
  4. 网络问题。解决了全国不同 IDC 的 Gaia 集群对 Registry 的访问,采取就近访问的原则,不产生跨 IDC 流量。
  5. 自动同步官方镜像。Docker 提供的官方镜像中,有很多还是非常有价值的,而官方的 Registry 又在墙外,为此,我们自动同步 docker 的官方镜像到我们的私有仓库中。

InfoQ:能否介绍下目前的一个 workflow?

罗韩梅:目前使用 Docker on Gaia 的方式有三种:1)通过 Gaia Portal;2)直接调用 Gaia api;3)通过上层各种 PaaS 平台透明间接使用 Gaia。比如在第一种方式中,用户通过 Gaia Portal 提交应用,之后 Gaia 调度器会自动分配资源,并且部署、启动 Docker 容器,用户可以在 Portal 上直接查看每个实例的状态、日志、异常等,甚至可以直接通过 webshell 登陆。同时,也可以根据需求对应用进行扩容、缩容、重启,以及灰度变更、停止实例 / 应用等操作。

InfoQ:目前平台主要部署了哪些服务?服务之间的调度是如何实现的?

罗韩梅:目前平台上的服务有 Hermes、通用推荐、广点通、游戏云等服务,很多服务都需要多实例部署,因此跨主机部署非常普遍,而不同服务直接也经常会有调用的需求,主要是通过 Gaia 提供的服务注册和服务发现机制。具体地,NM(Yarn 的一个组件)在启动 Docker 容器时,会将该 Docker 的真正地址,包括 ip 和所有的端口映射,都会通过 etcd 做自动的服务注册。对于 Docker 内部的服务,我们通过修改 Docker 源码,扩展了几个 Gaia 相关的环境变量,将 IP 以及端口映射传入。服务的注册和发现本质上一种名字服务,因此不难理解为什么在创建应用的时候,让用户填一个应用 name 的字段。而这种基于名字的服务是贯穿这个 Gaia 的过程的:在提交作业时,用户不需要指定 Gaia master 的地址,而是通过指定 Gaia 集群的 name 即可;在获取应用的地址时,也是通过应用的名字获取;本质上 port mapping 也是一种名字,只不过是将用户原来 expose 的端口作为 name,将实际端口作为 value。至此,不难理解为什么 name 需要检查冲突。

InfoQ:万台规模的 Docker 容器,网络问题是如何解决的?

罗韩梅:网卡及交换链路的带宽资源是有限的。如果某个作业不受限制产生过量的网络流量,必然会挤占其它作业的网络带宽和响应时延。因此 Gaia 将网络和 CPU、内存一样,作为一种资源维度纳入统一管理。业务在提交应用时指定自己的网络 IO 需求,我们使用 TC(Traffic Control)+ cgroups 实现网络出带宽控制,通过修改内核,增加网络入带宽的控制。具体的控制目标有:

  1. 在某个 cgroup 网络繁忙时,能保证其设定配额不会被其他 cgroup 挤占;
  2. 在某个 cgroup 没有用满其配额时,其他 cgroup 可以自动使用其空闲的部分带宽;
  3. 在多个 cgroup 分享其他 cgroup 的空闲带宽时,优先级高的优先; 优先级相同时,配额大的占用多,配额小的占用少;
  4. 尽量减少为了流控而主动丢包。