infra: deploy all services to Kapsule cluster

- 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 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-02-24 17:18:47 +01:00
parent f6fb67a58f
commit 3db5c950c7
9 changed files with 30 additions and 33 deletions

View File

@@ -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<DatabaseConfig> 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<BacktestingDatabaseConfig> 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
},

View File

@@ -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"]

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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