跳轉到

Go 遊戲後端 Observability 成熟度提升計劃:從 60 分到 95 分的完整路線圖與缺口診斷

文檔資訊

  • 分類: architecture
  • 難度: advanced
  • 預估閱讀時間: 12 分鐘
  • 標籤: observability, opentelemetry, tracing, tempo, loki, grafana, alertmanager, kubernetes, eks, correlation-id, runbook, external-secret

摘要

針對 Go 遊戲後端(MatchRPG)的 Observability 能力進行完整診斷,識別從 60 分到 95 分的關鍵缺口,並設計兩層式行動路線圖。核心洞察是:現況能力評分與行動優先順序是兩個不同維度,不能混為一談;trace transport 不通是最大單點阻塞,單項修好可提升 +10 到 +14 分。

關鍵學習

  • 現況能力分數(Current State Score)與行動優先順序(Action Priority)是兩個獨立維度,修復成本小不代表缺口不嚴重

  • Trace transport 是最大阻塞:game-server/publisher/admin 的 OTEL endpoint 仍指向 localhost:4318 而非叢集內 Tempo,這讓 dev tracing 完全不可靠

  • Admin tracing 不是純 Infra 問題:configmap 要改,但 server code 的 middleware chain 也缺 tracing middleware(只有 Recovery/Logging/Metrics)

  • Middleware 順序 bug:game-server 的順序是 Logging -> ResponseMeta -> Tracing,導致 ResponseMeta 在 trace_id 注入前就讀取,X-Trace-Id 抓不到

  • Correlation contract 標準欄位:request_id, trace_id, span_id, user_id, account_id, session_id, rpc/service, build_sha, config_version, env 必須同時出現在 response、app logs、spans、audit logs

  • Layer 2 項目(incident lookup、replay artifacts、synthetic trace CI gate)不該現在做,但現在要避免把未來做死——先設計好介面和資料欄位

  • 多環境 tracing 策略:dev/staging/prod 可以共用同一個 Tempo,但用 environment label 隔離,Grafana 用變數過濾,不需要部署三套

  • Terraform 管理的 Secret 安全性:密碼由 Terraform 產生並直接寫入 AWS SSM/Secrets Manager,整個路徑上沒有人類經手,是業界安全做法

  • Alertmanager Secret 最佳實踐:使用 ExternalSecret + useExistingSecret 方案,從 AWS Secrets Manager 同步,而非 hardcode 在 git 或讓人工設置

技術細節

評分框架

觀測性成熟度被拆分為兩個獨立維度:

  • 現況能力分數:系統今天實際能做到什麼(約 60-65 分)
  • 行動優先順序:哪些缺口要先修(由 patch size + impact 共同決定)

分數上限限制鏈(不修則封頂):

 Trace transport 未通      → 上限 65 分
 Correlation contract 未統一 → 上限 72 分
 Loki queryability 不足    → 上限 78 分
 Service coverage 不齊      → 上限 82 分
 Alert delivery 未實證      → 上限 85 分
 Runbook 未治理             → 上限 88 分
 Player incident tooling 缺  → 上限 90 分
 Repro artifacts 缺         → 上限 92 分
 Observability CI gate 缺   → 上限 94 分
 Drill & proof 未執行       → 95 分

具體技術缺口

Trace Transport 問題:

# 錯誤:base configmap 仍是 localhost
OTEL_ENDPOINT: "http://localhost:4318"

# 正確:應指向叢集內 Tempo
OTEL_ENDPOINT: "http://tempo.monitoring:4318"

game-server 程式碼本身支援 OTEL_* config,但 k8s/base/game-server/configmap.yaml 完全沒有這些環境變數。

Admin Middleware 缺口(非純 Infra 問題):

// cmd/admin/main.go:211-217
// 現況:只有 Recovery/Logging/Metrics,沒有 Tracing middleware
router.Use(Recovery())
router.Use(Logging())
router.Use(Metrics())
// 缺少:router.Use(Tracing())

Middleware 順序 Bug(game-server):

// internal/adapters/twirp/router.go:177-186
// 錯誤順序:Logging -> ResponseMeta -> Tracing
// ResponseMeta 在 Tracing 之前執行,trace_id 尚未注入 context
// 正確順序應為:Tracing -> ResponseMeta -> Logging

Correlation Contract 標準(缺 trace_id):

// pkg/middleware/logging.go:93-103
// 現況:只打 request_id
logger.With("request_id", requestID)

// 應補:
logger.With(
    "request_id", requestID,
    "trace_id", traceID,   // 缺少
    "user_id", userID,     // 缺少
    "account_id", accountID, // 缺少
)

多環境 Tracing 架構

dev/staging/prod 三個環境,共用同一個 Tempo instance,用 environment label 區分:

OTEL_RESOURCE_ATTRIBUTES: "environment=dev,service.version=${GIT_SHA}"

Grafana 用 $environment 變數過濾,不需要部署三套 Tempo。

ExternalSecret 方案(Alertmanager)

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: alertmanager-telegram-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: alertmanager-telegram-secret
    creationPolicy: Owner
  data:
    - secretKey: telegram_bot_token
      remoteRef:
        key: /matchrpg/monitoring/telegram
        property: bot_token
    - secretKey: telegram_chat_id
      remoteRef:
        key: /matchrpg/monitoring/telegram
        property: chat_id

What Changed

這次對話完成了 MatchRPG 後端系統 Observability 的完整診斷與行動計劃,並執行了多個具體實作任務。

診斷與決策層面: 確立了「現況評分 vs 行動優先順序」的雙維度框架,避免用修復成本來低估缺口嚴重性。最終確認現況約 60-65 分,修完 Server P0/P1 + Infra P0/P1 可達 78-85 分,而 95 分需要 Layer 2 的成熟度項目。

實際執行層面: 已完成或規劃的任務包括:game-server middleware 順序修正、logging 補 user_id/trace_id、admin 補 tracing middleware、Infra OTEL endpoint 修正、Promtail JSON pipeline_stages 配置、Admin/Battle-Validator Grafana dashboard、Alertmanager ExternalSecret 注入。

架構決策層面: 選定 ExternalSecret + useExistingSecret 方案管理 Alertmanager 憑證;確立多環境 tracing 共用 Tempo + environment label 隔離的策略;釐清 battle-validator 目前仍在 Noop/fallback 階段,不是第一波優先項。

So What

這個對話建立了一套可複用的 Observability 成熟度評估框架,對任何 live-service 遊戲後端都有參考價值。

最重要的洞察是:observability 不是元件裝了就算,而是鏈路是否閉環。系統可以裝了 Tempo、Loki、Grafana,但如果 OTEL endpoint 是 localhost、middleware 順序錯了、log 裡沒有 trace_id,整條鏈路就是斷的,玩家問題發生時工程師仍然得靠肉眼拼湊。

兩層式路線圖的設計也很重要:Layer 1 的 today fixes 成本極低(幾行 config + 幾行 middleware code),但能把系統從「看起來有觀測性」變成「真的可用」;Layer 2 的成熟度項目雖然不急,但現在要避免讓架構決策把未來做死。

Trade-offs

  • 共用 Tempo vs 各環境獨立部署:共用節省資源和維護成本,但需要在所有 query 加 environment filter,若 filter 忘記加會看到混合資料;獨立部署更乾淨但成本倍增
  • ExternalSecret vs Sealed Secrets:ExternalSecret 需要 AWS Secrets Manager,雲端依賴更重但 rotation 更方便;Sealed Secrets 純 k8s 但需要管理加密金鑰
  • 現在設計 Layer 2 介面 vs 完全延後:現在先設計好資料欄位可以避免未來重構成本,但可能過度設計;完全延後則風險是後來發現 schema 不相容
  • battle-validator 暫列低優先:目前它是 Noop/fallback,不影響主鏈觀測;但一旦它真正上線,如果沒有提前規劃 tracing,屆時補起來更麻煩

Try It Fast

# 驗證 trace 是否真的進到 Tempo(1 分鐘內可查)
# 先發一個合成請求
curl -X POST http://game-server.dev/rpc/... \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

# 在 Grafana Tempo 用 TraceQL 查詢
# { resource.service.name="game-server" && resource.environment="dev" }

# 驗證 log 包含必要欄位
kubectl logs -n game -l app=game-server --tail=10 | jq '. | {request_id, trace_id, user_id, status}'

# 驗證 Alertmanager 收到真實 secret
kubectl get secret alertmanager-telegram-secret -n monitoring -o jsonpath='{.data.telegram_bot_token}' | base64 -d

Recommendation

  1. 立即修正(today fixes):game-server middleware 順序(Tracing 必須在 ResponseMeta 之前)、logging 補 trace_id/user_id、admin 補 tracing middleware、Infra OTEL endpoint 從 localhost 改為 tempo.monitoring:4318
  2. Pre-staging hardening:Promtail JSON pipeline_stages(讓 request_id/trace_id/user_id 可在 LogQL 查詢)、admin + battle-validator dashboard、Alertmanager ExternalSecret 注入並演練 test alert
  3. 避免把未來做死:即使 Layer 2 現在不做,也要確保 structured log 的欄位 schema 設計好,避免之後補 incident lookup 工具時需要重構 log format
  4. 驗收標準要量化:任一玩家回報 15 分鐘內從 user_id 收斂到具體 pod + trace;critical 故障 10 分鐘內自動告警到真實 on-call
  5. battle-validator 暫緩:在它從 Noop 變成真實 gRPC client 之前,不要把它列入第一波 tracing 優先項

本文檔由 Semi-Brain 自動生成

Session ID: 6295486a-8e60-49c7-a5da-f375c806641a

分析信心度: 92%