探索使用Kubernetes扩展专用游戏服务器:第3部分 - 扩展节点

简介: 探索使用Kubernetes扩展专用游戏服务器:第3部分 - 扩展节点

在前两篇文章中,我们研究了如何在 Kubernetes 上托管专用游戏服务器,并测量和限制其内存和 CPU 资源。在本期中,我们将探讨如何利用上一篇文章中的 CPU 信息来确定何时需要扩展Kubernetes 集群,因为随着玩家人数的增加,我们已经没有足够的空间来容纳更多的游戏服务器。


分离 Apps 和 Game Servers


在开始编写代码以增加 Kubernetes 集群的大小之前,我们应该做的第一步是将我们的应用程序(例如,match makersgame server controllers 和即将编写的 node scaler)分离到不同的应用程序中 一 在集群的不同节点上,而不是游戏服务器运行的地方。


这有几个好处:


  1. 我们的应用程序的资源使用情况现在对游戏服务器没有影响,因为它们在不同的计算机上。这意味着,如果 matchmaker 由于某种原因而导致 CPU 峰值,那么将存在一个额外的障碍,以确保它不会不适当地影响正在运行的专用游戏服务器。
  2. 这使得扩展和缩小专用游戏服务器的容量变得更容易 — 因为我们只需要查看特定节点集的游戏服务器使用情况,而不是整个集群中的所有潜在容器。
  3. 在这种情况下,我们可以使用带有更多 CPU 核和内存的大机器来运行游戏服务器节点,也可以使用带有更少内核和内存的小机器来运行控制器应用程序,因为它们需要的资源更少。我们基本上能够为手头的工作选择合适的机器尺寸。这给了我们很大的灵活性,同时仍然具有成本效益。


Kubernetes 使建立异构集群相对简单,并为我们提供了工具,可通过节点上的节点选择器的功能来指定集群中 Pod 的调度位置。


值得注意的是,beta 中还具有更复杂的 Node Affinity 功能,但是在此示例中我们不需要它,因此我们暂时将其忽略。


首先,我们需要将标签(一组键-值对)分配给集群中的节点。这与您使用 Deployments 创建 Pods 并使用 Services 公开它们时所看到的情况完全相同,只是将其应用于节点。我使用谷歌的云平台的容器引擎和它使用节点池标签应用于集群中的节点创建和建立异构集群——但你也可以做类似的事情在其他云提供商,以及直接通过 Kubernetes API 或命令行客户端。


在本例中,我将标签role:apps和role:game-server添加到集群中的适当节点。然后,我们可以在Kubernetes配置中添加一个nodeSelector选项,以控制集群中的 Pods被调度到哪些节点上面。

image.gif

例如,下面是 matchmaker 应用程序的配置,您可以看到节点选择器设置为 role:apps,以确保它只在应用程序节点(标记为“apps”角色的节点)上创建容器实例。


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: matchmaker
spec:
  replicas: 5
  template:
    metadata:
      labels:
        role: matchmaker-server
    spec:
      nodeSelector:
        role: apps # here is the node selector
      containers:
      - name: matchmaker
        image: gcr.io/soccer/matchmaker
        ports:
        - containerPort: 8080


同样的,我们可以从上一篇文章中调整配置,使所有专用的游戏服务器 pod 调度仅在我们专门为它们指定的机器上,即那些标记为 role: game-server


apiVersion: v1
kind: Pod
metadata:
  generateName: "game-"
spec:
  hostNetwork: true
  restartPolicy: Never
  nodeSelector:
    role: game-server # here is the node selector
  containers:
    - name: soccer-server
      image: gcr.io/soccer/soccer-server:0.1
      env:
        - name: SESSION_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        resources:
          limits:
            cpu: "0.1"


请注意,在示例代码中,使用 Kubernetes API 提供了与上面相同的配置,但 yaml 版本更容易理解,而且它是我们在整个系列中一直使用的格式。


扩大规模的策略


云提供商上的 Kubernetes 往往带有自动伸缩功能,比如谷歌云平台集群自动伸缩器,但由于它们通常是为无状态应用程序构建的,而且我们的专用游戏服务器将游戏模拟存储在内存中,所以它们在这种情况下无法工作。然而,使用 Kubernetes 提供的工具,构建我们自己的定制 Kubernetes 集群自动scaler 并不是特别困难!


对于云环境,在 Kubernetes 集群中扩展和缩小节点可能更有意义,因为我们只

想为我们需要/使用的资源付费。如果我们在自己的场所中运行,则更改 Kubernetes 集群的大小可能没什么意义,而且我们可以在所有拥有的机器上运行一个大型集群,并将它们保持为静态大小,因为添加 并且删除物理计算机要比在云上花费更多,并且由于我们拥有/租赁计算机的时间更长,因此不一定能节省我们的钱。


有多种潜在策略可用来确定何时要扩展集群中的节点数量,但是在本示例中,我们将使事情变得相对简单:


  • 定义游戏服务器的最小和最大节点数,并确保我们在该限制之内。
  • 使用 CPU 资源容量和使用率作为我们跟踪集群中一个节点上可以容纳多少专用游戏服务器的指标(在本例中,我们假设我们总是有足够的内存)。
  • 在集群中,为一定数量的游戏服务器定义 CPU 容量缓冲区。也就是说,如果在任何时刻,你都无法在不耗尽集群 CPU 资源的情况下将 n 个服务器添加到集群中,那么就增加更多的节点。
  • 每当启动新的专用游戏服务器时,请计算是否需要在群集中添加新节点,因为跨节点的 CPU 容量低于缓冲区数量。
  • 作为故障保护,每隔 n 秒,还要计算是否需要将新节点添加到群集,因为所测量的 CPU 容量资源在缓冲区下方。


微信图片_20220611154641.png

创建 Node Scaler


node scaler 本质上是运行一个事件循环来执行上面概述的策略。

结合使用 Go 和原生 Kubernetes Go client library 库可以相对容易地实现这一点,如下面在节点缩放器的 Start() 函数中所见。


注意,为了使事件循环更清晰,我已经删除了大部分错误处理和其他样板文件,但如果您感兴趣,这里是原始代码。


// Start the HTTP server on the given port
func (s *Server) Start() error {
        // Access Kubernetes and return a client
        s.cs, _ = kube.ClientSet()
        // ... there be more code here ... 
        // Use the K8s client's watcher channels to see game server events
        gw, _ := s.newGameWatcher()
        gw.start()
        // async loop around either the tick, or the event stream
        // and then scaleNodes() if either occur.
        go func() {
                log.Print("[Info][Start] Starting node scaling...")
                tick := time.Tick(s.tick)
                // ^^^ MAIN EVENT LOOP HERE ^^^
                for {
                        select {
                        case <-gw.events:
                                log.Print("[Info][Scaling] Received Event, Scaling...")
                                s.scaleNodes()                          
                        case <-tick:
                                log.Printf("[Info][Scaling] Tick of %#v, Scaling...", tick)
                                s.scaleNodes()
                        }
                }
        }()
        // Start the HTTP server
        return errors.Wrap(s.srv.ListenAndServe(), "Error starting server")
}


对于那些不熟悉 Go 的人,让我们分析一下:


  1. kube.ClientSet() – 我们有一小段实用程序代码,它向我们返回一个 Kubernetes ClientSet,它使我们能够访问正在运行的集群的 Kubernetes API
  2. gw, _ := s.newGameWatcherKubernetes 具有 API,使您可以监视整个集群中的更改。在这种特殊情况下,此处的代码返回一个包含 Go Channel(本质上是一个阻塞队列)的数据结构,特别是 gw.events,每当在集群中添加或删除游戏 Pod 时,该数据结构都将返回一个值。
  3. tick := time.Tick(s.tick) – 这将创建另一个 Go Channel,该 Channel 一直阻塞到给定时间(在这种情况下为10秒),然后返回一个值。
  4. 主事件循环在 “// ^^^ MAIN EVENT LOOP HERE ^^^” 注释下。在此代码块中是一条 select 语句。这实际上声明了系统将阻塞,直到 gw.events channeltick channel(每 10 秒触发一次)返回一个值,然后执行 s.scaleNodes()。这意味着,每当添加/删除游戏服务器或每 10 秒触发一次 scaleNodes 命令。
  5. s.scaleNodes() – 运行上面概述的规模节点策略。


s.scaleNodes() 中,我们通过 Kubernetes API 查询我们在每个 Pod 上设置的 CPU 限制,以及集群中每个 Kubernetes 节点上可用的总 CPU。我们可以通过 Rest APIGo ClientPod specification 中查看已配置的 CPU 限制,这使我们能够跟踪每台游戏服务器占用的 CPU 数量以及任何存在于节点上 Kubernetes 管理的 Pod。通过 Node specificationGo Client 还可以跟踪每个节点中可用的 CPU 容量。在这种情况下,需要对 Pods 占用的 CPU 数量求和,然后从每个节点的容量中减去 CPU 的数量,然后确定是否需要将一个或多个节点添加到集群中,这样我们才能保持该缓冲区空间,用于创建新的游戏服务器。


如果您在此示例中深入研究代码,将会看到我们正在使用 Google Cloud Platform 上的 API 向集群添加新节点。为 Google Compute Engine 托管实例组提供的 API 允许我们从Kubernetes 集群的 Nodepool 中添加(和删除)实例。话虽这么说,任何云提供商都将具有类似的 API,让您做同样的事情,在这里您可以看到我们定义的接口,该接口用于抽象该实现细节,以便可以轻松地对其进行修改以与其他提供商一起使用。


部署节点缩放器


在下面,您可以看到节点缩放器的部署 YAML。如您所见,环境变量用于设置所有配置选项,包括:


  • 集群中的哪些节点应进行管理
  • 每个专用游戏服务器需要多少 CPU
  • 最小和最大节点数
  • 一直存在多少缓冲区


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nodescaler
spec:
  replicas: 1 # only want one, to avoid race conditions
  template:
    metadata:
      labels:
        role: nodescaler-server
    spec:
      nodeSelector:
        role: apps
      strategy:
        type: Recreate
      containers:
      - name: nodescaler
        image: gcr.io/soccer/nodescaler
        env:
          - name: NODE_SELECTOR # the nodes to be managed
            value: "role=game-server"
          - name: CPU_REQUEST # how much CPU each server needs
            value: "0.1"
          - name: BUFFER_COUNT # how many servers do we need buffer for
            value: "30"
          - name: TICK # how often to tick over and recheck everything
            value: "10s"
          - name: MIN_NODE # minimum number of nodes for game servers
            value: "1"
          - name: MAX_NODE # maximum number of nodes for game servers
            value: "15"


您可能已经注意到,我们将部署设置为 replicas: 1。我们这样做的原因是,我们总是希望在Kubernetes 集群中在任何给定的时间点上只有一个活跃的 node scaler 实例。这确保了集群中不会有超过一个进程试图扩大或最终缩小我们的节点,这肯定会导致竞争条件,并可能导致各种奇怪的情况。


同样,如果要更新节点缩放器,要确保在创建节点缩放器之前正确关闭节点缩放器,我们还配置strategy.type: Recreate,以便 Kubernetes 在重新创建节点缩放器之前销毁当前运行的节点缩放器 Pod。更新版本,也避免了任何潜在的竞争情况。


看看它的实际应用


部署节点缩放器后,让我们跟踪日志并查看其运行情况。在下面的视频中,通过日志可以看到,当群集中有一个节点分配给游戏服务器时,我们有能力启动 40 个专用游戏服务器,并配置了 30 个专用游戏服务器的缓冲区的需求。当我们通过 matchmaker 通过运行专用游戏服务器来填充可用的CPU容量时,请注意在剩余空间中可创建的游戏服务器数量会如何下降,最终会添加一个新节点来维护缓冲区!

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
1月前
|
弹性计算 安全 数据安全/隐私保护
幻兽帕鲁Palworld怎么搭建多人专用游戏服务器,阿里云上小白搭建攻略
对于许多《幻兽帕鲁》的忠实玩家来说,如何与好友一起联机探索这片神秘的大陆,一直是大家关心的焦点。或许你曾因为复杂的服务器设置而犹豫不决,但现在,一切都将变得简单明了。今天,我将为大家带来一份详尽的攻略,教你如何利用阿里云轻松搭建《幻兽帕鲁》的多人游戏专用服务器。
|
25天前
|
Kubernetes 容器
k8s容器时间与服务器时间不一致问题
k8s容器时间与服务器时间不一致问题
21 0
|
7天前
|
存储 Java 网络安全
ZooKeeper【搭建 03】apache-zookeeper-3.6.0 伪集群版(一台服务器实现三个节点的ZooKeeper集群)
【4月更文挑战第10天】ZooKeeper【搭建 03】apache-zookeeper-3.6.0 伪集群版(一台服务器实现三个节点的ZooKeeper集群)
12 1
|
28天前
|
Kubernetes API 调度
总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)
总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)
60 0
|
1月前
|
存储 Kubernetes 监控
容器服务ACK常见问题之容器服务ACK worker节点选择不同地域失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
1月前
|
Kubernetes 监控 Linux
容器服务ACK常见问题之新增一台CentOS 5.4内核的节点失败如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
1月前
|
Kubernetes 容器
k8s集群部署成功后某个节点突然出现notready状态的问题原因分析和解决办法
k8s集群部署成功后某个节点突然出现notready状态的问题原因分析和解决办法
17 0
|
1月前
|
消息中间件 存储 Kafka
Kafka【环境搭建 02】kafka_2.11-2.4.1 基于 zookeeper 搭建高可用伪集群(一台服务器实现三个节点的 Kafka 集群)
【2月更文挑战第19天】Kafka【环境搭建 02】kafka_2.11-2.4.1 基于 zookeeper 搭建高可用伪集群(一台服务器实现三个节点的 Kafka 集群)
140 1
|
1月前
|
弹性计算 搜索推荐
幻兽帕鲁palworld专用服务器价格多少钱?2024年阿里云幻兽帕鲁服务器1个月26元起
在探讨《幻兽帕鲁》游戏服务器价格前,我们先来简单了解这款近期爆火的游戏。《幻兽帕鲁》是一款由Pocketpair匠心打造的开放世界生存游戏,其独树一帜的题材与画风在全球范围内吸引了众多忠实玩家。随着游戏热度的不断攀升,越来越多的玩家开始追求更加个性化的游戏体验,搭建专属游戏服务器成为他们的首选。
|
1月前
|
弹性计算 Ubuntu 数据可视化
多人组队!2024年阿里云《幻兽帕鲁》专用服务器搭建部署教程,新手搭建指南
想要与好友在《幻兽帕鲁》中尽享私密、稳定的游戏时光吗?那就跟随本指南,一步步搭建属于您的专属游戏服务器吧!首先,您需要拥有一台服务器。在这里,我们强烈推荐使用阿里云服务器。它不仅能让您和朋友在独立的云端空间中畅快游戏,更能确保游戏的稳定性和私密性。

推荐镜像

更多