莉莉丝游戏剑与远征项目组主程探讨容器

北京著名皮炎医院 http://pf.39.net/bdfyy/bdfhl/210611/9052592.html

文/小莉慢品

最近这些年,以容器和函数计算为代表的云原生技术,正用一种全新的方式改变着我们构建和部署应用。AFK(剑与远征)在上线之前也完成了战斗校验场景容器化的落地,容器为我们带了简易运维,弹性伸缩等好处。但在上线后,我们逐步发现容器在弹性伸缩时延上面的不足,转而将目光聚焦到了另外一种云原生技术:函数计算。本文结合了AFK的实践,来分享一下两种云原生技术在弹性计算的使用、原理和思考。

——拉德,AFK(剑与远征)主程

一、相关概念

什么是弹性伸缩

系统能够随请求的增减,实现系统扩容,实现高可用,在业务下降的时候,能实现系统缩容,减少成本。简而言之,是一种低成本的可扩展计算。

什么是冷启动

冷启动是指一个应用从无到可以对外服务的过程。在游戏交互领域,一般5秒以上的等待时间,玩家是无法接受的。

什么是容器技术

Docker几乎是容器的代名词,Docker提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。Kubernetes(以下简称K8S)是容器集群的管理系统,可以实现容器集群的自动化部署、自动修复,自动扩缩容、无缝应用升级等功能。

什么是函数计算

函数计算又称Faas,全称Functionasaservice,是Serverless(云计算的方向之一)的子集,也是整个Serverless的核心。Serverless,又称"无服务器",是开发者将服务器逻辑运行在无状态的计算容器中,完全由第三方管理的。Faas具备细粒度调用,实时伸缩,无需关心底层基础设施等特性。

什么是战斗校验

战斗校验是在服务器跑的一段战斗逻辑代码,用来验证玩家客户端上传的战斗是否有作弊的情况。

战斗校验的弹性需求

战斗校验一般需要逐帧计算,CPU消耗会非常高,通常1队v1队的战斗需要n毫秒,而5队v5队的战斗则需要相应5n毫秒。以AFK国服为例,每天跨天重置任务,同时也是整个战斗校验集群的业务高峰,而每天夜里,随着在线人数的减少,整个战斗校验集群进入业务低谷期。两者CPU消耗差异有10倍之多。

二、容器的弹性伸缩

容器是通过轮训监控的指标数据,根据算法执行调度实现自动伸缩,主要由应用层维度(Pod)和资源层维度(Node)两部分配合调度完成。

应用层维度

应用层维度从应用场景来看,分为水平扩容和垂直扩容,篇幅有限,本篇介绍主流的水平扩容:

1.HPA

HorizontalPodAutoscaling,是Kubernetes中实现POD水平自动伸缩的功能。HPA组件会每隔30s从MetricsServer等监控组件获取CPU等监控指标,根据算法计算出期望副本数,通知Depolyment等组件执行扩缩容。

扩缩容算法:DesiredPods=ceil(sum(MetricValue)/Target)

举个例子:当前HPA设定CPU阀值:70%。当前有3个Pod,CPU都是90%。那期望的Pod数量=ceil(90%*3/70%)=5,此时HPA会进行新建2个Pod,进行水平扩容。

HPACPU

按CPU伸缩配置比较容易,但是有个缺陷,如果毛刺带来的负载大于%,HPA的认知就会被限制,无法通过一次计算就得出还需要多少个POD,就需要多次调整。每次调整中间还需要间隔一个扩张冷却周期,默认3分钟。如下图,Pod想从1个变成8个,需要经过3次计算周期。

HPAQPS

所以HPA就有了Custommetrics扩展,常用的是QPS。通过配置单个Pod的QPS10,当流量操作QPS阀值时候,集群就会自动扩容。QPS是一个潜在的约定,就是集群的每秒的请求消耗CPU比较平均,当特定时间点某种CPU消耗较多的请求大幅增加时候,QPS无法正确衡量。导致集群扩容的数量不能满足业务需求。

2.CronHPA

结合上文,我们会发现HPA的扩容调度有一定时延,业务遇到毛刺时候,HPA无法及时调整Pod到业务期望数量,造成部分应用不可用。这种业务抖动会给玩家带来非常差的体验。为了解决这个问题,我们引入了CronHPA,有点像Linux的Crontab,根据业务之前周期性的规律,在业务高峰前10分钟提前准备好资源,满足高负载的需求。CronHPA跟HPA不同,HPA是官方版本提供了实现方式,CronHPA基本要依赖于开源社区或者云厂商的实现方式。AFK所用的是阿里云的CronHPA,这里讲一下CronHPA的演进:

现在大部分厂商的CronHPA

目前大部分云厂商还是这种实现方式,包括之前的阿里云,CronHPA和HPA都是直接控制Deployment,来调度应用扩缩容的,因为二者无法彼此感知,所以CronHPA扩张上来的Pod很快会被HPA回收,两者并不兼容。如下图所示:

当时为了同时获得HPA和CronHPA的特性,AFK一直保持着双SVC的配置,分别支持HPA和CronHPA。每次和阿里云容器同学交流,我们总是敦促对方改进。

阿里云的新版CronHPA

终于阿里云的CronHPA终于在年3月开始兼容HPA了,算法也比较有意思,这里列一下实现方式:

①CronHPA控制的TargetRef从Deployment变成了HPA

②扩容时候调整HPA的Min值=max(CronHPAScaleUpReplicas,Currentreplicas)

③缩容时候调整HPA的Min值=min(CronHPAScaleDownReplicas,CurrentReplicas)

我们可以看到,这个实现方式一直在调整的是HPA的Min值,而非当前的Replicas数量。这样一个设计有个很巧妙的地方,比如我们的HPA是min/max:10/,n点-n+4点(n点为最高峰)是业务高峰。我们可以配置成n-1点50分扩容到,n点10分(不需要等到12点)缩容到10。我们发现尽管n点10分HPA的Min已经调整成10了,但是当前的Pod数量还是按CPU计算的,并没有直接减少,而是随着业务的减少慢慢向HPA的Min靠拢。这样不需要保持整个n点-n+4点都维持在的规模,极大减少了资源浪费。

在实际使用的时候,CronHPA非常适合有周期规律的应用场景,但是为了应对预估不足的流量,或者突发的流量,还是需要配置HPA作为最后的保障。

资源层维度

在资源层维度,目前主流方案是通过ClusterAutoscaler来进行节点的水平伸缩。当Pod不足时,ClusterAutoscaler安装集群配置的扩容实例规格,到云厂商的公共资源池去购买实例,初始化之后,注册到集群中,KubeScheduler会调度新的Pod到这个节点上。链路越长,越容易出错,结果往往就是集群弹不起来.

这里列出一些限制:

动态购买ECS:涉及的限制有库存、按量EcsQuota、批量创建机器云盘限流等

机器初始,安装K8S:涉及的限制有Yum源、MetadataServer、RamRole、内网OpenApi等

选择terway网络(一种和vpc打通的网络方式):涉及的限制有Eni数量Quota、Eni并发创建限流、Ecs规格所支持的Eni网卡数、RamRole等。

AFK被坑过两次:

一次我们所需的扩容的六代机型,严重低于阿里云公共资源池的水位线,导致ClusterAutoscaler无法购买到机器,集群扩容失败。因为集群扩容是按配置的机型顺序来扩容的,建议配置一些旧机型,保证水位线的充足。

CentOS社区Yum源权限变动,流入到下游的阿里云,导致弹性购买的机器无法初始化(错误),也就无法加入到K8S集群,集群扩容失败。阿里就此发了复盘报告,从阿里侧杜绝这个问题。

容器的冷启动链路

除了链路太长给弹性带来不稳定性外,整个资源层扩容时间,也是在2-3分钟左右。为了解决伸缩时延过长的问题,社区发布了一个新的组件,VirtualKubelet,通过它,K8S的节点可以用其他服务来伪装。比如阿里云的ECI,底层使用基于Kata的安全沙箱容器,对容器运行环境进行深度优化,提供比虚拟机更快的启动速度,整个资源层扩容时间可以缩减到30秒以内。

三、函数计算的弹性

上文提到Faas是serverless的核心,我们首先纠正两个经常误解的名词:

Serverless并不是说不需要服务器了,可能叫server-free相对好理解一点,只是说程序员可以不用关心server,


转载请注明:http://www.aierlanlan.com/grrz/1557.html

  • 上一篇文章:
  •   
  • 下一篇文章: