From 3db5c950c7e4e1a50fba691701b0ca141488d54e Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Tue, 24 Feb 2026 17:18:47 +0100 Subject: [PATCH] infra: deploy all services to Kapsule cluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix DB pool connect/acquire timeouts (50ms→5s) for cluster networking (pool-level timeouts, not query timeouts — HFT query timeout stays at 800μs) - Fix secret key references (DATABASE_PASSWORD→db-password) in all manifests - Fix api-gateway port (50050→50051) to match actual gRPC listen port - Fix web-gateway health probe path (/api/health→/health) - Fix S3 endpoint region (nl-ams→fr-par) in ml-training-service - Add TLS cert volume mount for ml-training-service - Add BENZINGA_API_KEY placeholder for backtesting-service startup - Remove always-on nodeSelector from services (let autoscaler handle) - Add serve subcommand to ml-training-service container All 10 pods (3 databases + 7 services) now 1/1 Running. Co-Authored-By: Claude Opus 4.6 --- common/src/database.rs | 12 ++++++------ infra/docker/Dockerfile.web-gateway | 2 +- infra/k8s/services/api-gateway.yaml | 12 +++++------- infra/k8s/services/backtesting-service.yaml | 6 +++--- infra/k8s/services/broker-gateway.yaml | 4 +--- infra/k8s/services/ml-training-service.yaml | 15 +++++++++++---- infra/k8s/services/trading-agent-service.yaml | 4 +--- infra/k8s/services/trading-service.yaml | 4 +--- infra/k8s/services/web-gateway.yaml | 4 +--- 9 files changed, 30 insertions(+), 33 deletions(-) diff --git a/common/src/database.rs b/common/src/database.rs index 806cf03b7..d04f86da6 100644 --- a/common/src/database.rs +++ b/common/src/database.rs @@ -96,8 +96,8 @@ impl Default for PoolConfig { Self { max_connections: 50, min_connections: 10, - connect_timeout_ms: 100, - acquire_timeout_ms: 50, + connect_timeout_ms: 5000, + acquire_timeout_ms: 5000, max_lifetime_seconds: 3600, idle_timeout_seconds: 300, } @@ -126,9 +126,9 @@ impl From for LocalDatabaseConfig { max_connections: config.max_connections, // 20% of max, min 2. Uses integer division intentionally for simplicity. min_connections: (config.max_connections / 5).max(2), - connect_timeout_ms: u64::try_from(config.connect_timeout.as_millis().min(100)) - .unwrap_or(100), // Convert to ms, cap at 100ms for HFT - acquire_timeout_ms: 50, // Fast acquire for HFT + connect_timeout_ms: u64::try_from(config.connect_timeout.as_millis()) + .unwrap_or(5000), // Pool connect timeout (not query timeout) + acquire_timeout_ms: 5000, // Pool acquire timeout (not query timeout) max_lifetime_seconds: 3600, // 1 hour default idle_timeout_seconds: 300, // 5 minutes default }, @@ -156,7 +156,7 @@ impl From for LocalDatabaseConfig { // 25% of max, min 2. Uses integer division intentionally for simplicity. min_connections: (max_conn / 4).max(2), connect_timeout_ms: config.acquire_timeout_ms.unwrap_or(1000), // Use acquire timeout as connection timeout - acquire_timeout_ms: 100, // Less strict for backtesting + acquire_timeout_ms: 5000, // Pool acquire timeout (not query timeout) max_lifetime_seconds: 3600, // 1 hour default idle_timeout_seconds: 600, // 10 minutes for backtesting }, diff --git a/infra/docker/Dockerfile.web-gateway b/infra/docker/Dockerfile.web-gateway index 3c7ccafaf..06df7f216 100644 --- a/infra/docker/Dockerfile.web-gateway +++ b/infra/docker/Dockerfile.web-gateway @@ -87,6 +87,6 @@ EXPOSE 3000 USER foxhunt HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD curl -f http://localhost:3000/api/health || exit 1 + CMD curl -f http://localhost:3000/health || exit 1 ENTRYPOINT ["./web-gateway"] diff --git a/infra/k8s/services/api-gateway.yaml b/infra/k8s/services/api-gateway.yaml index 75eb78f08..a485ab015 100644 --- a/infra/k8s/services/api-gateway.yaml +++ b/infra/k8s/services/api-gateway.yaml @@ -16,15 +16,13 @@ spec: labels: app.kubernetes.io/name: api-gateway spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: - name: api-gateway image: rg.fr-par.scw.cloud/foxhunt/api_gateway:latest ports: - - containerPort: 50050 + - containerPort: 50051 name: grpc - containerPort: 9091 name: metrics @@ -33,7 +31,7 @@ spec: valueFrom: secretKeyRef: name: foxhunt-secrets - key: DATABASE_PASSWORD + key: db-password - name: DATABASE_URL value: "postgresql://foxhunt:$(DATABASE_PASSWORD)@postgres:5432/foxhunt" - name: REDIS_URL @@ -61,7 +59,7 @@ spec: exec: command: - grpc_health_probe - - -addr=localhost:50050 + - -addr=localhost:50051 initialDelaySeconds: 10 periodSeconds: 10 resources: @@ -84,8 +82,8 @@ spec: selector: app.kubernetes.io/name: api-gateway ports: - - port: 50050 - targetPort: 50050 + - port: 50051 + targetPort: 50051 name: grpc - port: 9091 targetPort: 9091 diff --git a/infra/k8s/services/backtesting-service.yaml b/infra/k8s/services/backtesting-service.yaml index 4cb2d1e74..f6c0c077f 100644 --- a/infra/k8s/services/backtesting-service.yaml +++ b/infra/k8s/services/backtesting-service.yaml @@ -16,8 +16,6 @@ spec: labels: app.kubernetes.io/name: backtesting-service spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: @@ -33,7 +31,7 @@ spec: valueFrom: secretKeyRef: name: foxhunt-secrets - key: DATABASE_PASSWORD + key: db-password - name: DATABASE_URL value: "postgresql://foxhunt:$(DATABASE_PASSWORD)@postgres:5432/foxhunt" - name: REDIS_URL @@ -47,6 +45,8 @@ spec: value: foxhunt-api-gateway - name: JWT_AUDIENCE value: foxhunt-services + - name: BENZINGA_API_KEY + value: "placeholder" - name: RUST_LOG value: info readinessProbe: diff --git a/infra/k8s/services/broker-gateway.yaml b/infra/k8s/services/broker-gateway.yaml index 1a56d03d4..c5bbea331 100644 --- a/infra/k8s/services/broker-gateway.yaml +++ b/infra/k8s/services/broker-gateway.yaml @@ -16,8 +16,6 @@ spec: labels: app.kubernetes.io/name: broker-gateway spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: @@ -33,7 +31,7 @@ spec: valueFrom: secretKeyRef: name: foxhunt-secrets - key: DATABASE_PASSWORD + key: db-password - name: DATABASE_URL value: "postgresql://foxhunt:$(DATABASE_PASSWORD)@postgres:5432/foxhunt" - name: REDIS_URL diff --git a/infra/k8s/services/ml-training-service.yaml b/infra/k8s/services/ml-training-service.yaml index 2ac2e2a3c..b0e78221b 100644 --- a/infra/k8s/services/ml-training-service.yaml +++ b/infra/k8s/services/ml-training-service.yaml @@ -16,8 +16,6 @@ spec: labels: app.kubernetes.io/name: ml-training-service spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: @@ -33,7 +31,7 @@ spec: valueFrom: secretKeyRef: name: foxhunt-secrets - key: DATABASE_PASSWORD + key: db-password - name: DATABASE_URL value: "postgresql://foxhunt:$(DATABASE_PASSWORD)@postgres:5432/foxhunt" - name: REDIS_URL @@ -48,11 +46,16 @@ spec: - name: JWT_AUDIENCE value: foxhunt-services - name: S3_ENDPOINT - value: "https://s3.nl-ams.scw.cloud" + value: "https://s3.fr-par.scw.cloud" - name: S3_BUCKET value: foxhunt-artifacts - name: RUST_LOG value: info + command: ["./ml_training_service", "serve"] + volumeMounts: + - name: tls-certs + mountPath: /app/certs/ml_training_service + readOnly: true readinessProbe: httpGet: path: /health @@ -66,6 +69,10 @@ spec: limits: cpu: 500m memory: 512Mi + volumes: + - name: tls-certs + secret: + secretName: ml-training-tls --- apiVersion: v1 kind: Service diff --git a/infra/k8s/services/trading-agent-service.yaml b/infra/k8s/services/trading-agent-service.yaml index 3d1527009..6a0421a33 100644 --- a/infra/k8s/services/trading-agent-service.yaml +++ b/infra/k8s/services/trading-agent-service.yaml @@ -16,8 +16,6 @@ spec: labels: app.kubernetes.io/name: trading-agent-service spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: @@ -33,7 +31,7 @@ spec: valueFrom: secretKeyRef: name: foxhunt-secrets - key: DATABASE_PASSWORD + key: db-password - name: DATABASE_URL value: "postgresql://foxhunt:$(DATABASE_PASSWORD)@postgres:5432/foxhunt" - name: REDIS_URL diff --git a/infra/k8s/services/trading-service.yaml b/infra/k8s/services/trading-service.yaml index fa0216f91..f8d092ce7 100644 --- a/infra/k8s/services/trading-service.yaml +++ b/infra/k8s/services/trading-service.yaml @@ -16,8 +16,6 @@ spec: labels: app.kubernetes.io/name: trading-service spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: @@ -33,7 +31,7 @@ spec: valueFrom: secretKeyRef: name: foxhunt-secrets - key: DATABASE_PASSWORD + key: db-password - name: DATABASE_URL value: "postgresql://foxhunt:$(DATABASE_PASSWORD)@postgres:5432/foxhunt" - name: REDIS_URL diff --git a/infra/k8s/services/web-gateway.yaml b/infra/k8s/services/web-gateway.yaml index 7b661039e..a12a40698 100644 --- a/infra/k8s/services/web-gateway.yaml +++ b/infra/k8s/services/web-gateway.yaml @@ -16,8 +16,6 @@ spec: labels: app.kubernetes.io/name: web-gateway spec: - nodeSelector: - k8s.scaleway.com/pool-name: always-on imagePullSecrets: - name: scw-registry containers: @@ -48,7 +46,7 @@ spec: value: info readinessProbe: httpGet: - path: /api/health + path: /health port: 3000 initialDelaySeconds: 10 periodSeconds: 10