chore: adjust player tank's size

This commit is contained in:
jakciehan
2026-05-02 13:50:52 +08:00
parent 0e321bcea6
commit 38294c040c
35 changed files with 5767 additions and 348 deletions
+109
View File
@@ -0,0 +1,109 @@
#
# Edge reverse proxy: 42.194.185.163
# Forwards public 80/443 traffic (L4 passthrough) to the K8s worker nodes
# that run the warmcheck/nginx DaemonSet (hostNetwork hostPort 80/443).
#
# Worker public IPs (cross-VPC, so we must use public addresses):
# - 43.138.255.42 (cvm-42 / 172.16.16.17)
# - 159.75.104.221 (cvm-221 / 172.16.16.8)
#
# Master (43.139.80.61 / 172.16.16.16) is excluded — DaemonSet nodeAffinity
# skips control-plane nodes, so it does NOT listen on :80/:443.
#
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
# Load dynamic modules (stream module ships as a dynamic module on
# OpenCloudOS 9 / RHEL 9 and lives in /usr/share/nginx/modules/).
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 8192;
use epoll;
multi_accept on;
}
# ============================================================
# L4 stream passthrough (HTTP 80 + HTTPS 443 + WSS)
# ============================================================
stream {
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" '
'"$upstream_connect_time"';
access_log /var/log/nginx/stream-access.log basic buffer=32k flush=5s;
# ---- HTTP upstream (80) ----
upstream k8s_http {
# 2 workers; passive health check via max_fails/fail_timeout.
server 43.138.255.42:80 max_fails=3 fail_timeout=30s;
server 159.75.104.221:80 max_fails=3 fail_timeout=30s;
}
# ---- HTTPS upstream (443, SNI passthrough) ----
upstream k8s_https {
server 43.138.255.42:443 max_fails=3 fail_timeout=30s;
server 159.75.104.221:443 max_fails=3 fail_timeout=30s;
}
# ---- Listeners ----
server {
listen 80;
listen [::]:80;
proxy_pass k8s_http;
proxy_connect_timeout 5s;
proxy_timeout 300s; # long enough for WS keep-alive
proxy_socket_keepalive on;
}
server {
listen 443;
listen [::]:443;
proxy_pass k8s_https;
proxy_connect_timeout 5s;
proxy_timeout 300s; # long enough for WSS keep-alive
proxy_socket_keepalive on;
}
}
# ============================================================
# Local-only HTTP block for status / health probing on :8080
# (bound to 127.0.0.1 so it doesn't clash with stream :80)
# ============================================================
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
server {
listen 127.0.0.1:8080;
server_name _;
location = /edge-health {
return 200 "edge-ok\n";
add_header Content-Type text/plain;
}
location / {
return 404;
}
}
}
+62
View File
@@ -0,0 +1,62 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: tankwar-server
namespace: tankwar
labels:
app: tankwar-server
spec:
# Single replica for Plan A (in-memory room state).
# Kubernetes will auto-reschedule if the pod or its node fails.
replicas: 1
strategy:
# Recreate instead of RollingUpdate so the port & state are never
# duplicated across two pods with in-memory room registry.
type: Recreate
selector:
matchLabels:
app: tankwar-server
template:
metadata:
labels:
app: tankwar-server
spec:
terminationGracePeriodSeconds: 15
containers:
- name: tankwar-server
image: tankwar-server:latest
imagePullPolicy: IfNotPresent
ports:
- name: ws
containerPort: 3000
protocol: TCP
env:
- name: NODE_ENV
value: "production"
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "3000"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "1000m"
memory: "512Mi"
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 15
timeoutSeconds: 3
failureThreshold: 3
+7
View File
@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: tankwar
labels:
name: tankwar
app: tankwar
+165
View File
@@ -0,0 +1,165 @@
#!/usr/bin/env bash
# =============================================================================
# Tank War Server — one-shot K8s deploy
#
# Mirrors the style of WarmCheck's run-deploy.sh:
# 1) sync source to master
# 2) build docker image on master
# 3) distribute image tarball to all worker nodes and `ctr` import
# 4) apply K8s manifests and restart the deployment
# =============================================================================
set -euo pipefail
# ---------- Configurable ------------------------------------------------------
# Host that the LOCAL developer machine can reach (uses your ssh_config alias).
MASTER_HOST="${MASTER_HOST:-host_172.16.16.16}"
# Intranet IPs that the MASTER uses to reach workers (no alias on the CVMs).
WORKER_INTRANET_IPS=(
"172.16.16.17"
"172.16.16.8"
)
NAMESPACE="tankwar"
IMAGE_NAME="tankwar-server"
IMAGE_TAG="${IMAGE_TAG:-latest}"
REMOTE_WORKDIR="/root/tankwar"
SSH_USER="root"
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=10"
# ---------- Paths -------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
SERVER_DIR="${PROJECT_ROOT}/server"
K8S_DIR="${PROJECT_ROOT}/deploy/k8s"
# ---------- Helpers -----------------------------------------------------------
log() { printf "\033[1;36m[deploy]\033[0m %s\n" "$*"; }
ok() { printf "\033[1;32m[ ok ]\033[0m %s\n" "$*"; }
warn() { printf "\033[1;33m[warn]\033[0m %s\n" "$*"; }
die() { printf "\033[1;31m[fail]\033[0m %s\n" "$*" >&2; exit 1; }
ssh_master() { ssh ${SSH_OPTS} "${SSH_USER}@${MASTER_HOST}" "$@"; }
ssh_host() { local h="$1"; shift; ssh ${SSH_OPTS} "${SSH_USER}@${h}" "$@"; }
# =============================================================================
# Step 1 — sync server source code & k8s manifests to master
# =============================================================================
step_sync() {
log "1/5 Syncing source to master (${MASTER_HOST}) ..."
ssh_master "mkdir -p ${REMOTE_WORKDIR}/server ${REMOTE_WORKDIR}/deploy/k8s"
rsync -az --delete \
--exclude 'node_modules' \
--exclude '.git' \
--exclude '.DS_Store' \
-e "ssh ${SSH_OPTS}" \
"${SERVER_DIR}/" \
"${SSH_USER}@${MASTER_HOST}:${REMOTE_WORKDIR}/server/"
rsync -az --delete \
-e "ssh ${SSH_OPTS}" \
"${K8S_DIR}/" \
"${SSH_USER}@${MASTER_HOST}:${REMOTE_WORKDIR}/deploy/k8s/"
ok "source synced"
}
# =============================================================================
# Step 2 — build docker image on master
# =============================================================================
step_build() {
log "2/5 Building image ${IMAGE_NAME}:${IMAGE_TAG} on master ..."
ssh_master "cd ${REMOTE_WORKDIR}/server && \
docker build --pull -t ${IMAGE_NAME}:${IMAGE_TAG} -t ${IMAGE_NAME}:latest ."
ok "image built"
}
# =============================================================================
# Step 3 — distribute image to every worker via containerd (ctr import)
#
# The cluster uses containerd directly (not docker-shim). Each node must
# have the image in the "k8s.io" namespace to be usable by kubelet.
# =============================================================================
step_distribute() {
log "3/5 Distributing image to workers ..."
# Export once on master
local remote_tar="/tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar"
ssh_master "docker save ${IMAGE_NAME}:${IMAGE_TAG} -o ${remote_tar} && ls -lh ${remote_tar}"
# Import on master's containerd (k8s.io ns) so the scheduler can use it locally too
ssh_master "ctr -n k8s.io images import ${remote_tar} && \
ctr -n k8s.io images tag --force docker.io/library/${IMAGE_NAME}:${IMAGE_TAG} \
docker.io/library/${IMAGE_NAME}:latest"
ok "master imported"
# Fan-out to workers — executed FROM the master using intranet IPs.
for ip in "${WORKER_INTRANET_IPS[@]}"; do
log " -> ${ip}"
ssh_master "scp ${SSH_OPTS} ${remote_tar} ${SSH_USER}@${ip}:${remote_tar} && \
ssh ${SSH_OPTS} ${SSH_USER}@${ip} 'ctr -n k8s.io images import ${remote_tar} && \
ctr -n k8s.io images tag --force docker.io/library/${IMAGE_NAME}:${IMAGE_TAG} \
docker.io/library/${IMAGE_NAME}:latest && \
rm -f ${remote_tar}'"
ok " ${ip} imported"
done
ssh_master "rm -f ${remote_tar}"
ok "distribution done"
}
# =============================================================================
# Step 4 — apply manifests & roll the deployment
# =============================================================================
step_apply() {
log "4/5 Applying K8s manifests ..."
ssh_master "kubectl apply -f ${REMOTE_WORKDIR}/deploy/k8s/namespace.yaml"
ssh_master "kubectl apply -f ${REMOTE_WORKDIR}/deploy/k8s/service.yaml"
ssh_master "kubectl apply -f ${REMOTE_WORKDIR}/deploy/k8s/deployment.yaml"
# Force a new rollout so we pick up the newly-imported image even
# when the tag stays :latest.
ssh_master "kubectl -n ${NAMESPACE} set image deploy/tankwar-server \
tankwar-server=${IMAGE_NAME}:${IMAGE_TAG} --record=false || true"
log " waiting for rollout ..."
ssh_master "kubectl -n ${NAMESPACE} rollout status deploy/tankwar-server --timeout=180s"
ok "deployment is live"
}
# =============================================================================
# Step 5 — sanity check
# =============================================================================
step_verify() {
log "5/5 Verifying ..."
ssh_master "kubectl -n ${NAMESPACE} get pods,svc -o wide"
echo
ssh_master "kubectl -n ${NAMESPACE} logs deploy/tankwar-server --tail=20 || true"
echo
ok "all done. NodePort: 30081"
cat <<EOF
------------------------------------------------------------
Public endpoints (after DNS on www.igeek.site takes effect):
wss://www.igeek.site:30081/ (via NodePort on any of the 3 CVMs)
Direct CVM access for smoke test:
wscat -c ws://43.139.80.61:30081/
wscat -c ws://43.138.255.42:30081/
wscat -c ws://159.75.104.221:30081/
Remember to allow TCP/30081 in the CVM security group.
------------------------------------------------------------
EOF
}
main() {
log "Tank War Server deploy — tag=${IMAGE_TAG}"
step_sync
step_build
step_distribute
step_apply
step_verify
}
main "$@"
+48
View File
@@ -0,0 +1,48 @@
---
# ClusterIP service — consumed by Nginx reverse-proxy inside the cluster.
apiVersion: v1
kind: Service
metadata:
name: tankwar-server
namespace: tankwar
labels:
app: tankwar-server
spec:
type: ClusterIP
selector:
app: tankwar-server
ports:
- name: ws
port: 3000
targetPort: 3000
protocol: TCP
# Sticky sessions keep a given client pinned to the same pod while
# the (future) multi-replica version is considered.
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
---
# NodePort service — exposes the WebSocket server directly on every node
# at port 30081, so the public domain can be pointed here once DNS resolves.
apiVersion: v1
kind: Service
metadata:
name: tankwar-server-nodeport
namespace: tankwar
labels:
app: tankwar-server
spec:
type: NodePort
selector:
app: tankwar-server
ports:
- name: ws
port: 3000
targetPort: 3000
nodePort: 30081
protocol: TCP
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Convenience Nginx snippet for the cluster-internal nginx (warmcheck ns).
# Drop this into warmcheck's nginx configmap under `location /games/wx/tankwar`
# once the DNS for www.igeek.site points to the 3 CVMs.
#
# Paste this whole block inside the existing `server { ... }` block that
# serves www.igeek.site with TLS.
# server { ... listen 443 ssl; server_name www.igeek.site; ... }
# Health endpoint (handy for uptime checks; optional)
location = /games/wx/tankwar/health {
proxy_pass http://tankwar-server.tankwar.svc.cluster.local:3000/health;
proxy_http_version 1.1;
}
# WebSocket endpoint that the game actually uses
location /games/wx/tankwar/ws {
proxy_pass http://tankwar-server.tankwar.svc.cluster.local:3000;
proxy_http_version 1.1;
# WebSocket upgrade
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Long-lived WS — well past server HEARTBEAT_INTERVAL (10s)
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 10s;
proxy_buffering off;
}
+408
View File
@@ -0,0 +1,408 @@
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
gzip_types text/plain application/json application/javascript;
client_max_body_size 10m;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/s;
# Upstream definitions - using K8s service DNS names
# keepalive enables persistent connections to reduce latency
upstream user_service {
server user-service.warmcheck.svc.cluster.local:8081;
keepalive 16;
}
upstream interaction_service {
server interaction-service.warmcheck.svc.cluster.local:8082;
keepalive 16;
}
upstream social_service {
server social-service.warmcheck.svc.cluster.local:8083;
keepalive 8;
}
upstream push_service {
server push-service.warmcheck.svc.cluster.local:8084;
keepalive 8;
}
upstream ws_gateway {
server gateway.warmcheck.svc.cluster.local:8085;
}
upstream admin_service {
server admin-service.warmcheck.svc.cluster.local:8086;
keepalive 4;
}
# Tank War WebSocket server (separate namespace)
upstream tankwar_server {
server tankwar-server.tankwar.svc.cluster.local:3000;
keepalive 16;
}
# HTTPS server - for external access via HK CVM nginx
server {
listen 443 ssl;
server_name api.warmcheck.app;
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Health check
location /health {
return 200 '{"status":"ok","gateway":"nginx","ssl":true}';
add_header Content-Type application/json;
}
# Auth routes (stricter rate limit)
location /auth/ {
limit_req zone=auth burst=10 nodelay;
proxy_pass http://user_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# User service routes
location ~ ^/api/v1/(user|sign|growth|museum|feedback)(/|$) {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# User service routes (emergency contact)
location ~ ^/api/v1/users/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Interaction service routes
location ~ ^/api/v1/(story-card|care-card|urgent-care)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://interaction_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Social service routes
location ~ ^/api/v1/(magnet|chat)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://social_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Push service routes
location ~ ^/api/v1/notification/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://push_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Admin service routes (report & feedback submission from app)
location ~ ^/api/v1/(report|feedback)$ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://admin_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# WebSocket gateway
location /ws {
proxy_pass http://ws_gateway;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
# AI service routes
location /ai/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://ai-service.warmcheck.svc.cluster.local:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Analytics service routes
location /analytics/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://analytics-service.warmcheck.svc.cluster.local:5003;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin service routes (UI + API)
location /admin {
proxy_pass http://admin_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTP server - for internal health checks and backward compatibility
server {
listen 80;
server_name api.warmcheck.app;
# Health check
location /health {
return 200 '{"status":"ok","gateway":"nginx"}';
add_header Content-Type application/json;
}
# Auth routes (stricter rate limit)
location /auth/ {
limit_req zone=auth burst=10 nodelay;
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# User service routes (feedback uses exact path without trailing slash)
location ~ ^/api/v1/(user|sign|growth|museum|feedback)(/|$) {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# User service routes (emergency contact)
location ~ ^/api/v1/users/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Interaction service routes
location ~ ^/api/v1/(story-card|care-card|urgent-care)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://interaction_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Social service routes
location ~ ^/api/v1/(magnet|chat)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://social_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Push service routes
location ~ ^/api/v1/notification/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://push_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin service routes (report & feedback submission from app)
location ~ ^/api/v1/(report|feedback)$ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://admin_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# WebSocket gateway
location /ws {
proxy_pass http://ws_gateway;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
# AI service routes
location /ai/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://ai-service.warmcheck.svc.cluster.local:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Analytics service routes
location /analytics/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://analytics-service.warmcheck.svc.cluster.local:5003;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin service routes (UI + API)
location /admin {
proxy_pass http://admin_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# =========================================================
# www.igeek.site — Tank War game WebSocket entry
# Reuses the existing nginx-tls-secret (CN=igeek.site,
# SAN includes www.igeek.site).
# =========================================================
server {
listen 443 ssl;
server_name www.igeek.site igeek.site;
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Gateway self health
location = /health {
return 200 '{"status":"ok","gateway":"nginx","site":"igeek"}';
add_header Content-Type application/json;
}
# Tank War health passthrough
location = /games/wx/tankwar/health {
proxy_pass http://tankwar_server/health;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
}
# Tank War WebSocket endpoint
location /games/wx/tankwar/ws {
proxy_pass http://tankwar_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Long-lived WS — well past server HEARTBEAT_INTERVAL (10s)
proxy_connect_timeout 10s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}
# HTTP for www.igeek.site — redirect to HTTPS
server {
listen 80;
server_name www.igeek.site igeek.site;
location = /health {
return 200 '{"status":"ok","gateway":"nginx","site":"igeek","tls":false}';
add_header Content-Type application/json;
}
location / {
return 301 https://$host$request_uri;
}
}
}
@@ -0,0 +1,331 @@
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
gzip_types text/plain application/json application/javascript;
client_max_body_size 10m;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/s;
# Upstream definitions - using K8s service DNS names
# keepalive enables persistent connections to reduce latency
upstream user_service {
server user-service.warmcheck.svc.cluster.local:8081;
keepalive 16;
}
upstream interaction_service {
server interaction-service.warmcheck.svc.cluster.local:8082;
keepalive 16;
}
upstream social_service {
server social-service.warmcheck.svc.cluster.local:8083;
keepalive 8;
}
upstream push_service {
server push-service.warmcheck.svc.cluster.local:8084;
keepalive 8;
}
upstream ws_gateway {
server gateway.warmcheck.svc.cluster.local:8085;
}
upstream admin_service {
server admin-service.warmcheck.svc.cluster.local:8086;
keepalive 4;
}
# HTTPS server - for external access via HK CVM nginx
server {
listen 443 ssl;
server_name api.warmcheck.app;
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Health check
location /health {
return 200 '{"status":"ok","gateway":"nginx","ssl":true}';
add_header Content-Type application/json;
}
# Auth routes (stricter rate limit)
location /auth/ {
limit_req zone=auth burst=10 nodelay;
proxy_pass http://user_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# User service routes
location ~ ^/api/v1/(user|sign|growth|museum|feedback)(/|$) {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# User service routes (emergency contact)
location ~ ^/api/v1/users/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Interaction service routes
location ~ ^/api/v1/(story-card|care-card|urgent-care)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://interaction_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Social service routes
location ~ ^/api/v1/(magnet|chat)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://social_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Push service routes
location ~ ^/api/v1/notification/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://push_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# Admin service routes (report & feedback submission from app)
location ~ ^/api/v1/(report|feedback)$ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://admin_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s;
proxy_read_timeout 15s;
proxy_send_timeout 10s;
}
# WebSocket gateway
location /ws {
proxy_pass http://ws_gateway;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
# AI service routes
location /ai/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://ai-service.warmcheck.svc.cluster.local:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Analytics service routes
location /analytics/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://analytics-service.warmcheck.svc.cluster.local:5003;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin service routes (UI + API)
location /admin {
proxy_pass http://admin_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTP server - for internal health checks and backward compatibility
server {
listen 80;
server_name api.warmcheck.app;
# Health check
location /health {
return 200 '{"status":"ok","gateway":"nginx"}';
add_header Content-Type application/json;
}
# Auth routes (stricter rate limit)
location /auth/ {
limit_req zone=auth burst=10 nodelay;
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# User service routes (feedback uses exact path without trailing slash)
location ~ ^/api/v1/(user|sign|growth|museum|feedback)(/|$) {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# User service routes (emergency contact)
location ~ ^/api/v1/users/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Interaction service routes
location ~ ^/api/v1/(story-card|care-card|urgent-care)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://interaction_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Social service routes
location ~ ^/api/v1/(magnet|chat)/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://social_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Push service routes
location ~ ^/api/v1/notification/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://push_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin service routes (report & feedback submission from app)
location ~ ^/api/v1/(report|feedback)$ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://admin_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# WebSocket gateway
location /ws {
proxy_pass http://ws_gateway;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
# AI service routes
location /ai/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://ai-service.warmcheck.svc.cluster.local:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Analytics service routes
location /analytics/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://analytics-service.warmcheck.svc.cluster.local:5003;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin service routes (UI + API)
location /admin {
proxy_pass http://admin_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}