腾讯企业容器云平台技术解析


【编者的话】GaiaStack 是腾讯基于 Kubernetes 打造的容器私有云平台。它服务于腾讯内部各个 BG 业务,如广告、支付、游戏等。同时也为腾讯云的各行业客户私有云部署提供支持。本文将从自动化运维体系、多集群租户、网络模式等 13 个方面展开,具体阐述 GaiaStack 的技术点。

GaiaStack 的目标是支持各种类型的应用(包括微服务、DevOps 场景、大数据、有状态应用、AI 平台、区块链、物联网等)并从底层网络、存储、Docker、Kubernetes 以及部署、监控的产品化等各方面完善容器平台的企业级实现。
01.jpg

GaiaStack 应用场景

它提供了从代码构建到应用部署的全流程云容器服务,主要包括管理员的集群管理功能,以及用户应用的全部生命周期管理。
02.jpg

GaiaStack 产品功能

自动化运维体系

因为 GaiaStack 是私有云平台,需要将其全部的部署运维等工作交给客户以及服务商。这意味着平台的性质其实给开发人员提出了更高的要求,也就是他们需要在降低复杂度的同时提升平台的易用性。因此我们对 GaiaStack 的部署系统进行了产品化改造。GaiaStack 现在可以实现一键快速部署,通过 Web 页面的可视化操作对后台系统复杂组件进行自动化部署,这大大降低使用者的人力、学习成本。如下图所示,用户在页面上填上 license 之后,就可以一步步完成自动化安装(类似安装一个软件),如果遇上关键的步骤、进度和异常失败,它均会有提示。
03.jpg

GaiaStack 自动化部署

多集群多租户支持

企业内部通常会有多个 IDC、多个集群。而为了帮助企业更好地进行资源整合管理,GaiaStack 把所有 IDC 资源的管理划分成了三个层次:Global 层、IDC 层和 Cluster 层。
  • Global 层:Global 层是管理多 IDC、多集群的全局服务,有 Web Portal、Keystone、Docker Hub、Deployment、CI Server 等;
  • IDC 层:由于跨 IDC 和 IDC 内部网络情况存在非常大的区别,我们划分出了 IDC 层,供一个 IDC 的多个集群共享服务,包括 Docker Registry、etcd、Ceph、监控告警组件等;
  • Cluster 层:Cluster 层是一个个的 Kubernetes 集群,包括 Cluster 的 Master 和 Slave。


另外,在 Quota 管理中,为了实现对在线高优先级业务的资源保证,我们将 Quota 的层次改为 APP 级别,保障 Namespace 的 Quota 即便在集群最繁忙时也会有隔离与保证。

对于离线集群,我们在各个 Namespace 之间又实现了弹性的 Quota 管理,让各个业务可以在不同时段以不同使用率来使用整个集群的资源,提升集群的整体利用率。

在视图方面,我们对所有对象支持所有集群所有租户的统一视图,方便用户利用一个视图全方位把握所有集群的所有应用。
04.jpg

多集群多租户支持

全系统 HA、热升级

作为底层 Cluster OS,可用性至关重要。GaiaStack 对全平台所有组件都实现了 HA,并且保证集群的热升级特性。这里需要注意一点,社区版本的 GaiaStack 不一定保证跨版本之间的热升级。比如说,如果将 Kubernetes 从 1.4 版本升级到 1.9 版本,系统就会有很多变化:
  • Pod Hash 发生变化;
  • Container 名称发生变化;
  • 点分隔改为了下划线分隔;
  • 容器标签发生变化;
  • Pause 容器的标签 io.kubernetes.container.name=POD 改为 io.kubernetes.docker.type=podsandbox;
  • io.kubernetes.container.restartCount 改为 annotation.io.kubernetes.container.restartCount;
  • Cgroup 目录结构发生变化;
  • 新增了 Pod 层级。


平台上的应用势必会受到这些因素的影响(比如重启)。而 GaiaStack 实现了各种跨版本的兼容性,来保证企业级应用生产环境的应用不受任何影响。

另外,GaiaStack 同时面向腾讯内部和外部客户,我们的版本并不做区分,是完全一样的代码。新版本发布前,我们一定会事前在内部业务中测试它的运行稳定性,之后才会对外发布,保证私有云集群的安全可靠。

网络模式

存量业务往往要求 IP 端口固定,而微服务没有这些要求。相比离线业务,在线业务单台服务器的虚拟化比例较低,但是对网络性能的要求高。为支持这些不同的需求,GaiaStack 自研的 Galaxy 网络插件为用户提供两种网络类型:
  • Underlay 网络
  • Overlay 网络


Underlay 网络,即基于宿主机物理网络环境的方案。在这种方案下,容器与现有网络可以直接互通,不需要经过封包解包或是 NAT,其性能最好。但是它的缺点也很明显,就是普适性较差,且受宿主机网络架构的制约(比如 IP 可能不够用)。

Overlay 网络,即通用的虚拟化网络方案。这种方案不依赖于宿主机底层网络架构,可以适应任何应用场景,方便用户快速体验。但是它同样存在缺点:由于在原有网络的基础上叠加了一层 Overlay 网络,网络性能会因为封包解包或 NAT 有一定损耗。

在实现 Underlay 网络方案时,考虑到 GaiaStack 的应用场景不止局限于腾讯内部,它还涉及公有云场景和外部企业客户私有化场景,而每个场景的底层网络架构都很不一样,所以我们的 Underlay 方案不会对底层网络有入侵性。目前,我们支持了 Linux bridge/MacVlan 和 SRIOV,用户可以根据业务场景和硬件环境,具体选择使用哪种网桥。下面这两幅图就是生产环境使用 SRIOV 替换 bridge 网桥后带来的性能提升,CPU 使用降低约 1/3,包量反而增加了 6%。
05.jpg

性能升级 01

06.jpg

性能升级 02

我们通过实现 Kubernetes 调度器插件 galaxy-ipam 功能,支持存量业务使用 Underlay 网络 IP 不变的功能。图中 Floatingip 即指 Underlay IP。
07.jpg

网络模式

另外,我们开始就希望将在线和离线进行混部以节省服务器资源。事实上,我们也运营着这样的集群,所以网络的设计初衷就是不同的应用可以选择不同的网络模式,同一主机的不同容器可以选择不同的网络模式。

对于 Overlay 网络,我们调研了很多开源容器网络项目,发现其各有利弊。在综合考虑各方案的优缺点后,我们汲取了 Flannel/Calico 容器网络开源项目的优点,实现了基于 IPIP 和 Host Gateway 的混合方案。同节点的容器报文无桥接方式,利用主机路由表进行转发,避免跨主机容器访问时 bridge 的二层端口查询。二层相连节点的容器报文无封包,利用主机路由表进行转发,因为无封包所以性能最优。

跨网段节点容器报文利用 IPIP 协议封包,IPIP 外层额外包头仅 20 字节,开销较 VXLAN 50 字节更小,所以性能好于 vxlan。我们的方案提交到了 Flannel 官方,并被社区合并。下面的柱状图是在千兆网卡的环境使用 Netperf 对该方案进行的测试,图中长连接和短连接都是 64 字节。从图中可以看出 IPIP 和 Hostgateway 相比 VXLAN 带来 14% 到 40% 的性能提升。
08.jpg

Netperf 性能测试

在网络隔离方面,我们基于 Iptables 和 Ipset 实现了 Kubernetes 网络策略,为业务提供了细粒度的隔离能力。网络策略的设计如下图所示,它充分利用 Ipset 和 iptables multiport extension,减少了 Iptables 规则条数。
09.jpg

网络策略

全维度资源管理

Docker 和 Kubernetes 都默认支持 CPU 和内存管理,我们也将资源管理纬度扩展到全维度,包括 GPU、磁盘 IO、磁盘容量、网络 IO 等,以更好地保证在线离线业务可以共享集群资源。

很多业务都需要较大的本地磁盘空间,因此磁盘容量成为第一个扩展的资源维度。Disk Space 比 CPU、内存管理更复杂的方面是在多磁盘容量管理。在设计上,我们扩展 Scheduler 以避免多个决策中心。在对容量做控制时,采用 Softlimit + Hardlimit 的弹性控制算法,同时我们也考虑到了 Pod 的优先级。

Network IO 网络出带宽的管理比较成熟,TC + Cgroups 即可,并且可以做到弹性控制。但是对于网络入带宽却比较复杂,为此我们在内核中引入了 net_rx 模块。实现了以下设计目标:
  • 某个 Cgroup 网络繁忙时,能保证其设定配额不被其他 Cgroup 挤占;
  • 在某个 Cgroup 没有用满其配额时,其他 Cgroup 可以自动使用其空闲的部分带宽;
  • 在多个 Cgroup 分享其他 Cgroup 的空闲带宽时,优先级高的优先; 优先级相同时, 配额大的占用多,配额小的占用少;
  • 尽量减少为了流量控制而主动丢包。


10.jpg

GaiaStack 全维度资源管理

弹性伸缩

Kubernetes 为应用实现了很好的弹性伸缩机制,比如可以根据资源使用情况做自动的扩容和缩容。但在实际场景中,这还远远不够。因此 GaiaStack 对应用的弹性伸缩能力做了更多扩展,比如可以按照时间、周期来做自动的弹性伸缩,支持通过吞吐量、时延等指标对微服务进行扩容和缩容,支持自定义指标的弹性伸缩,支持对指定实例做定点裁撤等。扩容的实例版本可以和原来的版本有所不同。

Tapp 应用类型

应用管理方面, Kubernetes 帮助 Deployment、StatefulSet、Job 等应用类型各司其职,有条理地运行微服务、有状态服务和离线作业。这些应用类型看似美好,但是实际使用时会遇到各种各样的问题,比如 Deployment 无法支持按照指定的策略进行缩容;StatefulSet 的升级只能按标号顺序依次进行,且一个 StatefulSet 不能同时灰度两个以上的镜像版本;而支持离线的 Job 类型,Spark on Kubernetes 都没有用 Job 来运行。

腾讯内部很多业务都是存量业务,需要能按照运维人员的策略控制每个实例的状态,比如灰度升级场景与 StatefulSet 提供的灰度功能不太一样。根据业务需求,如果今天需要对某个联通 VIP 的业务实例进行升级,这个 VIP 下的业务实例的 ID 不一定是有序的。升级完一周后,如果运行稳定,再对其他 VIP 实例分批次进行升级,中间可能长时间维持运行多个版本的稳定状态。Statefulset 的功能无法达到这样的效果,所以我们开发了 TApp(Tencent App)的应用类型。

TApp 是利用 Kubernetes CRD 功能定义的扩展 API,TAppSpec 对 PodSpec 进行了封装,支持被指定的每个实例的 PodSpec 模版和期望状态。正是基于这样的设计,TApp 相比 Statefulset 的优势有:支持指定若干实例多次进行启动、停止、删除、原地灰度升级、回退等操作;灰度升级功能不只是修改镜像版本,甚至可以多加一个容器;单个 TApp 应用的 Pod 支持 N 个版本。此外 TApp 与 StatefulSet 应用类型具有一些相同点:Pod 具有唯一自增 ID、绑定单独云盘、迁移时数据盘跟随迁移。

在后来的推广中我们发现 TApp 不仅仅是腾讯的需求,很多企业都有类似的需求,因此我们现在称 TApp 为 “通用服务”。目前 GaiaStack 上运行的绝大多数任务,不论是在线服务,离线业务,都使用我们自研的通用服务类型。

丰富的云盘功能支持

Ceph 在云上存储方面,具有天然的优势,一方面是因为 Ceph 本身具有非常优秀的特性,另一方面,Docker、Kubernetes 等开源项目与 Ceph 形成了很好的结合。GaiaStack 团队的 Ceph 平台也在腾讯内部支持了各个 BG 共享存储平台,运营非常稳定。因此 GaiaStack 基于 Ceph 实现了云硬盘。

普通云硬盘

用户可以自己申请、维护云硬盘。他们可以提前将数据导入云硬盘,也可以由容器生成云硬盘数据,同一个云硬盘也可以作为状态保存媒介在容器间流转。云硬盘的生命周期完全交给用户去控制,并支持在线扩容。
11.jpg

普通云硬盘

内置云硬盘

除了容器云中普通云硬盘的场景,GaiaStack 还增加了内置云硬盘,即将云硬盘内嵌到 APP 中,不需要用户维护和关注,系统会自动为每个实例分配云硬盘。这种方法扩展了磁盘空间,也避免了在迁移时数据的丢失。用户程序可以像使用本地磁盘一样,不去修改原有业务逻辑,但是数据会被自动云化。
12.png

内置云盘

除了 RBD 类型的云硬盘,GaiaStack 还支持 CephFS 的共享云硬盘。

P2P 镜像服务

GaiaStack 的目标是支持成千上万的集群规模,这对镜像仓库的性能提出了要求。多个 Docker 客户端同时 pull image 会带来以下 2 个问题:
  • 流量大:每个 Client 的传输速度可达到 20M+/s,多个 Client 就可以占满 Registry 机器的网络带宽 ;
  • 并发请求多:Client 会同时请求多个 layer 的数据,请求数为:client 数 * layer 数。测试发现 1 台机器 pull 一个 1G 大小的 image 时间约为 1 分钟左右, 100 多台机器同时 pull 一个 1G 大小的 image 时间将会涨到 8 分钟左右。这是一个不可接受的事件。


面对这两个问题,大多数公司的临时解决方案都是提前 pull 这个 image 或基础镜像。但这会带来额外的运营成本,机器上能存储的 image 是有限的,而且它还会定期进行清理。因此,我们还需要找到更好的解决方案。

我们开发了带有 P2P 分发功能的 Registry,让节点之间可以传输 image 内容。我们在 200 台物理机上测试了在不同节点数和不同 image 大小情况下的 pull 时间,对比了原生的 Docker 和我们的 P2P Registry 效果。当 200 个节点同时 pull 1G image 时,Docker 均用时 571s,P2P Registry 用时 71s,可以看到 P2P Registry 的效果较 Docker 有显著提升。
13.jpg

全面监控、告警

运营是容器平台至关重要的一环。GaiaStack 对平台的所有组件都有监控和告警,保证平台在发生异常时,运维人员可及时发现。用户也可以对自己的应用自定义监控告警,并且随时修改告警策略。GaiaStack 同时支持事件和指标监控。

日志服务

日志服务其实是大部分容器平台都有的一环,GaiaStack 可以让用户通过三种方式来查看自己的 log:
  • 通过页面直接查看各个容器的 log;
  • 通过 WebShell 对 log 进行查看,并执行 Linux 命令;
  • 通过 GaiaStack 的日志系统来对 APP 的所有实例的 log 做全文检索和下载。


这些都无需用户修改自己的应用程序,上云的成本很低。最重要的一点,GaiaStack 将用户的日志管理与对本地存储管理结合起来,即日志和数据都自动纳入了 GaiaStack 的资源管理中。用户不必担心本地磁盘是否够用,以及计算节点是否会出现磁盘满的情况。

敏捷和 DevOps

DevOps 将开发、测试、运维整个产品研发流程标准化、自动化,从而提高整个产品的迭代效率。GaiaStack 与数字一体化团队合作,将腾讯内部的 DevOps 研发体系与容器化平台集成,实现编译、集成、打包、测试、发布的自动化,并自定义 DevOps 流水线。

支持 GPU 应用

GaiaStack 在对 GPU 的支持上做了很多工作,比如支持 GPU 的通用应用类型,镜像与驱动的分离,异构集群的精细化管理等。本节将重点讲两个方面:GPU 的拓扑控制和 GPU 虚拟化。

GPU 通信方式有四种,分别是 SOC、PXB、PHB 和 PIX,他们的通信代价依次降低,由拓扑关系决定。以下图为例,运行在 GPU-0 和 GPU-1 上的 APP 的运行时间会比运行在 GPU0 上和 GPU3 上小很多。因此,Gaia Scheduler 实现了 GPU 集群资源:访问代价树算法。该算法对 GPU 的拓扑关系进行感知,并且在调度中充分考虑拓扑关系。具体的实现可以参考我们即将在 The IEEE ISPA 2018 发表的论文《Gaia Scheduler: A Kubernetes-based Scheduler Framework》。
14.jpg

GPU 拓扑图

在 GPU 的资源管理方面。我们知道 NVIDIA 对单个 GPU 的共享有两种方式:VM 使用的 NVIDIA GRID 以及进程使用的 MPS Service。NVIDIA GRID 不适合 Kubernetes 的 Container Runtime 场景,MPS Service 未实现隔离,且对每个进程使用的 GPU 资源采用了硬限制方式,在程序运行中无法修改。分时调度也不是基于容器的资源请求。综上所述,GPU 是无法实现基于容器级的软件虚拟化的。而且由于 GPU 价格昂贵,实现 GPU 资源的容器级别的软件虚拟化具有巨大的意义。

实现 GPU 虚拟化有三个挑战:
  • Transparency(不对 Kubernetes 以及用户的应用程序做入侵);
  • 性能;
  • 隔离。


为了实现对 Kubernetes 的透明,GaiaStack 使用了 Device Plugin,来做 GPU 资源的发现任务、分配硬件资源、配置容器运行时环境。在具体实现中,引入了四个核心组件,GPU Manager、GPU Scheduler、vGPU Manager 和 vGPU Library。

如上图所示,GaiaStack 实现了双层资源管理。在主机层,GPU Manager 负责创建 vGPU。GPU Scheduler 负责为 vGPU 分配物理 GPU 资源。在容器层,vGPU Library 负责管理具体容器的 GPU 资源。用户的资源请求会通过 Manager 控制,但程序运行起来后,所有的数据读写就不再经过 Manager,最大限度减少 Overhead。我们选取了不同的深度学习框架进行测试,分别在物理机和容器内使用每一个框架运行 MNIST 应用,并测试执行时间,Overhead 都不超过 1%。具体的实现可以参考我们即将在 The IEEE ISPA 2018 发表的论文《GaiaGPU: Sharing GPUs in Container Clouds》。

结语

最后,我再陈述一下 GaiaStack 和社区版本的关系。首先,GaiaStack 会始终跟随社区,兼容 Kubernetes 的所有原生接口。其次,为了支持企业级的应用,GaiaStack 基于 Kubernetes,但也不同于 Kubernetes。第三,在架构上,除了 Kubernetes,GaiaStack 还有很多其他关键组件,包括开源组件和自研组件。最后,在特性上,我们会引入更多用户需要的特性。

原文链接:https://mp.weixin.qq.com/s/ApgZezIn4zfjAiTru8fgpg

0 个评论

要回复文章请先登录注册