diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index 40da71ab..a2026edc 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -5,7 +5,7 @@ name: Deploy to Staging on: push: branches: - - develop + - master paths: - 'services/iam-service-net/**' - 'services/merchant-service-net/**' @@ -15,6 +15,22 @@ on: - 'services/wallet-service-net/**' - 'services/catalog-service-net/**' - 'services/storage-service-net/**' + - 'services/booking-service-net/**' + - 'services/chat-service-net/**' + - 'services/social-service-net/**' + - 'services/promotion-service-net/**' + - 'services/membership-service-net/**' + - 'services/mining-service-net/**' + - 'services/mission-service-net/**' + - 'services/ads-manager-service-net/**' + - 'services/ads-serving-service-net/**' + - 'services/ads-billing-service-net/**' + - 'services/ads-tracking-service-net/**' + - 'services/ads-analytics-service-net/**' + - 'services/mkt-facebook-service-net/**' + - 'services/mkt-whatsapp-service-net/**' + - 'services/mkt-x-service-net/**' + - 'services/mkt-zalo-service-net/**' - 'apps/web-client-tpos-net/**' - 'deployments/staging/**' workflow_dispatch: @@ -34,10 +50,26 @@ on: - 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 env: - REGISTRY: docker.io + REGISTRY: harbor.techbi.org NAMESPACE: staging jobs: @@ -73,6 +105,22 @@ jobs: ["services/wallet-service-net"]="wallet-service" ["services/catalog-service-net"]="catalog-service" ["services/storage-service-net"]="storage-service" + ["services/booking-service-net"]="booking-service" + ["services/chat-service-net"]="chat-service" + ["services/social-service-net"]="social-service" + ["services/promotion-service-net"]="promotion-service" + ["services/membership-service-net"]="membership-service" + ["services/mining-service-net"]="mining-service" + ["services/mission-service-net"]="mission-service" + ["services/ads-manager-service-net"]="ads-manager-service" + ["services/ads-serving-service-net"]="ads-serving-service" + ["services/ads-billing-service-net"]="ads-billing-service" + ["services/ads-tracking-service-net"]="ads-tracking-service" + ["services/ads-analytics-service-net"]="ads-analytics-service" + ["services/mkt-facebook-service-net"]="mkt-facebook-service" + ["services/mkt-whatsapp-service-net"]="mkt-whatsapp-service" + ["services/mkt-x-service-net"]="mkt-x-service" + ["services/mkt-zalo-service-net"]="mkt-zalo-service" ["apps/web-client-tpos-net"]="pos-web" ) @@ -85,7 +133,7 @@ jobs: # EN: If deployment configs changed, deploy all # VI: Neu cau hinh deployment thay doi, deploy tat ca if echo "$CHANGED" | grep -q "^deployments/staging/"; then - SERVICES=("\"iam-service\"" "\"merchant-service\"" "\"order-service\"" "\"fnb-engine\"" "\"inventory-service\"" "\"wallet-service\"" "\"catalog-service\"" "\"storage-service\"" "\"pos-web\"") + SERVICES=("\"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\"") fi if [ ${#SERVICES[@]} -eq 0 ]; then @@ -108,9 +156,10 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Login to Docker Hub + - name: Login to Harbor Registry uses: docker/login-action@v3 with: + registry: ${{ secrets.DOCKER_REGISTRY }} username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -126,19 +175,51 @@ jobs: ["wallet-service"]="./services/wallet-service-net" ["catalog-service"]="./services/catalog-service-net" ["storage-service"]="./services/storage-service-net" + ["booking-service"]="./services/booking-service-net" + ["chat-service"]="./services/chat-service-net" + ["social-service"]="./services/social-service-net" + ["promotion-service"]="./services/promotion-service-net" + ["membership-service"]="./services/membership-service-net" + ["mining-service"]="./services/mining-service-net" + ["mission-service"]="./services/mission-service-net" + ["ads-manager-service"]="./services/ads-manager-service-net" + ["ads-serving-service"]="./services/ads-serving-service-net" + ["ads-billing-service"]="./services/ads-billing-service-net" + ["ads-tracking-service"]="./services/ads-tracking-service-net" + ["ads-analytics-service"]="./services/ads-analytics-service-net" + ["mkt-facebook-service"]="./services/mkt-facebook-service-net" + ["mkt-whatsapp-service"]="./services/mkt-whatsapp-service-net" + ["mkt-x-service"]="./services/mkt-x-service-net" + ["mkt-zalo-service"]="./services/mkt-zalo-service-net" ["pos-web"]="./apps/web-client-tpos-net" ) declare -A IMAGE_MAP=( - ["iam-service"]="goodgo/iam-service-net" - ["merchant-service"]="goodgo/merchant-service-net" - ["order-service"]="goodgo/order-service-net" - ["fnb-engine"]="goodgo/fnb-engine-net" - ["inventory-service"]="goodgo/inventory-service-net" - ["wallet-service"]="goodgo/wallet-service-net" - ["catalog-service"]="goodgo/catalog-service-net" - ["storage-service"]="goodgo/storage-service-net" - ["pos-web"]="goodgo/web-client-tpos-net" + ["iam-service"]="harbor.techbi.org/goodgo/iam-service-net" + ["merchant-service"]="harbor.techbi.org/goodgo/merchant-service-net" + ["order-service"]="harbor.techbi.org/goodgo/order-service-net" + ["fnb-engine"]="harbor.techbi.org/goodgo/fnb-engine-net" + ["inventory-service"]="harbor.techbi.org/goodgo/inventory-service-net" + ["wallet-service"]="harbor.techbi.org/goodgo/wallet-service-net" + ["catalog-service"]="harbor.techbi.org/goodgo/catalog-service-net" + ["storage-service"]="harbor.techbi.org/goodgo/storage-service-net" + ["booking-service"]="harbor.techbi.org/goodgo/booking-service-net" + ["chat-service"]="harbor.techbi.org/goodgo/chat-service-net" + ["social-service"]="harbor.techbi.org/goodgo/social-service-net" + ["promotion-service"]="harbor.techbi.org/goodgo/promotion-service-net" + ["membership-service"]="harbor.techbi.org/goodgo/membership-service-net" + ["mining-service"]="harbor.techbi.org/goodgo/mining-service-net" + ["mission-service"]="harbor.techbi.org/goodgo/mission-service-net" + ["ads-manager-service"]="harbor.techbi.org/goodgo/ads-manager-service-net" + ["ads-serving-service"]="harbor.techbi.org/goodgo/ads-serving-service-net" + ["ads-billing-service"]="harbor.techbi.org/goodgo/ads-billing-service-net" + ["ads-tracking-service"]="harbor.techbi.org/goodgo/ads-tracking-service-net" + ["ads-analytics-service"]="harbor.techbi.org/goodgo/ads-analytics-service-net" + ["mkt-facebook-service"]="harbor.techbi.org/goodgo/mkt-facebook-service-net" + ["mkt-whatsapp-service"]="harbor.techbi.org/goodgo/mkt-whatsapp-service-net" + ["mkt-x-service"]="harbor.techbi.org/goodgo/mkt-x-service-net" + ["mkt-zalo-service"]="harbor.techbi.org/goodgo/mkt-zalo-service-net" + ["pos-web"]="harbor.techbi.org/goodgo/web-client-tpos-net" ) echo "context=${CONTEXT_MAP[${{ matrix.service }}]}" >> $GITHUB_OUTPUT @@ -180,7 +261,7 @@ jobs: --project services/iam-service-net/src/IamService.Infrastructure/IamService.Infrastructure.csproj \ --startup-project services/iam-service-net/src/IamService.API/IamService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_IAM_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_IAM_DATABASE_URL_STAGING }} - name: Run Merchant migrations if: contains(needs.detect-changes.outputs.services, 'merchant-service') @@ -189,7 +270,7 @@ jobs: --project services/merchant-service-net/src/MerchantService.Infrastructure/MerchantService.Infrastructure.csproj \ --startup-project services/merchant-service-net/src/MerchantService.API/MerchantService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_MERCHANT_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_MERCHANT_DATABASE_URL_STAGING }} - name: Run Order migrations if: contains(needs.detect-changes.outputs.services, 'order-service') @@ -198,7 +279,7 @@ jobs: --project services/order-service-net/src/OrderService.Infrastructure/OrderService.Infrastructure.csproj \ --startup-project services/order-service-net/src/OrderService.API/OrderService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_ORDER_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_ORDER_DATABASE_URL_STAGING }} - name: Run FnB Engine migrations if: contains(needs.detect-changes.outputs.services, 'fnb-engine') @@ -207,7 +288,7 @@ jobs: --project services/fnb-engine-net/src/FnbEngine.Infrastructure/FnbEngine.Infrastructure.csproj \ --startup-project services/fnb-engine-net/src/FnbEngine.API/FnbEngine.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_FNB_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_FNB_DATABASE_URL_STAGING }} - name: Run Inventory migrations if: contains(needs.detect-changes.outputs.services, 'inventory-service') @@ -216,7 +297,7 @@ jobs: --project services/inventory-service-net/src/InventoryService.Infrastructure/InventoryService.Infrastructure.csproj \ --startup-project services/inventory-service-net/src/InventoryService.API/InventoryService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_INVENTORY_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_INVENTORY_DATABASE_URL_STAGING }} - name: Run Wallet migrations if: contains(needs.detect-changes.outputs.services, 'wallet-service') @@ -225,7 +306,7 @@ jobs: --project services/wallet-service-net/src/WalletService.Infrastructure/WalletService.Infrastructure.csproj \ --startup-project services/wallet-service-net/src/WalletService.API/WalletService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_WALLET_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_WALLET_DATABASE_URL_STAGING }} - name: Run Catalog migrations if: contains(needs.detect-changes.outputs.services, 'catalog-service') @@ -234,7 +315,7 @@ jobs: --project services/catalog-service-net/src/CatalogService.Infrastructure/CatalogService.Infrastructure.csproj \ --startup-project services/catalog-service-net/src/CatalogService.API/CatalogService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_CATALOG_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_CATALOG_DATABASE_URL_STAGING }} - name: Run Storage migrations if: contains(needs.detect-changes.outputs.services, 'storage-service') @@ -243,7 +324,124 @@ jobs: --project services/storage-service-net/src/StorageService.Infrastructure/StorageService.Infrastructure.csproj \ --startup-project services/storage-service-net/src/StorageService.API/StorageService.API.csproj env: - ConnectionStrings__DefaultConnection: ${{ secrets.NEON_STORAGE_DATABASE_URL_STAGING }} + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_STORAGE_DATABASE_URL_STAGING }} + + - name: Run Booking migrations + if: contains(needs.detect-changes.outputs.services, 'booking-service') + run: | + dotnet ef database update \ + --project services/booking-service-net/src/BookingService.Infrastructure/BookingService.Infrastructure.csproj \ + --startup-project services/booking-service-net/src/BookingService.API/BookingService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_BOOKING_DATABASE_URL_STAGING }} + + - name: Run Chat migrations + if: contains(needs.detect-changes.outputs.services, 'chat-service') + run: | + dotnet ef database update \ + --project services/chat-service-net/src/ChatService.Infrastructure/ChatService.Infrastructure.csproj \ + --startup-project services/chat-service-net/src/ChatService.API/ChatService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_CHAT_DATABASE_URL_STAGING }} + + - name: Run Social migrations + if: contains(needs.detect-changes.outputs.services, 'social-service') + run: | + dotnet ef database update \ + --project services/social-service-net/src/SocialService.Infrastructure/SocialService.Infrastructure.csproj \ + --startup-project services/social-service-net/src/SocialService.API/SocialService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_SOCIAL_DATABASE_URL_STAGING }} + + - name: Run Promotion migrations + if: contains(needs.detect-changes.outputs.services, 'promotion-service') + run: | + dotnet ef database update \ + --project services/promotion-service-net/src/PromotionService.Infrastructure/PromotionService.Infrastructure.csproj \ + --startup-project services/promotion-service-net/src/PromotionService.API/PromotionService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_PROMOTION_DATABASE_URL_STAGING }} + + - name: Run Membership migrations + if: contains(needs.detect-changes.outputs.services, 'membership-service') + run: | + dotnet ef database update \ + --project services/membership-service-net/src/MembershipService.Infrastructure/MembershipService.Infrastructure.csproj \ + --startup-project services/membership-service-net/src/MembershipService.API/MembershipService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_MEMBERSHIP_DATABASE_URL_STAGING }} + + - name: Run Mining migrations + if: contains(needs.detect-changes.outputs.services, 'mining-service') + run: | + dotnet ef database update \ + --project services/mining-service-net/src/MiningService.Infrastructure/MiningService.Infrastructure.csproj \ + --startup-project services/mining-service-net/src/MiningService.API/MiningService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_MINING_DATABASE_URL_STAGING }} + + - name: Run Mission migrations + if: contains(needs.detect-changes.outputs.services, 'mission-service') + run: | + dotnet ef database update \ + --project services/mission-service-net/src/MissionService.Infrastructure/MissionService.Infrastructure.csproj \ + --startup-project services/mission-service-net/src/MissionService.API/MissionService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_MISSION_DATABASE_URL_STAGING }} + + - name: Run Ads Manager migrations + if: contains(needs.detect-changes.outputs.services, 'ads-manager-service') + run: | + dotnet ef database update \ + --project services/ads-manager-service-net/src/AdsManagerService.Infrastructure/AdsManagerService.Infrastructure.csproj \ + --startup-project services/ads-manager-service-net/src/AdsManagerService.API/AdsManagerService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_ADS_MANAGER_DATABASE_URL_STAGING }} + + - name: Run Ads Serving migrations + if: contains(needs.detect-changes.outputs.services, 'ads-serving-service') + run: | + dotnet ef database update \ + --project services/ads-serving-service-net/src/AdsServingService.Infrastructure/AdsServingService.Infrastructure.csproj \ + --startup-project services/ads-serving-service-net/src/AdsServingService.API/AdsServingService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_ADS_SERVING_DATABASE_URL_STAGING }} + + - name: Run Ads Billing migrations + if: contains(needs.detect-changes.outputs.services, 'ads-billing-service') + run: | + dotnet ef database update \ + --project services/ads-billing-service-net/src/AdsBillingService.Infrastructure/AdsBillingService.Infrastructure.csproj \ + --startup-project services/ads-billing-service-net/src/AdsBillingService.API/AdsBillingService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_ADS_BILLING_DATABASE_URL_STAGING }} + + - name: Run Ads Tracking migrations + if: contains(needs.detect-changes.outputs.services, 'ads-tracking-service') + run: | + dotnet ef database update \ + --project services/ads-tracking-service-net/src/AdsTrackingService.Infrastructure/AdsTrackingService.Infrastructure.csproj \ + --startup-project services/ads-tracking-service-net/src/AdsTrackingService.API/AdsTrackingService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_ADS_TRACKING_DATABASE_URL_STAGING }} + + - name: Run Ads Analytics migrations + if: contains(needs.detect-changes.outputs.services, 'ads-analytics-service') + run: | + dotnet ef database update \ + --project services/ads-analytics-service-net/src/AdsAnalyticsService.Infrastructure/AdsAnalyticsService.Infrastructure.csproj \ + --startup-project services/ads-analytics-service-net/src/AdsAnalyticsService.API/AdsAnalyticsService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_ADS_ANALYTICS_DATABASE_URL_STAGING }} + + - name: Run Mkt Zalo migrations + if: contains(needs.detect-changes.outputs.services, 'mkt-zalo-service') + run: | + dotnet ef database update \ + --project services/mkt-zalo-service-net/src/MktZaloService.Infrastructure/MktZaloService.Infrastructure.csproj \ + --startup-project services/mkt-zalo-service-net/src/MktZaloService.API/MktZaloService.API.csproj + env: + ConnectionStrings__DefaultConnection: ${{ secrets.REMOTE_MKT_ZALO_DATABASE_URL_STAGING }} # ========================================================================= # Deploy to Kubernetes @@ -268,9 +466,11 @@ jobs: kubectl apply -f deployments/staging/kubernetes/namespace.yaml kubectl apply -f deployments/staging/kubernetes/configmap.yaml - - name: Deploy Redis + - name: Deploy Infrastructure run: | kubectl apply -f deployments/staging/kubernetes/redis.yaml + kubectl apply -f deployments/staging/kubernetes/rabbitmq.yaml + kubectl apply -f deployments/staging/kubernetes/minio.yaml - name: Deploy services run: | @@ -285,6 +485,22 @@ jobs: ["wallet-service"]="wallet-service.yaml" ["catalog-service"]="catalog-service.yaml" ["storage-service"]="storage-service.yaml" + ["booking-service"]="booking-service.yaml" + ["chat-service"]="chat-service.yaml" + ["social-service"]="social-service.yaml" + ["promotion-service"]="promotion-service.yaml" + ["membership-service"]="membership-service.yaml" + ["mining-service"]="mining-service.yaml" + ["mission-service"]="mission-service.yaml" + ["ads-manager-service"]="ads-manager-service.yaml" + ["ads-serving-service"]="ads-serving-service.yaml" + ["ads-billing-service"]="ads-billing-service.yaml" + ["ads-tracking-service"]="ads-tracking-service.yaml" + ["ads-analytics-service"]="ads-analytics-service.yaml" + ["mkt-facebook-service"]="mkt-facebook-service.yaml" + ["mkt-whatsapp-service"]="mkt-whatsapp-service.yaml" + ["mkt-x-service"]="mkt-x-service.yaml" + ["mkt-zalo-service"]="mkt-zalo-service.yaml" ["pos-web"]="pos-web.yaml" ) @@ -307,6 +523,10 @@ jobs: run: | kubectl apply -f deployments/staging/kubernetes/ingress.yaml + - name: Apply network policies + run: | + kubectl apply -f deployments/staging/kubernetes/network-policy.yaml + - name: Wait for rollouts run: | SERVICES='${{ needs.detect-changes.outputs.services }}' @@ -320,6 +540,22 @@ jobs: ["wallet-service"]="wallet-service" ["catalog-service"]="catalog-service" ["storage-service"]="storage-service" + ["booking-service"]="booking-service" + ["chat-service"]="chat-service" + ["social-service"]="social-service" + ["promotion-service"]="promotion-service" + ["membership-service"]="membership-service" + ["mining-service"]="mining-service" + ["mission-service"]="mission-service" + ["ads-manager-service"]="ads-manager-service" + ["ads-serving-service"]="ads-serving-service" + ["ads-billing-service"]="ads-billing-service" + ["ads-tracking-service"]="ads-tracking-service" + ["ads-analytics-service"]="ads-analytics-service" + ["mkt-facebook-service"]="mkt-facebook-service" + ["mkt-whatsapp-service"]="mkt-whatsapp-service" + ["mkt-x-service"]="mkt-x-service" + ["mkt-zalo-service"]="mkt-zalo-service" ["pos-web"]="pos-web" ) diff --git a/deployments/local/.env b/deployments/local/.env index a864e344..3f4bf879 100644 --- a/deployments/local/.env +++ b/deployments/local/.env @@ -50,28 +50,28 @@ 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 +# 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 diff --git a/deployments/staging/kubernetes/ads-analytics-service.yaml b/deployments/staging/kubernetes/ads-analytics-service.yaml new file mode 100644 index 00000000..a4fde68c --- /dev/null +++ b/deployments/staging/kubernetes/ads-analytics-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/ads-billing-service.yaml b/deployments/staging/kubernetes/ads-billing-service.yaml new file mode 100644 index 00000000..705d4fa8 --- /dev/null +++ b/deployments/staging/kubernetes/ads-billing-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/ads-manager-service.yaml b/deployments/staging/kubernetes/ads-manager-service.yaml new file mode 100644 index 00000000..6a12d3a0 --- /dev/null +++ b/deployments/staging/kubernetes/ads-manager-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/ads-serving-service.yaml b/deployments/staging/kubernetes/ads-serving-service.yaml new file mode 100644 index 00000000..5704f8bf --- /dev/null +++ b/deployments/staging/kubernetes/ads-serving-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/ads-tracking-service.yaml b/deployments/staging/kubernetes/ads-tracking-service.yaml new file mode 100644 index 00000000..29e9dcaf --- /dev/null +++ b/deployments/staging/kubernetes/ads-tracking-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/booking-service.yaml b/deployments/staging/kubernetes/booking-service.yaml index 525a72fe..2f95022c 100644 --- a/deployments/staging/kubernetes/booking-service.yaml +++ b/deployments/staging/kubernetes/booking-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: booking-service - image: goodgo/booking-service-net:staging + image: harbor.techbi.org/goodgo/booking-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/catalog-service.yaml b/deployments/staging/kubernetes/catalog-service.yaml index 1e7e82a2..9ba9ff52 100644 --- a/deployments/staging/kubernetes/catalog-service.yaml +++ b/deployments/staging/kubernetes/catalog-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: catalog-service - image: goodgo/catalog-service-net:staging + image: harbor.techbi.org/goodgo/catalog-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/chat-service.yaml b/deployments/staging/kubernetes/chat-service.yaml new file mode 100644 index 00000000..636346f1 --- /dev/null +++ b/deployments/staging/kubernetes/chat-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/configmap.yaml b/deployments/staging/kubernetes/configmap.yaml index 1687144f..363b6257 100644 --- a/deployments/staging/kubernetes/configmap.yaml +++ b/deployments/staging/kubernetes/configmap.yaml @@ -36,6 +36,22 @@ data: 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 @@ -43,6 +59,14 @@ data: 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://pos.staging.goodgo.vn,https://staging.goodgo.vn,https://admin.staging.goodgo.vn" diff --git a/deployments/staging/kubernetes/fnb-engine.yaml b/deployments/staging/kubernetes/fnb-engine.yaml index bef56d25..9ebab42f 100644 --- a/deployments/staging/kubernetes/fnb-engine.yaml +++ b/deployments/staging/kubernetes/fnb-engine.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: fnb-engine - image: goodgo/fnb-engine-net:staging + image: harbor.techbi.org/goodgo/fnb-engine-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/iam-service.yaml b/deployments/staging/kubernetes/iam-service.yaml index 9fd8009e..f37b9031 100644 --- a/deployments/staging/kubernetes/iam-service.yaml +++ b/deployments/staging/kubernetes/iam-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: iam-service - image: goodgo/iam-service-net:staging + image: harbor.techbi.org/goodgo/iam-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/ingress.yaml b/deployments/staging/kubernetes/ingress.yaml index 53388135..4051701c 100644 --- a/deployments/staging/kubernetes/ingress.yaml +++ b/deployments/staging/kubernetes/ingress.yaml @@ -16,18 +16,16 @@ metadata: environment: staging 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 middleware - # VI: Middleware gioi han toc do - traefik.ingress.kubernetes.io/router.middlewares: staging-cors@kubernetescrd,staging-secure-headers@kubernetescrd - # EN: cert-manager TLS - # VI: TLS bang cert-manager - cert-manager.io/cluster-issuer: letsencrypt-staging + # EN: Nginx Ingress class + # VI: Ingress class cua Nginx + 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: 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: traefik + ingressClassName: nginx tls: - hosts: - api.staging.goodgo.vn @@ -268,6 +266,279 @@ spec: 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 + - path: /api/v1/appointments + pathType: Prefix + backend: + service: + name: booking-service + port: + number: 8080 + - path: /api/v1/therapists + pathType: Prefix + backend: + service: + name: booking-service + port: + number: 8080 + + # ===== Chat Service ===== + - path: /api/v1/chats + pathType: Prefix + backend: + service: + name: chat-service + port: + number: 8080 + - path: /api/v1/messages + pathType: Prefix + backend: + service: + name: chat-service + port: + number: 8080 + - path: /api/v1/conversations + pathType: Prefix + backend: + service: + name: chat-service + port: + number: 8080 + # EN: Chat SignalR Hub (WebSocket) + # VI: Chat SignalR Hub (WebSocket) + - path: /hubs/chat + pathType: Prefix + backend: + service: + name: chat-service + port: + number: 8080 + + # ===== Social Service ===== + - path: /api/v1/social + pathType: Prefix + backend: + service: + name: social-service + port: + number: 8080 + - path: /api/v1/relationships + pathType: Prefix + backend: + service: + name: social-service + port: + number: 8080 + + # ===== Promotion Service ===== + - path: /api/v1/promotions + pathType: Prefix + backend: + service: + name: promotion-service + port: + number: 8080 + - path: /api/v1/vouchers + pathType: Prefix + backend: + service: + name: promotion-service + port: + number: 8080 + + # ===== Membership Service ===== + - path: /api/v1/members + pathType: Prefix + backend: + service: + name: membership-service + port: + number: 8080 + - path: /api/v1/levels + pathType: Prefix + backend: + service: + name: membership-service + port: + number: 8080 + + # ===== Mining Service ===== + - path: /api/v1/mining + pathType: Prefix + backend: + service: + name: mining-service + port: + number: 8080 + - path: /api/v1/circles + pathType: Prefix + backend: + service: + name: mining-service + port: + number: 8080 + - path: /api/v1/referrals + pathType: Prefix + backend: + service: + name: mining-service + port: + number: 8080 + + # ===== Mission Service ===== + - path: /api/v1/missions + pathType: Prefix + backend: + service: + name: mission-service + port: + number: 8080 + - path: /api/v1/checkins + pathType: Prefix + backend: + service: + name: mission-service + port: + number: 8080 + + # ===== Ads Manager Service ===== + - path: /api/v1/ads + pathType: Prefix + backend: + service: + name: ads-manager-service + port: + number: 8080 + - path: /api/v1/campaigns + pathType: Prefix + backend: + service: + name: ads-manager-service + port: + number: 8080 + - path: /api/v1/adsets + pathType: Prefix + backend: + service: + name: ads-manager-service + port: + number: 8080 + - path: /api/v1/audiences + pathType: Prefix + backend: + service: + name: ads-manager-service + port: + number: 8080 + + # ===== Ads Serving Service ===== + - path: /api/v1/ads-serving + pathType: Prefix + backend: + service: + name: ads-serving-service + port: + number: 8080 + + # ===== Ads Billing Service ===== + - path: /api/v1/ads-billing + pathType: Prefix + backend: + service: + name: ads-billing-service + port: + number: 8080 + - path: /api/v1/ad-invoices + pathType: Prefix + backend: + service: + name: ads-billing-service + port: + number: 8080 + + # ===== Ads Tracking Service ===== + - path: /api/v1/ad-events + pathType: Prefix + backend: + service: + name: ads-tracking-service + port: + number: 8080 + - path: /api/v1/pixels + pathType: Prefix + backend: + service: + name: ads-tracking-service + port: + number: 8080 + - path: /api/v1/conversions + pathType: Prefix + backend: + service: + name: ads-tracking-service + port: + number: 8080 + + # ===== Ads Analytics Service ===== + - path: /api/v1/ad-analytics + pathType: Prefix + backend: + service: + name: ads-analytics-service + port: + number: 8080 + - path: /api/v1/ad-reports + pathType: Prefix + backend: + service: + name: ads-analytics-service + port: + number: 8080 + + # ===== Marketing Services ===== + - path: /api/v1/mkt/facebook + pathType: Prefix + backend: + service: + name: mkt-facebook-service + port: + number: 8080 + - path: /api/v1/mkt/whatsapp + pathType: Prefix + backend: + service: + name: mkt-whatsapp-service + port: + number: 8080 + - path: /api/v1/mkt/x + pathType: Prefix + backend: + service: + name: mkt-x-service + port: + number: 8080 + - path: /api/v1/mkt/zalo + pathType: Prefix + backend: + service: + name: mkt-zalo-service + port: + number: 8080 + --- # ============================================================================= # POS Frontend Ingress @@ -281,11 +552,10 @@ metadata: environment: staging platform: goodgo annotations: - traefik.ingress.kubernetes.io/router.entrypoints: websecure - traefik.ingress.kubernetes.io/router.tls: "true" - cert-manager.io/cluster-issuer: letsencrypt-staging + nginx.ingress.kubernetes.io/proxy-body-size: "50m" + cert-manager.io/cluster-issuer: letsencrypt-prod spec: - ingressClassName: traefik + ingressClassName: nginx tls: - hosts: - pos.staging.goodgo.vn diff --git a/deployments/staging/kubernetes/inventory-service.yaml b/deployments/staging/kubernetes/inventory-service.yaml index cbd77820..df1d4d4e 100644 --- a/deployments/staging/kubernetes/inventory-service.yaml +++ b/deployments/staging/kubernetes/inventory-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: inventory-service - image: goodgo/inventory-service-net:staging + image: harbor.techbi.org/goodgo/inventory-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/membership-service.yaml b/deployments/staging/kubernetes/membership-service.yaml new file mode 100644 index 00000000..680c3860 --- /dev/null +++ b/deployments/staging/kubernetes/membership-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/merchant-service.yaml b/deployments/staging/kubernetes/merchant-service.yaml index f5f73d70..81545833 100644 --- a/deployments/staging/kubernetes/merchant-service.yaml +++ b/deployments/staging/kubernetes/merchant-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: merchant-service - image: goodgo/merchant-service-net:staging + image: harbor.techbi.org/goodgo/merchant-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/mining-service.yaml b/deployments/staging/kubernetes/mining-service.yaml new file mode 100644 index 00000000..3b8da795 --- /dev/null +++ b/deployments/staging/kubernetes/mining-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/minio.yaml b/deployments/staging/kubernetes/minio.yaml new file mode 100644 index 00000000..52cfab90 --- /dev/null +++ b/deployments/staging/kubernetes/minio.yaml @@ -0,0 +1,128 @@ +# EN: MinIO - S3-compatible object storage for file uploads and media +# VI: MinIO - Luu tru doi tuong tuong thich S3 cho file upload va media +apiVersion: apps/v1 +kind: Deployment +metadata: + name: minio + namespace: staging + labels: + app: minio + environment: staging + platform: goodgo + tier: infrastructure +spec: + replicas: 1 + selector: + matchLabels: + app: minio + template: + metadata: + labels: + app: minio + environment: staging + spec: + containers: + - name: minio + image: minio/minio:latest + command: + - server + - /data + - "--console-address" + - ":9001" + ports: + - containerPort: 9000 + protocol: TCP + - containerPort: 9001 + protocol: TCP + env: + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: goodgo-secrets + key: Storage__MinIO__AccessKey + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: goodgo-secrets + key: Storage__MinIO__SecretKey + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /minio/health/live + port: 9000 + initialDelaySeconds: 15 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /minio/health/ready + port: 9000 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + volumeMounts: + - name: minio-data + mountPath: /data + volumes: + - name: minio-data + persistentVolumeClaim: + claimName: minio-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: minio + namespace: staging + labels: + app: minio + environment: staging +spec: + selector: + app: minio + ports: + - name: minio + protocol: TCP + port: 9000 + targetPort: 9000 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: minio-console + namespace: staging + labels: + app: minio + environment: staging +spec: + selector: + app: minio + ports: + - name: console + protocol: TCP + port: 9001 + targetPort: 9001 + type: ClusterIP +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: minio-pvc + namespace: staging + labels: + app: minio + environment: staging +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi diff --git a/deployments/staging/kubernetes/mission-service.yaml b/deployments/staging/kubernetes/mission-service.yaml new file mode 100644 index 00000000..9be68211 --- /dev/null +++ b/deployments/staging/kubernetes/mission-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/mkt-facebook-service.yaml b/deployments/staging/kubernetes/mkt-facebook-service.yaml new file mode 100644 index 00000000..2e3cab44 --- /dev/null +++ b/deployments/staging/kubernetes/mkt-facebook-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/mkt-whatsapp-service.yaml b/deployments/staging/kubernetes/mkt-whatsapp-service.yaml new file mode 100644 index 00000000..f4dbbe21 --- /dev/null +++ b/deployments/staging/kubernetes/mkt-whatsapp-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/mkt-x-service.yaml b/deployments/staging/kubernetes/mkt-x-service.yaml new file mode 100644 index 00000000..56e5e86b --- /dev/null +++ b/deployments/staging/kubernetes/mkt-x-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/mkt-zalo-service.yaml b/deployments/staging/kubernetes/mkt-zalo-service.yaml new file mode 100644 index 00000000..43061351 --- /dev/null +++ b/deployments/staging/kubernetes/mkt-zalo-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/network-policy.yaml b/deployments/staging/kubernetes/network-policy.yaml index 8acc0c11..d5f5f53f 100644 --- a/deployments/staging/kubernetes/network-policy.yaml +++ b/deployments/staging/kubernetes/network-policy.yaml @@ -8,6 +8,8 @@ # 4. Allow ingress from Traefik (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 # ============================================================================= # Default Deny — block all ingress + egress by default @@ -52,8 +54,6 @@ spec: --- # ============================================================================= # Allow Traefik ingress → microservices (port 8080) -# EN: Traefik runs in kube-system namespace (or traefik namespace). -# VI: Traefik chay trong namespace kube-system (hoac traefik namespace). # ============================================================================= apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -78,6 +78,21 @@ spec: - 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 @@ -96,8 +111,6 @@ spec: --- # ============================================================================= # Allow microservices to egress to each other (port 8080) -# EN: Services communicate internally via REST (HTTP/8080). -# VI: Cac service giao tiep noi bo qua REST (HTTP/8080). # ============================================================================= apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -122,6 +135,21 @@ spec: - 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: @@ -140,6 +168,21 @@ spec: - 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 @@ -147,8 +190,6 @@ spec: --- # ============================================================================= # Allow Redis access — only from app services (port 6379) -# EN: Redis is accessed only by application pods (not pos-web frontend). -# VI: Redis chi duoc truy cap boi cac pod ung dung (khong phai pos-web frontend). # ============================================================================= apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -164,6 +205,7 @@ spec: - key: app operator: In values: + - redis - redis-master - redis-replica policyTypes: @@ -184,6 +226,16 @@ spec: - 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 @@ -268,6 +320,16 @@ spec: - 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: @@ -277,6 +339,7 @@ spec: - key: app operator: In values: + - redis - redis-master - redis-replica - redis-sentinel @@ -286,11 +349,137 @@ spec: - 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 -# EN: Prometheus runs in monitoring namespace and scrapes /metrics. -# VI: Prometheus chay trong namespace monitoring va thu thap /metrics. # ============================================================================= apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -315,6 +504,21 @@ spec: - 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 @@ -329,9 +533,7 @@ spec: --- # ============================================================================= -# Allow microservices to reach external services (Neon PostgreSQL, etc.) -# EN: Egress to external HTTPS/PostgreSQL (Neon cloud DB, SMTP, etc.) -# VI: Egress ra ngoai HTTPS/PostgreSQL (Neon cloud DB, SMTP, v.v.) +# Allow microservices to reach external services (PostgreSQL, SMTP, etc.) # ============================================================================= apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -356,6 +558,21 @@ spec: - 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: @@ -364,6 +581,8 @@ spec: protocol: TCP - port: 5432 protocol: TCP + - port: 30992 + protocol: TCP - port: 5671 protocol: TCP - port: 5672 diff --git a/deployments/staging/kubernetes/order-service.yaml b/deployments/staging/kubernetes/order-service.yaml index e2329151..6c8f9e3d 100644 --- a/deployments/staging/kubernetes/order-service.yaml +++ b/deployments/staging/kubernetes/order-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: order-service - image: goodgo/order-service-net:staging + image: harbor.techbi.org/goodgo/order-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/pos-web.yaml b/deployments/staging/kubernetes/pos-web.yaml index da46048f..600896e6 100644 --- a/deployments/staging/kubernetes/pos-web.yaml +++ b/deployments/staging/kubernetes/pos-web.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: pos-web - image: goodgo/web-client-tpos-net:staging + image: harbor.techbi.org/goodgo/web-client-tpos-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/promotion-service.yaml b/deployments/staging/kubernetes/promotion-service.yaml new file mode 100644 index 00000000..5f3f069e --- /dev/null +++ b/deployments/staging/kubernetes/promotion-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/rabbitmq.yaml b/deployments/staging/kubernetes/rabbitmq.yaml new file mode 100644 index 00000000..6e258699 --- /dev/null +++ b/deployments/staging/kubernetes/rabbitmq.yaml @@ -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 diff --git a/deployments/staging/kubernetes/secrets.yaml b/deployments/staging/kubernetes/secrets.yaml index 4c49138c..243a4975 100644 --- a/deployments/staging/kubernetes/secrets.yaml +++ b/deployments/staging/kubernetes/secrets.yaml @@ -13,14 +13,30 @@ # Or use sealed-secrets / external-secrets operator in production. # # GitHub Secrets used in CI/CD: -# - 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 +# - 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 @@ -47,17 +63,33 @@ stringData: # VI: IdentityServer Issuer IdentityServer__IssuerUri: "https://api.staging.goodgo.vn" - # EN: Neon PostgreSQL Connection Strings (per-service databases) - # VI: Chuoi ket noi Neon PostgreSQL (database rieng cho tung service) - # Format: postgresql://user:password@ep-xxx.region.neon.tech/dbname?sslmode=require - IAM_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/iam_staging?sslmode=require" - MERCHANT_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/merchant_staging?sslmode=require" - ORDER_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/order_staging?sslmode=require" - FNB_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/fnb_staging?sslmode=require" - INVENTORY_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/inventory_staging?sslmode=require" - WALLET_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/wallet_staging?sslmode=require" - CATALOG_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/catalog_staging?sslmode=require" - STORAGE_DATABASE_URL: "PLACEHOLDER-postgresql://user:pass@ep-xxx.region.neon.tech/storage_staging?sslmode=require" + # 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 diff --git a/deployments/staging/kubernetes/social-service.yaml b/deployments/staging/kubernetes/social-service.yaml new file mode 100644 index 00000000..38789564 --- /dev/null +++ b/deployments/staging/kubernetes/social-service.yaml @@ -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: 2 + 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: "250m" + 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: 2 + maxReplicas: 4 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 75 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 80 diff --git a/deployments/staging/kubernetes/storage-service.yaml b/deployments/staging/kubernetes/storage-service.yaml index 3ffa07c9..02731498 100644 --- a/deployments/staging/kubernetes/storage-service.yaml +++ b/deployments/staging/kubernetes/storage-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: storage-service - image: goodgo/storage-service-net:staging + image: harbor.techbi.org/goodgo/storage-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/deployments/staging/kubernetes/wallet-service.yaml b/deployments/staging/kubernetes/wallet-service.yaml index a8f1f9d8..f59eca81 100644 --- a/deployments/staging/kubernetes/wallet-service.yaml +++ b/deployments/staging/kubernetes/wallet-service.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: wallet-service - image: goodgo/wallet-service-net:staging + image: harbor.techbi.org/goodgo/wallet-service-net:staging ports: - containerPort: 8080 protocol: TCP diff --git a/infra/observability/alertmanager/alertmanager.yml b/infra/observability/alertmanager/alertmanager.yml index 97eb255b..1fe46998 100644 --- a/infra/observability/alertmanager/alertmanager.yml +++ b/infra/observability/alertmanager/alertmanager.yml @@ -62,7 +62,7 @@ receivers: # VI: Canh bao critical — Slack + email - name: 'critical-receiver' slack_configs: - - api_url: '${ALERTMANAGER_SLACK_WEBHOOK_URL}' + - api_url: 'https://hooks.slack.com/services/placeholder' channel: '#alerts-critical' send_resolved: true title: ':fire: [CRITICAL] {{ .GroupLabels.alertname }}' @@ -83,7 +83,7 @@ receivers: # VI: Canh bao warning — chi Slack - name: 'warning-receiver' slack_configs: - - api_url: '${ALERTMANAGER_SLACK_WEBHOOK_URL}' + - api_url: 'https://hooks.slack.com/services/placeholder' channel: '#alerts-warning' send_resolved: true title: ':warning: [WARNING] {{ .GroupLabels.alertname }}' @@ -98,7 +98,7 @@ receivers: # VI: Receiver ha tang — doi DevOps - name: 'infra-receiver' slack_configs: - - api_url: '${ALERTMANAGER_SLACK_WEBHOOK_URL}' + - api_url: 'https://hooks.slack.com/services/placeholder' channel: '#alerts-infra' send_resolved: true title: ':gear: [INFRA] {{ .GroupLabels.alertname }}' diff --git a/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/DependencyInjection.cs b/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/DependencyInjection.cs index d9fd1444..069a28db 100644 --- a/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/DependencyInjection.cs +++ b/services/ads-billing-service-net/src/AdsBillingService.Infrastructure/DependencyInjection.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using AdsBillingService.Infrastructure.Idempotency; @@ -27,6 +28,9 @@ public static class DependencyInjection errorCodesToAdd: null); }); + options.ConfigureWarnings(w => + w.Ignore(RelationalEventId.PendingModelChangesWarning)); + if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development") { options.EnableSensitiveDataLogging(); diff --git a/services/membership-service-net/src/MembershipService.Infrastructure/DependencyInjection.cs b/services/membership-service-net/src/MembershipService.Infrastructure/DependencyInjection.cs index fb8cae80..70f3d1f0 100644 --- a/services/membership-service-net/src/MembershipService.Infrastructure/DependencyInjection.cs +++ b/services/membership-service-net/src/MembershipService.Infrastructure/DependencyInjection.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MembershipService.Domain.AggregatesModel.ExperienceAggregate; @@ -41,6 +42,9 @@ public static class DependencyInjection errorCodesToAdd: null); }); + options.ConfigureWarnings(w => + w.Ignore(RelationalEventId.PendingModelChangesWarning)); + // EN: Enable sensitive data logging in development only // VI: Chỉ bật sensitive data logging trong development if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development") diff --git a/services/mkt-facebook-service-net/Dockerfile b/services/mkt-facebook-service-net/Dockerfile index c1c753ca..f817aad4 100644 --- a/services/mkt-facebook-service-net/Dockerfile +++ b/services/mkt-facebook-service-net/Dockerfile @@ -30,9 +30,10 @@ RUN dotnet publish "FacebookService.API.csproj" -c Release -o /app/publish /p:Us FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final WORKDIR /app -# EN: Create non-root user for security -# VI: Tạo user non-root cho bảo mật -RUN groupadd -g 1001 dotnetuser && \ +# EN: Install curl for health check + create non-root user +# VI: Cài curl cho health check + tạo user non-root +RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* && \ + groupadd -g 1001 dotnetuser && \ useradd -u 1001 -g dotnetuser -s /bin/sh dotnetuser # EN: Copy published application diff --git a/services/mkt-facebook-service-net/src/FacebookService.API/FacebookService.API.csproj b/services/mkt-facebook-service-net/src/FacebookService.API/FacebookService.API.csproj index 07edba81..08bb97f7 100644 --- a/services/mkt-facebook-service-net/src/FacebookService.API/FacebookService.API.csproj +++ b/services/mkt-facebook-service-net/src/FacebookService.API/FacebookService.API.csproj @@ -15,6 +15,9 @@ + + + diff --git a/services/mkt-whatsapp-service-net/Dockerfile b/services/mkt-whatsapp-service-net/Dockerfile index 51a228d5..50c583de 100644 --- a/services/mkt-whatsapp-service-net/Dockerfile +++ b/services/mkt-whatsapp-service-net/Dockerfile @@ -30,9 +30,10 @@ RUN dotnet publish "WhatsAppService.API.csproj" -c Release -o /app/publish /p:Us FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final WORKDIR /app -# EN: Create non-root user for security -# VI: Tạo user non-root cho bảo mật -RUN groupadd -g 1001 dotnetuser && \ +# EN: Install curl for health check + create non-root user +# VI: Cài curl cho health check + tạo user non-root +RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* && \ + groupadd -g 1001 dotnetuser && \ useradd -u 1001 -g dotnetuser -s /bin/sh dotnetuser # EN: Copy published application diff --git a/services/mkt-whatsapp-service-net/src/WhatsAppService.API/WhatsAppService.API.csproj b/services/mkt-whatsapp-service-net/src/WhatsAppService.API/WhatsAppService.API.csproj index c254af9c..760a346d 100644 --- a/services/mkt-whatsapp-service-net/src/WhatsAppService.API/WhatsAppService.API.csproj +++ b/services/mkt-whatsapp-service-net/src/WhatsAppService.API/WhatsAppService.API.csproj @@ -15,6 +15,9 @@ + + + diff --git a/services/mkt-x-service-net/Dockerfile b/services/mkt-x-service-net/Dockerfile index 290e57c9..8c9143d2 100644 --- a/services/mkt-x-service-net/Dockerfile +++ b/services/mkt-x-service-net/Dockerfile @@ -30,9 +30,10 @@ RUN dotnet publish "MktXService.API.csproj" -c Release -o /app/publish /p:UseApp FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final WORKDIR /app -# EN: Create non-root user for security -# VI: Tạo user non-root cho bảo mật -RUN groupadd -g 1001 dotnetuser && \ +# EN: Install curl for health check + create non-root user +# VI: Cài curl cho health check + tạo user non-root +RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* && \ + groupadd -g 1001 dotnetuser && \ useradd -u 1001 -g dotnetuser -s /bin/sh dotnetuser # EN: Copy published application diff --git a/services/mkt-x-service-net/src/MktXService.API/MktXService.API.csproj b/services/mkt-x-service-net/src/MktXService.API/MktXService.API.csproj index 87003523..9eb7c8c7 100644 --- a/services/mkt-x-service-net/src/MktXService.API/MktXService.API.csproj +++ b/services/mkt-x-service-net/src/MktXService.API/MktXService.API.csproj @@ -15,6 +15,9 @@ + + + diff --git a/services/mkt-zalo-service-net/Dockerfile b/services/mkt-zalo-service-net/Dockerfile index c3ff8097..9b587ac5 100644 --- a/services/mkt-zalo-service-net/Dockerfile +++ b/services/mkt-zalo-service-net/Dockerfile @@ -30,9 +30,10 @@ RUN dotnet publish "MktZaloService.API.csproj" -c Release -o /app/publish /p:Use FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final WORKDIR /app -# EN: Create non-root user for security -# VI: Tạo user non-root cho bảo mật -RUN groupadd -g 1001 dotnetuser && \ +# EN: Install curl for health check + create non-root user +# VI: Cài curl cho health check + tạo user non-root +RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* && \ + groupadd -g 1001 dotnetuser && \ useradd -u 1001 -g dotnetuser -s /bin/sh dotnetuser # EN: Copy published application diff --git a/services/mkt-zalo-service-net/src/MktZaloService.API/MktZaloService.API.csproj b/services/mkt-zalo-service-net/src/MktZaloService.API/MktZaloService.API.csproj index eb0494f7..98ee87be 100644 --- a/services/mkt-zalo-service-net/src/MktZaloService.API/MktZaloService.API.csproj +++ b/services/mkt-zalo-service-net/src/MktZaloService.API/MktZaloService.API.csproj @@ -15,6 +15,9 @@ + + +