【阅读原文】戳:分钟级到秒级:Yahaha 基于 OpenKruiseGame 的 UE5 游戏云原生实践
关于 Yahaha
Yahaha Studios [1] 是一家致力于降低 3D 内容创作门槛的元宇宙平台,让用户无需代码即可轻松创建、分享和体验 3D 游戏及互动内容。
前言
《STRIDEN》[2] 是我们与重要的合作伙伴工作室 5 Fortress 即将联合推出的一款基于 UE5 开发的 FPS 在线游戏,目前正紧锣密鼓地准备 Steam 的 EA 版本上线。
在项目合作之初,我们面临一个核心挑战:合作伙伴之前的技术栈是一套基于云厂商弹性伸缩组(Auto Scaling Group)的方案。这套方案虽然能实现游戏服务器的自动扩容,但无法很好地处理服务器缩容、快速原地更新、多 Region 发布等游戏典型运维场景。在游戏这种有状态服务的精细化管理、无损更新和运维标准化方面,与我们设想的云原生体系相去甚远。
更为严峻的是,留给我们的时间窗口极其有限——我们只有短短两个月的时间,必须将整套部署方案全面重构为云原生架构,以确保游戏能够如期、高质量地上线 Steam。
因此,《STRIDEN》项目不仅仅是一款备受期待的新品,它更成为了我们技术团队的试金石。它迫使我们直面传统部署模式的种种局限,并以实战的方式,将我们对云原生游戏部署的构想,加速落地为一套稳定、高效的生产级解决方案。
接下来,我将详细分享云原生架构实践背后的思考、挑战与选择。
一、为什么是 OpenKruiseGame?
在确认使用 OpenKruiseGame [3] (下文统一称:OKG)这套云原生架构之前,我们存在两大运维痛点:
- 在我们此前的非云原生方案中,无论是版本更新还是日常维护,实现无损的服务器上下线都依赖于复杂且高维护成本的定制化脚本;
- 我们的后端服务早已全面拥抱 K8s,而游戏服务器却运行在另一套独立的管理体系中。这种“双轨制”造成了不小的运维内耗和沟通成本。
因此,在 STRIDEN 项目上,我们的目标变得很清晰:寻找一个能够同时优雅地管理“无状态后端”与“有状态游戏服”的统一平台。答案,最终指向了 Kubernetes (K8s) 所代表的云原生生态。
K8s 的核心魅力在于其强大的声明式 API 和控制器模式,而游戏云原生架构,则是将游戏服务器也作为一种“工作负载”纳入 K8s 的统一管理之下,从而拉平两套系统的运维差异,实现真正的基础设施即代码(IaC)。
明确了走向 K8s 的大方向后,我们开始在社区中寻找成熟的解决方案。最终,我们选择了 OKG。这个决定基于几点关键考量:
- 功能适配性与灵活度:OKG 专为游戏“有状态”特性设计,其高级网络模型、服务质量定义与伸缩策略,为实现无损扩缩容提供了比传统方案更优雅、可靠的路径。
- 社区支持与响应速度:在评估期间,我们感受到了 OKG 社区极高的响应效率和专业度。我们提出的问题和反馈总能得到及时、有效的解答,这种紧密的社区互动对于我们将一项核心技术引入生产环境至关重要。
- 本土化与集成优势:作为一套源自阿里云,在多家知名游戏公司经过线上实践的开源游戏服 K8s 工作负载项目,OKG 在文档、社区交流以及与国内外主流云服务的集成方面,对我们而言更具天然的亲和力。
二、云原生架构实践的挑战
理论选型完成后,真正的考验来自于将《STRIDEN》这款实际的、复杂的 FPS 游戏从传统的弹性伸缩组(ASG)方案迁移到云原生架构的实践过程。在这个过程中,我们直面了几个非常具体且棘手的技术挑战,这些挑战也进一步验证了我们选择 OKG 的正确性。
原始架构
1. 游戏服务器的“冷启动”之痛:分钟级的启动耗时
在原有的 ASG 方案中,一个新游戏服实例的启动流程漫长而笨重:
创建EC2实例 -> 下载游戏服务器镜像 -> 解压镜像 -> 下载Steam等平台依赖 -> 启动UE Game Server
整个过程走下来,启动一台可用的游戏服务器平均耗时约 3 分钟。在玩家数量平稳时,这个延迟尚可接受。但在高峰期或突发流量涌入时,这种分钟级的启动速度完全无法满足“弹性”的需求,会导致大量玩家因匹配不到服务器而等待,严重影响用户体验。而云原生的核心优势之一就是容器的秒级启动,如何将我们庞大的游戏服务器资产进行高效的容器化改造,是我们要攻克的第一个难关。
2. 公网 IP:昂贵且复杂的网络接入
对于《STRIDEN》这样的 FPS 游戏,为了实现最低的玩家延迟,通常需要玩家客户端能直接连接到游戏服务器实例的公网 IP 和端口。在旧的 ASG 方案下,这就带来了一个棘手的两难问题。
- 一方面,是高昂的经济成本。最直接的做法是为每一个游戏服务器实例都绑定一个独立的弹性公网 IP(EIP)。这种“一对一”的绑定模式,不仅导致了巨大的 IP 资源浪费,也直接推高了我们的云服务账单。
- 另一方面,是复杂的运维成本。管理成百上千个与服务器生命周期同步的公网 IP,以及它们对应的防火墙和安全组规则,是一项繁重且极易出错的工作。这层额外的网络接入管理,在批量创建和销毁服务器时,成为了自动化流程中的一个巨大障碍,严重拖慢了运维效率。
3. 运维的“手工作坊”模式:低效且高风险
旧的管理平台暴露了两个致命的运维缺陷:
- 缺乏自动弹性扩缩容:当需要增减服务器时,运维同学必须登录平台,手动地、一台一台地去创建或销毁实例。这种操作不仅效率低下,而且在全球多 Region 的部署环境下,运维管理的复杂度和出错风险呈指数级增长。
- 无法实现全球同步发布:当需要更新游戏服务器版本时,我们无法做到一键式的全球同步发布。运维需要逐个区域(Region)进行操作,不仅耗时耗力,还极易导致全球版本不一致的问题,这对于一款竞技类游戏是不可接受的。
4. “无感知”的缩容:成本与体验的失衡
游戏服务器是有状态的。最大的运维挑战之一,就是如何精准地缩容而又不影响在线玩家。旧的管理平台无法感知到某台游戏服务器上是否还有玩家在线。这意味着,在缩容决策时,我们只能“盲猜”:
- 如果策略过于保守,保留大量低负载甚至空载的服务器,会导致严重的成本浪费。
- 如果策略过于激进,直接销毁实例,则极有可能强制中断正在游戏中的玩家,造成最恶劣的用户体验。
这种无法在服务器成本和玩家体验之间取得精准平衡的困境,是促使我们必须寻求更智能化调度方案的核心驱动力。我们需要一个能准确标记“可回收”服务器,并执行“无损”缩容的控制器。
这些在传统架构下的难题,正是云原生,特别是像 OKG 这样专为游戏场景设计的框架所要解决的核心问题。它为我们提供了标准化的工具和声明式的 API,将这些复杂的、手动的运维流程,转变为自动化的、可靠的控制器逻辑。
云原生架构
面对上一章提到的种种挑战,我们并非束手无策。恰恰相反,这些问题正是我们选择 OKG 所期望解决的典型场景。它提供了一套为游戏“有状态”特性量身定制的工具集,帮助我们逐一击破了这些难关。
1. 破解“冷启动”:以容器镜像实现秒级部署
针对长达 3 分钟的启动时间,我们的核心思路是“变流程为镜像” (From Process to Image)。我们利用容器化技术,将原先需要在虚拟机启动后才执行的一系列步骤,全部预先“烘焙”到一个标准化的游戏服务器容器镜像中。
- 镜像预打包:我们将完整的游戏服务器程序、所有依赖(包括 Steam 相关库)以及优化的启动脚本,全部打包到一个容器镜像内。
- 优化慢流程:当需要扩容时,K8s 集群不再需要经历创建 EC2、下载、解压等漫长过程。它要做的仅仅是从镜像仓库(Registry)拉取这个预制好的镜像,并在几秒钟内启动容器。
通过这种方式,我们将游戏服务器的启动耗时从“分钟级”压缩到了“秒级”,为真正的无损弹性伸缩创造了先决条件。
2. 网络标准化:使用 OKG 网络模型
OKG 提供了接入层网络自动化管理 [4]的能力,用户无需手动为每个区服构建/析构网络,并且针对不同场景支持了不同的网络模型。Yahaha 根据自身业务需要在多云场景下部署的特点,选择使用了 Kubernetes-HostPort 模型。
并且由于项目使用 Steam SDK,需要容器内部实际运行的端口和向公网暴露的端口保持一致,因此使用了基于 Kubernetes-HostPort 模型的扩展特性:SameAsHost。
SameAsHost 特性的接入,无需对游戏服务器进行入侵,只需要在 GameServerSet 的 yaml 文件中增加部分参数配置即可。参见下面的伪代码 yaml,只需要修改 networkConf 即可。然后通过 DownwardAPI,下沉至业务容器中的网络信息,就可以提取到我们所需的网络端口,供游戏服业务容器使用。
apiVersion: game.kruise.io/v1alpha1 kind: GameServerSet // 省略.... spec: // 省略..... network: networkType: Kubernetes-HostPort networkConf: - name: ContainerPorts value: "striden-server:SameAsHost/UDP,SameAsHost/UDP" gameServerTemplate: spec: // 省略...... containers: volumeMounts: - name: podinfo mountPath: /etc/podinfo volumes: - name: podinfo downwardAPI: items: - path: "network" fieldRef: fieldPath: metadata.annotations['game.kruise.io/network-status']
3. 告别“手工作坊”:以声明式 API 实现自动化运维
OKG 引入了两个核心的 CRD (Custom Resource Definition)—— GameServer 和 GameServerSet,这正是我们实现自动化运维的关键。
- GameServerSet 实现自动扩缩容:它类似于 K8s 原生的 Deployment 或 ReplicaSet,但专为游戏服务器设计。运维工程师不再需要手动操作单台机器,而是通过一个 YAML 文件“声明”期望的状态,比如:“我需要在全球各区服,始终保持 100 个 v1.2 版本的《STRIDEN》游戏服务器在运行”。OKG 的控制器会持续工作,自动创建或删除 GameServer 实例,以确保实际状态与期望状态一致。结合 HPA(Horizontal Pod Autoscaler),我们还能基于 CPU、内存或玩家数量等自定义指标,实现全自动的弹性扩缩容。
- 声明式 API 赋能全球同步发布:当需要发布新版本时,我们只需修改 GameServerSet 定义文件中的镜像版本号,然后通过 GitOps [5] 等 CI/CD 工具,将这个变更同时应用(apply)到部署在全球各地的 K8s 集群上。K8s 和 OKG 的控制器会以标准化的滚动更新(或其他高级更新策略)方式,自动、安全地完成全球范围的版本升级,彻底告别了“人肉”发布的低效与风险。并且由于通过声明式 API 保证了部署流程的标准化,我们也可以不用绑定某个云服务厂商,可以选择多个云服务厂商,更加灵活。
4. 实现“智能缩容”:精准无损,兼顾成本与体验
这可以说是 OKG 对我们帮助最大的一点。它通过精巧的设计,完美解决了“无感知”缩容的难题。
- 状态感知:我们改造了游戏服务器程序,使其能够定期将自身的玩家数量等状态,通过将匹配状态、在线玩家数量、游戏服务器启动状态等自定义服务质量 [6] 写入 GameServer 本地文件,再通过 probe.sh 的探测机制,更新到其对应的 GameServer 资源的 opsState 。这使得 K8s 管理平台能够实时感知到每一台服务器的在线情况。
- 自定义缩容策略:OKG 允许我们定义缩容的优先级 [7]。在《STRIDEN》项目中,我们的策略非常明确:优先删除玩家数量为 0 的服务器 (playerCount == 0)。
- 自定义扩容策略:OKG 除了支持传统的按照 CPU 和 Memory 利用率来进行扩容之外,还支持设置 opsState 为 None 的游戏服的最小个数 [8]。在当前所有 opsState 为 None 的游戏服数量少于设置的值时,OKG 将自动扩容出新的游戏服,使 opsState 为 None 的游戏服数量满足设置的最小个数。当 opsState为 None 的游戏服务器数量大于设置的值 maxAvailable 时,OKG 则会自动缩容,保证集群资源不会浪费。
- 无损删除(Graceful Deletion):当控制器决定缩容某台服务器时,它并非粗暴地直接终止。而是先将其 opsState(操作状态)标记为 WaitToBeDeleted。同时我们也使用了最新的 Lifecycle Hook 功能 [9],通过 delete-block 标签控制游戏服务器的删除时机,在真正删除之前,我们的匹配服务会识别这个状态,并停止向该服务器分配新的游戏对局。
通过这套“标记 -> 隔离新玩家 -> 等待老玩家退出 -> 关闭匹配 -> 安全回收”的闭环流程,我们真正实现了精准的、对玩家体验毫无损伤的缩容,在保证服务质量的同时,最大限度地优化了服务器成本。
成果对比
指标 (Metric) | 传统 ASG 方案 | 云原生 OKG 方案 | 提升效果 |
服务器启动耗时 | ~ 3 分钟 | < 10 秒 | 秒级启动 |
扩容响应速度 | 分钟级 | 秒级 | 实时弹性 |
版本发布模式 | 手动、分区执行 | 声明式、全球同步 | 自动化、高效率 |
缩容策略 | 靠经验“盲猜” | 基于玩家状态精准回收 | 无损缩容、成本优化 |
运维人力成本 | 高 (依赖脚本和手动) | 低 (基础设施即代码) | 大幅降低 |
综上所述,OKG 并非一个简单的工具,它为我们提供了一整套符合游戏运维逻辑的“方法论”和“武器库”,让我们得以将《STRIDEN》的运维水平,从传统的、被动的模式,一举提升到了现代化的、自动化的云原生新高度。
三、总结与展望:这只是一个开始
回顾《STRIDEN》项目在短短两个月内完成云原生转型的历程,它验证了一条清晰、可行的路径,即如何利用云原生技术,从根本上解决现代在线游戏所面临的运维复杂性难题。
我们从这次转型中收获了什么?
- 一套标准化的方法论:我们成功地将游戏这种典型的“有状态服务”,无缝融入了 K8s 的声明式生态。从容器化打包、自动化部署到智能化的弹性伸缩与无损更新,我们沉淀了一套完整的、可复用的解决方案。
- 运维理念的深刻变革:我们的运维模式从过去的“人肉驱动、被动响应”,彻底转变为“声明驱动、主动管理”。运维团队得以从繁琐、重复的服务器管理工作中解放出来,将更多精力投入到平台稳定性建设、成本优化和工具链创新等更高价值的工作上。
- 成本与体验的双赢:通过引入 OKG ,我们终于有能力在服务器成本和玩家体验之间找到最佳平衡点。精准的无损缩容,让我们在为玩家提供稳定服务的同时,也为公司的资源投入带来了实实在在的降本增效。
展望未来
《STRIDEN》项目的成功仅仅是一个开始。这套经过实战检验的云原生游戏部署架构,将作为我们未来所有在线游戏的技术基座,被推广和应用到 Yahaha 平台的更多产品中。接下来,我们将继续在云原生领域深耕,探索更多可能性,例如:
- 更深度的 AIOps:结合可观测性数据与 AI 算法,实现更智能的故障预测和容量规划。
- 更灵活的调度策略:探索基于玩家画像、网络延迟等更多维度的混合调度,进一步优化全球玩家的匹配体验。
归根结底,技术是为产品和用户服务的。我们坚信,通过坚定不移地拥抱云原生,Yahaha 将能够构建一个更敏捷、更稳定、更具扩展性的游戏平台,最终赋能我们的开发者,为全球玩家创造出更多元、更精彩的互动娱乐体验。
四、欢迎体验云原生的力量
我们投入巨大心血打造的这套云原生架构,其最终的稳定性与流畅性,都凝聚在了《STRIDEN》这款游戏中。理论的价值最终要由实践来证明。我们诚挚地邀请您在 7 月 12 日前往 Steam,亲身体验云原生架构带来的秒级匹配与稳定服务。您的每一次流畅对战,都是对我们这套技术方案最好的压力测试与肯定。
STRIDEN Steam 项目主页:
https://store.steampowered.com/app/2052970/STRIDEN/
OKG 社区交流群:钉钉群号 44862615
相关链接:
[1] Yahaha Studios
[2] 《STRIDEN》
https://store.steampowered.com/app/2052970/STRIDEN/
[3] OpenKruiseGame
https://openkruise.io/zh/kruisegame/introduction
[4] 网络自动化管理
https://openkruise.io/zh/kruisegame/user-manuals/network
[5] GitOps
https://mp.weixin.qq.com/s/TOPcOsE5WCIIXkgo9jujlA
[6] 自定义服务质量
https://openkruise.io/zh/kruisegame/user-manuals/service-qualities
[7] 缩容的优先级
[8] 设置 opsState 为 None 的游戏服的最小个数
[9] Lifecycle Hook 功能
https://openkruise.io/zh/kruisegame/user-manuals/lifecycle
我们是阿里巴巴云计算和大数据技术幕后的核心技术输出者。
获取关于我们的更多信息~