This commit is contained in:
Ho Ngoc Hai
2026-05-23 18:37:02 +07:00
parent f15d91ee29
commit 76d75c753b
3993 changed files with 403 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
# =============================================================================
# GoodGo Platform - Local Docker Environment
# =============================================================================
# EN: Auto-generated for self-contained local Docker deployment.
# VI: Tự động tạo cho deployment Docker local tự hoàn chỉnh.
# =============================================================================
ASPNETCORE_ENVIRONMENT=Development
NODE_ENV=development
LOG_LEVEL=Information
API_VERSION=v1
# JWT / Auth
JWT_SECRET=GoodGo-Local-Dev-JWT-Secret-2024-Min32Chars!!
JWT_REFRESH_SECRET=GoodGo-Local-Dev-Refresh-Secret-2024-32Ch!!
JWT_ID_SECRET=GoodGo-Local-Dev-ID-Secret-2024-Min32Char!!
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
JWT_ID_EXPIRES_IN=1h
JWT_ISSUER=goodgo-platform
JWT_AUDIENCE=goodgo-services
JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15
JWT_REFRESH_TOKEN_EXPIRY_DAYS=7
# Security
ENCRYPTION_KEY=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
# Redis (local container)
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=goodgo-redis-local
REDIS_DATABASE=0
REDIS_CONNECTION_STRING=redis:6379,password=goodgo-redis-local
# MinIO (local container)
MINIO_ENDPOINT=minio:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin123
# RabbitMQ (local container)
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=goodgo-rabbitmq-local
# Feature flags
FEATURE_SWAGGER_ENABLED=true
FEATURE_DETAILED_ERRORS=true
CORS_ORIGIN=http://localhost:3000,http://localhost:3001,http://localhost,http://admin.localhost
TRACING_ENABLED=false
JAEGER_ENDPOINT=http://jaeger:14268/api/traces
METRICS_ENABLED=true
SEQ_URL=http://localhost:5341
# Database connection strings (Remote PostgreSQL - 212.28.186.239:30992)
IAM_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=iam_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
STORAGE_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=storage_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MEMBERSHIP_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=membership_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MERCHANT_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=merchant_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
WALLET_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=wallet_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
CHAT_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=chat_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
SOCIAL_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=social_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MINING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mining_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MISSION_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mission_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
PROMOTION_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=promotion_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
CATALOG_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=catalog_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ORDER_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=order_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
INVENTORY_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=inventory_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
FNB_ENGINE_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=fnb_engine;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
BOOKING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=booking_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_MANAGER_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_manager_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_ANALYTICS_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_analytics_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_SERVING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_serving_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_BILLING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_billing_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_TRACKING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_tracking_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_FACEBOOK_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_facebook_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_WHATSAPP_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_whatsapp_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_X_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_x_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_ZALO_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_zalo_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer

View File

@@ -0,0 +1,77 @@
# =============================================================================
# GoodGo Platform - Local Docker Environment
# =============================================================================
# EN: Auto-generated for self-contained local Docker deployment.
# VI: Tự động tạo cho deployment Docker local tự hoàn chỉnh.
# =============================================================================
ASPNETCORE_ENVIRONMENT=Development
NODE_ENV=development
LOG_LEVEL=Information
API_VERSION=v1
# JWT / Auth
JWT_SECRET=GoodGo-Local-Dev-JWT-Secret-2024-Min32Chars!!
JWT_REFRESH_SECRET=GoodGo-Local-Dev-Refresh-Secret-2024-32Ch!!
JWT_ID_SECRET=GoodGo-Local-Dev-ID-Secret-2024-Min32Char!!
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
JWT_ID_EXPIRES_IN=1h
JWT_ISSUER=goodgo-platform
JWT_AUDIENCE=goodgo-services
JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15
JWT_REFRESH_TOKEN_EXPIRY_DAYS=7
# Security
ENCRYPTION_KEY=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
# Redis (local container)
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=goodgo-redis-local
REDIS_DATABASE=0
REDIS_CONNECTION_STRING=redis:6379,password=goodgo-redis-local
# MinIO (local container)
MINIO_ENDPOINT=minio:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin123
# RabbitMQ (local container)
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=goodgo-rabbitmq-local
# Feature flags
FEATURE_SWAGGER_ENABLED=true
FEATURE_DETAILED_ERRORS=true
CORS_ORIGIN=http://localhost:3000,http://localhost:3001,http://localhost,http://admin.localhost
TRACING_ENABLED=false
JAEGER_ENDPOINT=http://jaeger:14268/api/traces
METRICS_ENABLED=true
SEQ_URL=http://localhost:5341
# Database connection strings (local PostgreSQL container)
IAM_DATABASE_URL=Host=postgres;Port=5432;Database=iam_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
STORAGE_DATABASE_URL=Host=postgres;Port=5432;Database=storage_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MEMBERSHIP_DATABASE_URL=Host=postgres;Port=5432;Database=membership_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MERCHANT_DATABASE_URL=Host=postgres;Port=5432;Database=merchant_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
WALLET_DATABASE_URL=Host=postgres;Port=5432;Database=wallet_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
CHAT_DATABASE_URL=Host=postgres;Port=5432;Database=chat_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
SOCIAL_DATABASE_URL=Host=postgres;Port=5432;Database=social_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MINING_DATABASE_URL=Host=postgres;Port=5432;Database=mining_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MISSION_DATABASE_URL=Host=postgres;Port=5432;Database=mission_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
PROMOTION_DATABASE_URL=Host=postgres;Port=5432;Database=promotion_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
CATALOG_DATABASE_URL=Host=postgres;Port=5432;Database=catalog_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
ORDER_DATABASE_URL=Host=postgres;Port=5432;Database=order_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
INVENTORY_DATABASE_URL=Host=postgres;Port=5432;Database=inventory_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
FNB_ENGINE_DATABASE_URL=Host=postgres;Port=5432;Database=fnb_engine;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
BOOKING_DATABASE_URL=Host=postgres;Port=5432;Database=booking_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
ADS_MANAGER_DATABASE_URL=Host=postgres;Port=5432;Database=ads_manager_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
ADS_ANALYTICS_DATABASE_URL=Host=postgres;Port=5432;Database=ads_analytics_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
ADS_SERVING_DATABASE_URL=Host=postgres;Port=5432;Database=ads_serving_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
ADS_BILLING_DATABASE_URL=Host=postgres;Port=5432;Database=ads_billing_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
ADS_TRACKING_DATABASE_URL=Host=postgres;Port=5432;Database=ads_tracking_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MKT_FACEBOOK_DATABASE_URL=Host=postgres;Port=5432;Database=mkt_facebook_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MKT_WHATSAPP_DATABASE_URL=Host=postgres;Port=5432;Database=mkt_whatsapp_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MKT_X_DATABASE_URL=Host=postgres;Port=5432;Database=mkt_x_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable
MKT_ZALO_DATABASE_URL=Host=postgres;Port=5432;Database=mkt_zalo_service;Username=goodgo;Password=goodgo-local-2024;SSL Mode=Disable

View File

@@ -0,0 +1,82 @@
# =============================================================================
# GoodGo Platform - Hybrid Dev Environment (Remote DB + MinIO, Local Redis + RabbitMQ)
# =============================================================================
# EN: Points PostgreSQL and MinIO to remote staging servers.
# Redis and RabbitMQ run locally on non-standard ports to avoid conflicts.
# VI: Trỏ PostgreSQL và MinIO lên remote staging servers.
# Redis và RabbitMQ chạy local trên port khác để tránh xung đột.
# =============================================================================
ASPNETCORE_ENVIRONMENT=Development
NODE_ENV=development
LOG_LEVEL=Information
API_VERSION=v1
# JWT / Auth
JWT_SECRET=GoodGo-Local-Dev-JWT-Secret-2024-Min32Chars!!
JWT_REFRESH_SECRET=GoodGo-Local-Dev-Refresh-Secret-2024-32Ch!!
JWT_ID_SECRET=GoodGo-Local-Dev-ID-Secret-2024-Min32Char!!
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
JWT_ID_EXPIRES_IN=1h
JWT_ISSUER=goodgo-platform
JWT_AUDIENCE=goodgo-services
JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15
JWT_REFRESH_TOKEN_EXPIRY_DAYS=7
# Security
ENCRYPTION_KEY=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
# Redis (LOCAL container on non-standard port to avoid conflict with ga-redis)
REDIS_HOST=localhost
REDIS_PORT=16379
REDIS_PASSWORD=goodgo-redis-dev
REDIS_DATABASE=0
REDIS_CONNECTION_STRING=localhost:16379,password=goodgo-redis-dev
# MinIO (REMOTE - staging server via HTTPS)
MINIO_ENDPOINT=minio.techbi.org
MINIO_ACCESS_KEY=admin
MINIO_SECRET_KEY=Velik@2026
MINIO_USE_SSL=true
MINIO_BUCKET=goodgo-staging
# RabbitMQ (LOCAL container on non-standard port to avoid conflict with ga-rabbitmq)
RABBITMQ_HOST=localhost
RABBITMQ_PORT=25672
RABBITMQ_MANAGEMENT_PORT=35672
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=goodgo-rabbitmq-dev
# Feature flags
FEATURE_SWAGGER_ENABLED=true
FEATURE_DETAILED_ERRORS=true
CORS_ORIGIN=http://localhost:3000,http://localhost:3001,http://localhost,http://admin.localhost
TRACING_ENABLED=false
METRICS_ENABLED=false
# Database connection strings (REMOTE PostgreSQL - Staging Neon via NodePort)
IAM_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=iam_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
STORAGE_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=storage_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MEMBERSHIP_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=membership_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MERCHANT_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=merchant_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
WALLET_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=wallet_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
CHAT_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=chat_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
SOCIAL_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=social_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MINING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mining_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MISSION_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mission_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
PROMOTION_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=promotion_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
CATALOG_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=catalog_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ORDER_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=order_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
INVENTORY_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=inventory_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
FNB_ENGINE_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=fnb_engine;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
BOOKING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=booking_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_MANAGER_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_manager_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_ANALYTICS_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_analytics_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_SERVING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_serving_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_BILLING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_billing_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
ADS_TRACKING_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=ads_tracking_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_FACEBOOK_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_facebook_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_WHATSAPP_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_whatsapp_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_X_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_x_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer
MKT_ZALO_DATABASE_URL=Host=212.28.186.239;Port=30992;Database=mkt_zalo_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer

View File

@@ -0,0 +1,51 @@
# Local Development Deployment
Docker Compose configuration for running the GoodGo platform locally.
## Quick Start
```bash
# Setup environment
cp env.local.example .env
cp env.local.example .env.local
# Update all placeholder secrets/connection strings in both files
# before starting the stack.
# Start platform
docker-compose up -d
# View status
docker-compose ps
```
## Access
- **Traefik Dashboard**: http://localhost:8080
- **Auth Service**: http://localhost/api/v1/auth
- **Web Admin**: http://admin.localhost (currently disabled)
- **Web Client**: http://localhost (currently disabled)
## Documentation
For detailed documentation, see:
- **English**: [docs/en/guides/local-deployment.md](../../docs/en/guides/local-deployment.md)
- **Vietnamese**: [docs/vi/guides/local-deployment.md](../../docs/vi/guides/local-deployment.md)
## Files
- `docker-compose.yml` - Service orchestration
- `env.local.example` - Sanitized environment variables template
- `.env` - Docker Compose interpolation file (fill with real values)
- `.env.local` - Local override file (fill with real values)
## Common Commands
```bash
docker-compose up -d # Start all
docker-compose logs -f [service] # View logs
docker-compose down # Stop all
docker-compose ps # Check status
```
For troubleshooting and advanced usage, see the full documentation above.

View File

@@ -0,0 +1,57 @@
# =============================================================================
# GoodGo Platform - Lightweight Dev Infrastructure
# =============================================================================
# EN: Only Redis + RabbitMQ for local dev. PostgreSQL and MinIO are on remote.
# VI: Chỉ Redis + RabbitMQ cho local dev. PostgreSQL và MinIO ở remote server.
#
# Usage:
# docker compose -f docker-compose.dev.yml up -d
# docker compose -f docker-compose.dev.yml down
#
# Ports (non-standard to avoid conflicts):
# Redis: 16379 (instead of 6379)
# RabbitMQ: 25672 (AMQP), 35672 (Management UI)
# =============================================================================
services:
# Redis 7 - Cache & SignalR Backplane (dev)
redis-dev:
image: redis:7-alpine
container_name: goodgo-redis-dev
command: redis-server --requirepass goodgo-redis-dev --maxmemory 256mb --maxmemory-policy allkeys-lru
ports:
- "16379:6379"
volumes:
- redis_dev_data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "-a", "goodgo-redis-dev", "ping"]
interval: 10s
timeout: 5s
retries: 5
# RabbitMQ 3 - Message Broker (dev)
rabbitmq-dev:
image: rabbitmq:3-management-alpine
container_name: goodgo-rabbitmq-dev
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=goodgo-rabbitmq-dev
ports:
- "25672:5672" # AMQP
- "35672:15672" # Management UI
volumes:
- rabbitmq_dev_data:/var/lib/rabbitmq
restart: unless-stopped
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 15s
timeout: 10s
retries: 5
start_period: 30s
volumes:
redis_dev_data:
driver: local
rabbitmq_dev_data:
driver: local

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
# =============================================================================
# GoodGo Platform - Local Environment Template
# =============================================================================
# EN: Copy this file to both `.env` and `.env.local` before running docker compose.
# VI: Sao chép file này thành cả `.env` và `.env.local` trước khi chạy docker compose.
#
# cp env.local.example .env
# cp env.local.example .env.local
#
# EN: Never commit real credentials.
# VI: Không commit thông tin nhạy cảm thật.
# =============================================================================
# -----------------------------------------------------------------------------
# Runtime
# -----------------------------------------------------------------------------
ASPNETCORE_ENVIRONMENT=Development
NODE_ENV=development
LOG_LEVEL=Information
API_VERSION=v1
# -----------------------------------------------------------------------------
# JWT / Auth (shared across services)
# -----------------------------------------------------------------------------
JWT_SECRET=replace-with-min-32-char-secret
JWT_REFRESH_SECRET=replace-with-min-32-char-secret
JWT_ID_SECRET=replace-with-min-32-char-secret
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
JWT_ID_EXPIRES_IN=1h
JWT_ISSUER=goodgo-platform
JWT_AUDIENCE=goodgo-services
JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15
JWT_REFRESH_TOKEN_EXPIRY_DAYS=7
# -----------------------------------------------------------------------------
# Security / Encryption
# -----------------------------------------------------------------------------
ENCRYPTION_KEY=replace-with-64-char-hex-key
# -----------------------------------------------------------------------------
# Redis
# -----------------------------------------------------------------------------
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=replace-with-redis-password
REDIS_DATABASE=0
REDIS_CONNECTION_STRING=redis:6379,password=replace-with-redis-password
# -----------------------------------------------------------------------------
# MinIO / Object storage
# -----------------------------------------------------------------------------
MINIO_ENDPOINT=minio:9000
MINIO_ACCESS_KEY=replace-with-minio-access-key
MINIO_SECRET_KEY=replace-with-minio-secret-key
# -----------------------------------------------------------------------------
# RabbitMQ
# -----------------------------------------------------------------------------
RABBITMQ_USERNAME=guest
RABBITMQ_PASSWORD=replace-with-rabbitmq-password
# -----------------------------------------------------------------------------
# IAM feature flags / misc
# -----------------------------------------------------------------------------
FEATURE_SWAGGER_ENABLED=true
FEATURE_DETAILED_ERRORS=true
CORS_ORIGIN=http://localhost:3000,http://localhost:3001,http://localhost,http://admin.localhost
TRACING_ENABLED=false
JAEGER_ENDPOINT=http://jaeger:14268/api/traces
METRICS_ENABLED=true
SEQ_URL=http://localhost:5341
# -----------------------------------------------------------------------------
# Service database connection strings
# -----------------------------------------------------------------------------
IAM_DATABASE_URL=Host=your-neon-host;Port=5432;Database=iam_service;Username=your-user;Password=your-password;SSL Mode=Require
STORAGE_DATABASE_URL=Host=your-neon-host;Port=5432;Database=storage_service;Username=your-user;Password=your-password;SSL Mode=Require
MEMBERSHIP_DATABASE_URL=Host=your-neon-host;Port=5432;Database=membership_service;Username=your-user;Password=your-password;SSL Mode=Require
MERCHANT_DATABASE_URL=Host=your-neon-host;Port=5432;Database=merchant_service;Username=your-user;Password=your-password;SSL Mode=Require
WALLET_DATABASE_URL=Host=your-neon-host;Port=5432;Database=wallet_service;Username=your-user;Password=your-password;SSL Mode=Require
CHAT_DATABASE_URL=Host=your-neon-host;Port=5432;Database=chat_service;Username=your-user;Password=your-password;SSL Mode=Require
SOCIAL_DATABASE_URL=Host=your-neon-host;Port=5432;Database=social_service;Username=your-user;Password=your-password;SSL Mode=Require
MINING_DATABASE_URL=Host=your-neon-host;Port=5432;Database=mining_service;Username=your-user;Password=your-password;SSL Mode=Require
MISSION_DATABASE_URL=Host=your-neon-host;Port=5432;Database=mission_service;Username=your-user;Password=your-password;SSL Mode=Require
PROMOTION_DATABASE_URL=Host=your-neon-host;Port=5432;Database=promotion_service;Username=your-user;Password=your-password;SSL Mode=Require
CATALOG_DATABASE_URL=Host=your-neon-host;Port=5432;Database=catalog_service;Username=your-user;Password=your-password;SSL Mode=Require
ORDER_DATABASE_URL=Host=your-neon-host;Port=5432;Database=order_service;Username=your-user;Password=your-password;SSL Mode=Require
INVENTORY_DATABASE_URL=Host=your-neon-host;Port=5432;Database=inventory_service;Username=your-user;Password=your-password;SSL Mode=Require
FNB_ENGINE_DATABASE_URL=Host=your-neon-host;Port=5432;Database=fnb_engine;Username=your-user;Password=your-password;SSL Mode=Require
BOOKING_DATABASE_URL=Host=your-neon-host;Port=5432;Database=booking_service;Username=your-user;Password=your-password;SSL Mode=Require
ADS_MANAGER_DATABASE_URL=Host=your-neon-host;Port=5432;Database=ads_manager_service;Username=your-user;Password=your-password;SSL Mode=Require
ADS_ANALYTICS_DATABASE_URL=Host=your-neon-host;Port=5432;Database=ads_analytics_service;Username=your-user;Password=your-password;SSL Mode=Require
ADS_SERVING_DATABASE_URL=Host=your-neon-host;Port=5432;Database=ads_serving_service;Username=your-user;Password=your-password;SSL Mode=Require
ADS_BILLING_DATABASE_URL=Host=your-neon-host;Port=5432;Database=ads_billing_service;Username=your-user;Password=your-password;SSL Mode=Require
ADS_TRACKING_DATABASE_URL=Host=your-neon-host;Port=5432;Database=ads_tracking_service;Username=your-user;Password=your-password;SSL Mode=Require
MKT_FACEBOOK_DATABASE_URL=Host=your-neon-host;Port=5432;Database=mkt_facebook_service;Username=your-user;Password=your-password;SSL Mode=Require
MKT_WHATSAPP_DATABASE_URL=Host=your-neon-host;Port=5432;Database=mkt_whatsapp_service;Username=your-user;Password=your-password;SSL Mode=Require
MKT_X_DATABASE_URL=Host=your-neon-host;Port=5432;Database=mkt_x_service;Username=your-user;Password=your-password;SSL Mode=Require
MKT_ZALO_DATABASE_URL=Host=your-neon-host;Port=5432;Database=mkt_zalo_service;Username=your-user;Password=your-password;SSL Mode=Require

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# =============================================================================
# GoodGo Platform - PostgreSQL Database Initialization Script
# =============================================================================
# EN: Creates all required databases for each microservice on first startup.
# VI: Tạo tất cả databases cần thiết cho từng microservice khi khởi động lần đầu.
# =============================================================================
set -e
DATABASES=(
"ads_analytics_service"
"ads_billing_service"
"ads_manager_service"
"ads_serving_service"
"ads_tracking_service"
"booking_service"
"catalog_service"
"chat_service"
"fnb_engine"
"iam_service"
"inventory_service"
"membership_service"
"merchant_service"
"mining_service"
"mission_service"
"mkt_facebook_service"
"mkt_whatsapp_service"
"mkt_x_service"
"mkt_zalo_service"
"order_service"
"promotion_service"
"social_service"
"storage_service"
"wallet_service"
)
echo "=== GoodGo: Creating databases ==="
for DB_NAME in "${DATABASES[@]}"; do
echo "Creating database: $DB_NAME"
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
SELECT 'CREATE DATABASE $DB_NAME'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec
EOSQL
done
echo "=== GoodGo: All databases created successfully ==="

View File

@@ -0,0 +1,213 @@
# Local Kubernetes Deployment Guide (Docker Desktop)
## Prerequisites
- Docker Desktop for macOS M4 Max
- kubectl CLI installed
- Minimum 8GB RAM allocated to Docker Desktop
## Step 1: Enable Kubernetes in Docker Desktop
1. Open Docker Desktop
2. Go to **Settings** (gear icon)
3. Click **Kubernetes** tab
4. Check **Enable Kubernetes**
5. Click **Apply & Restart**
6. Wait for Kubernetes to start (green indicator)
Verify installation:
```bash
kubectl version --client
kubectl cluster-info
kubectl get nodes
```
Expected output:
```
NAME STATUS ROLES AGE VERSION
docker-desktop Ready control-plane 1d v1.28.2
```
## Step 2: Create Local Namespace
```bash
kubectl create namespace iam-local
kubectl config set-context --current --namespace=iam-local
```
## Step 3: Create Secrets
```bash
# Generate strong secrets (DO NOT use these in production!)
JWT_SECRET=$(openssl rand -base64 32)
JWT_REFRESH_SECRET=$(openssl rand -base64 32)
JWT_ID_SECRET=$(openssl rand -base64 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
# Create Kubernetes secret
kubectl create secret generic iam-service-secrets \
--from-literal=jwt-secret="$JWT_SECRET" \
--from-literal=jwt-refresh-secret="$JWT_REFRESH_SECRET" \
--from-literal=jwt-id-secret="$JWT_ID_SECRET" \
--from-literal=encryption-key="$ENCRYPTION_KEY" \
--from-literal=database-url="postgresql://username:password@host.neon.tech/database?sslmode=require" \
-n iam-local
```
**IMPORTANT**: Update `database-url` with your actual Neon PostgreSQL connection string.
## Step 4: Create ConfigMap
```bash
kubectl apply -f deployments/local/kubernetes/iam-service-configmap.yaml -n iam-local
```
## Step 5: Build and Load Docker Image
```bash
# Build image
cd /Users/velikho/Desktop/WORKING/Base
docker build -t iam-service:local -f services/iam-service/Dockerfile .
# Verify image
docker images | grep iam-service
```
**Note**: Docker Desktop Kubernetes can access images built locally, no need to push to registry.
## Step 6: Deploy Service
```bash
kubectl apply -f deployments/local/kubernetes/iam-service-deployment.yaml -n iam-local
```
## Step 7: Verify Deployment
```bash
# Check pods
kubectl get pods -n iam-local
# Check deployment
kubectl get deployment -n iam-local
# Check logs
kubectl logs -f deployment/iam-service -n iam-local
# Describe pod (if issues)
kubectl describe pod <pod-name> -n iam-local
```
## Step 8: Expose Service (LoadBalancer)
```bash
kubectl apply -f deployments/local/kubernetes/iam-service-service.yaml -n iam-local
```
For Docker Desktop, LoadBalancer will be available at `localhost`.
## Step 9: Test Endpoints
```bash
# Get service URL
kubectl get svc iam-service -n iam-local
# Test health
curl http://localhost:<PORT>/health/live
curl http://localhost:<PORT>/health/ready
# Test registration
curl -X POST http://localhost:<PORT>/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"k8s-test@example.com","password":"Test@123456","username":"k8suser"}'
```
## Step 10: Run Database Migrations
```bash
# Port-forward to access service
kubectl port-forward deployment/iam-service 5001:5001 -n iam-local
# In another terminal, run migrations
cd services/iam-service
DATABASE_URL="<your-neon-db-url>" pnpm prisma:deploy
```
## Troubleshooting
### Pod Not Starting
```bash
# Check events
kubectl get events -n iam-local --sort-by='.lastTimestamp'
# Check pod logs
kubectl logs <pod-name> -n iam-local
# Check pod description
kubectl describe pod <pod-name> -n iam-local
```
Common issues:
- **ImagePullBackOff**: Image not found locally, rebuild image
- **CrashLoopBackOff**: Check logs for errors, verify secrets/configmap
- **Pending**: Resource constraints, check Docker Desktop RAM allocation
### Service Not Accessible
```bash
# Check service
kubectl get svc -n iam-local
# Check endpoints
kubectl get endpoints -n iam-local
# Port forward for testing
kubectl port-forward svc/iam-service 5001:80 -n iam-local
```
### Database Connection Issues
- Verify DATABASE_URL in secret
- Check if Neon database allows connections from your IP
- Test connection manually: `psql <database-url>`
## Cleanup
```bash
# Delete all resources
kubectl delete namespace iam-local
# Or delete individual resources
kubectl delete deployment iam-service -n iam-local
kubectl delete service iam-service -n iam-local
kubectl delete configmap iam-service-config -n iam-local
kubectl delete secret iam-service-secrets -n iam-local
```
## Next Steps
After successful local K8s deployment:
1. Test all API endpoints
2. Verify health checks
3. Test autoscaling (HPA)
4. Test rolling updates
5. Simulate pod failures
## Differences from Production
| Aspect | Local K8s | Production K8s |
|--------|-----------|----------------|
| **Cluster** | Docker Desktop | Cloud (GKE/EKS/AKS) |
| **LoadBalancer** | localhost | Cloud LB with public IP |
| **Ingress** | Optional | Required (with TLS) |
| **Secrets** | kubectl create | External secrets manager |
| **Database** | Neon (shared) | Dedicated production DB |
| **Monitoring** | Optional | Required (Prometheus/Grafana) |
| **Replicas** | 1-2 | 3+ with HPA |
| **Resources** | Minimal | Production-grade limits |
## Resources
- [Docker Desktop Kubernetes](https://docs.docker.com/desktop/kubernetes/)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Kubernetes Documentation](https://kubernetes.io/docs/home/)

View File

@@ -0,0 +1,130 @@
#!/bin/bash
# EN: Quick deploy script for local Kubernetes (Docker Desktop)
# VI: Script deploy nhanh cho local Kubernetes (Docker Desktop)
set -e # Exit on error
echo "🚀 IAM Service - Local Kubernetes Deployment"
echo "=============================================="
echo ""
# Check if kubectl is installed
if ! command -v kubectl &> /dev/null; then
echo "❌ kubectl not found. Please install kubectl first."
echo " Install: brew install kubectl"
exit 1
fi
# Check if Kubernetes is running
if ! kubectl cluster-info &> /dev/null; then
echo "❌ Kubernetes cluster not accessible."
echo " Please enable Kubernetes in Docker Desktop:"
echo " Settings → Kubernetes → Enable Kubernetes"
exit 1
fi
echo "✅ kubectl installed"
echo "✅ Kubernetes cluster accessible"
echo ""
# Create namespace
echo "📦 Creating namespace 'iam-local'..."
kubectl create namespace iam-local --dry-run=client -o yaml | kubectl apply -f -
# Set context
kubectl config set-context --current --namespace=iam-local
echo "✅ Namespace created and set as default"
echo ""
# Prompt for database URL
echo "🔐 Setting up secrets..."
read -p "Enter your Neon DATABASE_URL: " DATABASE_URL
if [ -z "$DATABASE_URL" ]; then
echo "❌ DATABASE_URL is required"
exit 1
fi
# Generate secrets
echo "🔑 Generating JWT secrets..."
JWT_SECRET=$(openssl rand -base64 32)
JWT_REFRESH_SECRET=$(openssl rand -base64 32)
JWT_ID_SECRET=$(openssl rand -base64 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
# Create secret
kubectl create secret generic iam-service-secrets \
--from-literal=jwt-secret="$JWT_SECRET" \
--from-literal=jwt-refresh-secret="$JWT_REFRESH_SECRET" \
--from-literal=jwt-id-secret="$JWT_ID_SECRET" \
--from-literal=encryption-key="$ENCRYPTION_KEY" \
--from-literal=database-url="$DATABASE_URL" \
--dry-run=client -o yaml | kubectl apply -f -
echo "✅ Secrets created"
echo ""
# Apply ConfigMap
echo "⚙️ Applying ConfigMap..."
kubectl apply -f iam-service-configmap.yaml
echo "✅ ConfigMap applied"
echo ""
# Build Docker image
echo "🐳 Building Docker image..."
cd ../../..
docker build -t iam-service:local -f services/iam-service/Dockerfile .
cd deployments/local/kubernetes
echo "✅ Docker image built"
echo ""
# Apply Deployment
echo "🚀 Deploying IAM Service..."
kubectl apply -f iam-service-deployment.yaml
echo "✅ Deployment created"
echo ""
# Apply Service
echo "🌐 Creating Service..."
kubectl apply -f iam-service-service.yaml
echo "✅ Service created"
echo ""
# Wait for deployment
echo "⏳ Waiting for deployment to be ready..."
kubectl wait --for=condition=available --timeout=120s deployment/iam-service
echo "✅ Deployment ready!"
echo ""
# Get service info
echo "📊 Service Information:"
kubectl get svc iam-service
echo ""
# Get pod info
echo "📦 Pod Information:"
kubectl get pods -l app=iam-service
echo ""
# Show logs
echo "📝 Recent logs:"
kubectl logs -l app=iam-service --tail=20
echo ""
echo "✅ Deployment complete!"
echo ""
echo "🎯 Next steps:"
echo " 1. Run migrations: DATABASE_URL='$DATABASE_URL' pnpm --filter @goodgo/iam-service prisma:deploy"
echo " 2. Test health: kubectl port-forward svc/iam-service 5001:80"
echo " 3. Access API: curl http://localhost:5001/health/live"
echo ""
echo "📚 Useful commands:"
echo " - View logs: kubectl logs -f deployment/iam-service"
echo " - Describe pod: kubectl describe pod <pod-name>"
echo " - Delete all: kubectl delete namespace iam-local"

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: iam-service-config
namespace: iam-local
data:
# Node Environment
NODE_ENV: "development"
LOG_LEVEL: "debug"
# Service Configuration
PORT: "5001"
SERVICE_NAME: "iam-service"
API_VERSION: "v1"
# Redis Configuration
REDIS_HOST: "redis"
REDIS_PORT: "6379"
# JWT Configuration
JWT_EXPIRES_IN: "15m"
JWT_REFRESH_EXPIRES_IN: "7d"
JWT_ID_EXPIRES_IN: "1h"
JWT_ISSUER: "goodgo-auth"
JWT_AUDIENCE: "goodgo-api"
# CORS Configuration
CORS_ORIGIN: "http://localhost:3000,http://localhost:3001,http://localhost"
# Observability
TRACING_ENABLED: "false"
METRICS_ENABLED: "true"

View File

@@ -0,0 +1,102 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: iam-service
namespace: iam-local
labels:
app: iam-service
version: local
spec:
replicas: 1
selector:
matchLabels:
app: iam-service
template:
metadata:
labels:
app: iam-service
version: local
spec:
containers:
- name: iam-service
image: iam-service:local
imagePullPolicy: IfNotPresent # Use local image, don't pull from registry
ports:
- containerPort: 5001
name: http
protocol: TCP
# Environment variables from ConfigMap
envFrom:
- configMapRef:
name: iam-service-config
# Sensitive environment variables from Secret
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: iam-service-secrets
key: database-url
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: iam-service-secrets
key: jwt-secret
- name: JWT_REFRESH_SECRET
valueFrom:
secretKeyRef:
name: iam-service-secrets
key: jwt-refresh-secret
- name: JWT_ID_SECRET
valueFrom:
secretKeyRef:
name: iam-service-secrets
key: jwt-id-secret
- name: ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: iam-service-secrets
key: encryption-key
# Resource limits (adjust based on Docker Desktop allocation)
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
# Liveness probe - is the container running?
livenessProbe:
httpGet:
path: /health/live
port: 5001
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# Readiness probe - is the container ready to serve traffic?
readinessProbe:
httpGet:
path: /health/ready
port: 5001
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 3
# Startup probe - give container time to start
startupProbe:
httpGet:
path: /health/live
port: 5001
initialDelaySeconds: 0
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 12 # 60 seconds total (12 * 5s)
# Restart policy
restartPolicy: Always

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: iam-service
namespace: iam-local
labels:
app: iam-service
spec:
type: LoadBalancer # Docker Desktop will expose on localhost
selector:
app: iam-service
ports:
- name: http
port: 80
targetPort: 5001
protocol: TCP
sessionAffinity: None

View File

@@ -0,0 +1,19 @@
# Production Environment Variables
# Use these values to create Kubernetes secrets
# Neon Database (Production branch)
DATABASE_URL=postgresql://user:password@ep-xxx.region.neon.tech/dbname?sslmode=require&pgbouncer=true
# JWT Secrets (use strong random strings - min 32 chars)
JWT_SECRET=your-production-jwt-secret-min-32-chars
JWT_REFRESH_SECRET=your-production-refresh-secret-min-32-chars
# Redis
REDIS_HOST=redis-service
REDIS_PORT=6379
# Notes:
# - Store these in Kubernetes secrets or GitHub Secrets
# - Never commit actual values to Git
# - Use kubectl create secret or GitHub Secrets for CI/CD
# - Rotate secrets regularly

View File

@@ -0,0 +1,136 @@
# EN: Booking Service - Booking & Reservation System
# VI: Booking Service - He thong Dat cho & Dat lich
apiVersion: apps/v1
kind: Deployment
metadata:
name: booking-service
namespace: production
labels:
app: booking-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: booking-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: booking-service
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- booking-service
topologyKey: kubernetes.io/hostname
containers:
- name: booking-service
image: goodgo/booking-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: BOOKING_DATABASE_URL
- name: IamService__ServiceName
value: "booking-service"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: booking-service
namespace: production
labels:
app: booking-service
environment: production
spec:
selector:
app: booking-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: booking-service-hpa
namespace: production
labels:
app: booking-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: booking-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,136 @@
# EN: Catalog Service - Polymorphic Product & Category Management
# VI: Catalog Service - Quan ly San pham & Danh muc da hinh
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-service
namespace: production
labels:
app: catalog-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: catalog-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: catalog-service
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- catalog-service
topologyKey: kubernetes.io/hostname
containers:
- name: catalog-service
image: goodgo/catalog-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: CATALOG_DATABASE_URL
- name: IamService__ServiceName
value: "catalog-service"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: catalog-service
namespace: production
labels:
app: catalog-service
environment: production
spec:
selector:
app: catalog-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: catalog-service-hpa
namespace: production
labels:
app: catalog-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: catalog-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,58 @@
# EN: Shared configuration for all GoodGo production services
# VI: Cau hinh chung cho tat ca cac service production cua GoodGo
apiVersion: v1
kind: ConfigMap
metadata:
name: goodgo-config
namespace: production
labels:
environment: production
platform: goodgo
data:
# EN: ASP.NET Core Configuration
# VI: Cau hinh ASP.NET Core
ASPNETCORE_ENVIRONMENT: "Production"
ASPNETCORE_URLS: "http://+:8080"
# EN: JWT Configuration (shared across all services)
# VI: Cau hinh JWT (dung chung cho tat ca services)
Jwt__Authority: "http://iam-service:8080"
Jwt__Audience: "goodgo-api"
Jwt__RequireHttpsMetadata: "true"
# EN: Service Discovery URLs (K8s DNS: {service-name}.production.svc.cluster.local)
# VI: URL tim kiem service (K8s DNS: {service-name}.production.svc.cluster.local)
IamService__BaseUrl: "http://iam-service:8080"
MerchantService__BaseUrl: "http://merchant-service:8080"
CatalogService__BaseUrl: "http://catalog-service:8080"
OrderService__BaseUrl: "http://order-service:8080"
InventoryService__BaseUrl: "http://inventory-service:8080"
WalletService__BaseUrl: "http://wallet-service:8080"
StorageService__BaseUrl: "http://storage-service:8080"
FnbEngine__BaseUrl: "http://fnb-engine:8080"
BookingService__BaseUrl: "http://booking-service:8080"
# EN: Redis Configuration
# VI: Cau hinh Redis
Redis__Host: "redis"
Redis__Port: "6379"
Redis__Database: "0"
# EN: CORS Configuration
# VI: Cau hinh CORS
Cors__AllowedOrigins: "https://pos.goodgo.vn,https://goodgo.vn,https://admin.goodgo.vn"
# EN: Logging (stricter for production)
# VI: Ghi log (nghiem ngat hon cho production)
Serilog__MinimumLevel__Default: "Warning"
Serilog__MinimumLevel__Override__Microsoft: "Error"
Serilog__MinimumLevel__Override__System: "Error"
# EN: Feature Flags
# VI: Tinh nang bat/tat
Features__SwaggerEnabled: "false"
Features__DetailedErrors: "false"
# EN: API Version
# VI: Phien ban API
API_VERSION: "v1"

View File

@@ -0,0 +1,143 @@
# EN: FnB Engine - Table, Session, Kitchen & Reservation Management (SignalR for Kitchen Display)
# VI: FnB Engine - Quan ly Ban, Phien, Bep & Dat ban (SignalR cho Man hinh bep)
apiVersion: apps/v1
kind: Deployment
metadata:
name: fnb-engine
namespace: production
labels:
app: fnb-engine
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: fnb-engine
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: fnb-engine
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- fnb-engine
topologyKey: kubernetes.io/hostname
containers:
- name: fnb-engine
image: goodgo/fnb-engine-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: FNB_DATABASE_URL
- name: IamService__ServiceName
value: "fnb-engine"
# EN: Redis for SignalR backplane (Kitchen Display)
# VI: Redis cho SignalR backplane (Man hinh bep)
- name: ConnectionStrings__Redis
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ConnectionStrings__Redis
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: fnb-engine
namespace: production
labels:
app: fnb-engine
environment: production
spec:
selector:
app: fnb-engine
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: fnb-engine-hpa
namespace: production
labels:
app: fnb-engine
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: fnb-engine
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,145 @@
# EN: IAM Service - Identity & Access Management (Duende IdentityServer, JWT, RBAC, MFA)
# VI: IAM Service - Quan ly Danh tinh & Truy cap (Duende IdentityServer, JWT, RBAC, MFA)
apiVersion: apps/v1
kind: Deployment
metadata:
name: iam-service
namespace: production
labels:
app: iam-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: iam-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: iam-service
environment: production
spec:
# EN: Pod anti-affinity to spread replicas across nodes
# VI: Anti-affinity de phan bo replica tren nhieu node
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
topologyKey: kubernetes.io/hostname
containers:
- name: iam-service
image: goodgo/iam-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: IAM_DATABASE_URL
- name: IamService__ServiceName
value: "iam-service"
- name: IdentityServer__IssuerUri
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: IdentityServer__IssuerUri
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: iam-service
namespace: production
labels:
app: iam-service
environment: production
spec:
selector:
app: iam-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: iam-service-hpa
namespace: production
labels:
app: iam-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: iam-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,289 @@
# EN: Traefik Ingress for GoodGo Production - API Gateway routing
# VI: Traefik Ingress cho GoodGo Production - Dinh tuyen API Gateway
#
# Routes match infra/traefik/dynamic/routes.yml for consistency
# Host: api.goodgo.vn (API), pos.goodgo.vn (POS Frontend)
# =============================================================================
# API Ingress - Backend services
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: production
labels:
environment: production
platform: goodgo
annotations:
# EN: Traefik Ingress class
# VI: Ingress class cua Traefik
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
# EN: Rate limiting and security middlewares
# VI: Middleware gioi han toc do va bao mat
traefik.ingress.kubernetes.io/router.middlewares: production-cors@kubernetescrd,production-secure-headers@kubernetescrd,production-rate-limit@kubernetescrd
# EN: cert-manager TLS (production issuer)
# VI: TLS bang cert-manager (issuer production)
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: traefik
tls:
- hosts:
- api.goodgo.vn
secretName: api-production-tls
rules:
- host: api.goodgo.vn
http:
paths:
# ===== IAM Service =====
- path: /api/v1/auth
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/users
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/identity
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/access
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/governance
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/rbac
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/mfa
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /api/v1/sessions
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
# EN: IdentityServer OIDC endpoints
# VI: IdentityServer OIDC endpoints
- path: /connect
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
- path: /.well-known
pathType: Prefix
backend:
service:
name: iam-service
port:
number: 8080
# ===== Merchant Service =====
- path: /api/v1/merchants
pathType: Prefix
backend:
service:
name: merchant-service
port:
number: 8080
- path: /api/v1/shops
pathType: Prefix
backend:
service:
name: merchant-service
port:
number: 8080
- path: /api/v1/subscriptions
pathType: Prefix
backend:
service:
name: merchant-service
port:
number: 8080
# ===== Order Service =====
- path: /api/v1/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
# EN: POS/KDS SignalR Hub (WebSocket)
# VI: POS/KDS SignalR Hub (WebSocket)
- path: /hubs/pos
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
# ===== FnB Engine =====
- path: /api/v1/kitchen
pathType: Prefix
backend:
service:
name: fnb-engine
port:
number: 8080
- path: /api/v1/fnb
pathType: Prefix
backend:
service:
name: fnb-engine
port:
number: 8080
- path: /api/v1/tables
pathType: Prefix
backend:
service:
name: fnb-engine
port:
number: 8080
# EN: Kitchen Display SignalR Hub
# VI: SignalR Hub Man hinh bep
- path: /hubs/kitchen
pathType: Prefix
backend:
service:
name: fnb-engine
port:
number: 8080
# ===== Inventory Service =====
- path: /api/v1/inventory
pathType: Prefix
backend:
service:
name: inventory-service
port:
number: 8080
- path: /api/v1/stock
pathType: Prefix
backend:
service:
name: inventory-service
port:
number: 8080
# ===== Wallet Service =====
- path: /api/v1/wallets
pathType: Prefix
backend:
service:
name: wallet-service
port:
number: 8080
- path: /api/v1/points
pathType: Prefix
backend:
service:
name: wallet-service
port:
number: 8080
- path: /api/v1/payments
pathType: Prefix
backend:
service:
name: wallet-service
port:
number: 8080
# ===== Catalog Service =====
- path: /api/v1/products
pathType: Prefix
backend:
service:
name: catalog-service
port:
number: 8080
- path: /api/v1/categories
pathType: Prefix
backend:
service:
name: catalog-service
port:
number: 8080
# ===== Booking Service =====
- path: /api/v1/bookings
pathType: Prefix
backend:
service:
name: booking-service
port:
number: 8080
- path: /api/v1/reservations
pathType: Prefix
backend:
service:
name: booking-service
port:
number: 8080
---
# =============================================================================
# POS Frontend Ingress
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pos-web-ingress
namespace: production
labels:
environment: production
platform: goodgo
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: traefik
tls:
- hosts:
- pos.goodgo.vn
secretName: pos-production-tls
rules:
- host: pos.goodgo.vn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: pos-web
port:
number: 8080

View File

@@ -0,0 +1,136 @@
# EN: Inventory Service - Stock Management & Deduction (Retail + FnB)
# VI: Inventory Service - Quan ly Ton kho & Tru kho (Retail + FnB)
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory-service
namespace: production
labels:
app: inventory-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: inventory-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: inventory-service
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- inventory-service
topologyKey: kubernetes.io/hostname
containers:
- name: inventory-service
image: goodgo/inventory-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: INVENTORY_DATABASE_URL
- name: IamService__ServiceName
value: "inventory-service"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: inventory-service
namespace: production
labels:
app: inventory-service
environment: production
spec:
selector:
app: inventory-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: inventory-service-hpa
namespace: production
labels:
app: inventory-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: inventory-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,136 @@
# EN: Merchant Service - Merchant & Shop Management
# VI: Merchant Service - Quan ly Merchant & Shop
apiVersion: apps/v1
kind: Deployment
metadata:
name: merchant-service
namespace: production
labels:
app: merchant-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: merchant-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: merchant-service
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- merchant-service
topologyKey: kubernetes.io/hostname
containers:
- name: merchant-service
image: goodgo/merchant-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MERCHANT_DATABASE_URL
- name: IamService__ServiceName
value: "merchant-service"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: merchant-service
namespace: production
labels:
app: merchant-service
environment: production
spec:
selector:
app: merchant-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: merchant-service-hpa
namespace: production
labels:
app: merchant-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: merchant-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,10 @@
# EN: Production namespace for GoodGo Platform
# VI: Namespace production cho GoodGo Platform
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
environment: production
platform: goodgo
managed-by: kubectl

View File

@@ -0,0 +1,144 @@
# EN: Order Service - Order Processing & POS API (SignalR WebSocket for POS/KDS)
# VI: Order Service - Xu ly Order & POS API (SignalR WebSocket cho POS/KDS)
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: production
labels:
app: order-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: order-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: order-service
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- order-service
topologyKey: kubernetes.io/hostname
containers:
- name: order-service
image: goodgo/order-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ORDER_DATABASE_URL
- name: IamService__ServiceName
value: "order-service"
# EN: Inter-service communication
# VI: Giao tiep giua cac service
- name: CatalogService__BaseUrl
value: "http://catalog-service:8080"
- name: InventoryService__BaseUrl
value: "http://inventory-service:8080"
- name: WalletService__BaseUrl
value: "http://wallet-service:8080"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: order-service
namespace: production
labels:
app: order-service
environment: production
spec:
selector:
app: order-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
namespace: production
labels:
app: order-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,122 @@
# EN: Redis - Cache & SignalR Backplane for production
# VI: Redis - Cache & SignalR Backplane cho production
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: production
labels:
app: redis
environment: production
platform: goodgo
tier: infrastructure
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
environment: production
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- "--requirepass"
- "$(REDIS_PASSWORD)"
- "--maxmemory"
- "512mb"
- "--maxmemory-policy"
- "allkeys-lru"
- "--appendonly"
- "yes"
- "--appendfsync"
- "everysec"
- "--save"
- "900 1"
- "--save"
- "300 10"
- "--save"
- "60 10000"
ports:
- containerPort: 6379
protocol: TCP
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
exec:
command:
- redis-cli
- -a
- "$(REDIS_PASSWORD)"
- ping
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- redis-cli
- -a
- "$(REDIS_PASSWORD)"
- ping
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: redis-data
mountPath: /data
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: production
labels:
app: redis
environment: production
spec:
selector:
app: redis
ports:
- name: redis
protocol: TCP
port: 6379
targetPort: 6379
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: production
labels:
app: redis
environment: production
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi

View File

@@ -0,0 +1,64 @@
# EN: Kubernetes Secrets Template for GoodGo Production
# VI: Template Secrets Kubernetes cho GoodGo Production
#
# DO NOT commit actual secrets to Git.
# Use this as a template to create secrets via kubectl or sealed-secrets.
#
# =============================================================================
# Option 1: Create secrets using kubectl (manual)
# =============================================================================
#
# kubectl create secret generic goodgo-secrets \
# --from-literal=Jwt__Secret='your-production-jwt-secret-min-64-chars-strong-random' \
# --from-literal=Jwt__RefreshSecret='your-production-refresh-secret-min-64-chars-strong-random' \
# --from-literal=IdentityServer__IssuerUri='https://api.goodgo.vn' \
# --from-literal=IAM_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/iam_production?sslmode=require&pgbouncer=true' \
# --from-literal=MERCHANT_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/merchant_production?sslmode=require&pgbouncer=true' \
# --from-literal=ORDER_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/order_production?sslmode=require&pgbouncer=true' \
# --from-literal=FNB_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/fnb_production?sslmode=require&pgbouncer=true' \
# --from-literal=INVENTORY_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/inventory_production?sslmode=require&pgbouncer=true' \
# --from-literal=WALLET_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/wallet_production?sslmode=require&pgbouncer=true' \
# --from-literal=CATALOG_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/catalog_production?sslmode=require&pgbouncer=true' \
# --from-literal=BOOKING_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/booking_production?sslmode=require&pgbouncer=true' \
# --from-literal=Redis__Password='your-strong-redis-password' \
# --from-literal=ConnectionStrings__Redis='redis:6379,password=your-strong-redis-password,abortConnect=false' \
# --from-literal=Storage__MinIO__Endpoint='minio.goodgo.vn' \
# --from-literal=Storage__MinIO__AccessKey='your-minio-access-key' \
# --from-literal=Storage__MinIO__SecretKey='your-minio-secret-key' \
# --from-literal=RabbitMQ__Host='rabbitmq' \
# --from-literal=RabbitMQ__Username='goodgo' \
# --from-literal=RabbitMQ__Password='your-strong-rabbitmq-password' \
# -n production
#
# =============================================================================
# Option 2: Use GitHub Secrets in CI/CD (for automated deployments)
# =============================================================================
#
# Required GitHub Secrets:
# - KUBECONFIG_PRODUCTION (base64 encoded kubeconfig)
# - DOCKER_USERNAME / DOCKER_PASSWORD
# - NEON_IAM_DATABASE_URL_PRODUCTION
# - NEON_MERCHANT_DATABASE_URL_PRODUCTION
# - NEON_ORDER_DATABASE_URL_PRODUCTION
# - NEON_FNB_DATABASE_URL_PRODUCTION
# - NEON_INVENTORY_DATABASE_URL_PRODUCTION
# - NEON_WALLET_DATABASE_URL_PRODUCTION
# - NEON_CATALOG_DATABASE_URL_PRODUCTION
# - NEON_BOOKING_DATABASE_URL_PRODUCTION
# - JWT_SECRET_PRODUCTION
# - JWT_REFRESH_SECRET_PRODUCTION
# - REDIS_PASSWORD_PRODUCTION
# - MINIO_ACCESS_KEY_PRODUCTION
# - MINIO_SECRET_KEY_PRODUCTION
# - RABBITMQ_PASSWORD_PRODUCTION
#
# =============================================================================
# Option 3: Use sealed-secrets or external-secrets operator (RECOMMENDED for production)
# =============================================================================
#
# Install sealed-secrets controller:
# kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.5/controller.yaml
#
# Create sealed secret:
# kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# kubectl apply -f sealed-secret.yaml

View File

@@ -0,0 +1,136 @@
# EN: Wallet Service - Wallet & Payment Management
# VI: Wallet Service - Quan ly Vi & Thanh toan
apiVersion: apps/v1
kind: Deployment
metadata:
name: wallet-service
namespace: production
labels:
app: wallet-service
environment: production
platform: goodgo
tier: backend
spec:
replicas: 3
selector:
matchLabels:
app: wallet-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: wallet-service
environment: production
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- wallet-service
topologyKey: kubernetes.io/hostname
containers:
- name: wallet-service
image: goodgo/wallet-service-net:IMAGE_TAG
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: WALLET_DATABASE_URL
- name: IamService__ServiceName
value: "wallet-service"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: wallet-service
namespace: production
labels:
app: wallet-service
environment: production
spec:
selector:
app: wallet-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: wallet-service-hpa
namespace: production
labels:
app: wallet-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: wallet-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,18 @@
# Staging Environment Variables
# Use these values to create Kubernetes secrets
# Neon Database (Staging branch)
DATABASE_URL=postgresql://user:password@ep-xxx.region.neon.tech/dbname?sslmode=require&pgbouncer=true
# JWT Secrets (use strong random strings)
JWT_SECRET=your-staging-jwt-secret-min-32-chars
JWT_REFRESH_SECRET=your-staging-refresh-secret-min-32-chars
# Redis
REDIS_HOST=redis-service
REDIS_PORT=6379
# Notes:
# - Store these in Kubernetes secrets or GitHub Secrets
# - Never commit actual values to Git
# - Use kubectl create secret or GitHub Secrets for CI/CD

View File

@@ -0,0 +1,50 @@
# EN: RBAC for Gitea act_runner to deploy to staging namespace
# VI: RBAC cho Gitea act_runner deploy vao namespace staging
#
# The act_runner ServiceAccount (in gitea namespace) needs permissions to:
# - Create Kaniko Jobs for building Docker images
# - Apply manifests (deployments, services, configmaps, secrets, ingress, hpa, networkpolicies, pvc)
# - Patch deployments (set image, rollout restart)
# - Read pods/logs (rollout status)
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: act-runner-staging
namespace: staging
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["services", "configmaps", "secrets", "persistentvolumeclaims"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses", "networkpolicies"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "create", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: act-runner-staging-binding
namespace: staging
subjects:
- kind: ServiceAccount
name: act-runner
namespace: gitea
roleRef:
kind: Role
name: act-runner-staging
apiGroup: rbac.authorization.k8s.io

View File

@@ -0,0 +1,125 @@
# EN: Ads Analytics Service - Ads performance analytics, reporting & insights
# VI: Ads Analytics Service - Phan tich hieu suat quang cao, bao cao & thong ke
apiVersion: apps/v1
kind: Deployment
metadata:
name: ads-analytics-service
namespace: staging
labels:
app: ads-analytics-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: ads-analytics-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ads-analytics-service
environment: staging
spec:
containers:
- name: ads-analytics-service
image: harbor.techbi.org/goodgo/ads-analytics-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ADS_ANALYTICS_DATABASE_URL
- name: AdsAnalyticsService__ServiceName
value: "ads-analytics-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: ads-analytics-service
namespace: staging
labels:
app: ads-analytics-service
environment: staging
spec:
selector:
app: ads-analytics-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ads-analytics-service-hpa
namespace: staging
labels:
app: ads-analytics-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ads-analytics-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,123 @@
# EN: Ads Billing Service - Advertising payment and invoice processing
# VI: Ads Billing Service - Xu ly thanh toan va hoa don quang cao
apiVersion: apps/v1
kind: Deployment
metadata:
name: ads-billing-service
namespace: staging
labels:
app: ads-billing-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: ads-billing-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ads-billing-service
environment: staging
spec:
containers:
- name: ads-billing-service
image: harbor.techbi.org/goodgo/ads-billing-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ADS_BILLING_DATABASE_URL
- name: AdsBillingService__ServiceName
value: "ads-billing-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: ads-billing-service
namespace: staging
labels:
app: ads-billing-service
environment: staging
spec:
selector:
app: ads-billing-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ads-billing-service-hpa
namespace: staging
labels:
app: ads-billing-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ads-billing-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,125 @@
# EN: Ads Manager Service - Ads campaign creation & management
# VI: Ads Manager Service - Tao va quan ly chien dich quang cao
apiVersion: apps/v1
kind: Deployment
metadata:
name: ads-manager-service
namespace: staging
labels:
app: ads-manager-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: ads-manager-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ads-manager-service
environment: staging
spec:
containers:
- name: ads-manager-service
image: harbor.techbi.org/goodgo/ads-manager-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ADS_MANAGER_DATABASE_URL
- name: AdsManagerService__ServiceName
value: "ads-manager-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: ads-manager-service
namespace: staging
labels:
app: ads-manager-service
environment: staging
spec:
selector:
app: ads-manager-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ads-manager-service-hpa
namespace: staging
labels:
app: ads-manager-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ads-manager-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,127 @@
# EN: Ads Serving Service - Ad delivery and targeting engine
# VI: Ads Serving Service - Phan phoi va nham muc tieu quang cao
apiVersion: apps/v1
kind: Deployment
metadata:
name: ads-serving-service
namespace: staging
labels:
app: ads-serving-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: ads-serving-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ads-serving-service
environment: staging
spec:
containers:
- name: ads-serving-service
image: harbor.techbi.org/goodgo/ads-serving-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ADS_SERVING_DATABASE_URL
- name: AdsServingService__ServiceName
value: "ads-serving-service"
- name: RabbitMQ__Host
value: "rabbitmq"
- name: RabbitMQ__Port
value: "5672"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: ads-serving-service
namespace: staging
labels:
app: ads-serving-service
environment: staging
spec:
selector:
app: ads-serving-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ads-serving-service-hpa
namespace: staging
labels:
app: ads-serving-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ads-serving-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,127 @@
# EN: Ads Tracking Service - Advertising event tracking and attribution
# VI: Ads Tracking Service - Theo doi su kien va phan bo quang cao
apiVersion: apps/v1
kind: Deployment
metadata:
name: ads-tracking-service
namespace: staging
labels:
app: ads-tracking-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: ads-tracking-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ads-tracking-service
environment: staging
spec:
containers:
- name: ads-tracking-service
image: harbor.techbi.org/goodgo/ads-tracking-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ADS_TRACKING_DATABASE_URL
- name: AdsTrackingService__ServiceName
value: "ads-tracking-service"
- name: RabbitMQ__Host
value: "rabbitmq"
- name: RabbitMQ__Port
value: "5672"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: ads-tracking-service
namespace: staging
labels:
app: ads-tracking-service
environment: staging
spec:
selector:
app: ads-tracking-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ads-tracking-service-hpa
namespace: staging
labels:
app: ads-tracking-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ads-tracking-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,125 @@
# EN: Booking Service - Booking & Reservation Management (Spa, Beauty, Karaoke scheduling)
# VI: Booking Service - Quan ly Dat lich & Dat cho (Spa, Beauty, Karaoke)
apiVersion: apps/v1
kind: Deployment
metadata:
name: booking-service
namespace: staging
labels:
app: booking-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: booking-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: booking-service
environment: staging
spec:
containers:
- name: booking-service
image: harbor.techbi.org/goodgo/booking-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: BOOKING_DATABASE_URL
- name: BookingService__ServiceName
value: "booking-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: booking-service
namespace: staging
labels:
app: booking-service
environment: staging
spec:
selector:
app: booking-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: booking-service-hpa
namespace: staging
labels:
app: booking-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: booking-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,123 @@
# EN: Catalog Service - Polymorphic Product & Category Management
# VI: Catalog Service - Quan ly San pham & Danh muc da hinh
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-service
namespace: staging
labels:
app: catalog-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: catalog-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: catalog-service
environment: staging
spec:
containers:
- name: catalog-service
image: harbor.techbi.org/goodgo/catalog-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: CATALOG_DATABASE_URL
- name: IamService__ServiceName
value: "catalog-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: catalog-service
namespace: staging
labels:
app: catalog-service
environment: staging
spec:
selector:
app: catalog-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: catalog-service-hpa
namespace: staging
labels:
app: catalog-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: catalog-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,134 @@
# EN: Chat Service - Real-time messaging with SignalR & Redis backplane
# VI: Chat Service - Nhan tin thoi gian thuc voi SignalR & Redis backplane
apiVersion: apps/v1
kind: Deployment
metadata:
name: chat-service
namespace: staging
labels:
app: chat-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: chat-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: chat-service
environment: staging
spec:
containers:
- name: chat-service
image: harbor.techbi.org/goodgo/chat-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: CHAT_DATABASE_URL
# EN: Redis connection for SignalR backplane
# VI: Ket noi Redis cho SignalR backplane
- name: ConnectionStrings__Redis
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ConnectionStrings__Redis
- name: SignalR__Redis__Enabled
value: "true"
- name: ChatService__ServiceName
value: "chat-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: chat-service
namespace: staging
labels:
app: chat-service
environment: staging
spec:
selector:
app: chat-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: chat-service-hpa
namespace: staging
labels:
app: chat-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: chat-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,88 @@
# EN: Shared configuration for all GoodGo staging services
# VI: Cau hinh chung cho tat ca cac service staging cua GoodGo
apiVersion: v1
kind: ConfigMap
metadata:
name: goodgo-config
namespace: staging
labels:
environment: staging
platform: goodgo
data:
# EN: ASP.NET Core Configuration
# VI: Cau hinh ASP.NET Core
ASPNETCORE_ENVIRONMENT: "Staging"
ASPNETCORE_URLS: "http://+:8080"
# EN: JWT Configuration (shared across all services)
# VI: Cau hinh JWT (dung chung cho tat ca services)
# EN: Use internal K8s DNS for OIDC discovery — pods cannot reach external HTTPS.
# Issuer in tokens is still https://api.techbi.org (set in iam-service IssuerUri).
# VI: Dùng K8s DNS nội bộ cho OIDC discovery — pods không thể reach HTTPS bên ngoài.
# Issuer trong tokens vẫn là https://api.techbi.org (set trong iam-service IssuerUri).
Jwt__Authority: "http://iam-service:8080"
Jwt__Audience: "goodgo-api"
# EN: false because Authority is HTTP (internal K8s). Token signature is still validated.
# VI: false vì Authority là HTTP (K8s nội bộ). Chữ ký token vẫn được xác thực.
Jwt__RequireHttpsMetadata: "false"
# EN: Service Discovery URLs (K8s DNS: {service-name}.staging.svc.cluster.local)
# VI: URL tim kiem service (K8s DNS: {service-name}.staging.svc.cluster.local)
IamService__BaseUrl: "http://iam-service:8080"
MerchantService__BaseUrl: "http://merchant-service:8080"
CatalogService__BaseUrl: "http://catalog-service:8080"
OrderService__BaseUrl: "http://order-service:8080"
InventoryService__BaseUrl: "http://inventory-service:8080"
WalletService__BaseUrl: "http://wallet-service:8080"
StorageService__BaseUrl: "http://storage-service:8080"
FnbEngine__BaseUrl: "http://fnb-engine:8080"
BookingService__BaseUrl: "http://booking-service:8080"
ChatService__BaseUrl: "http://chat-service:8080"
SocialService__BaseUrl: "http://social-service:8080"
PromotionService__BaseUrl: "http://promotion-service:8080"
MembershipService__BaseUrl: "http://membership-service:8080"
MiningService__BaseUrl: "http://mining-service:8080"
MissionService__BaseUrl: "http://mission-service:8080"
AdsManagerService__BaseUrl: "http://ads-manager-service:8080"
AdsServingService__BaseUrl: "http://ads-serving-service:8080"
AdsBillingService__BaseUrl: "http://ads-billing-service:8080"
AdsTrackingService__BaseUrl: "http://ads-tracking-service:8080"
AdsAnalyticsService__BaseUrl: "http://ads-analytics-service:8080"
MktFacebookService__BaseUrl: "http://mkt-facebook-service:8080"
MktWhatsappService__BaseUrl: "http://mkt-whatsapp-service:8080"
MktXService__BaseUrl: "http://mkt-x-service:8080"
MktZaloService__BaseUrl: "http://mkt-zalo-service:8080"
# EN: Redis Configuration
# VI: Cau hinh Redis
Redis__Host: "redis"
Redis__Port: "6379"
Redis__Database: "0"
# EN: RabbitMQ Configuration (non-secret)
# VI: Cau hinh RabbitMQ (khong bi mat)
RabbitMQ__Port: "5672"
# EN: MinIO Configuration (non-secret)
# VI: Cau hinh MinIO (khong bi mat)
Storage__MinIO__BucketName: "goodgo-staging"
# EN: CORS Configuration
# VI: Cau hinh CORS
Cors__AllowedOrigins: "https://platform.techbi.org,https://api.techbi.org,https://admin.techbi.org"
# EN: Logging
# VI: Ghi log
Serilog__MinimumLevel__Default: "Information"
Serilog__MinimumLevel__Override__Microsoft: "Warning"
Serilog__MinimumLevel__Override__System: "Warning"
# EN: Feature Flags
# VI: Tinh nang bat/tat
Features__SwaggerEnabled: "true"
Features__DetailedErrors: "false"
# EN: API Version
# VI: Phien ban API
API_VERSION: "v1"

View File

@@ -0,0 +1,130 @@
# EN: FnB Engine - Table, Session, Kitchen & Reservation Management (SignalR for Kitchen Display)
# VI: FnB Engine - Quan ly Ban, Phien, Bep & Dat ban (SignalR cho Man hinh bep)
apiVersion: apps/v1
kind: Deployment
metadata:
name: fnb-engine
namespace: staging
labels:
app: fnb-engine
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: fnb-engine
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: fnb-engine
environment: staging
spec:
containers:
- name: fnb-engine
image: harbor.techbi.org/goodgo/fnb-engine-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: FNB_DATABASE_URL
- name: IamService__ServiceName
value: "fnb-engine"
# EN: Redis for SignalR backplane (Kitchen Display)
# VI: Redis cho SignalR backplane (Man hinh bep)
- name: ConnectionStrings__Redis
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ConnectionStrings__Redis
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: fnb-engine
namespace: staging
labels:
app: fnb-engine
environment: staging
spec:
selector:
app: fnb-engine
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: fnb-engine-hpa
namespace: staging
labels:
app: fnb-engine
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: fnb-engine
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,69 @@
# EN: CronJob to sync GitHub → Gitea every 5 minutes
# VI: CronJob dong bo GitHub → Gitea moi 5 phut
#
# Flow: GitHub (hongochai10/Microservices-Development)
# → git clone --bare via SSH
# → git push --mirror to Gitea (admin/pos-system)
#
# Prerequisites:
# 1. Create Gitea repo: admin/pos-system on gitea.techbi.org
# 2. Create secrets:
# kubectl create secret generic pos-gitea-push-creds -n gitea \
# --from-literal=url=https://admin:Velik%402026@gitea.techbi.org/admin/pos-system.git
# (git-ssh-key secret already exists in gitea namespace from neon-ui setup)
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: github-gitea-sync-pos
namespace: gitea
labels:
app: pos-system
platform: goodgo
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 2
jobTemplate:
spec:
backoffLimit: 1
ttlSecondsAfterFinished: 120
template:
spec:
containers:
- name: sync
image: alpine/git:latest
command: ["sh", "-c"]
args:
- |
mkdir -p /root/.ssh
cp /ssh/ssh-privatekey /root/.ssh/id_ed25519
cp /ssh/known_hosts /root/.ssh/known_hosts
chmod 600 /root/.ssh/id_ed25519
git clone --bare git@github.com:hongochai10/Microservices-Development.git /tmp/repo
cd /tmp/repo
git push --mirror "${GITEA_PUSH_URL}"
env:
- name: GITEA_PUSH_URL
valueFrom:
secretKeyRef:
name: pos-gitea-push-creds
key: url
volumeMounts:
- name: git-ssh
mountPath: /ssh
readOnly: true
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
restartPolicy: Never
volumes:
- name: git-ssh
secret:
secretName: git-ssh-key
defaultMode: 0600

View File

@@ -0,0 +1,144 @@
# EN: IAM Service - Identity & Access Management (Duende IdentityServer, JWT, RBAC, MFA)
# VI: IAM Service - Quan ly Danh tinh & Truy cap (Duende IdentityServer, JWT, RBAC, MFA)
apiVersion: apps/v1
kind: Deployment
metadata:
name: iam-service
namespace: staging
labels:
app: iam-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: iam-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: iam-service
environment: staging
spec:
containers:
- name: iam-service
image: harbor.techbi.org/goodgo/iam-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: IAM_DATABASE_URL
- name: IamService__ServiceName
value: "iam-service"
- name: IdentityServer__IssuerUri
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: IdentityServer__IssuerUri
# EN: Signing certificate for IdentityServer in non-Development environments
# VI: Certificate ky cho IdentityServer trong moi truong khong phai Development
- name: IdentityServer__SigningCertificatePath
value: "/certs/signing.pfx"
- name: IdentityServer__SigningCertificatePassword
value: "GoodGo2026!"
volumeMounts:
- name: signing-cert
mountPath: /certs
readOnly: true
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
volumes:
- name: signing-cert
secret:
secretName: iam-signing-cert
---
apiVersion: v1
kind: Service
metadata:
name: iam-service
namespace: staging
labels:
app: iam-service
environment: staging
spec:
selector:
app: iam-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: iam-service-hpa
namespace: staging
labels:
app: iam-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: iam-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,84 @@
# EN: Nginx Ingress → Traefik proxy for GoodGo POS System
# VI: Nginx Ingress → Traefik proxy cho he thong GoodGo POS
#
# Architecture:
# Internet → Nginx Ingress (TLS, port 443) → Traefik (routing, port 80) → Services
# Nginx handles: TLS termination, cert-manager, external access
# Traefik handles: path routing, middleware (rate-limit, retry, compress, headers)
# =============================================================================
# API Ingress — proxies all API traffic to Traefik
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
# EN: WebSocket support for SignalR hubs
# VI: Ho tro WebSocket cho SignalR hubs
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
# EN: Pass original Host header to Traefik for routing decisions
# VI: Truyen Host header goc cho Traefik de dinh tuyen
nginx.ingress.kubernetes.io/upstream-vhost: "api.techbi.org"
# EN: cert-manager TLS (Let's Encrypt production)
# VI: TLS bang cert-manager (Let's Encrypt production)
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.techbi.org
secretName: api-techbi-tls
rules:
- host: api.techbi.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: traefik
port:
number: 80
---
# =============================================================================
# POS Frontend Ingress — proxies to Traefik
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pos-web-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/upstream-vhost: "platform.techbi.org"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- platform.techbi.org
secretName: platform-techbi-tls
rules:
- host: platform.techbi.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: traefik
port:
number: 80

View File

@@ -0,0 +1,123 @@
# EN: Inventory Service - Stock Management & Deduction (Retail + FnB)
# VI: Inventory Service - Quan ly Ton kho & Tru kho (Retail + FnB)
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory-service
namespace: staging
labels:
app: inventory-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: inventory-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: inventory-service
environment: staging
spec:
containers:
- name: inventory-service
image: harbor.techbi.org/goodgo/inventory-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: INVENTORY_DATABASE_URL
- name: IamService__ServiceName
value: "inventory-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: inventory-service
namespace: staging
labels:
app: inventory-service
environment: staging
spec:
selector:
app: inventory-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: inventory-service-hpa
namespace: staging
labels:
app: inventory-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: inventory-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,125 @@
# EN: Membership Service - Membership, loyalty points & tier management
# VI: Membership Service - Quan ly thanh vien, diem tich luy & cap bac
apiVersion: apps/v1
kind: Deployment
metadata:
name: membership-service
namespace: staging
labels:
app: membership-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: membership-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: membership-service
environment: staging
spec:
containers:
- name: membership-service
image: harbor.techbi.org/goodgo/membership-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MEMBERSHIP_DATABASE_URL
- name: MembershipService__ServiceName
value: "membership-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: membership-service
namespace: staging
labels:
app: membership-service
environment: staging
spec:
selector:
app: membership-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: membership-service-hpa
namespace: staging
labels:
app: membership-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: membership-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,123 @@
# EN: Merchant Service - Merchant & Shop Management
# VI: Merchant Service - Quan ly Merchant & Shop
apiVersion: apps/v1
kind: Deployment
metadata:
name: merchant-service
namespace: staging
labels:
app: merchant-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: merchant-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: merchant-service
environment: staging
spec:
containers:
- name: merchant-service
image: harbor.techbi.org/goodgo/merchant-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MERCHANT_DATABASE_URL
- name: IamService__ServiceName
value: "merchant-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: merchant-service
namespace: staging
labels:
app: merchant-service
environment: staging
spec:
selector:
app: merchant-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: merchant-service-hpa
namespace: staging
labels:
app: merchant-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: merchant-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,125 @@
# EN: Mining Service - Data mining, analytics & business intelligence
# VI: Mining Service - Khai thac du lieu, phan tich & tri tue kinh doanh
apiVersion: apps/v1
kind: Deployment
metadata:
name: mining-service
namespace: staging
labels:
app: mining-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mining-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mining-service
environment: staging
spec:
containers:
- name: mining-service
image: harbor.techbi.org/goodgo/mining-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MINING_DATABASE_URL
- name: MiningService__ServiceName
value: "mining-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: mining-service
namespace: staging
labels:
app: mining-service
environment: staging
spec:
selector:
app: mining-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mining-service-hpa
namespace: staging
labels:
app: mining-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mining-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,33 @@
# EN: MinIO ExternalName Service - Points to existing MinIO in minio namespace
# VI: MinIO ExternalName Service - Tro den MinIO hien tai trong namespace minio
#
# Existing MinIO: https://minio.techbi.org (namespace: minio)
# Console: https://minio-console.techbi.org
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: staging
labels:
app: minio
environment: staging
platform: goodgo
tier: infrastructure
spec:
type: ExternalName
externalName: minio.minio.svc.cluster.local
---
apiVersion: v1
kind: Service
metadata:
name: minio-console
namespace: staging
labels:
app: minio-console
environment: staging
platform: goodgo
tier: infrastructure
spec:
type: ExternalName
externalName: minio-console.minio.svc.cluster.local

View File

@@ -0,0 +1,125 @@
# EN: Mission Service - Gamification missions, challenges & rewards
# VI: Mission Service - Nhiem vu gamification, thu thach & phan thuong
apiVersion: apps/v1
kind: Deployment
metadata:
name: mission-service
namespace: staging
labels:
app: mission-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mission-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mission-service
environment: staging
spec:
containers:
- name: mission-service
image: harbor.techbi.org/goodgo/mission-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MISSION_DATABASE_URL
- name: MissionService__ServiceName
value: "mission-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: mission-service
namespace: staging
labels:
app: mission-service
environment: staging
spec:
selector:
app: mission-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mission-service-hpa
namespace: staging
labels:
app: mission-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mission-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,127 @@
# EN: Marketing Facebook Service - Facebook marketing integration and campaign management
# VI: Marketing Facebook Service - Tich hop tiep thi Facebook va quan ly chien dich
apiVersion: apps/v1
kind: Deployment
metadata:
name: mkt-facebook-service
namespace: staging
labels:
app: mkt-facebook-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mkt-facebook-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mkt-facebook-service
environment: staging
spec:
containers:
- name: mkt-facebook-service
image: harbor.techbi.org/goodgo/mkt-facebook-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MKT_FACEBOOK_DATABASE_URL
- name: MktFacebookService__ServiceName
value: "mkt-facebook-service"
- name: RabbitMQ__Host
value: "rabbitmq"
- name: RabbitMQ__Port
value: "5672"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: mkt-facebook-service
namespace: staging
labels:
app: mkt-facebook-service
environment: staging
spec:
selector:
app: mkt-facebook-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mkt-facebook-service-hpa
namespace: staging
labels:
app: mkt-facebook-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mkt-facebook-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,127 @@
# EN: Marketing WhatsApp Service - WhatsApp messaging integration and automation
# VI: Marketing WhatsApp Service - Tich hop nhan tin WhatsApp va tu dong hoa
apiVersion: apps/v1
kind: Deployment
metadata:
name: mkt-whatsapp-service
namespace: staging
labels:
app: mkt-whatsapp-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mkt-whatsapp-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mkt-whatsapp-service
environment: staging
spec:
containers:
- name: mkt-whatsapp-service
image: harbor.techbi.org/goodgo/mkt-whatsapp-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MKT_WHATSAPP_DATABASE_URL
- name: MktWhatsappService__ServiceName
value: "mkt-whatsapp-service"
- name: RabbitMQ__Host
value: "rabbitmq"
- name: RabbitMQ__Port
value: "5672"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: mkt-whatsapp-service
namespace: staging
labels:
app: mkt-whatsapp-service
environment: staging
spec:
selector:
app: mkt-whatsapp-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mkt-whatsapp-service-hpa
namespace: staging
labels:
app: mkt-whatsapp-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mkt-whatsapp-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,127 @@
# EN: Marketing X Service - X (Twitter) social media integration and marketing
# VI: Marketing X Service - Tich hop mang xa hoi X (Twitter) va tiep thi
apiVersion: apps/v1
kind: Deployment
metadata:
name: mkt-x-service
namespace: staging
labels:
app: mkt-x-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mkt-x-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mkt-x-service
environment: staging
spec:
containers:
- name: mkt-x-service
image: harbor.techbi.org/goodgo/mkt-x-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MKT_X_DATABASE_URL
- name: MktXService__ServiceName
value: "mkt-x-service"
- name: RabbitMQ__Host
value: "rabbitmq"
- name: RabbitMQ__Port
value: "5672"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: mkt-x-service
namespace: staging
labels:
app: mkt-x-service
environment: staging
spec:
selector:
app: mkt-x-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mkt-x-service-hpa
namespace: staging
labels:
app: mkt-x-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mkt-x-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,127 @@
# EN: Marketing Zalo Service - Zalo messaging integration and marketing automation
# VI: Marketing Zalo Service - Tich hop nhan tin Zalo va tu dong hoa tiep thi
apiVersion: apps/v1
kind: Deployment
metadata:
name: mkt-zalo-service
namespace: staging
labels:
app: mkt-zalo-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mkt-zalo-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mkt-zalo-service
environment: staging
spec:
containers:
- name: mkt-zalo-service
image: harbor.techbi.org/goodgo/mkt-zalo-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: MKT_ZALO_DATABASE_URL
- name: MktZaloService__ServiceName
value: "mkt-zalo-service"
- name: RabbitMQ__Host
value: "rabbitmq"
- name: RabbitMQ__Port
value: "5672"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: mkt-zalo-service
namespace: staging
labels:
app: mkt-zalo-service
environment: staging
spec:
selector:
app: mkt-zalo-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mkt-zalo-service-hpa
namespace: staging
labels:
app: mkt-zalo-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mkt-zalo-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,10 @@
# EN: Staging namespace for GoodGo Platform
# VI: Namespace staging cho GoodGo Platform
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: staging
platform: goodgo
managed-by: kubectl

View File

@@ -0,0 +1,851 @@
# EN: Kubernetes NetworkPolicy — default-deny + explicit allow rules (DEVOPS-W-05)
# VI: Kubernetes NetworkPolicy — tu choi mac dinh + cho phep tuong minh (DEVOPS-W-05)
#
# Strategy:
# 1. Default-deny all ingress and egress in staging namespace
# 2. Allow DNS resolution (kube-dns)
# 3. Allow inter-service communication via explicit rules (BOTH egress AND ingress)
# 4. Allow ingress from Nginx Ingress Controller (API gateway)
# 5. Allow Prometheus scraping metrics from all services
# 6. Allow Redis access only from application services
# 7. Allow RabbitMQ access from services that use messaging
# 8. Allow MinIO access from storage service
# 9. Allow Neon PostgreSQL access (port 5432 + NodePort 30992)
# =============================================================================
# Default Deny — block all ingress + egress by default
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# =============================================================================
# Allow DNS (kube-dns) — required for all pods to resolve service names
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
---
# =============================================================================
# Allow Nginx Ingress + Traefik → microservices (port 8080)
# Nginx handles external TLS, Traefik handles internal routing
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-traefik-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- pos-web
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
# EN: Allow Traefik pod (same namespace) to reach services
# VI: Cho phep Traefik pod (cung namespace) truy cap services
- podSelector:
matchLabels:
app: traefik
ports:
- port: 8080
protocol: TCP
---
# =============================================================================
# Allow Nginx Ingress → Traefik (port 80)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-nginx-to-traefik
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchLabels:
app: traefik
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
# EN: Nginx on hostNetwork appears as node IP, need ipBlock to allow
# VI: Nginx tren hostNetwork xuat hien la node IP, can ipBlock de cho phep
- ipBlock:
cidr: 0.0.0.0/0
ports:
- port: 80
protocol: TCP
---
# =============================================================================
# Allow Traefik DNS resolution (kube-dns)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-traefik-dns-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchLabels:
app: traefik
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
---
# =============================================================================
# Allow Traefik → microservices (egress port 8080)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-traefik-to-services-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchLabels:
app: traefik
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- pos-web
ports:
- port: 8080
protocol: TCP
---
# =============================================================================
# Allow inter-service INGRESS — services can receive requests from other services
# CRITICAL: Without this, health checks between services fail (e.g. promotion→wallet)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-inter-service-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- pos-web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- pos-web
ports:
- port: 8080
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-inter-service-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- pos-web
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
ports:
- port: 8080
protocol: TCP
---
# =============================================================================
# Allow Redis access — only from app services (port 6379)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-redis-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
- redis-master
- redis-replica
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-tracking-service
- ads-analytics-service
ports:
- port: 6379
protocol: TCP
---
# Allow Redis master → replica replication egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-redis-replication
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
- redis-master
- redis-replica
- redis-sentinel
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
- redis-master
- redis-replica
- redis-sentinel
ports:
- port: 6379
protocol: TCP
- port: 26379
protocol: TCP
egress:
- to:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
- redis-master
- redis-replica
- redis-sentinel
ports:
- port: 6379
protocol: TCP
- port: 26379
protocol: TCP
---
# =============================================================================
# Allow microservices to reach Redis (egress)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-redis-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-tracking-service
- ads-analytics-service
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
- redis-master
- redis-replica
- redis-sentinel
ports:
- port: 6379
protocol: TCP
- port: 26379
protocol: TCP
---
# =============================================================================
# Allow RabbitMQ ingress — from messaging services (port 5672)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-rabbitmq-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchLabels:
app: rabbitmq
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchExpressions:
- key: app
operator: In
values:
- ads-serving-service
- ads-tracking-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- chat-service
- order-service
ports:
- port: 5672
protocol: TCP
---
# =============================================================================
# Allow microservices to reach RabbitMQ (egress)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-rabbitmq-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- ads-serving-service
- ads-tracking-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- chat-service
- order-service
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: rabbitmq
ports:
- port: 5672
protocol: TCP
---
# =============================================================================
# Allow MinIO ingress — from storage service (port 9000)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-minio-ingress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchLabels:
app: minio
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: storage-service
ports:
- port: 9000
protocol: TCP
---
# =============================================================================
# Allow storage-service to reach MinIO (egress)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-minio-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchLabels:
app: storage-service
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: minio
ports:
- port: 9000
protocol: TCP
---
# =============================================================================
# Allow Prometheus scrape — port 8080 metrics from all app pods
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-prometheus-scrape
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
- pos-web
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports:
- port: 8080
protocol: TCP
---
# =============================================================================
# Allow microservices to reach external services (PostgreSQL, SMTP, etc.)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
policyTypes:
- Egress
egress:
- ports:
- port: 443
protocol: TCP
- port: 5432
protocol: TCP
- port: 30992
protocol: TCP
- port: 5671
protocol: TCP
- port: 5672
protocol: TCP
---
# =============================================================================
# Allow microservices to reach Neon PostgreSQL (neon namespace + NodePort)
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-neon-egress
namespace: staging
labels:
environment: staging
platform: goodgo
spec:
podSelector:
matchExpressions:
- key: app
operator: In
values:
- iam-service
- merchant-service
- order-service
- fnb-engine
- inventory-service
- wallet-service
- catalog-service
- storage-service
- booking-service
- chat-service
- social-service
- promotion-service
- membership-service
- mining-service
- mission-service
- ads-manager-service
- ads-serving-service
- ads-billing-service
- ads-tracking-service
- ads-analytics-service
- mkt-facebook-service
- mkt-whatsapp-service
- mkt-x-service
- mkt-zalo-service
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: neon
ports:
- port: 5432
protocol: TCP
- to:
- ipBlock:
cidr: 212.28.186.239/32
ports:
- port: 30992
protocol: TCP

View File

@@ -0,0 +1,131 @@
# EN: Order Service - Order Processing & POS API (SignalR WebSocket for POS/KDS)
# VI: Order Service - Xu ly Order & POS API (SignalR WebSocket cho POS/KDS)
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: staging
labels:
app: order-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: order-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: order-service
environment: staging
spec:
containers:
- name: order-service
image: harbor.techbi.org/goodgo/order-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: ORDER_DATABASE_URL
- name: IamService__ServiceName
value: "order-service"
# EN: Inter-service communication
# VI: Giao tiep giua cac service
- name: CatalogService__BaseUrl
value: "http://catalog-service:8080"
- name: InventoryService__BaseUrl
value: "http://inventory-service:8080"
- name: WalletService__BaseUrl
value: "http://wallet-service:8080"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: order-service
namespace: staging
labels:
app: order-service
environment: staging
spec:
selector:
app: order-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
namespace: staging
labels:
app: order-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,155 @@
# EN: POS Web Client - Blazor WebAssembly Hosted (TPOS multi-vertical)
# VI: POS Web Client - Blazor WebAssembly Hosted (TPOS da nganh doc)
apiVersion: apps/v1
kind: Deployment
metadata:
name: pos-web
namespace: staging
labels:
app: pos-web
environment: staging
platform: goodgo
tier: frontend
spec:
replicas: 1
selector:
matchLabels:
app: pos-web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: pos-web
environment: staging
spec:
containers:
- name: pos-web
image: harbor.techbi.org/goodgo/web-client-tpos-net:staging
ports:
- containerPort: 8080
protocol: TCP
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Staging"
- name: ASPNETCORE_URLS
value: "http://+:8080"
# EN: API Gateway URL for backend communication
# VI: URL API Gateway de giao tiep voi backend
- name: ApiSettings__GatewayUrl
value: "https://api.staging.goodgo.vn"
# EN: IAM Service for auth
# VI: IAM Service cho xac thuc
- name: IamService__BaseUrl
value: "http://iam-service:8080"
# EN: BFF IdentityServer client credentials
# VI: Thong tin xac thuc BFF IdentityServer client
- name: IdentityServer__ClientId
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: IdentityServer__ClientId
- name: IdentityServer__ClientSecret
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: IdentityServer__ClientSecret
# EN: YARP Reverse Proxy cluster addresses (K8s internal DNS)
# VI: Dia chi cluster YARP Reverse Proxy (K8s internal DNS)
- name: ReverseProxy__Clusters__iam-cluster__Destinations__destination1__Address
value: "http://iam-service:8080"
- name: ReverseProxy__Clusters__merchant-cluster__Destinations__destination1__Address
value: "http://merchant-service:8080"
- name: ReverseProxy__Clusters__catalog-cluster__Destinations__destination1__Address
value: "http://catalog-service:8080"
- name: ReverseProxy__Clusters__order-cluster__Destinations__destination1__Address
value: "http://order-service:8080"
# EN: BFF HTTP Proxy - Forward requests to microservice APIs
# VI: BFF HTTP Proxy - Chuyen tiep request sang microservice APIs
- name: MerchantService__BaseUrl
value: "http://merchant-service:8080"
- name: CatalogService__BaseUrl
value: "http://catalog-service:8080"
- name: OrderService__BaseUrl
value: "http://order-service:8080"
- name: InventoryService__BaseUrl
value: "http://inventory-service:8080"
- name: WalletService__BaseUrl
value: "http://wallet-service:8080"
- name: FnbEngine__BaseUrl
value: "http://fnb-engine:8080"
- name: StorageService__BaseUrl
value: "http://storage-service:8080"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: pos-web
namespace: staging
labels:
app: pos-web
environment: staging
spec:
selector:
app: pos-web
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: pos-web-hpa
namespace: staging
labels:
app: pos-web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: pos-web
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75

View File

@@ -0,0 +1,125 @@
# EN: Promotion Service - Promotions, discounts & coupon management
# VI: Promotion Service - Quan ly khuyen mai, giam gia & ma coupon
apiVersion: apps/v1
kind: Deployment
metadata:
name: promotion-service
namespace: staging
labels:
app: promotion-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: promotion-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: promotion-service
environment: staging
spec:
containers:
- name: promotion-service
image: harbor.techbi.org/goodgo/promotion-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: PROMOTION_DATABASE_URL
- name: PromotionService__ServiceName
value: "promotion-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: promotion-service
namespace: staging
labels:
app: promotion-service
environment: staging
spec:
selector:
app: promotion-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: promotion-service-hpa
namespace: staging
labels:
app: promotion-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: promotion-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,111 @@
# EN: RabbitMQ - Message Broker for async communication between microservices
# VI: RabbitMQ - Message Broker cho giao tiep bat dong bo giua cac microservices
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabbitmq
namespace: staging
labels:
app: rabbitmq
environment: staging
platform: goodgo
tier: infrastructure
spec:
replicas: 1
selector:
matchLabels:
app: rabbitmq
template:
metadata:
labels:
app: rabbitmq
environment: staging
spec:
containers:
- name: rabbitmq
image: rabbitmq:3-management-alpine
ports:
- containerPort: 5672
protocol: TCP
- containerPort: 15672
protocol: TCP
env:
- name: RABBITMQ_DEFAULT_USER
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: RabbitMQ__Username
- name: RABBITMQ_DEFAULT_PASS
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: RabbitMQ__Password
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
livenessProbe:
exec:
command:
- rabbitmq-diagnostics
- ping
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- rabbitmq-diagnostics
- check_port_connectivity
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: rabbitmq-data
mountPath: /var/lib/rabbitmq
volumes:
- name: rabbitmq-data
persistentVolumeClaim:
claimName: rabbitmq-pvc
---
apiVersion: v1
kind: Service
metadata:
name: rabbitmq
namespace: staging
labels:
app: rabbitmq
environment: staging
spec:
selector:
app: rabbitmq
ports:
- name: amqp
protocol: TCP
port: 5672
targetPort: 5672
- name: management
protocol: TCP
port: 15672
targetPort: 15672
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rabbitmq-pvc
namespace: staging
labels:
app: rabbitmq
environment: staging
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi

View File

@@ -0,0 +1,130 @@
# EN: Redis configuration — ConfigMap with scripts and config files for Redis StatefulSet
# VI: Cấu hình Redis — ConfigMap chứa scripts và config files cho Redis StatefulSet
#
# Volume mount layout:
# Redis pod init container: /config (this ConfigMap) → copies to /tmp
# Redis container: /tmp (scripts + configs from init)
# Sentinel container: /config (this ConfigMap directly)
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: staging
labels:
app: redis
component: config
platform: goodgo
tier: infrastructure
data:
redis-master.conf: |
# Redis Master Configuration
bind 0.0.0.0
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 60
maxmemory 512mb
maxmemory-policy allkeys-lru
maxmemory-samples 10
maxclients 10000
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-use-rdb-preamble yes
save 900 1
save 300 10
save 60 10000
hz 10
dynamic-hz yes
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
lazyfree-lazy-user-del yes
lua-time-limit 5000
busy-reply-threshold 5000
loglevel notice
slowlog-log-slower-than 10000
slowlog-max-len 128
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
redis-replica.conf: |
# Redis Replica Configuration
bind 0.0.0.0
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 60
maxmemory 512mb
maxmemory-policy allkeys-lru
maxmemory-samples 10
maxclients 10000
replica-read-only yes
replica-serve-stale-data yes
repl-diskless-sync yes
repl-diskless-sync-delay 5
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes
save 900 1
save 300 10
hz 10
dynamic-hz yes
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
lazyfree-lazy-user-del yes
lua-time-limit 5000
busy-reply-threshold 5000
loglevel notice
slowlog-log-slower-than 10000
slowlog-max-len 128
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
sentinel.conf: |
# Redis Sentinel Configuration
port 26379
sentinel monitor redis-master redis-0.redis-headless.staging.svc.cluster.local 6379 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 10000
sentinel parallel-syncs redis-master 1
sentinel resolve-hostnames yes
sentinel announce-hostnames yes
# EN: Redis init container copies all files to /tmp; redis container reads from /tmp
# VI: Redis init container copy tất cả files sang /tmp; redis container đọc từ /tmp
start-redis.sh: |
#!/bin/sh
set -e
HOSTNAME=$(hostname)
INDEX="${HOSTNAME##*-}"
# Config files already in /tmp from init container
if [ "$INDEX" = "0" ]; then
cp /tmp/redis-master.conf /tmp/redis.conf
else
cp /tmp/redis-replica.conf /tmp/redis.conf
echo "replicaof redis-0.redis-headless.staging.svc.cluster.local 6379" >> /tmp/redis.conf
echo "masterauth ${REDIS_PASSWORD}" >> /tmp/redis.conf
fi
echo "requirepass ${REDIS_PASSWORD}" >> /tmp/redis.conf
echo "masterauth ${REDIS_PASSWORD}" >> /tmp/redis.conf
exec redis-server /tmp/redis.conf
# EN: Sentinel has /config mounted directly (no init container)
# VI: Sentinel mount /config trực tiếp (không có init container)
start-sentinel.sh: |
#!/bin/sh
set -e
cp /config/sentinel.conf /tmp/sentinel-run.conf
echo "sentinel auth-pass redis-master ${REDIS_PASSWORD}" >> /tmp/sentinel-run.conf
# Wait for Redis master to be ready
until redis-cli -h redis-0.redis-headless.staging.svc.cluster.local -p 6379 -a "${REDIS_PASSWORD}" ping 2>/dev/null; do
echo "Waiting for Redis master..."
sleep 2
done
exec redis-sentinel /tmp/sentinel-run.conf

View File

@@ -0,0 +1,427 @@
# EN: Redis HA with Sentinel — replaces single-instance redis.yaml (DEVOPS-W-04)
# VI: Redis HA voi Sentinel — thay the redis.yaml don le (DEVOPS-W-04)
#
# Architecture:
# - redis-master: 1 pod StatefulSet (read/write)
# - redis-replica: 2 pod StatefulSet (read-only replicas)
# - redis-sentinel: 3 pod StatefulSet (monitors master, auto-failover)
#
# EN: Apply this file AND remove (or stop applying) redis.yaml to avoid conflicts.
# VI: Apply file nay VA xoa (hoac ngung apply) redis.yaml de tranh conflict.
# =============================================================================
# ConfigMap — Sentinel configuration template
# =============================================================================
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-sentinel-config
namespace: staging
labels:
app: redis-sentinel
environment: staging
platform: goodgo
data:
sentinel.conf: |
sentinel resolve-hostnames yes
sentinel announce-hostnames yes
sentinel monitor goodgo-master redis-master-0.redis-master.staging.svc.cluster.local 6379 2
sentinel auth-pass goodgo-master $(REDIS_PASSWORD)
sentinel down-after-milliseconds goodgo-master 5000
sentinel failover-timeout goodgo-master 60000
sentinel parallel-syncs goodgo-master 1
replica.conf: |
replicaof redis-master-0.redis-master.staging.svc.cluster.local 6379
masterauth $(REDIS_PASSWORD)
requirepass $(REDIS_PASSWORD)
maxmemory 256mb
maxmemory-policy allkeys-lru
appendonly yes
---
# =============================================================================
# StatefulSet — Redis Master (1 replica)
# =============================================================================
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-master
namespace: staging
labels:
app: redis-master
role: master
environment: staging
platform: goodgo
tier: infrastructure
spec:
serviceName: redis-master
replicas: 1
selector:
matchLabels:
app: redis-master
role: master
template:
metadata:
labels:
app: redis-master
role: master
environment: staging
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- "--requirepass"
- "$(REDIS_PASSWORD)"
- "--maxmemory"
- "256mb"
- "--maxmemory-policy"
- "allkeys-lru"
- "--appendonly"
- "yes"
ports:
- containerPort: 6379
protocol: TCP
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
livenessProbe:
exec:
command:
- sh
- -c
- redis-cli -a "$REDIS_PASSWORD" ping
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- sh
- -c
- redis-cli -a "$REDIS_PASSWORD" ping
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: redis-master-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-master-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
# Service — Redis Master (headless for StatefulSet DNS)
apiVersion: v1
kind: Service
metadata:
name: redis-master
namespace: staging
labels:
app: redis-master
role: master
environment: staging
spec:
clusterIP: None
selector:
app: redis-master
role: master
ports:
- name: redis
port: 6379
targetPort: 6379
---
# Service — Redis write endpoint (used by apps)
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: staging
labels:
app: redis-master
role: master
environment: staging
spec:
selector:
app: redis-master
role: master
ports:
- name: redis
port: 6379
targetPort: 6379
type: ClusterIP
---
# =============================================================================
# StatefulSet — Redis Replicas (2 replicas for HA)
# =============================================================================
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-replica
namespace: staging
labels:
app: redis-replica
role: replica
environment: staging
platform: goodgo
tier: infrastructure
spec:
serviceName: redis-replica
replicas: 2
selector:
matchLabels:
app: redis-replica
role: replica
template:
metadata:
labels:
app: redis-replica
role: replica
environment: staging
spec:
initContainers:
- name: init-replica-conf
image: busybox:1.36
command:
- sh
- -c
- |
sed "s/\$(REDIS_PASSWORD)/$REDIS_PASSWORD/g" /config/replica.conf > /data/redis.conf
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
volumeMounts:
- name: redis-config
mountPath: /config
- name: redis-replica-data
mountPath: /data
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- /data/redis.conf
ports:
- containerPort: 6379
protocol: TCP
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
livenessProbe:
exec:
command:
- sh
- -c
- redis-cli -a "$REDIS_PASSWORD" ping
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- sh
- -c
- redis-cli -a "$REDIS_PASSWORD" ping
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: redis-replica-data
mountPath: /data
volumes:
- name: redis-config
configMap:
name: redis-sentinel-config
volumeClaimTemplates:
- metadata:
name: redis-replica-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
# Service — Redis Replicas (headless)
apiVersion: v1
kind: Service
metadata:
name: redis-replica
namespace: staging
labels:
app: redis-replica
role: replica
environment: staging
spec:
clusterIP: None
selector:
app: redis-replica
role: replica
ports:
- name: redis
port: 6379
targetPort: 6379
---
# =============================================================================
# StatefulSet — Redis Sentinel (3 nodes — quorum = 2)
# =============================================================================
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-sentinel
namespace: staging
labels:
app: redis-sentinel
role: sentinel
environment: staging
platform: goodgo
tier: infrastructure
spec:
serviceName: redis-sentinel
replicas: 3
selector:
matchLabels:
app: redis-sentinel
role: sentinel
template:
metadata:
labels:
app: redis-sentinel
role: sentinel
environment: staging
spec:
initContainers:
- name: init-sentinel-conf
image: busybox:1.36
command:
- sh
- -c
- |
sed "s/\$(REDIS_PASSWORD)/$REDIS_PASSWORD/g" /config/sentinel.conf > /data/sentinel.conf
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
volumeMounts:
- name: sentinel-config
mountPath: /config
- name: sentinel-data
mountPath: /data
containers:
- name: sentinel
image: redis:7-alpine
command:
- redis-sentinel
- /data/sentinel.conf
ports:
- containerPort: 26379
protocol: TCP
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
livenessProbe:
exec:
command:
- redis-cli
- -p
- "26379"
- ping
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- redis-cli
- -p
- "26379"
- ping
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: sentinel-data
mountPath: /data
volumes:
- name: sentinel-config
configMap:
name: redis-sentinel-config
volumeClaimTemplates:
- metadata:
name: sentinel-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Mi
---
# Service — Redis Sentinel (headless + ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: redis-sentinel
namespace: staging
labels:
app: redis-sentinel
role: sentinel
environment: staging
spec:
selector:
app: redis-sentinel
role: sentinel
ports:
- name: sentinel
port: 26379
targetPort: 26379
type: ClusterIP

View File

@@ -0,0 +1,114 @@
# EN: Redis - Cache & SignalR Backplane for staging
# VI: Redis - Cache & SignalR Backplane cho staging
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: staging
labels:
app: redis
environment: staging
platform: goodgo
tier: infrastructure
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
environment: staging
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- "--requirepass"
- "$(REDIS_PASSWORD)"
- "--maxmemory"
- "256mb"
- "--maxmemory-policy"
- "allkeys-lru"
- "--appendonly"
- "yes"
ports:
- containerPort: 6379
protocol: TCP
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Redis__Password
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
livenessProbe:
exec:
command:
- redis-cli
- -a
- "$(REDIS_PASSWORD)"
- ping
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- redis-cli
- -a
- "$(REDIS_PASSWORD)"
- ping
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: redis-data
mountPath: /data
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-pvc
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: staging
labels:
app: redis
environment: staging
spec:
selector:
app: redis
ports:
- name: redis
protocol: TCP
port: 6379
targetPort: 6379
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
namespace: staging
labels:
app: redis
environment: staging
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,114 @@
# EN: Shared secrets for all GoodGo staging services
# VI: Secrets dung chung cho tat ca cac service staging cua GoodGo
#
# IMPORTANT: This file contains PLACEHOLDER values only.
# DO NOT commit real credentials to Git.
#
# Create secrets using kubectl:
# kubectl create secret generic goodgo-secrets \
# --from-literal=ConnectionStrings__DefaultConnection='postgresql://...' \
# --from-literal=Jwt__Secret='...' \
# -n staging
#
# Or use sealed-secrets / external-secrets operator in production.
#
# GitHub Secrets used in CI/CD:
# - REMOTE_IAM_DATABASE_URL_STAGING
# - REMOTE_MERCHANT_DATABASE_URL_STAGING
# - REMOTE_ORDER_DATABASE_URL_STAGING
# - REMOTE_FNB_DATABASE_URL_STAGING
# - REMOTE_INVENTORY_DATABASE_URL_STAGING
# - REMOTE_WALLET_DATABASE_URL_STAGING
# - REMOTE_CATALOG_DATABASE_URL_STAGING
# - REMOTE_STORAGE_DATABASE_URL_STAGING
# - REMOTE_BOOKING_DATABASE_URL_STAGING
# - REMOTE_CHAT_DATABASE_URL_STAGING
# - REMOTE_SOCIAL_DATABASE_URL_STAGING
# - REMOTE_PROMOTION_DATABASE_URL_STAGING
# - REMOTE_MEMBERSHIP_DATABASE_URL_STAGING
# - REMOTE_MINING_DATABASE_URL_STAGING
# - REMOTE_MISSION_DATABASE_URL_STAGING
# - REMOTE_ADS_MANAGER_DATABASE_URL_STAGING
# - REMOTE_ADS_SERVING_DATABASE_URL_STAGING
# - REMOTE_ADS_BILLING_DATABASE_URL_STAGING
# - REMOTE_ADS_TRACKING_DATABASE_URL_STAGING
# - REMOTE_ADS_ANALYTICS_DATABASE_URL_STAGING
# - REMOTE_MKT_FACEBOOK_DATABASE_URL_STAGING
# - REMOTE_MKT_WHATSAPP_DATABASE_URL_STAGING
# - REMOTE_MKT_X_DATABASE_URL_STAGING
# - REMOTE_MKT_ZALO_DATABASE_URL_STAGING
# - JWT_SECRET_STAGING
# - JWT_REFRESH_SECRET_STAGING
# - REDIS_PASSWORD_STAGING
# - MINIO_ACCESS_KEY_STAGING
# - MINIO_SECRET_KEY_STAGING
# - RABBITMQ_PASSWORD_STAGING
apiVersion: v1
kind: Secret
metadata:
name: goodgo-secrets
namespace: staging
labels:
environment: staging
platform: goodgo
type: Opaque
stringData:
# EN: JWT Secrets (use strong random strings, min 32 characters)
# VI: JWT Secrets (su dung chuoi ngau nhien manh, toi thieu 32 ky tu)
Jwt__Secret: "PLACEHOLDER-staging-jwt-secret-min-32-chars"
Jwt__RefreshSecret: "PLACEHOLDER-staging-refresh-secret-min-32-chars"
# EN: IdentityServer Issuer
# VI: IdentityServer Issuer
IdentityServer__IssuerUri: "https://api.techbi.org"
# EN: BFF Client credentials (used by pos-web to obtain tokens from IdentityServer)
# VI: Thông tin xác thực BFF Client (pos-web dùng để lấy token từ IdentityServer)
IdentityServer__ClientId: "bff-client"
IdentityServer__ClientSecret: "PLACEHOLDER-bff-client-secret"
# EN: PostgreSQL Connection Strings (per-service databases)
# VI: Chuoi ket noi PostgreSQL (database rieng cho tung service)
# Format: Host=ip;Port=port;Database=db;Username=user;Password=pass;SSL Mode=Prefer
IAM_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=iam_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MERCHANT_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=merchant_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
ORDER_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=order_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
FNB_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=fnb_engine;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
INVENTORY_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=inventory_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
WALLET_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=wallet_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
CATALOG_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=catalog_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
STORAGE_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=storage_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
BOOKING_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=booking_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
CHAT_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=chat_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
SOCIAL_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=social_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
PROMOTION_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=promotion_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MEMBERSHIP_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=membership_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MINING_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=mining_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MISSION_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=mission_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
ADS_MANAGER_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=ads_manager_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
ADS_SERVING_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=ads_serving_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
ADS_BILLING_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=ads_billing_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
ADS_TRACKING_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=ads_tracking_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
ADS_ANALYTICS_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=ads_analytics_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MKT_FACEBOOK_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=mkt_facebook_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MKT_WHATSAPP_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=mkt_whatsapp_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MKT_X_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=mkt_x_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
MKT_ZALO_DATABASE_URL: "PLACEHOLDER-Host=db-host;Port=30992;Database=mkt_zalo_service;Username=cloud_admin;Password=CHANGE_ME;SSL Mode=Prefer"
# EN: Redis Password
# VI: Mat khau Redis
Redis__Password: "PLACEHOLDER-redis-password"
ConnectionStrings__Redis: "redis:6379,password=PLACEHOLDER-redis-password"
# EN: MinIO / S3 Storage Credentials
# VI: Thong tin xac thuc MinIO / S3
Storage__MinIO__AccessKey: "PLACEHOLDER-minio-access-key"
Storage__MinIO__SecretKey: "PLACEHOLDER-minio-secret-key"
Storage__MinIO__Endpoint: "minio.techbi.org"
# EN: RabbitMQ Credentials
# VI: Thong tin xac thuc RabbitMQ
RabbitMQ__Host: "rabbitmq"
RabbitMQ__Username: "goodgo"
RabbitMQ__Password: "PLACEHOLDER-rabbitmq-password"

View File

@@ -0,0 +1,56 @@
# EN: Kubernetes Secrets Template for GoodGo Staging
# VI: Template Secrets Kubernetes cho GoodGo Staging
#
# DO NOT commit actual secrets to Git.
# Use this as a template to create secrets via kubectl.
#
# =============================================================================
# Option 1: Create secrets using kubectl (recommended for staging)
# =============================================================================
#
# kubectl create secret generic goodgo-secrets \
# --from-literal=Jwt__Secret='your-staging-jwt-secret-min-32-chars' \
# --from-literal=Jwt__RefreshSecret='your-staging-refresh-secret-min-32-chars' \
# --from-literal=IdentityServer__IssuerUri='https://api.staging.goodgo.vn' \
# --from-literal=IAM_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/iam_staging?sslmode=require' \
# --from-literal=MERCHANT_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/merchant_staging?sslmode=require' \
# --from-literal=ORDER_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/order_staging?sslmode=require' \
# --from-literal=FNB_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/fnb_staging?sslmode=require' \
# --from-literal=INVENTORY_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/inventory_staging?sslmode=require' \
# --from-literal=WALLET_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/wallet_staging?sslmode=require' \
# --from-literal=CATALOG_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/catalog_staging?sslmode=require' \
# --from-literal=STORAGE_DATABASE_URL='postgresql://user:pass@ep-xxx.region.neon.tech/storage_staging?sslmode=require' \
# --from-literal=Redis__Password='your-redis-password' \
# --from-literal=ConnectionStrings__Redis='redis:6379,password=your-redis-password' \
# --from-literal=Storage__MinIO__Endpoint='minio.staging.goodgo.vn' \
# --from-literal=Storage__MinIO__AccessKey='your-minio-access-key' \
# --from-literal=Storage__MinIO__SecretKey='your-minio-secret-key' \
# --from-literal=RabbitMQ__Host='rabbitmq' \
# --from-literal=RabbitMQ__Username='goodgo' \
# --from-literal=RabbitMQ__Password='your-rabbitmq-password' \
# -n staging
#
# =============================================================================
# Option 2: Use GitHub Secrets in CI/CD (for automated deployments)
# =============================================================================
#
# Required GitHub Secrets:
# - KUBECONFIG_STAGING (base64 encoded kubeconfig)
# - DOCKER_USERNAME / DOCKER_PASSWORD
# - NEON_IAM_DATABASE_URL_STAGING
# - NEON_MERCHANT_DATABASE_URL_STAGING
# - NEON_ORDER_DATABASE_URL_STAGING
# - NEON_FNB_DATABASE_URL_STAGING
# - NEON_INVENTORY_DATABASE_URL_STAGING
# - NEON_WALLET_DATABASE_URL_STAGING
# - NEON_CATALOG_DATABASE_URL_STAGING
# - NEON_STORAGE_DATABASE_URL_STAGING
# - JWT_SECRET_STAGING
# - JWT_REFRESH_SECRET_STAGING
# - REDIS_PASSWORD_STAGING
# - MINIO_ACCESS_KEY_STAGING
# - MINIO_SECRET_KEY_STAGING
#
# =============================================================================
# Option 3: Use sealed-secrets or external-secrets operator (recommended for production)
# =============================================================================

View File

@@ -0,0 +1,82 @@
#!/bin/bash
# EN: Setup K8s secrets for GoodGo staging deployment
# VI: Thiet lap K8s secrets cho GoodGo staging deployment
#
# Prerequisites:
# - kubectl configured with cluster access
# - Gitea repo admin/pos-system created on gitea.techbi.org
# - Harbor project "goodgo" created on harbor.techbi.org
#
# Usage: ./setup-secrets.sh
set -e
NS="staging"
echo "=== Creating namespace ==="
kubectl create namespace "$NS" --dry-run=client -o yaml | kubectl apply -f -
echo "=== Creating Gitea push credentials (for CronJob sync) ==="
kubectl create secret generic pos-gitea-push-creds -n gitea \
--from-literal=url='https://admin:Velik%402026@gitea.techbi.org/admin/pos-system.git' \
--dry-run=client -o yaml | kubectl apply -f -
echo "=== Creating Harbor pull secret (for K8s to pull images) ==="
kubectl create secret docker-registry harbor-pull-secret -n "$NS" \
--docker-server=harbor.techbi.org \
--docker-username=admin \
--docker-password='Velik@2026' \
--docker-email=admin@techbi.org \
--dry-run=client -o yaml | kubectl apply -f -
echo "=== Applying RBAC for act_runner ==="
kubectl apply -f act-runner-rbac.yaml
echo "=== Applying K8s secrets (DB, JWT, Redis, etc.) ==="
# Create goodgo-secrets with real values
kubectl create secret generic goodgo-secrets -n "$NS" \
--from-literal=Jwt__Secret='GoodGo-Local-Dev-JWT-Secret-2024-Min32Chars!!' \
--from-literal=Jwt__RefreshSecret='GoodGo-Local-Dev-Refresh-Secret-2024-32Ch!!' \
--from-literal=IdentityServer__IssuerUri='https://api.staging.goodgo.vn' \
--from-literal=Redis__Password='goodgo-redis-local' \
--from-literal=ConnectionStrings__Redis='redis:6379,password=goodgo-redis-local' \
--from-literal=Storage__MinIO__AccessKey='minioadmin' \
--from-literal=Storage__MinIO__SecretKey='minioadmin123' \
--from-literal=Storage__MinIO__Endpoint='minio.staging.svc.cluster.local:9000' \
--from-literal=RabbitMQ__Host='rabbitmq' \
--from-literal=RabbitMQ__Username='goodgo' \
--from-literal=RabbitMQ__Password='goodgo-rabbitmq-local' \
--from-literal=IAM_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=iam_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MERCHANT_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=merchant_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=ORDER_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=order_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=FNB_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=fnb_engine;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=CATALOG_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=catalog_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=INVENTORY_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=inventory_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=WALLET_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=wallet_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=STORAGE_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=storage_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=BOOKING_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=booking_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=CHAT_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=chat_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=SOCIAL_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=social_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=PROMOTION_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=promotion_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MEMBERSHIP_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=membership_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MINING_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=mining_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MISSION_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=mission_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=ADS_MANAGER_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=ads_manager_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=ADS_SERVING_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=ads_serving_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=ADS_BILLING_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=ads_billing_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=ADS_TRACKING_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=ads_tracking_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=ADS_ANALYTICS_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=ads_analytics_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MKT_FACEBOOK_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=mkt_facebook_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MKT_WHATSAPP_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=mkt_whatsapp_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MKT_X_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=mkt_x_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--from-literal=MKT_ZALO_DATABASE_URL='Host=212.28.186.239;Port=30992;Database=mkt_zalo_service;Username=cloud_admin;Password=XbnKQ2ONe6pMxxCh;SSL Mode=Prefer' \
--dry-run=client -o yaml | kubectl apply -f -
echo ""
echo "=== Setup complete ==="
echo "Next steps:"
echo " 1. Create Harbor project 'goodgo' at https://harbor.techbi.org"
echo " 2. Create Gitea repo 'admin/pos-system' at https://gitea.techbi.org"
echo " 3. Set Gitea repo secrets: HARBOR_USERNAME=admin, HARBOR_PASSWORD=Velik@2026"
echo " 4. Apply CronJob: kubectl apply -f gitea-sync-cronjob.yaml"
echo " 5. Apply manifests: kubectl apply -f deployments/staging/kubernetes/"

View File

@@ -0,0 +1,125 @@
# EN: Social Service - Social features, posts, interactions & community
# VI: Social Service - Tinh nang xa hoi, bai dang, tuong tac & cong dong
apiVersion: apps/v1
kind: Deployment
metadata:
name: social-service
namespace: staging
labels:
app: social-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: social-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: social-service
environment: staging
spec:
containers:
- name: social-service
image: harbor.techbi.org/goodgo/social-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
# EN: Override service-specific database URL
# VI: Override URL database rieng cho service
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: SOCIAL_DATABASE_URL
- name: SocialService__ServiceName
value: "social-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: social-service
namespace: staging
labels:
app: social-service
environment: staging
spec:
selector:
app: social-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: social-service-hpa
namespace: staging
labels:
app: social-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: social-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,144 @@
# EN: Storage Service - File Storage Management (MinIO S3-compatible)
# VI: Storage Service - Quan ly Luu tru File (MinIO tuong thich S3)
apiVersion: apps/v1
kind: Deployment
metadata:
name: storage-service
namespace: staging
labels:
app: storage-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: storage-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: storage-service
environment: staging
spec:
containers:
- name: storage-service
image: harbor.techbi.org/goodgo/storage-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: STORAGE_DATABASE_URL
- name: IamService__ServiceName
value: "storage-service"
- name: Storage__Provider
value: "minio"
- name: Storage__DefaultBucket
value: "goodgo-staging"
- name: Storage__MinIO__UseSSL
value: "true"
- name: Storage__MinIO__Endpoint
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Storage__MinIO__Endpoint
- name: Storage__MinIO__AccessKey
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Storage__MinIO__AccessKey
- name: Storage__MinIO__SecretKey
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: Storage__MinIO__SecretKey
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: storage-service
namespace: staging
labels:
app: storage-service
environment: staging
spec:
selector:
app: storage-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: storage-service-hpa
namespace: staging
labels:
app: storage-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: storage-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

View File

@@ -0,0 +1,671 @@
# EN: Traefik v3 - Internal API Gateway for GoodGo POS System
# VI: Traefik v3 - API Gateway noi bo cho he thong GoodGo POS
#
# Architecture:
# Internet → Nginx Ingress (TLS termination, port 443)
# → Traefik (internal routing, middleware, port 80)
# → Backend microservices (port 8080)
#
# Benefits:
# - Rate limiting, circuit breaker, retry middleware
# - Consistent with local dev (Docker Compose + Traefik v3)
# - Nginx handles TLS + external, Traefik handles internal routing
---
# =============================================================================
# Traefik Static Configuration (ConfigMap)
# =============================================================================
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config
namespace: staging
labels:
app: traefik
environment: staging
platform: goodgo
data:
traefik.yml: |
api:
dashboard: false
insecure: false
entryPoints:
web:
address: ":80"
providers:
file:
filename: /etc/traefik/dynamic/routes.yml
watch: true
log:
level: INFO
accessLog:
format: json
metrics:
prometheus:
entryPoint: web
ping:
entryPoint: web
routes.yml: |
http:
# =============================================
# Middlewares
# =============================================
middlewares:
rate-limit:
rateLimit:
average: 100
burst: 200
period: 1s
retry:
retry:
attempts: 3
initialInterval: 100ms
compress:
compress: {}
secure-headers:
headers:
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: "strict-origin-when-cross-origin"
customResponseHeaders:
X-Powered-By: ""
Server: ""
api-chain:
chain:
middlewares:
- rate-limit
- retry
- compress
- secure-headers
websocket-headers:
headers:
customRequestHeaders:
Connection: "Upgrade"
Upgrade: "websocket"
# =============================================
# Routers — api.techbi.org
# =============================================
routers:
# --- IAM Service ---
iam-auth:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/auth`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-users:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/users`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-identity:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/identity`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-access:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/access`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-governance:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/governance`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-rbac:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/rbac`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-mfa:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/mfa`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-sessions:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/sessions`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-oidc-connect:
rule: "Host(`api.techbi.org`) && PathPrefix(`/connect`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
iam-oidc-wellknown:
rule: "Host(`api.techbi.org`) && PathPrefix(`/.well-known`)"
entryPoints: [web]
middlewares: [api-chain]
service: iam-service
# --- Merchant Service ---
merchant-merchants:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/merchants`)"
entryPoints: [web]
middlewares: [api-chain]
service: merchant-service
merchant-shops:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/shops`)"
entryPoints: [web]
middlewares: [api-chain]
service: merchant-service
merchant-subscriptions:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/subscriptions`)"
entryPoints: [web]
middlewares: [api-chain]
service: merchant-service
# --- Order Service ---
order-orders:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/orders`)"
entryPoints: [web]
middlewares: [api-chain]
service: order-service
order-hub:
rule: "Host(`api.techbi.org`) && PathPrefix(`/hubs/pos`)"
entryPoints: [web]
middlewares: [websocket-headers]
service: order-service
# --- FnB Engine ---
fnb-kitchen:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/kitchen`)"
entryPoints: [web]
middlewares: [api-chain]
service: fnb-engine
fnb-fnb:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/fnb`)"
entryPoints: [web]
middlewares: [api-chain]
service: fnb-engine
fnb-tables:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/tables`)"
entryPoints: [web]
middlewares: [api-chain]
service: fnb-engine
fnb-hub:
rule: "Host(`api.techbi.org`) && PathPrefix(`/hubs/kitchen`)"
entryPoints: [web]
middlewares: [websocket-headers]
service: fnb-engine
# --- Catalog Service ---
catalog-products:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/products`)"
entryPoints: [web]
middlewares: [api-chain]
service: catalog-service
catalog-categories:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/categories`)"
entryPoints: [web]
middlewares: [api-chain]
service: catalog-service
# --- Inventory Service ---
inventory:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/inventory`)"
entryPoints: [web]
middlewares: [api-chain]
service: inventory-service
inventory-stock:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/stock`)"
entryPoints: [web]
middlewares: [api-chain]
service: inventory-service
# --- Wallet Service ---
wallet-wallets:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/wallets`)"
entryPoints: [web]
middlewares: [api-chain]
service: wallet-service
wallet-points:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/points`)"
entryPoints: [web]
middlewares: [api-chain]
service: wallet-service
wallet-payments:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/payments`)"
entryPoints: [web]
middlewares: [api-chain]
service: wallet-service
# --- Storage Service ---
storage-files:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/files`)"
entryPoints: [web]
middlewares: [api-chain]
service: storage-service
storage-quota:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/quota`)"
entryPoints: [web]
middlewares: [api-chain]
service: storage-service
storage-uploads:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/uploads`)"
entryPoints: [web]
middlewares: [api-chain]
service: storage-service
# --- Booking Service ---
booking-bookings:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/bookings`)"
entryPoints: [web]
middlewares: [api-chain]
service: booking-service
booking-reservations:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/reservations`)"
entryPoints: [web]
middlewares: [api-chain]
service: booking-service
booking-appointments:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/appointments`)"
entryPoints: [web]
middlewares: [api-chain]
service: booking-service
booking-therapists:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/therapists`)"
entryPoints: [web]
middlewares: [api-chain]
service: booking-service
# --- Chat Service ---
chat-chats:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/chats`)"
entryPoints: [web]
middlewares: [api-chain]
service: chat-service
chat-messages:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/messages`)"
entryPoints: [web]
middlewares: [api-chain]
service: chat-service
chat-conversations:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/conversations`)"
entryPoints: [web]
middlewares: [api-chain]
service: chat-service
chat-hub:
rule: "Host(`api.techbi.org`) && PathPrefix(`/hubs/chat`)"
entryPoints: [web]
middlewares: [websocket-headers]
service: chat-service
# --- Social Service ---
social:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/social`)"
entryPoints: [web]
middlewares: [api-chain]
service: social-service
social-relationships:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/relationships`)"
entryPoints: [web]
middlewares: [api-chain]
service: social-service
# --- Promotion Service ---
promotion-promotions:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/promotions`)"
entryPoints: [web]
middlewares: [api-chain]
service: promotion-service
promotion-vouchers:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/vouchers`)"
entryPoints: [web]
middlewares: [api-chain]
service: promotion-service
# --- Membership Service ---
membership-members:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/members`)"
entryPoints: [web]
middlewares: [api-chain]
service: membership-service
membership-levels:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/levels`)"
entryPoints: [web]
middlewares: [api-chain]
service: membership-service
# --- Mining Service ---
mining:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/mining`)"
entryPoints: [web]
middlewares: [api-chain]
service: mining-service
mining-circles:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/circles`)"
entryPoints: [web]
middlewares: [api-chain]
service: mining-service
mining-referrals:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/referrals`)"
entryPoints: [web]
middlewares: [api-chain]
service: mining-service
# --- Mission Service ---
mission-missions:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/missions`)"
entryPoints: [web]
middlewares: [api-chain]
service: mission-service
mission-checkins:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/checkins`)"
entryPoints: [web]
middlewares: [api-chain]
service: mission-service
# --- Ads Manager Service ---
ads-ads:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ads`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-manager-service
ads-campaigns:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/campaigns`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-manager-service
ads-adsets:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/adsets`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-manager-service
ads-audiences:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/audiences`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-manager-service
# --- Ads Serving ---
ads-serving:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ads-serving`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-serving-service
# --- Ads Billing ---
ads-billing:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ads-billing`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-billing-service
ads-invoices:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ad-invoices`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-billing-service
# --- Ads Tracking ---
ads-events:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ad-events`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-tracking-service
ads-pixels:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/pixels`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-tracking-service
ads-conversions:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/conversions`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-tracking-service
# --- Ads Analytics ---
ads-analytics:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ad-analytics`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-analytics-service
ads-reports:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/ad-reports`)"
entryPoints: [web]
middlewares: [api-chain]
service: ads-analytics-service
# --- Marketing Services ---
mkt-facebook:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/mkt/facebook`)"
entryPoints: [web]
middlewares: [api-chain]
service: mkt-facebook-service
mkt-whatsapp:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/mkt/whatsapp`)"
entryPoints: [web]
middlewares: [api-chain]
service: mkt-whatsapp-service
mkt-x:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/mkt/x`)"
entryPoints: [web]
middlewares: [api-chain]
service: mkt-x-service
mkt-zalo:
rule: "Host(`api.techbi.org`) && PathPrefix(`/api/v1/mkt/zalo`)"
entryPoints: [web]
middlewares: [api-chain]
service: mkt-zalo-service
# =============================================
# Router — platform.techbi.org (POS Frontend)
# =============================================
pos-web:
rule: "Host(`platform.techbi.org`)"
entryPoints: [web]
middlewares: [compress, secure-headers]
service: pos-web
# =============================================
# Services (backend targets)
# =============================================
services:
iam-service:
loadBalancer:
servers:
- url: "http://iam-service:8080"
merchant-service:
loadBalancer:
servers:
- url: "http://merchant-service:8080"
order-service:
loadBalancer:
servers:
- url: "http://order-service:8080"
fnb-engine:
loadBalancer:
servers:
- url: "http://fnb-engine:8080"
catalog-service:
loadBalancer:
servers:
- url: "http://catalog-service:8080"
inventory-service:
loadBalancer:
servers:
- url: "http://inventory-service:8080"
wallet-service:
loadBalancer:
servers:
- url: "http://wallet-service:8080"
storage-service:
loadBalancer:
servers:
- url: "http://storage-service:8080"
booking-service:
loadBalancer:
servers:
- url: "http://booking-service:8080"
chat-service:
loadBalancer:
servers:
- url: "http://chat-service:8080"
social-service:
loadBalancer:
servers:
- url: "http://social-service:8080"
promotion-service:
loadBalancer:
servers:
- url: "http://promotion-service:8080"
membership-service:
loadBalancer:
servers:
- url: "http://membership-service:8080"
mining-service:
loadBalancer:
servers:
- url: "http://mining-service:8080"
mission-service:
loadBalancer:
servers:
- url: "http://mission-service:8080"
ads-manager-service:
loadBalancer:
servers:
- url: "http://ads-manager-service:8080"
ads-serving-service:
loadBalancer:
servers:
- url: "http://ads-serving-service:8080"
ads-billing-service:
loadBalancer:
servers:
- url: "http://ads-billing-service:8080"
ads-tracking-service:
loadBalancer:
servers:
- url: "http://ads-tracking-service:8080"
ads-analytics-service:
loadBalancer:
servers:
- url: "http://ads-analytics-service:8080"
mkt-facebook-service:
loadBalancer:
servers:
- url: "http://mkt-facebook-service:8080"
mkt-whatsapp-service:
loadBalancer:
servers:
- url: "http://mkt-whatsapp-service:8080"
mkt-x-service:
loadBalancer:
servers:
- url: "http://mkt-x-service:8080"
mkt-zalo-service:
loadBalancer:
servers:
- url: "http://mkt-zalo-service:8080"
pos-web:
loadBalancer:
servers:
- url: "http://pos-web:8080"
---
# =============================================================================
# Traefik Deployment
# =============================================================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik
namespace: staging
labels:
app: traefik
environment: staging
platform: goodgo
spec:
replicas: 1
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
environment: staging
spec:
containers:
- name: traefik
image: traefik:v3.3
ports:
- containerPort: 80
protocol: TCP
name: web
args:
- "--configFile=/etc/traefik/traefik.yml"
volumeMounts:
- name: traefik-config
mountPath: /etc/traefik
- name: traefik-dynamic
mountPath: /etc/traefik/dynamic
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
livenessProbe:
httpGet:
path: /ping
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ping
port: 80
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: traefik-config
configMap:
name: traefik-config
items:
- key: traefik.yml
path: traefik.yml
- name: traefik-dynamic
configMap:
name: traefik-config
items:
- key: routes.yml
path: routes.yml
---
# =============================================================================
# Traefik Service (ClusterIP - internal only)
# =============================================================================
apiVersion: v1
kind: Service
metadata:
name: traefik
namespace: staging
labels:
app: traefik
environment: staging
platform: goodgo
spec:
selector:
app: traefik
ports:
- name: web
port: 80
targetPort: 80
protocol: TCP
type: ClusterIP

View File

@@ -0,0 +1,123 @@
# EN: Wallet Service - Wallet & Payment Management
# VI: Wallet Service - Quan ly Vi & Thanh toan
apiVersion: apps/v1
kind: Deployment
metadata:
name: wallet-service
namespace: staging
labels:
app: wallet-service
environment: staging
platform: goodgo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: wallet-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: wallet-service
environment: staging
spec:
containers:
- name: wallet-service
image: harbor.techbi.org/goodgo/wallet-service-net:staging
ports:
- containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: goodgo-config
- secretRef:
name: goodgo-secrets
env:
- name: ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name: goodgo-secrets
key: WALLET_DATABASE_URL
- name: IamService__ServiceName
value: "wallet-service"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
---
apiVersion: v1
kind: Service
metadata:
name: wallet-service
namespace: staging
labels:
app: wallet-service
environment: staging
spec:
selector:
app: wallet-service
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: wallet-service-hpa
namespace: staging
labels:
app: wallet-service
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: wallet-service
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80