腾讯会议,一款联合国都Pick的线上会议解决方案,提供完美会议品质和灵活协作空间,广泛应用在政府、医疗、教育、企业等各个行业。大家从文章8天扩容100万核,腾讯会议是如何做到的?都知道腾讯会议背后的计算资源已过百万核,如此体量的业务,如何通过云原生技术提升研发和运维效率,是一个非常有价值的课题。这里我将为大家揭秘腾讯自研上云容器平台TKEx在支持腾讯会议全量云原生化上云背后的技术。
TKEx平台是以腾讯云容器服务(Tencent Kubernetes Engine, TKE)为底座,服务于腾讯自研业务的容器平台。腾讯自研业务类型众多、规模超大,云原生上云面临的挑战可想而知。TKEx平台在腾讯自研业务上云的过程中沉淀的最佳实践和解决方案,我们将会在TKE中提供给客户。
在Kubernetes中,我们习惯把应用分为无状态和有状态两类,有状态应用主要指实例标识、网络、存储的有状态。腾讯会议的一些服务有如下特性:
这对Kubernetes管理这种有状态服务提出了更高能力和性能要求。TKEx平台抽象出业务特性背后的产品需求,在灰度发布、多集群工作负载管理、计算资源管理运营、Node稳定性等方面进行了增强和优化,沉淀出了通用的音视频业务容器编排能力。
StatefulSetPlus是我们2018年研发并投入生产的首批Operator之一,核心特性包括:
这里主要介绍为腾讯会议上TKE新增的两个发布能力增强:大规模自动分批灰度发布和ConfigMap分批灰度发布。
TKEx平台在原来StatefulSetPlus手动分批发布能力基础上,这次又开发了自动分批发布的特性,解决像腾讯会议这种大体量业务灰度发布的痛点。用户只要在发布时配置各个批次更新副本的百分比,比如第一批40%,第二批60%。StatefulSetPlus-Operator会根据Readiness探针完成情况,自动进行下一批次的更新,其原理如下。
StatefulSetPlus核心Field说明如下:
StatefulSetPlus对发布过程进行了精细化的监控,提供staus.batchDeployStatus
查询发布详细状态,这使得通过CI Pipeline发布变得更显示和可控。
Next
表示进行下一批发布,WaitToConfirm
表示等待确认该批次发布是否成功,Completed
表示所有批次均已确认发布成功。可在annotations加上platform.tkex/pause-auto-batchDeploy: "true"
来暂停自动分批发布和失败自动回滚。
在TKEx平台上,通过如下操作流程即可轻松完成自动分批发布。
腾讯会议最大的模块需要支持上万个Pods的灰度发布,这是前所未有的挑战。这一次,我们对StatefulSetPlus-Operator进行了优化,性能得到大幅提升。对于一万个pod的StatefulSetPlus,分5批自动升级,单批次2000个pod,不挂载cbs盘的场景,表现如下:
Kubernetes原生的ConfigMap更新是一次性全量更新到容器内的对应的配置文件,所以通过原生的方式更新配置文件是极其危险的事情。Kubernetes 1.18支持了Immutable ConfigMap/Secret,可以保护关键配置被误改导致业务受影响。业务对容器环境下配置文件的发布同样有着分批灰度发布的极高诉求。
于是我们给StatefulSetPlus赋予了分批发布配置文件的能力,提升了云原生场景下配置文件发布的安全性,原理如下:
方案概述:
spec.containers[*].image, spec.containers[*].resources(if inplace resources update feature enabled),spec.initContainers[*].image, spec.activeDeadlineSeconds or spec.tolerations(only additions to existing tolerations)
,因此需要修改kube-apiserver代码,使得允许update/patch volumes。为防止ConfigMap累积过多,影响etcd集群的性能,我们在自研组件
TKEx-GC-Controller
增加ConfigMap的回收逻辑,只保留最近10个版本的ConfigMap。
用户只要在更新Workload页面,选择手动分批或者自动分批更新,在数据卷选项重新选择新版本的ConfigMap即可。可以在更新业务镜像的同时也更新ConfigMap配置文件,或者只更新ConfigMap配置文件。
ConfigMap配置文件更新,需要容器内业务进程能watch到配置文件的变更进行重启加载或者热加载。然而有些业务当前并没有这个能力,因此TKEx在ConfigMap发布的入口提供配置文件更新后的ProUpdate Hook,比如业务进程的冷/热重启命令。
拒绝胖容器模式(把容器当虚拟机用)是TKEx平台的原则,如何使用镜像发布并且提供像进程重启一样的ms级业务抖动,这是腾讯会议容器化上云最有挑战性的需求之一。TKEx平台在灰度发布能力上已经做了长期的技术沉淀,上万个业务模块在使用,但当前能力仍无法满足这一需求,镜像预加载+容器原地升级的方案,仍与这目标差距甚远。
经过多个方案的设计、分析、测试对比,考虑通用性、云原生、发布效率多个因素,最终使用如下方案:
Pod里面有3个关键容器,它们的职责分别如下:
升级流程概述
以业务容器镜像从版本V1升级到版本V2为例,升级流程描述如下:
需要说明以下两点:
在多地域服务管理上,我们主要解决两个诉求:
TKEx提供了便捷的多地域多集群业务部署和业务同步升级能力。
TKEx平台的集群资源是所有服务共享的,各种服务混部在集群和节点中。各个产品都有自己的资源预算,平台接受各个产品的预算,然后根据自动生成对应的资源配额,以此控制各个产品在整个平台上的Quota。产品部署后,涉及到成本核算,平台会根据真实使用的资源量,以小时为时间计量粒度,跟踪统计每个业务产品下面各个Workload的资源使用情况。
Kubernetes原生用ResourceQuota来做资源限制,但是它与我们的期望相比存在如下问题:
基于我们对于业务产品的管理需求及期望,TKEx的配额管理系统须满足如下特性:
我们设计了一个DynamicQuota CRD,用来管理集群中各个业务产品的Quota,实现以上能力。
产品完成预算归属到TKEx平台后,平台将自动为产品增加对应的产品配额,自动修改DynamicQuota。用户可以在TKEx监控面板中查看归属产品的资源配额。
TKEx会以**核*时
**为业务使用资源的计量粒度进行成本核算,用户可以在TKEx监控面板中查看具体的各个Kubernetes Workload的详细资源使用情况。
随着集群规模和节点部署密度越来越高,集群平均负载超过50%,高峰期很多节点的负载甚至80%以上,一些稳定性问题开始显现,为此TKEx针对节点稳定性做了如下优化:
Node-Problem-Detector
(简称NPD)组件中增加了节点pids,file-max的监控,达到相关资源使用水位线时,会自动检测消耗pids和file-max最多的Container并上报,主动触发告警并对Container进行原地重启。以上几项能力都在NPD组件中实现,负责监控节点的工作状态,包括内核死锁、OOM频率、系统线程数压力、系统文件描述符压力等指标,做节点驱逐、节点打Taint等动作,并通过Node Condition或者Event的形式上报给Apiserver。
当前NPD组件会在节点中增加如下特定的Conditions:
Condition Type | 默认值 | 描述 |
---|---|---|
ReadonlyFilesystem | False | 文件系统是否只读 |
FDPressure | False | 查看主机的文件描述符数量是否达到最大值的80% |
PIDPressure | False | 查看主机是否已经消耗了90%以上的pids |
FrequentKubeletRestart | False | Kubelet是否在20Min内重启超过5次 |
CorruptDockerOverlay2 | False | DockerImage 是否存在问题 |
KubeletProblem | False | Kubelet service是否Running |
KernelDeadlock | False | 内核是否存在死锁 |
FrequentDockerRestart | False | Docker是否在20Min内重启超过5次 |
FrequentContainerdRestart | False | Containerd是否在20Min内重启超过5次 |
DockerdProblem | False | Docker service是否Running(若节点运行时为Containerd,则一直为False) |
ContainerdProblem | False | Containerd service是否Running(若节点运行时为Docker,则一直为False |
ThreadPressure | False | 系统目前线程数是否达到最大值的90% |
NetworkUnavailable | False | NTP service是否Running |
有些事件是不适合在NDP DaemonSet做分布式检测的,我们就放在TKEx Node Controller中去做中心式检测,由其生成Event并发送到Apiserver。比如:
TKEx-descheduler则负责ListWatch NPD和TKEx Node Controller发送的Events,做出对应的行为决策,比如对Pod内某个问题Container进行原地重启、问题Pod的驱逐等。
TKEx之前提供的VPC+ENI
的Underlay网络方案,使得容器网络和CVM网络、IDC网络在同一网络平面,并且支持容器固定IP,极大地方便自研业务上云。这次TEKx平台的容器网络能力再升级,支持在使用HostNetwork
和VPC+ENI
容器网络方案上,再为Pod分配EIP(弹性公网IP)的能力。
当后端集群资源池耗尽,会有大量的待调度的pending pods,此时使用任何类型的Workload进行镜像更新时都会出现资源抢占导致升级失败的情况。
为了解决这个问题,提升业务升级的稳定性,我们优化了Kubernetes Scheduler Cache的逻辑,给StatefulSet/StatefulSetPlus升级时提供了资源预抢占的调度能力,很好的保证了在不新增资源的情况下StatefulSet/StatefulSetPlus能正常升级成功,不会被调度队列中的Pendnig Pod抢占资源。
后面团队会单独输出一篇技术文章对此进行详细分析
本文总结了腾讯会议在TKE容器化部署时用到的平台相关特性,包括业务镜像自动分批灰度发布、ConfigMap分批灰度发布、Pod内A/B容器ms级切换发布、多集群发布管理、基于DynamicQuota的产品配额管理、探测节点和集群稳定性问题以提升自愈能力等。腾讯自研业务在TKE上沉淀的优秀组件和方案,后面会在公网TKE产品中提供给公网客户,也在计划开源,敬请期待。