工程筆記
從 K8s 遷移到 Amazon GameLift:Palworld 幻獸帕魯多人伺服器架構實戰
Pocketpair × AWS — Externalize State, Adapter Pattern, and Exactly-One Persistent Worlds on Ephemeral Compute
AI Engineering Bloss0m Note 057 這是一場充滿實戰乾貨的架構分享。議程主題為:
從 K8s 遷移到 Amazon GameLift:Palworld 幻獸帕魯多人遊戲伺服器架構
主講分為兩段:
- 前半:AWS 專員介紹 Amazon GameLift 託管服務
- 後半:Pocketpair 平台工程師 ヤマウチ・ケイゴ(Keigo Yamauchi) 分享 Palworld 官方伺服器從 Kubernetes 遷移到 GameLift 的設計與踩坑
核心命題很尖銳:雲端運算本質是臨時、可拋棄的(Ephemeral),但 Palworld 的遊戲世界卻高度持久(Persistent)。要在託管架構上跑 24/7 世界,必須把「計算可替換」與「狀態不可丟」徹底拆開。
亦可對照本站談企業平台化的文章,例如 AWS × HoyaBit Bedrock AgentCore——同樣是把基礎設施稅交給平台,讓團隊專注核心邏輯;只是這裡的核心是遊戲世界存檔,而非 Agent 工作流。
議程總覽
| 段落 | 重點 | 帶走什麼 |
|---|---|---|
| GameLift 高階介紹 | 託管比喻、彈性、成本、更新效率 | 為何考慮離開自建/自管 K8s |
| Palworld 遷移設計 | 狀態外部化、Adapter、Exactly One、監控串接 | 持久世界上託管的設計原則 |
| 三大故障案例 | Terraform Drift、假健康 Fleet、Ping 失效 | 遷移後真正會踩的坑 |
| Key Takeaways | 四條啟示 | 可複用的平台工程檢查清單 |
第一部分:Amazon GameLift 服務高階介紹
1. 什麼是託管服務?買車 vs 叫計程車
講者以生活比喻說明 Managed Service:
| 模式 | 比喻 | 你要負責什麼 |
|---|---|---|
| 自建伺服器 | 買車 | 養車、換零件、保養、維修——大量運維精力 |
| 託管服務 | 叫計程車/租車 | 專注「目的地」:遊戲開發與設計;車輛保養與駕駛交給 AWS |
重點不是「自己完全不用懂基礎設施」,而是把重複且高風險的運維負擔,轉成可預期的平台能力與 SLA。
2. GameLift:為即時多人遊戲打造的 purpose-built 服務
GameLift 定位為專為多人連線、低延遲、即時(Real-time)遊戲設計的服務。分享中提到的實績與能力包括:
極端壓力測試
AWS 團隊自行測試約 1 億同時在線用戶(CCU) 的極限場景,並達成:
- 每秒增加約 10 萬 名玩家
- 每分鐘處理 6 萬 個以上 Session
這類數字是壓力上限訊號;對多數團隊更實用的,是後面「按 Session 縮放」與 Spot 安全回收這類日常運維能力。
全球化部署與成本優勢
| 面向 | 重點 |
|---|---|
| 區域覆蓋 | 全球約 25 個 AWS 區域(含台北區域,以及當年 6 月新增的越南 Local Zone) |
| 頻寬 | 使用第六代(Gen 6)以後機型,網路流出頻寬(Bandwidth)免費,主要收取運算費用 |
| 配對 | 支援 FlexMatch 玩家配對引擎 |
| 可靠與安全 | 提供 99.9% SLA;內建 UDP 專屬 DDoS 防護 |
多重成本優化
-
依 Session 自動縮放(Auto-scaling) 傳統常以 CPU/記憶體縮放;但多人遊戲中,CPU 可能仍低、Session 卻已滿,必須開新機器。GameLift 能針對 Session 數量 縮放,更贴近遊戲真實瓶頸。
-
Spot 實例安全託管 價格可達原價約 2 折。關鍵不只是便宜,而是預測回收:在 Spot 快被回收前提早發訊號,讓伺服器安全移轉存檔,降低玩家體驗中斷。
-
Graviton(ARM)實例 提供高性價比運算選項。
更新效率
- 過去更新/發 Patch:約 40 分鐘甚至 1 小時
- 後來縮短到約 8 分鐘
- 當年目標:全球部署縮到 5 分鐘內
對正式營運的遊戲而言,部署窗口縮短不只是工程爽感,而是事故修復與活動上線的反應速度。
第二部分:Palworld 遷移實戰——持久世界如何住進拋棄式運算
Keigo Yamauchi 拆解官方伺服器從 K8s 遷到 GameLift 的核心難題與解法。
1. 核心衝突:Ephemeral Compute × Persistent World
| 雲端本質 | Palworld 現實 |
|---|---|
| 基礎設施臨時、可拋棄 | 世界高度持久,進度絕對不能丟 |
| 實例可隨時替換 | 伺服器 24/7 運行;崩潰/斷線立刻影響玩家 |
現況規模感:
- 每個伺服器最多約 128 個玩家基地
- 約 1000 隻帕魯(生物)
- 需要持續運行,且 絕對不能遺失世界進度(State)
於是設計原則被收斂成一句話:
計算是可拋棄的,但狀態(存檔)不是。
2. 四大關注重點
① 狀態外部化(Externalize State)
為了讓運算實例隨時可替換,存檔必須剝離到外部 Amazon S3:
flowchart LR
Boot[啟動] -->|從 S3 載入最新存檔| Run[運行中]
Run -->|定期同步寫入 S3| Run
Run -->|關機快照上傳| Stop[關機 / 替換]
Stop -->|GameLift 拉起新實例| Boot
存檔再分成三層防護:
| 類型 | 用途 |
|---|---|
| Active Save | 目前玩家遊玩的存檔點 |
| Snapshots | 故障時歷史回滾 |
| Exports | 開發調查、共享或 debug |
這不只是「備份」,而是讓世界狀態成為一等公民,運算變成可替換的執行器。
② 生命週期轉譯(Translate Life Cycle)
GameLift 有既定生命週期協定(宣告 Ready、結束 Session、回報健康度等)。為了避免大改遊戲本體,Pocketpair 做了輕量 Adapter/Wrapper:
- Wrapper 負責與 GameLift 溝通
- 遊戲本體不必大幅重構
- 保留遷移彈性與後續換平台空間
這是經典 Adapter Pattern:用薄適配層吸收平台差異,而不是讓業務核心耦合託管 API。
③ 確保「永遠只有一個」世界實例(Exactly One)
Palworld 每個伺服器世界必須唯一。做法包括:
- 將單一 Fleet 容量限制為 1;實例異常消失時,GameLift 自動重建
- 防止競態(Race Conditions):重建時若多實例同時讀寫同一 S3 存檔,可能損壞檔案——因此在外部做併發抑制與冪等操作
- 每 4 小時 graceful 重啟計畫:
sequenceDiagram
participant EB as EventBridge Cron
participant L as Lambda
participant W as Server Wrapper
participant S3 as Amazon S3
participant GL as GameLift
EB->>L: 每 4 小時觸發
L->>W: 通知存檔、告知玩家、優雅關機
W->>S3: 上傳最新存檔
W->>GL: 進程結束
GL->>GL: 偵測關機並啟動乾淨實例
GL->>S3: 新實例載入存檔
重點在於:規則不是寫在文件裡希望大家遵守,而是用自動化主動維護「永遠只有一個世界」。
④ 串接既有監控資產
遷移時把 GameLift 指標接到既有 CloudWatch、Slack 告警、Grafana,讓維運不必整套重學工具。這常被低估,卻直接決定遷移後的組織摩擦成本。
第三部分:遷移後三大實戰故障案例
案例 1:Terraform 狀態漂移(Drift)
| 項目 | 內容 |
|---|---|
| 問題 | CI/CD 自動更新並發布新映像後,運維執行 Terraform 出現未預期 Drift,程式碼與雲端實際狀態不一致 |
| 原因 | 自動發布直接改了運行中的 Container Digest,Terraform State 不知情 |
| 解法 | 在 Terraform 明確使用 Digest(而非 Tag) 鎖定映像,並寫回 Terraform 控制,讓每次 apply 趨近 0 drift |
啟示:映像「漂」一下看似小事,但在 IaC 世界會直接變成信任危機——你以為 apply 是宣告式收斂,實際上每次都在追落後的真相。
案例 2:無聲的 Fleet 故障(顯示 Healthy 卻無法連線)
| 項目 | 內容 |
|---|---|
| 問題 | 儀表板綠燈/健康,但玩家完全無法加入 |
| 原因 | 傳統監控只看「實例是否存活」;實例內的遊戲進程/Game Session 其實已崩潰 |
| 解法 | 改監控 不變量(Invariant):活躍 Game Session 數量與玩家人數。基礎設施健康卻沒有活躍 Session,就視為異常並自動觸發重建 |
編者補充: 「機器活著 ≠ 服務正確」。對 Agent 平台、遊戲伺服器、交易系統都一樣——要監控業務不變量,而不只是 VM/Pod 心跳。
案例 3:Ping 值與延遲測量失效
| 項目 | 內容 |
|---|---|
| 問題 | 遷移後,玩家用戶端在社群伺服器列表無法再用傳統 ICMP Ping 測延遲 |
| 原因 | 安全考量下,GameLift 預設不回應 ICMP,只開放遊戲特定 UDP/TCP 埠 |
| 解法 | 用戶端改向該區域 GameLift Ping Beacon(Ping 燈塔) 做 UDP RTT 測試,估算真實連線延遲 |
這提醒產品與基礎設施工必須一起改:平台換了,延遲量測協定也可能要換,否則社群列表會突然「全部延遲未知」。
結論:四大啟示(Key Takeaways)
Keigo Yamauchi 收斂出四條可複用原則:
-
狀態外部化(Externalize State) 計算與狀態徹底分離——把持久服務放到拋棄式託管架構上的黃金法則。
-
善用適配器(Adapter Pattern) 用輕量 Wrapper 轉譯生命週期,不必大改遊戲程式碼即可對接新平台。
-
用運維設計維護規則 「永遠只有一個實例」這類約束,不要只靠設定檔與人治;要用 Lambda、併發抑制、冪等流程主動維護。
-
保留既有資產 Log、指標、告警盡量接到原有維運介面,大幅降低團隊適應成本。
可帶回團隊的檢查清單
- 你們的「世界/Session/租戶狀態」是否已外部化到可靠儲存?
- 平台生命週期是否有 Adapter,而不是侵入核心邏輯?
- Exactly One/唯一寫入者,是否有自動化防競態,而不只是文件規範?
- 監控看的是基礎設施心跳,還是業務不變量?
- IaC 是否用不可變 Digest 鎖定發布物,避免 Drift?
- 用戶端健康檢查/延遲探測,是否仍假設舊網路行為(如 ICMP)?
關鍵結語
這場 Palworld 遷移分享,把多人遊戲後端最難的一句話講清楚了:
雲端給你的是可拋棄的算力;玩家要的是不可拋棄的世界。
GameLift 提供的是專為即時多人遊戲打造的彈性、成本與更新效率;Pocketpair 真正解題的地方,則是用狀態外部化、Adapter、Exactly One 自動化與既有監控資產,把「持久世界」安全地放進「臨時運算」裡。
遷移成功與否,往往不取決於能不能把容器跑在新平台上,而取決於:存檔會不會壞、規則會不會破、監控會不會騙人、玩家會不會在你以為一切正常時突然連不進來。