云原生游戏最佳实践系列

2022-11-22 671 发布于辽宁

版权

举报

版权声明:

本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议》和 《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

开发者学堂课程【云原生游戏最佳实践系列:云原生游戏最佳实践系列】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/1195/detail/18134

云原生游戏最佳实践系列

内容介绍:

一、背景

二、云原生游戏项目 Agones

三、游戏云原生落地难点

四、Open'K'ruiseGame

一、背景

1、游戏服架构演进历史

(1)单体服务

单机部署

计算存储耦合

(2)分区分服

平行世界

数据库拆分

(3)角色拆分

对战/场景/网关/社交系统 拆分

向云原生靠拢

游戏服架构演进大致分成三个阶段,单体服务、分区分服还有角色拆分。在网络游戏刚刚兴起的时候,游戏服务大多是在单机部署,除了服务本身的进程以外,数据库也会部署在同一台服务器上,服务计算和存储都是耦合的。随着互联网的逐渐兴起,游戏玩家也会逐渐增多,由于单台机器的承载能力有限,游戏服诞生了新的架构分区分服,所有的玩家会切分至不同的平行世界,位于不同大区的玩家相互是不感知的,数据库也是单独部署、单独存储的。不同服的玩家也会偶尔会进行一些交互,比如在一些跨服的活动中进行相互的交互。目前为止游戏各个角色的进程耦合性还是比较重的。直到后来云计算带来的一些技术红利,使游戏服务将各个角色拆分出来,比如有对战服务、房间服务还有不同的场景服、聊天服、社交和 jm 服等等。不同的角色单独部署有利于扩容的灵活性,更好地能够利用好计算资源,从这点上来看游戏服正在向云原生靠拢。

2、游戏行业现状

后疫情时代,游戏行业步入高质量发展期,

“效率”、“成本”、“安全”成为游戏开发者关注的三大因素。

“效率”-快速开服、测试、发布是游戏成功的重要因素

“成本”-游戏峰谷容量差异较大,弹性平均降本 30%

“安全”-上线新游是DDOS、BotAttack、CC 攻击的重灾区

在后疫情时代的今天有些行业进入了一个新的发展阶段,越来越多的游戏公司希望保证服务稳定性的前提下,降低成本去提高效率。比如降本增效可以发现传统机器的采购中期和游戏运营的周期非常不匹配,为了保证游戏正常上线、稳定运行,难免存在一些时间上的资源浪费,就算是上线运行的阶段,游戏的波峰波谷容量差异也比较大,资源的利用率还有很大的提升空间,所以有些行业的云原生是势在必行的。

3、游戏服架构演进趋势

游戏开发运维耦合                游戏开发运维更加敏捷

运维流程不敏捷                  资源按需分配,利用率高

资源利用率低                    云原生化

从本质上来看未来游戏服架构演进趋势将会按照图所示的向去发展,游戏服务计算资源逐步耦合,会导致开发和运维流程变得相对独立,会提高游戏产品的迭代效率。除此之外资源可以按需分配,使得利用率得到提高,降低游戏运营的成本。

二、云原生游戏项目 Agones

原生游戏有众多优势,在目前的社区中有比较成熟的解决方案。

1、agones

用于在 Kubernetes 上托管、运行和扩展专用游戏服务器的库

agones 用于在 Kubernetes 上托管、运行和扩展专用游戏服务器的库,可以理解为 Kubernetes 上的一个 operator,控制了与游戏服务有关的 CRD 。

2、agones 网络模式

HostPort 端口转发

首先是网络模式,实际上采用的是整体的访问链路,比较简单,玩家可以直接通过访问主机的 IP 端口,然后会转发至游戏服务的端口。好处有两点,首先第一点是降低了延迟,延迟相对比较低,没有 IP tables 做二次转发。其次也会避免使用 hostnetwork 导致端口冲突的问题。agones 会自己陪护一个端口映射表,避免映射关系的混乱。

3、agones 生命周期

第一个图 agones 定义了一个 CRD,叫做game server这个对象实际上是对 pod 的进一步封装。状态相比 pod 更加复杂。agones 官方的状态机可以看到 game server 对象会有比如 pod 的Alloccation、creating、starting、schedule、dreserved、requestready、ready、shutdown、Allocated、Unhealty 等等,感觉非常复杂实际上可以看到状态的转移,很多都是通过 SDK 去进行实现的,SDK 实际上暴露了游戏服务进程的某些状态,让上层的K8S 能知道,游戏服本身的状态比较复杂,是一个强硬状态类型的应用,有关于游戏服务器状态后面会有详细的介绍。

生命周期管理可以通过这幅图看到是跟 pob 的生命周期有一定有关系的,比如 pob 在创建或者刚刚调的时候,会变成一个 creating 的状态,pob 已经 ready 或者已经 running 的时候,会变成一个 ready 的状态。会涉及到一个比较重要的一个状态 Allocated,Allocated 意味着已经为玩家服务分配了玩家,玩家服已经处于一个被分配的状态。在这种状态下的玩家服有一个强保护的机制,不能随意的删除。

4、agones 动态伸缩

agones 有 game server 对象,除了 game server 对象agones 也定义其他的一些 SRD 的,比如 Fleet 可以理解为 deployment管理 game server的方式,跟 deployment 管理 pod 有些类似,都可以通过定义副本数来实现对应 depends 的扩缩容。动态伸缩的维度还是有区别的,deployment 是通过 HKA 实现的动态伸缩,HKA 更加关注的是资源情况,Fleet 自动伸缩关注的更多是在业务的层面。可以通过定义一个 buffer,可以实现一个自动伸缩。状态转移图里面可以看到 game server 的状态叫做 Allocated,实际上是表明现在游戏服已经分配,已经有玩家在玩的一个状态,allocated的状态是由上层匹配系统去决定的。假如现在 Fleet 管理所有游戏已经都被分配都被使用,会担心玩家没有可分配的游戏服,会希望多一些准备好的游戏服,随时为新的玩家提供游戏服务的 buffer,它定义的就是 Allocated的数目之上的 buffer 数量。比如这幅图的例子,现在有 buffer 定义的是在 Allocated 数目之上定义两个 buffer,当前 Allocated 的数目是三,会把 Fleet 的数目调整为五,会自动扩出来两个已经 ready 的 gameserver,随时为新玩家去提供服务。如果缩容的时候比如 Allocated game server 玩家对战已经结束没有玩家,可以收回,Allocated 置为 ready 或者其他状态会上传自动扩缩的统计,发现当前 Allocated 的数目减少,与之对应的 buffer 数目是在当前 Allocated 的数目之上的一个数目定义,整体的数目也会相应的减少,比如已经释放了两个 Allocated 的 game server,整体的数目也会进行相应的减少两个,通过这样的一个方式实现波峰和波谷之间合理分配,agones 动态伸缩。

5、agones on ACK

agones 实际上在 ACK 已经有所支持,可以通过 ACK 的应用市场去搜索 agones,然后通过 helm 的 charge 进行一键式的安装,目前支持的版本是 1.23。

三、游戏云原生落地难点

大部分的游戏都可以利用 agones 来进行原生的落地吗,回答问题之前先了解一下游戏后端架构维度游戏有哪些类型。

1、游戏类型 PvP vs PvE

PVP

房间/对战/回合为短生命周期【相较基础设施】

网络链路、质量、实时性要求高

玩家服之间通常无配置差异

Others

PVE

分区分服的大世界类型游戏为主

玩家/服务器长周期绑定

对单个玩家服有定向运维动作

可以看到有很多熟悉的游戏,比如王者荣耀、绝地求生、三国志战略版、魔兽、元神等等。从玩家的角度看的这些游戏有的是 FPS 的设计类,有的是 MMO 的,有的是 mobile 的,有的可能是 SLG 策略类型的。从后端的架构上可以分成两类,一类是 PVP 类型,一类是 PVE 类型。PVP 类型特点是比如有房间、对战回合的概念,生命周期相对于基础设施会比较的短,除此之外对网络的链路质量、实时性要求都会比较高。从运维配置管理层面上看,玩家服务之间通常的配置没有太大差异或者没有差异。

对于 PVE 类型的游戏一般都是分区分服,大世界类型为主的游戏,有不同的场景服,有大世界服,可能会有一个大网关去进行连接转发,玩家和服务器是一个长周期绑定的关系,可能每个 name server 的配置都是不一样的,对于某一个 game server 可能会有定向的运维动作,这是 PVE 类型的特点。agones 针对游戏的原声场景做了很多工作,但是很多游戏却难以在agones 落地,能够使用 agones 游戏往往是 PPT 类型的游戏。

不仅是 agones 现在社区很多原生游戏的开源项目,关注的都是PVP 类型的场景。在当下的游戏市场中也会有大量的 PVE 类型的游戏,或者有的游戏是获客类型,既有大世界场景服也有战斗房间服,这是难以落地的原因。另一方面即使 PPT 类型的房间类游戏,游戏行业的基础设施国内外之间是有一些差异的,国外的游戏厂商云化的程度比较深,上门的时间比较早已经经历过游戏语言深化阶段,正式地迈入云原生游戏的领域,在国内目前正在经历游戏云原生化改造的一个阶段,二者的环境是有所差异的,这也是为什么 agones 无法在国内游戏行业被广泛应用的原因之一,所以 agones 并不是原生游戏的最优解。如何做游戏的原生化回答这个问题之前,要思考一个问题是为什么游戏不像其他的业务服务那么容易的进行容器化,通常都会有一个答案是因为游戏的玩家服是有状态的,非常抽象,似乎解释了问题,但是解释的又非常模糊。

2、游戏玩家服“有状态”

有状态:

内存状态、连接状态、运维状态

游戏服务的有状态主要体现在三个方面,第一点内存状态,游戏由于独特的滇池特性,天然追求高速通信,进程之间的关系会比较耦合,很多时候即使游戏进行容器化,很多游戏也是以父容器的形式存在。进程之间可能使用共享内存的技术,很少使用远程调用,这是内存状态。

第二点是连接状态,游戏是强交互类型应用,玩家和它对应的游戏服绑定的关系是非常紧密的,很多时候玩家客户端是以长连接的方式和游戏建立连接,不会像其他外部类型服务产品的规定,所以在游戏场景中,很难运用负载均衡的概念。

第三是运维状态,运维状态可以理解为是由前两种状态衍生出来的一种有状态的理想,是由于有些服务存在内存状态和连接状态,所以在运维的过程中往往需要一种标识去分开各个游戏服务,标识作为游戏公司进行游戏运维的依据,很多时候游戏运维都要对特定游戏服做定向的操作,比如利用一些运维工具,或者运维系统进行一些运维脚本等等,这个时候游戏服的标志就显得非常重要。在传统的行业从物理基因时代开始,很多游戏都是用 IP 作为游戏服务器标志,即使到了 2022 年的今天,由于有些行业更加关注的是游戏的稳定性和游戏的玩法,所以它的基础架构系统迭代的比较缓慢,依然会用一些比如 IP 作为游戏的标识,所以会发现很多游戏公司,比较关注的是云上固定 IP 特性,也是有状态的一个需求,通过内存状态、连接状态、运维状态来理解游戏玩家服为何是有状态的,清楚了游戏玩家服容器化。容器化不是狭义的,是游戏服打包成镜像,然后让容器运行起来。实际上在生产的环境中要考虑的是如何管理批量的容器化游戏服务,Kubernetes 作为容器编排的事实标准是游戏原生化绕不开的一个话题,Kubernetes 的设计理念和游戏玩家服的特点是有所差异的。

3、Kubernetes VS 游戏玩家服

Kubernetes    

Kubernetes 通用负载

Deployment/StatefulSet 无法满足

游戏玩家服

随着时间推移,各游戏服之间差异性明显。例如, PvE 游戏后期玩家数目不均衡,需要指定下线/合服

有些游戏使用进程重载,解耦引整层与脚本层,在 hotfix 时通过热更新的方式平滑升级

大规模游戏服,分区分服的情况下需要做到分批灰度发布、并且能够控制发布规模与速度

Kubernetes

Kubernetes Pod 不是游戏服最匹配的抽象实体

游戏玩家服

游戏服很多以富容器的形式存在,维护着进程级别的内存状态

Kubernetes

Kubernetes 通用的容器网络不关注游戏服的网络需求

游戏玩家服

游戏对网络延迟敏感,通常需要直连IP

游戏运维依托于游戏公司传统基于IP的运维体系,催生出固定游戏服IP的网络诉求

在故障或维护时需要隔离环境,有摘除网络的需求

Kubernetes 的游戏服总会遇到各种水土不服的问题,第一个问题是找不到 Kubernetes 通用负载,可以很好和游戏服契合,游戏服的运维状态它需要一个标识去代表对应游戏服,很多时候标识是 IP,还有很多时候标识可能是承载游戏服机器,对应在 K8S 里面就是 pod。这也是很多公司选择用 stuff that 作为游戏负载的原因,但是 stuff that 不是真的可以作为游戏玩家服的负载。游戏公司使用的是 oneself that one pot 这种模式,也就是一个 stuff that 只管理一个 pob,然后通过上层的 paas 平台进行 pob 平台。首先比如随着时间的推移,各个游戏服之间的差异性会越来越明显,比如 PVP 类型的游戏到后期玩家数目不均衡,可能会需要指定下线和合服,StatefulSet 控制的顺序是固定的,缩容只能缩倒数第一个,缩倒数第二个,扩容的时候只能按正序去扩容,跟游戏玩家服是不匹配的。除此之外有的游戏使用的是进程重载技术,会把引擎层和脚本层进行结耦,比如有的时候会进行 hotfix 通过热更新的方式进行平滑升级,k8s 通用负载不管是 deployment 还是 StatefulSet 都没有提供这样的能力。

除此之外还有是大规模游戏分区分服情况下,需要做到分批的发布,要指定的是发布的顺序、发布的规模、发布的速度,要控制发布的节奏,所以在 k8s 中的 deployment 或者 StatefulSet 有办法做到这样的能力,所以 Kubernetes 的通用负载是没有办法满足游戏玩家服的场景这是第一点。第二点是 pob 和游戏服这两个概念之间实际上并不是很匹配。

很多游戏服会以父容器的形式存在,内存状态对于游戏服是非常重要的,然而 pod 对内存的管理比较匮乏的,Pod 的涉及两种探针一个是 linus 存活探针,一个是 Reynolds 就绪探针,存活探针探测失败以后容器要被杀死,就绪探针失败之后会变成 noready 切断流量,非常的简单粗暴,实际在生产的环境中内存状态是非常复杂的,很多时候游戏服轻微的异常需要处理,但是不希望重启或者断流,背景的 pod 是无法解决的。

第三点是游戏服的网络需求是特殊的,Kubernetes 标准网络插件是无法覆盖的,比如网络延迟,很多游戏对网络延迟是敏感的,需要指定IP,不能使用 place service 模式。除此之外有些运维依托于游戏公司传统基于 IP 运营体系,催生出游戏服物联 IP 的诉求,有的时候会在指定运维某一个游戏服务的时候,根据自己的一些脚本判断,或者是等等这些操作,去决定现在需要把环境隔离要手动的去摘除网络,这些需求自身或者标准的网络电视没有支持。总结下来由于游戏玩家服的特点,使得游戏服务在 Kubernetes 上的落地会变得比较困难,因此提出了 OpenKruisegame。

四、Open'K'ruiseGame

1、OpenKruiseGame

OpenKruise 实际是增强 k8s 上的通用负载,k8s 的通用负载可能会有 deployment,针对的无状态应用,可能会有 StatefulSet 管理的是一种有状态类型的应用,可能还会有 game sight。对游戏来说可能关注 deployment 或者 StatefulSet。通常游戏公司可能会用两种 k8s 通用负载去部署游戏服务。

OpenKruise 通用负载比如 deployment 和 StatefulSet 没有办法很好的去满足游戏服务的需求。OpenKruise 是一个什么样的东西或者是什么项目,为什么可以很好的去满足需求,先看一下官方文档。

(1)OpenKruise 是什么

欢迎来到 OpenKruise 的世界!

OpenKruise 是一个基于 Kubernetes 的扩展套件,主要聚焦于云原生应用的自动化,比如部署、发布、运维以及可用性能护

OpenKruise 提供的绝大部分能力都是基于 CRD 扩展来定义,它们不存在于任何外部依赖,可以运行在任意纯净的 Kubernetes 集群中

(2)核心能力

①增强版本的 Workloads

OpenKruise 包含了一系列增强版本的Workloads(工作负载),比如CloneSet、Advanced StatefulSetAdvanced DaemonSet. BroadcastJob 等。

它们不仅支持类似于 Kubernetes 原生 Workloads 的基础功能,还提供了如原地升级、可配置的扩缩容/发布策略、并发操作等。

其中,原地升级是一种升级应用容器镜像甚至环境变量的全新方式。它只会用新的镜像重建 Pod 中的特定容器,整个 Pod 以及其中的其他容器都不会被影响,因此它带来了更快的发布谏摩,以及谢鱼了对其他 Scheduer.CNCSI 等组件的负面影响。

②应用的旁路管理

OpenKruise 提供了多种通过旁路管理应用 sidecar 容器、多区域部著的方式,“旁路”意味着你可以不需要修改应用的 Workloads 来实现它们。

比如,SidecarSet 能帮助你在所有匹配的 Pod 创建的时候都注入特定的 sidecar 容器,甚至可以原地升级已经注入的 sidecar 容器镜像、并且对 Pod 中其他容器不造成影响。

而 WorkloadSpread 可以约束无状态 Workload 扩容出来 Pod的区域分布,予单一 workioad 的多区域和弹性部署的能力。

③高可用性防护

OpenKruise 在为应用的高可用性防护方面也做出了很多努力。

目前它可以保护你的 Kubernetes 资源不受级联删除机制的干扰,包括 CRD、Namespace 以及几乎全部的 Workloads 类型资源。

相比于 Kubernetes 原生的 PDB 只提供针对Pod Eviction的防护,PodUnavailableBudget 能够防护 Pod DeletionEviction、Update 等许多种 voluntary disruption 场景。

④高级的应用运维能力

OpenKruise 也提供了很多高级的运维能力来帮助你更好地管理应用。

你可以通过 ImagePullJob 来在任意范围的节点上预先拉取某些镜像,或者指定某个 Pod 中的一个或多个容器被原地重启。

OpenKruise 实际上是一个基于 Kubernetes 的扩展套件,提供了绝大部分的能力,都是基于 CRD 进行扩展的,因此不会存在对于外部的任何依赖。可以把 OpenKruise 部署在任何 Kubernetes 的集群中,是一个完全中立的项目。目前 OpenKruise 也是 CNCF 中的一个 stuff 项目,除了非游戏领域之外也会得到很多广泛的应用。目前发现在某种程度上可以解决 OpenKruise 无法解决的一些问题,比如 OpenKruise 的核心能力叫做原地升级,原地升级概念首先在 k8s 种pod 在更新的时候是需要重建的,重建是把 pod 删除之后重新创一个 pod 出来,pop 的 ID name 或者 IP 都会发生变化,name 发生变化可能会跟负载类型有关固定 pod name,如果是deployment 可能也会发生变化,是 k8s 原生更新的时候带来的重建机制,很多时候不希望 pod 重建,更新的只仅仅是 pod 中的某一个容器,不需要把所有的容器都进行一次杀死,然后重新创建,Pod的 ID、IP 都会变化,很多场景下是无法忍受的。

OpenKruise 提供了一种人机升级的能力,在 pod 不重建的基础上去定向的更新某一个容器,如果指定了三个容器和两个容器中的某一个容器,仅更新 pod 对应的容器,pod 的IP、ID 标识不会发生变化,由此也可以实现另外一种热更新,比如游戏服可能隐形侧在主容器里面,脚本玩法或者一些文件,Set 文件会在一些 sidecar 容器里面,有的时候在做一些 workloadspread 的时候加一些 set 文件进到 Pod 中,然后让主进程进行一些整载。

不需要把整个 pod 删除,需要定向更新 sidecar 容器,所以原地升级更新变得非常重要,这是OpenKruise 所提供的能力,在 pod 维度更新力度上面,通用负载批量管理的时候也会存在一些问题,比如 StatefulSet 是一个管理有状态类型的应用负载,管理的 pod 序号是固定的,假如现在管理十个 pod ,十个 pod 的名字一定是零到九。假如考虑 PVE 场景下玩家数量流失的情况,想进行合服操作可能不是针对杠九 pod 游戏服,可能操作是杠二或者杠五、杠七,不是杠九。或者有的时候可能有些 PVP 场景下的也需要利 pod name 作为系统标识,所以会选择 StatefulSet 作为负载,可能会需要去对于某一个指定的或者当前某一个 PVP 游戏房间服优先级会比较高删除这个,有可能已经没有玩家想要删除对应的 pod,在 StatefulSet 中是没有办法做的。

(3)Advanced StatefulSet

这个控制器基于原生 StatefulSet 上增强了发布能力,比如maxUnavailable 并行发布、原地升级等。

如果你对原生 StatefulSet 不是很了解,我们强烈建议你先阅读它的文档(在学习 Advanced StatefulSet 之前):

Concept of Kubenetes StatefulSet.Deploying a stateful application

注意Advanced StatefulSet 是一个CRD,kind名字也是StatefulSet,但是 apiVersion 是 appskruise.io/v1beta1。这个CRD 的所有默认字段、默认行为与原生 StatefulSet 完全一致,除此之外还提供了一些 optional 字段来扩展增强的策略。

因此,用户从原生 StatefulSet 迁移到 AdvancedStatefulSet,只需要把 apiversion 修改后提交即可:

- apiversion:apps/v1

+ apiversion:appskruise.io/v1betal

kind:StatefulSet netadata:

name:sample

Spec:

#....

注意从 Kruise 0.7.0 开始,Advanced StatefulSet 版本升级到了v1beta1,并与 v1alpha1 兼容。对于低于 v0.7.0 版本的 Kruise,只能使用 v1alpha1

MaxUnavailable 最大不可用

Advanced StatefulSet 在 RolingUpdate5tatefulSetStrategy 中新增了 naxnavailable 策略来支持井行Pod发布,它会保证发布过程中最多有金少个 Pod 处于不可用状态。注意,maxinavailable只能配合 podManagementPolicy 为 Parallel 来使用。

这个策略的效果和 Deployment 中的类似,但是可能会导致发布过程中的 order 顺序不能严格保证。如果不配置 maxtnavailable,它的默认值为1,也就是和原生 StatefulSet 一样只能 one by one 串行发布 Pod,即使把podManagementPolicy配置为Parallel也是这样。

但是 OpenKruise Advanced StatefulSet 实际上是对于 StatefulSet的一种增强,提供了序号保留的能力。

(4)序号保留(跳过)

从 Advanced StatefulSet 的 v1beta1 版本开始(Kruise>=v0.7.0),支持序号保留功能。

通过在 reserve0rdinals 字段中写入需要保留的序号,Advanced StatefulSet 会自动过创津这些序号的 Pod,如果 Pod 已经存在,则会被刑除。注意,spec.replicas是期望运行的Pod数量,spec.reserverdinals 是要跳过的序号。

apiversion:apps.kruise.io/vlbetal

kind:StatefulSet

spec:

#....

replicas: 4

reserveOrdinals:

-1

对于一个replicas=4,reserve0rdinals=[1)的Advanced StatefulSet,实际运行的 Pod 序号为[0,2,3,4].

如果要把 Pod-3做迁移并保留序号,则把(3追加到reserve0rdinals 列表中。控制器会把 Pod-3 除井创建 Pod-5 (此时运行中 Pod 为[0,2,4,51)。

如果只想删除 Pod-3,则把追加到 reserve0rdinals 列表并同时把replicas 减一修改为。控制器会把 Pod-3 删除(k 时运行中 Pod 为[e,2,4]).

序号保留的能力可以理解为对应 pod 序号的删除,序号的保留。假如可以看到文档里面有两个字段的设计(replicas: 4 reserveOrdinals;)replicas 原生自带字段,reserveOrdinals 保留字段,假如现在有十个副本,把副本数设置为九,原来是十设置为九,然后把 reserveOrdinals 中的 slide 数组添加一个5,会优先的去缩5,这就是 Advanced StatefulSet 能够提供的能力 StatefulSet 无法提供。

提出 OpenKruise game 的原因是需要 OpenKruise 一些通用负载解决不了的能力,可以通过 OpenKruise 去解决,比如增强型的advanced StatefulSet 可以去解决,比如 kruiseSet 去解决原生,提供原地升级,热更新啊,批量灰度发布。

(5)升级顺序

Advanced StatefulSet 在 spec.updateStrategy.rollingUpdate下面新增了 unorderedUpdate 结构,提供给不按 order 顺序的升级策略。如果 unorderedUpdate 不为空,所有 Pod 的发布顺序就不一定会按照 order 顺序了。注意,unorderedUpdate 只能配合 Parallel podManagementPolicy 用。

目前,unorderedUpdate 下面只包含 priorityStrateg一个优先级策略。

优先级策略

这个策略定义了控制器计算 Pod 发布优先级的规则,所有需要更新的 Pod 都会通过这个优先级规则计算后序。目前 priority 可以通过 weight (机重)和 order (序号)两种方式来指定。

·weight:Pod 优先级是由所有 weights 列表中的 term 来计算match selector 得出。如下:

apiVersion! apps.kruise.io/vlbetal

kind: StatefulSet

Spec:

#....

updateStrategy:

rollingUpdate:

Unorderedupdate:

priorityStrategy:

weightPriority:

-weight:50

matchSelector:

natchLabels:

test-key: foo

-weight: 30

Matchselector:

matchLabels:

test-key:bar

order:Pod 优先级是由 orderKey 的 value 决定,这里要求对应的 value 的结尾能解析为 int  值。比如 value"5”的优先级是5,value"sts-10* 的优先级是 10.

apiversion: apps.kruise.io/v1betal

kind: StatefulSet

Spec:

#...

updateStrategy:

rollingUpdate:

Unorderedupdate:

Prioritystrategy:

orderPriority:

-orderedkey:

some-label-key

比如发布升级的时候 k8s 原生的 pod 升级顺序有一定的顺序,可优先会升级根据 pod 的状态、阶段去进行升级,没有办法根据业务层定义的优先级去进行升级,只需要去指定优先级策略,根据 weight pod 可以给权重,可以实现升级顺序的控制。

(6)Partition 分批灰度

Partition 的语义是保留旧版本 Pod 的数量或百分比,默认为@。这里的 partition 不表示任何 order 序号。

如果在发布过程中设置了 partition:

如果是数字,控制器会将( replicas=partition )数量的 Pod 更新到最新版本。

如果是百分比,控制器会将( replicas*(100%-partition) )数量的 Pod 更新到最新版本。

FEATURE STATE: Krulse v1.2.0

如果partition是百分比,并且满足 partition<100% 66reolicas>1.CloneSet  会保证至少有一个 Pod会被升级到最新版本。

用户可以使用status.updatedReol1cas >mstatus.Expecte dundatedReplicas 条件,来判断在当前 partition 字段的限制下,CloneSet 是否已经完成了预期数量 Pod 的版本升级。

比如,我们将 CloneSet  例子的 imaoe 更新为 nginximainline 并具设置 partition=3,过了一会,查到的 CloneSet 如下:

apiversion:apps.kruise.1o/vlalpha1

kind:CloneSet

Metadata;

#....

generation: 2

spec:

replicas:5

template:

metadata:

labels:

app:sample

spec:

containers:

-inage:nginxinainline

imagePulLPolicy:Always

name: nginx

updateStrategyi

partition: 3

#....

status:

observedGeneration:2

readyReplicas:5

replicas:5

currentRevision:sample-d4d4fb5bduodateRevision:sample-56dfb978d4

updatedReadyReplicas:2

updatedReplicas:2

Partition 是分批灰度,只保留旧版本 pod 数量的百分比,通过partition 可以去保留一定数量的 pod,只是升级对应数量的pod。升级完成之后,可以再改变 partition,然后依次控制整个更新的节奏,所以在分批灰度、分批更新场景下游戏服也有这样的需求,所以可以通过 OpenKruise 解决一系列问题。游戏场景还有一些别的问题,pod 并不是一个游戏服最匹配的抽象实体,除此之外还有网络的一些诉求,负载层面是没有办法合理去解决的。

2、OpenKruiseGame 能力

Kubernetes 通用负载 Deployment/StatefulSet 无法满足

基于 OpenKruise 的能力,提供以下游戏业务批量管理能力原地升级、热更新、分批灰度、控制顺序、镜像预热等

Kubernetes Pod不是游戏服最匹配的抽象实体

引入 GameServer CRD,提供用户自定义服务质量的功能并且在Pod 基础上增强游戏服状态管理能力

Kubernetes 通用的容器网络不关注游戏服的网络需求

以 Cloud Provider 的形式为 GameServer 提供容器网络基础设施,实现固定 IP、网络直连、网络隔离等功能

OpenKruise 的能力有原地升级更新、分批灰度、控制顺序还有镜像预热,比如升级的时候镜像要提前去做一些拉取,有的时候要手动拉取,避免在升级的过程中耗时过长,因为有的时候可能是一个停服更新,停服更新耗时更长会对玩家会造成很恶劣的影响,有时候停服过长,可能还会对玩家进行一些经济上的补偿等等,所以进行预热也是很重要的,假如没有这个功能,可能都需要额外的去通过手动或者说平台去做一些额外的操作,这些层面都是负载层面维度上的能力,在负载之外 pod 不可以完全的代表游戏服,因为 pod 关注的只有read 不 read 、running 不 running,很多时候内存状态 pod 无法感知到,需要新增一种探测,能够探测到 pod 内部的内存状态,或者服务更多服务质量的状态。

然后让用户自定义对应的一些操作,而不是简单的做一些杀死或者直接断流粗暴的操作,可能会进一步的去维护 pod 之上,game server 的一个操作,所以引入一个 ID 叫做 game server,CRD 是包裹在 pod 之上的 CRD,会给用户提供一种自定义的服务质量功能,用户可以通过 CRD 中的某些服务质量的字段定义去探测某个进程,或者某一个游戏服务特定的一些状态到什么样的程度,然后去定义一个 action 可能会有一个动作,把对应游戏服的状态置为相应的动作,并不会去影响 pound 的生命周期。假如定一个服务质量,可以是一个空闲的服务质量,空闲的服务质量是可能会暴露一个 API或者一个服务,然后通过类似于 pod 探针finance 或者 lemons 探针的一种方式去探测到。目前 pod 已经处于一种空闲的状态,空闲状态不应该马上删除或者断流或者更新,不应该把操作定死,而是把操作回馈给用户,让用户去决定。可以在对应的 action 里去把 game server 的状态去进行一个标度,暴露给用户之后用户再去决定现在应该做什么操作,这是 pod 没法提供的能力,这是定义 game server 的原因,是在 pod 基础上更加,因为游戏服丰富的内存管理内存有状态的特点去设计的功能,或者CRD 对象。游戏的网络和其他 web 类型的网络有很大差异,网络可能会像其他的 web 类型的应用通过暴露一个 service ,然后去进行一个非常简单的负载均衡,然后转发到对应的 pod 上面,这是一个非常经典的模式,在游戏中不能完全这么做,首先很多时候游戏服也许不会暴露一个端口,也许会暴露一系列的手段,有的时候可能还会有一些网络直连的需求,需求可能会是各式各样的,根据不同的游戏类型,根据不同游戏公司的体系,可能会有不同的网络需求需要做的是提供一种类似于 Could Provider 形式给 game server 提供网络的基础设施,可以是一种带外的组件。在不同的云基础设施或者不同的云环境下,可能会有不同 Could Provider。兼容性比较好的方式去支持网络层面,可能跟基础设施比较耦合的能力,希望通过openkruisegame 能去推动游戏原生化的一个进程。

游戏领域实际上痛点很明显,痛点可能并不是很统一,每家公司有自己的历史包袱,每家公司还有自己额外的特定需求,有的时候很难去通过一种负载或者一种模型去完全的覆盖到全部的游戏或者全部的类型,需要对于云原生游戏领域去做一些共识的建立。

希望大家可以踊跃的分享交流自己对于云原生游戏的看法或者定义、未来的走向应该是什么样子的。国内外之间的环境的差异国外可能会比较前,对于国内来讲正在云原生时代 openkruise 不能解决的问题,如果解决不了应该去怎样做,实际上是会有一系列的问题需要大家共同的来讨论,共同的去营造一个游戏领域基础设施的构建。

相关实践学习

通过Ingress进行灰度发布

本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。

容器应用与集群管理

欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用

相关知识

云原生游戏最佳实践系列
云原生游戏第 2 讲:OpenKruiseGame 设计理念详解
云原生游戏第1讲:游戏玩家服容器化的困境与解法
基于云原生架构的游戏开发成本优化策略研究与实践
云原生架构下的手游开发:Kubernetes与Docker在游戏部署中的应用实践
莉莉丝游戏云原生之路
云原生架构下的完美世界原版游戏开发:Python与Kubernetes的融合实践
“天翼云游戏大赛”助力云原生游戏内容开发
“天翼云游戏大赛”发布 中国电信助力云原生游戏内容开发
OpenKruiseGame × KubeSphere 联合发布游戏服运维控制台,推动云原生游戏落地

网址: 云原生游戏最佳实践系列 http://www.hyxgl.com/newsview387577.html

推荐资讯