pvpserver · 实时 PVP 对战游戏服务
pvpserver 是 game 命名空间下的一个对战游戏后端,镜像 ghcr.io/yldm-tech/pvpserver 由 yldm-tech 自建。
从 manifest 可推断它是一个 Go/Gin 编写的 HTTP + WebSocket 服务:容器以 GIN_MODE=release 运行,对外暴露 8080 HTTP 端口、9090 metrics 端口;配置里带有 game 段(tick_rate、send_rate、max_players、匹配与排名开关),并通过 ConfigMap、ExternalSecret 接入 PostgreSQL、Redis 与 Consul。它是 game 类目下的常规无状态服务,由 ApplicationSet yldm-services 生成对应的 ArgoCD Application game-pvpserver,kustomization 设置 namespace: game 与 namePrefix: game-,所以集群内资源都带 game- 前缀。
部署形态
- Name
- 命名空间
- Description
- game
- Name
- 工作负载类型
- Description
- Deployment(无状态,RollingUpdate,maxSurge 1 / maxUnavailable 0)
- Name
- 镜像与版本
- Description
- ghcr.io/yldm-tech/pvpserver:2.3.1(tag 由 argocd-image-updater 按 semver 写回 kustomization)
- Name
- 副本数
- Description
- 2(HPA 下限 2,上限 8)
- Name
- 调度
- Description
- 无 nodeSelector / workload 标签;配置 podAntiAffinity(preferred,topologyKey kubernetes.io/hostname)尽量把两个副本分散到不同节点
- Name
- 端口
- Description
- 容器 8080(http)、9090(metrics)
- Name
- 资源
- Description
- requests 512Mi / 500m,limits 1Gi / 1000m
- Name
- 存储
- Description
- 无 PVC,无状态服务,仅挂载 ConfigMap
容器声明了完整的三类探针,全部走 8080:startupProbe 命中 /health(最长 60s 启动窗口),livenessProbe 命中 /health,readinessProbe 命中 /health/ready。优雅退出方面,preStop 先 sleep 15,terminationGracePeriodSeconds 为 30,配合 RollingUpdate 的 maxUnavailable 0 让滚动更新期间始终有可用副本。镜像拉取用 ghcr-secret(GHCR 私有镜像)。
配置与依赖
服务挂载两个 ConfigMap:集群共享的 base-config(挂到 /root/configs/base)和本服务的 pvpserver-config(pvp.yaml 挂到 /root/configs/services/games/pvp.yaml)。pvp.yaml 中绝大多数连接参数用 ${ENV:default} 占位,真实值由容器环境变量注入,环境变量又来自 ExternalSecret 同步出的 Secret,因此敏感信息不落在 git 里。
ExternalSecret pvpserver-secret 通过 ClusterSecretStore vault-backend 从 Vault 拉取,刷新间隔 1h,写出名为 pvpserver-db-secret 的 Secret。它的 remoteRef.key 跨三个 Vault 路径:
| Vault 路径 | 取出的字段 |
|---|---|
yldm/production/pvpserver | db_host、db_port、db_name、db_user、db_password、redis_db |
yldm/production/common | redis_host、redis_port、redis_password、jwt_secret、jwt_expires_in、jwt_refresh_expires_in |
yldm/database | DB_ADMIN_USER / DB_ADMIN_PASSWORD(user / password) |
依赖的中间件:
- 数据库走 PostgreSQL,但
DB_HOST在 deployment 里硬编码为pgbouncer.postgres.svc.cluster.local,即通过 PgBouncer 连接池接入 postgres 命名空间的 Postgres,业务库默认名yldm_pvp。 - Redis 用于 pubsub 与缓存,配置里
db: 4、key 前缀pvp:,pubsub 走 redis 引擎并启用死信队列(保留 168h)。 - Consul 服务发现已启用(
CONSUL_ENABLED=true),地址consul.consul.svc.cluster.local:8500。
关键 env 还包括限流(RATE_LIMIT_GLOBAL=1000 / RATE_LIMIT_BURST=2000)、JSON 结构化日志(LOG_FORMAT=json、LOG_OUTPUT=stdout、LOG_LEVEL=info)以及 METRICS_ENABLED=true。
访问与监控
集群内提供两个 Service:普通 ClusterIP pvpserver(80 → 8080)与 headless pvpserver-headless(clusterIP None,同样 80 → 8080)。
对外通过 Ingress pvpserver-ingress 暴露,ingressClassName: traefik,host 为 pvp.yldm.tech,TLS 证书由 cert-manager 的 letsencrypt-prod ClusterIssuer 签发到 secret pvpserver-tls-cert,并强制 SSL 重定向。DNS 经 external-dns 写成指向 Cloudflare Tunnel(*.cfargotunnel.com)的 CNAME 且开启 Cloudflare proxied。Ingress 上有针对 WebSocket 的一组配置:websocket-services 指向 game-pvpserver,proxy read/send/connect 超时均 3600s,并启用 cookie 会话亲和(pvpserver-session,max-age 10800)以保证 WebSocket 长连在同一后端 Pod 上,入口侧限流 limit-rps: 100。
监控方面,Pod 带 prometheus.io/scrape: "true"、prometheus.io/port: "9090"、prometheus.io/path: "/metrics" 注解暴露指标;本目录下没有 ServiceMonitor 或 PrometheusRule。伸缩与可用性:HPA pvpserver-hpa 按 CPU 70% / 内存 80% 在 2–8 副本间扩缩;VPA pvpserver-vpa 为 updateMode: "Off"(仅给建议,不自动改资源,区间 cpu 200m–2 / memory 256Mi–2Gi);PDB pvpserver 设 minAvailable: 1,配合至少 2 副本,节点驱逐时不会被单副本 PDB 卡住。
返回 game 服务总览