ACK One x OpenKruiseGame 全球遊戲服多地域一致性交付最佳實踐

作者:劉秋陽、蔡靖

前言

在當今全球一體化的經濟環境下,數字娛樂產業正日益成爲文化和商業交流的有力代表。在此背景下大量遊戲廠商嘗試遊戲出海並取得了令人矚目的成績,許多遊戲以全球同服架構吸引着世界各地廣泛的玩家羣體。遊戲全球化部署不僅擴大了單個產品的市場規模,而且提高了遊戲廠商在全球範圍的影響力,但與此同時也帶來了許多技術挑戰:

遊戲服務所要求的高頻交互和低延遲性質,使得在全球同服框架下,遊戲服務器需要在多個地區進行部署。在實際運營過程中,我們通常需要根據目標用戶羣的地理位置和對延遲的容忍度預先規劃服務器的設置地點。一般而言,以下這些區域是我們優先考慮的服務器地址——美東地區人口稠密,能爲大批北美玩家提供服務;法蘭克福地區是歐洲互聯網的交匯點,能有效服務整個歐洲的玩家網絡體驗;新加坡地區則廣泛覆蓋東南亞的玩家羣體;東京地區主要爲日本和韓國的玩家提供支持

面對不同地區可能存在的配置差異、遊戲版本更新以及服務器數目的不一致,如何在全球範圍內有效實現遊戲服的一致性交付,成爲我們在全球同服架構設計時必須面對和解決的核心挑戰。本文將通過一個示例來爲大家講解全球遊戲服多地域一致性交付最佳實踐。

部署架構

在示例中,我們計劃在上海、東京、法蘭克福三地開服,因此我們需要這三個地區的基礎設施資源。面對基礎設施異構且複雜的情景,雲原生帶來的聲明式 API、一致性交付的特性可以充分屏蔽底層資源的差異性,讓遊戲運維工程師專注應用本身,大幅度提高遊戲服交付效率。從區域自治穩定性、用戶調度複雜性的角度考慮,每個開服地域獨立部署Kubernetes集羣,並通過多集羣的能力統一運維管理是我們認爲遊戲服一致性交付的最佳方式。

在本次實踐中,我們選擇阿里雲分佈式雲容器平臺 ACK One 管理多地域 Kubernetes 集羣。ACK One 作爲阿里雲面向混合雲、多集羣、容災等場景退出的企業級雲原生平臺,可以連接和管理任何地域、任何基礎設施上的 Kubernetes 集羣,並提供一致的管理,支持對應用、流量、安全、存儲、可觀測等進行統一管控。

本示例的部署架構如圖所展示,包括 3 個不同地域的生產環境和 1 個開發測試環境。通常來說,通過在研發測試環境中驗證並確認版本穩定後,再將其部署到生產環境,這一流程有助於確保項目的整體穩定性,並有效預防潛在的風險。

示例採用多集羣混合雲架構。具體地,Shanghai 集羣、Frankfurt 集羣、及 ShangHai Dev 集羣爲阿里雲 ACK 集羣;而 Japan 集羣爲非阿里雲 Kubernetes 集羣,其以註冊集羣的方式集成和納管。在每個集羣內部,我們採用了 GameServerSet 來部署遊戲服務器。GameServerSet 是由雲原生計算基金會(CNCF)孵化中的開源項目 OpenKruise 所提供的遊戲專項工作負載。與原生的 Deployment 和 StatefulSet 工作負載相比,GameServerSet 具備遊戲語意,更貼近遊戲場景,使得對遊戲服務器的運維管理更加方便和高效。

集羣納管

Kubernetes 集羣準備完成後,我們使用 ACK One 艦隊統一管理雲上雲下集羣:

首先,通過 ACK One 註冊集羣 [ 1] 將 IDC 或第三方公共雲集羣註冊到阿里雲,具體地:

  1. 創建註冊集羣 [ 2] ,並在創建好的註冊集羣,右側單擊操作列下的詳情

  2. 集羣信息頁面單擊連接信息頁籤。

  3. 集羣導入代理配置區域根據需要選擇公網或者私網,然後單擊右側的複製,將公網或私網頁籤的內容複製到一個文件中,並執行 kubectl 命令,將目標集羣註冊至新集羣中。例如,新建 agent.yaml 文件,將以上內容複製到 agent.yaml 文件中,並在目標集羣中執行 kubectl apply -f agent.yaml 命令。

通過此步驟,Japan 集羣已經被註冊到阿里雲。

其次,開啓 ACK One 多集羣艦隊 [ 3] ,並在 ACK One 控制檯 [ 4] 上關聯註冊集羣和雲上集羣。由於集羣跨多個地域,所以 ACK One 艦隊會使用公網的方式關聯集羣,艦隊所在 VPC 則需配置公網 NAT 網關。

至此,一個多集羣艦隊已經 Ready。示例對應的示意圖如下:

遊戲服發佈

在執行示例具體的發佈操作之前,我們一起認識下雲原生的交付思想 —— 聲明式而非面向過程,這也就意味着雲原生式的應用交付關注的並不是應用的部署過程而是對應用的定義。而應用的定義就是 Yaml,它通過配置參數化的方式描述這個應用該是什麼樣子。因此,一切有關應用的變更和發佈實際上都是對應用描述(Yaml)的更改。

至此我們發現,我們需要一個倉庫將 Yaml 落盤,記錄當前對應用的描述,並且能夠追溯和審計過去 Yaml 的變更。說到這裏我相信大家會發現 git repo 天然符合該特點,運維工程師可以通過提交 Commit 和 Merge Request 的方式將 Yaml 上傳並落盤,權限管理、審計都遵循 git 規範。在理想狀態下,我們只需要維護一套對遊戲服描述的 Yaml,一鍵觸發全球多地域的遊戲服發佈,無需面向過程一一操作集羣,去執行部署動作。這就是 GitOps 的思想。

在 GitOps 落地過程中最富有挑戰的事情實際上是對遊戲服應用的描述抽象。正如文章開頭提到的,每個地域的遊戲服或多或少存在着一些差異,似乎難以通過一個 Yaml 將所有遊戲服都概括。舉個例子,在上海我希望發佈 10 個遊戲區服,而在法蘭克福我只希望發佈 3 個區服,這樣一來,一個 Yaml 因爲 replicas 字段的差異就無法描述不同地域的遊戲服。難道我們需要爲每一個地域維護一個 Yaml 嗎?這樣也非合理的做法,當進行非差異性字段變更時(例如,爲所有地域的遊戲服打上一個標籤),我們需要重複地執行多個 Yaml 的更改,集羣數量多的時候容易造成遺漏或者錯誤,這並不符合雲原生交付思想。

實際上,我們可以通過 Helm Chart 進行遊戲服應用的進一步抽象,將差異性的部分作爲 Value 提取出來。在我們本次的示例中(GitHub 遊戲服 Helm Chart 示例 [ 5] ),我們抽象出這樣幾個差異性字段:

  • 主鏡像 —— 每個地域/集羣的主鏡像可能存在差異
  • sidecar 鏡像 —— 每個地域/集羣的 sidecar 鏡像可能存在差異
  • 副本數 —— 每個地域/集羣的發佈的遊戲服數量可能存在差異
  • 是否自動伸縮 —— 每個地域/集羣對於自動伸縮的要求可能存在差異

除此之外的其他字段都保持一致,意味着不存在地域差異性影響。

在理解了 GitOps 並對遊戲服應用進行了抽象、描述後,我們利用 ACK One GitOps 進行應用交付的實操。接下來我們展開具體的操作:

連接 Git 倉庫

登錄 ArgoCD UI:在 ACK One 控制檯左側導航欄艦隊 -> GitOps -> GitOps 控制檯,並在登錄頁面,單擊 LOG IN VIA ALIYUN,登錄到 ArgoCD UI。需要公網訪問則需要開通公網訪問 GitOps [ 6]

  1. 在 ArgoCD UI 左側導航欄選擇 Settings,然後選擇 Repositories > + Connect Repo。

  2. 在彈出的面板中配置以下信息,然後單擊 CONNECT 添加連接。

發佈 PvE 類型遊戲

PvE 類型遊戲通常存在區服概念,大多情況下由運維工程師手動控制各地域的開服數量。關於 PvE 遊戲雲原生化最佳實踐可參考 OKG PvE 遊戲最佳實踐文檔 [ 7]

白屏化管理應用

在初次嘗試 ArgoCD 時,我們可以使用白屏控制檯爲每個地域的集羣分別創建 Application:

  1. 在 ArgoCD UI 左側導航欄選擇 Applications,然後單擊+NEW APP。

  2. 在彈出的面板配置以下信息,然後單擊 CREATE 進行創建。(以 opengame-demo-shanghai-dev 爲例)。

  1. 創建完成後,在 Application 頁面,即可看到 opengame-demo-shanghai-dev 的應用狀態。如果 SYNC POLICY 選擇的是 Manual 方式,需要手動點擊 SYNC,將應用同步部署至目標集羣。應用的 Status 爲 Healthy 和 Synced,表示已經成功同步。

  1. 單擊 opengame-demo-shanghai-dev 應用名稱,即可查看應用詳情,展示應用相關的 Kubernetes 資源的拓撲結構及相應狀態。

通過 ApplicationSet 一鍵發佈

對 ArgoCD 有所熟悉了之後,我們也可以通過 ApplicationSet 對象來一鍵發佈遊戲服。各個集羣的差異性通過elements抽象出來,例如下面 Yaml 中,以集羣維度抽象出三個字段:cluster 集羣名稱用於區分 Application 名稱;url 用於區分目標集羣地址;replicas 用於區別不同集羣發佈的遊戲服數量。

編寫完成該 ApplicationSet Yaml 後,將其部署到 ACK One 艦隊集羣即可自動創建出四個 Application。

kubectl apply -f pve.yaml -n argocd

# pve.yaml 內容如下:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: minecraft
spec:
  generators:
  - list:
      elements:
      - cluster: shanghai-dev
        url: <https://47.100.237.xxx:6443>
        replicas: '1'
      - cluster: shanghai-prod
        url: <https://47.101.214.xxx:6443>
        replicas: '3'
      - cluster: frankfurt-prod
        url: <https://8.209.103.xxx:6443>
        replicas: '2'
      - cluster: japan-prod
        url: <https://10.0.0.xxx:6443>
        replicas: '2'
  template:
    metadata:
      name: '{{cluster}}-minecraft'
    spec:
      project: default
      source:
        repoURL: '<https://github.com/AliyunContainerService/gitops-demo.git>'
        targetRevision: HEAD
        path: manifests/helm/open-game
        helm:
          valueFiles:
          - values.yaml
          parameters: #對應helm chart中提取的value參數
          - name: replicas
            value: '{{replicas}}'
          - name: scaled.enabled 
            value: 'false'
      destination:
        server: '{{url}}'
        namespace: game-server #部署到對應集羣的game-server命名空間下
      syncPolicy:
        syncOptions:
          - CreateNamespace=true #若集羣中命名空間不存在則自動創建

在該 Yaml 中,所有的鏡像版本都一致,若希望各集羣鏡像版本出現差異,可以仿照 replicas 的方式,添加新的 parameters 參數。

發佈 PvP 類型遊戲

對於 PvP 類型的遊戲,房間服的數量由自身伸縮器調配,而非運維工程師手動指定。有關 PvP 類型遊戲的雲原生化最佳實踐可參考 OKG PvP 遊戲最佳實踐文檔 [ 8]

在 OKG 中我們通過爲 GameServerSet 配置 ScaledObject 對象來實現房間服的彈性伸縮。因此,scaled.enabled 在此場景下需要開啓。此外,房間服的副本數有 ArgoCD 和 OKG 2 個控制者而衝突,可以通過讓 ArgoCD 忽略 GameServerSet 資源的副本數變化來解決,具體在 spec.ignoreDifferences 設置相應字段即可。考慮以上情況,該 pvp.yaml 如下所示:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: pvp
spec:
  generators:
  - list:
      elements:
      - cluster: shanghai-dev
        url: <https://47.100.237.xxx:6443>
      - cluster: shanghai-prod
        url: <https://47.101.214.xxx:6443>
      - cluster: frankfurt-prod
        url: <https://8.209.103.xxx:6443>
      - cluster: japan-prod
        url: <https://10.0.0.xxx:6443>
  template:
    metadata:
      name: '{{cluster}}-pvp'
    spec:
      project: defaultminecraft
      ignoreDifferences: # 設置 GameServerSet minecraft副本數目由集羣自控制
      - group: game.kruise.io
        kind: GameServerSet
        name: minecraft
        namespace: game
        jsonPointers:
        - /spec/replicas
      source:
        repoURL: '<https://github.com/AliyunContainerService/gitops-demo.git>'
        targetRevision: HEAD
        path: manifests/helm/open-game
        helm:
          valueFiles:
          - values.yaml
      destination:
        server: '{{url}}'
        namespace: pvp-server
      syncPolicy:
        syncOptions:
          - CreateNamespace=true

總結

本文通過一個示例介紹了 ACK One 在全球遊戲服多地域一致性交付最佳實踐。示例中涉及到 4 個 Kubernetes 集羣和一個簡單遊戲服 Yaml。而當實際生產環境中,很可能出現集羣數量更多、遊戲服應用描述更復雜的情況,此時做好應用的抽象是關鍵之處。

歡迎加入雲原生遊戲釘釘羣 (羣號:44862615) 和 OpenKruiseGame 開發者以及遊戲行業研發運維工程師們共同溝通討論;有關 ACK One 的相關問題也可以加入釘釘羣 (羣號:35688562) 進行諮詢。

相關鏈接:

[1] ACK One 註冊集羣

https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/overview-9?spm=a2c4g.11186623.0.0.3e4157eb3o9J3v

[2] 創建註冊集羣

https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/create-a-cluster-registration-proxy-and-register-a-kubernetes-cluster-deployed-in-a-data-center?spm=a2c4g.11186623.0.0.2f833eb6R1YTOq

[3] 開啓 ACK One 多集羣艦隊

https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/enable-fleet-management?spm=a2c4g.11186623.0.0.8cc462853sti0H

[4] ACK One 控制檯

https://account.aliyun.com/login/login.htm?oauth_callback=https%3A%2F%2Fcs.console.aliyun.com%2Fone

[5] GitHub 遊戲服 Helm Chart 示例

https://github.com/AliyunContainerService/gitops-demo/tree/main/manifests/helm/open-game

[6] 需要開通公網訪問 GitOps

https://help.aliyun.com/zh/ack/distributed-cloud-container-platform-for-kubernetes/user-guide/enable-gitops-public-network-access?spm=a2c4g.11186623.0.0.e7db48aeenz8AX

[7] OKG PvE 遊戲最佳實踐文檔

https://openkruise.io/zh/kruisegame/best-practices/pve-game

[8] OKG PvP 遊戲最佳實踐文檔

https://openkruise.io/zh/kruisegame/best-practices/session-based-game/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章