feat(infra): migrate container registry from SCW to internal GitLab

Full migration off Scaleway Container Registry to internal GitLab
registry backed by MinIO S3. All 4 images (ci-builder, ci-builder-cpu,
foxhunt-runtime, foxhunt-training-runtime) rebuilt in internal registry.

Registry & images:
- All image refs → gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/
- imagePullSecrets: scw-registry → gitlab-registry
- Kaniko build template: two-step DAG (git-clone → kaniko-build) with shared PVC
- Kaniko layer cache enabled at root/foxhunt/cache
- AWS_ACCESS_KEY_ID: $SCW_ACCESS_KEY → $MINIO_ACCESS_KEY in .gitlab-ci.yml

Network policies:
- ci-pipeline: add HTTP/80, registry/5000, webservice/8181 egress rules

DNS & Tailscale proxy cleanup:
- Remove ci, prometheus, monitor DNS records (no longer exposed)
- Rename s3 → minio DNS record
- Remove Argo UI, Prometheus, monitor nginx server blocks
- Remove argo-htpasswd volume mount
- Tailscale proxy nodeSelector: infra → platform

Terraform cleanup:
- Delete infra/modules/registry/ (SCW CR namespace)
- Delete infra/modules/object-storage/ (SCW S3 buckets)
- Delete infra/modules/secrets/ (SCW secrets)
- Delete corresponding live configs
- TF state backend: S3 → GitLab HTTP

Argo workflows:
- Add events/ (GitLab push eventsource + ci-pipeline sensor)
- ci-pipeline + training templates: SCW → internal registry
- Delete obsolete compile-training-template.yaml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-05 13:52:24 +01:00
parent 32e7ba2507
commit 68b6aa8313
62 changed files with 504 additions and 931 deletions

View File

@@ -2,7 +2,7 @@
# Built by CI, pushed to GitLab registry as devcontainer:latest # Built by CI, pushed to GitLab registry as devcontainer:latest
# See: docs/plans/2026-02-25-devcontainer-design.md # See: docs/plans/2026-02-25-devcontainer-design.md
ARG CI_BUILDER_IMAGE=rg.fr-par.scw.cloud/foxhunt-ci/ci-builder:latest ARG CI_BUILDER_IMAGE=gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder:latest
FROM ${CI_BUILDER_IMAGE} FROM ${CI_BUILDER_IMAGE}
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive

View File

@@ -4,7 +4,7 @@
"dockerfile": "Dockerfile", "dockerfile": "Dockerfile",
"context": "..", "context": "..",
"args": { "args": {
"CI_BUILDER_IMAGE": "rg.fr-par.scw.cloud/foxhunt-ci/ci-builder:latest" "CI_BUILDER_IMAGE": "gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder:latest"
} }
}, },
"remoteUser": "dev", "remoteUser": "dev",

View File

@@ -13,16 +13,18 @@
# Pools: ci-compile-cpu (POP2-32C-128G), ci-training (L40S), ci-training-h100 (H100), services, gitlab # Pools: ci-compile-cpu (POP2-32C-128G), ci-training (L40S), ci-training-h100 (H100), services, gitlab
# All compilation (services + training) runs on ci-compile-cpu. CUDA stubs in ci-builder image. # All compilation (services + training) runs on ci-compile-cpu. CUDA stubs in ci-builder image.
# Ensure pipeline is always created — individual job rules handle filtering. # DISABLED 2026-03-04: Migrated to Argo Workflows (infra/k8s/argo/).
# Without this, GitLab CE may silently drop push pipelines when changes: # GitLab still serves as git host; Argo Events webhook triggers pipelines.
# evaluation fails to match (known issue with path glob evaluation). # To re-enable: remove the "when: never" rule below and restore the original rules.
workflow: workflow:
rules: rules:
- if: $CI_PIPELINE_SOURCE == "push" - when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Original rules (disabled):
- if: $CI_PIPELINE_SOURCE == "schedule" # - if: $CI_PIPELINE_SOURCE == "push"
- if: $CI_PIPELINE_SOURCE == "api" # - if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "web" # - if: $CI_PIPELINE_SOURCE == "schedule"
# - if: $CI_PIPELINE_SOURCE == "api"
# - if: $CI_PIPELINE_SOURCE == "web"
stages: stages:
- prepare - prepare
@@ -41,26 +43,31 @@ variables:
JWT_SECRET: "CiTestSecret_Kx7mP9nR2sW5vY8bC3fG6jH1kL4pQ7tZ0uN9dM5eV8xS2wT6yA4zB_64chars_min" JWT_SECRET: "CiTestSecret_Kx7mP9nR2sW5vY8bC3fG6jH1kL4pQ7tZ0uN9dM5eV8xS2wT6yA4zB_64chars_min"
# Training data on block storage PVC (mounted at /mnt/training-data by runner) # Training data on block storage PVC (mounted at /mnt/training-data by runner)
FOXHUNT_DATA_DIR: "/mnt/training-data/futures-baseline" FOXHUNT_DATA_DIR: "/mnt/training-data/futures-baseline"
# sccache base dir on PVC — GPU stages override to /mnt/sccache/sm_<cap> # sccache backed by MinIO S3 — shared across all nodes (no PVC needed)
SCCACHE_DIR: "/mnt/sccache" SCCACHE_BUCKET: foxhunt-sccache
SCCACHE_ENDPOINT: https://minio.foxhunt.svc.cluster.local:9000/
SCCACHE_S3_KEY_PREFIX: cpu
SCCACHE_S3_USE_SSL: "true"
SCCACHE_S3_NO_CREDENTIALS: ""
SCCACHE_NO_CERT_VERIFICATION: "true"
RUSTC_WRAPPER: /usr/local/bin/sccache RUSTC_WRAPPER: /usr/local/bin/sccache
# Build profile: "dev-release" (thin LTO, fast) is default for quick iteration # Build profile: "dev-release" (thin LTO, fast) is default for quick iteration
# Set DEV_RELEASE=false in pipeline vars to use full "release" (fat LTO) profile # Set DEV_RELEASE=false in pipeline vars to use full "release" (fat LTO) profile
DEV_RELEASE: "true" DEV_RELEASE: "true"
CARGO_BUILD_PROFILE: dev-release CARGO_BUILD_PROFILE: dev-release
# S3 credentials for Kaniko registry auth and Dockerfile builds # S3 credentials for sccache MinIO backend (also used by rclone binary uploads)
AWS_ACCESS_KEY_ID: $SCW_ACCESS_KEY AWS_ACCESS_KEY_ID: $MINIO_ACCESS_KEY
AWS_SECRET_ACCESS_KEY: $SCW_SECRET_KEY AWS_SECRET_ACCESS_KEY: $MINIO_SECRET_KEY
# CI builder image on Scaleway Container Registry (reachable by Kapsule nodes) # CI builder images on internal GitLab registry (backed by MinIO)
CI_BUILDER_IMAGE: rg.fr-par.scw.cloud/foxhunt-ci/ci-builder:latest CI_BUILDER_IMAGE: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder:latest
CI_BUILDER_CPU_IMAGE: rg.fr-par.scw.cloud/foxhunt-ci/ci-builder-cpu:latest CI_BUILDER_CPU_IMAGE: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder-cpu:latest
# Scaleway Container Registry for service images # Container registry for all images
REGISTRY: rg.fr-par.scw.cloud/foxhunt-ci REGISTRY: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt
# IaC runner image on Scaleway Container Registry # Infrastructure runner image
INFRA_RUNNER_IMAGE: rg.fr-par.scw.cloud/foxhunt-ci/infra-runner:latest INFRA_RUNNER_IMAGE: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/infra-runner:latest
# Generic runtime images for S3 binary share (service pods + training pods + node builder) # Generic runtime images for S3 binary share (service pods + training pods + node builder)
RUNTIME_IMAGE: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest RUNTIME_IMAGE: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
TRAINING_RUNTIME_IMAGE: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-training-runtime:latest TRAINING_RUNTIME_IMAGE: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-training-runtime:latest
# Node builder image eliminated — web dashboard uses node:22-slim + inline rclone # Node builder image eliminated — web dashboard uses node:22-slim + inline rclone
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@@ -157,8 +164,8 @@ build-devcontainer:
--context "${CI_PROJECT_DIR}" --context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/.devcontainer/Dockerfile" --dockerfile "${CI_PROJECT_DIR}/.devcontainer/Dockerfile"
--cache=true --cache-repo="${REGISTRY}/cache" --cache=true --cache-repo="${REGISTRY}/cache"
--destination "rg.fr-par.scw.cloud/foxhunt-ci/devcontainer:${CI_COMMIT_SHA}" --destination "gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/devcontainer:${CI_COMMIT_SHA}"
--destination "rg.fr-par.scw.cloud/foxhunt-ci/devcontainer:latest" --destination "gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/devcontainer:latest"
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Stage 0c: Build infra-runner image → push to Scaleway CR # Stage 0c: Build infra-runner image → push to Scaleway CR
@@ -374,7 +381,7 @@ scan-runtime-images:
KUBERNETES_MEMORY_REQUEST: "8Gi" KUBERNETES_MEMORY_REQUEST: "8Gi"
KUBERNETES_MEMORY_LIMIT: "16Gi" KUBERNETES_MEMORY_LIMIT: "16Gi"
script: script:
- mkdir -p "$SCCACHE_DIR" && sccache --zero-stats || true - sccache --zero-stats || true
- PROFILE=${DEV_RELEASE:+dev-release}; PROFILE=${PROFILE:-release} - PROFILE=${DEV_RELEASE:+dev-release}; PROFILE=${PROFILE:-release}
- | - |
# CalVer: YYYY.MM.<pipeline_iid> # CalVer: YYYY.MM.<pipeline_iid>
@@ -429,8 +436,7 @@ test:
else else
echo "No nvidia-smi — using CUDA stubs, CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP" echo "No nvidia-smi — using CUDA stubs, CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP"
fi fi
- export SCCACHE_DIR="/mnt/sccache/sm_${CUDA_COMPUTE_CAP}" - export SCCACHE_S3_KEY_PREFIX="cuda/sm_${CUDA_COMPUTE_CAP}"
- mkdir -p "$SCCACHE_DIR"
# Wait for Redis sidecar (K8s executor doesn't wait for service readiness) # Wait for Redis sidecar (K8s executor doesn't wait for service readiness)
- | - |
for i in $(seq 1 30); do for i in $(seq 1 30); do
@@ -605,8 +611,8 @@ compile-training:
- if: $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api" - if: $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api"
script: script:
- echo "CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP" - echo "CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP"
- export SCCACHE_DIR="/mnt/sccache/sm_${CUDA_COMPUTE_CAP}" - export SCCACHE_S3_KEY_PREFIX="cuda/sm_${CUDA_COMPUTE_CAP}"
- mkdir -p "$SCCACHE_DIR" && sccache --zero-stats || true - sccache --zero-stats || true
- PROFILE=${DEV_RELEASE:+dev-release}; PROFILE=${PROFILE:-release} - PROFILE=${DEV_RELEASE:+dev-release}; PROFILE=${PROFILE:-release}
- | - |
# CalVer: YYYY.MM.<pipeline_iid> # CalVer: YYYY.MM.<pipeline_iid>

View File

@@ -12,6 +12,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
git \ git \
curl \ curl \
ca-certificates \ ca-certificates \
openssh-client \
pkg-config \ pkg-config \
libssl-dev \ libssl-dev \
lld \ lld \

View File

@@ -2,8 +2,8 @@
# ~2-3GB vs ~8GB for the CUDA devel variant (Dockerfile.ci-builder) # ~2-3GB vs ~8GB for the CUDA devel variant (Dockerfile.ci-builder)
# Contains: Rust 1.89, protoc, sccache, git, OpenSSL, clang, mold, lld, make # Contains: Rust 1.89, protoc, sccache, git, OpenSSL, clang, mold, lld, make
# Build: docker build -f infra/docker/Dockerfile.ci-builder-cpu -t foxhunt-ci-builder-cpu . # Build: docker build -f infra/docker/Dockerfile.ci-builder-cpu -t foxhunt-ci-builder-cpu .
# Push: docker tag foxhunt-ci-builder-cpu rg.fr-par.scw.cloud/foxhunt-ci/ci-builder-cpu:latest # Push: docker tag foxhunt-ci-builder-cpu gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder-cpu:latest
# docker push rg.fr-par.scw.cloud/foxhunt-ci/ci-builder-cpu:latest # docker push gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder-cpu:latest
FROM rust:1.89-slim-bookworm FROM rust:1.89-slim-bookworm
@@ -11,6 +11,7 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
git \ git \
openssh-client \
curl \ curl \
ca-certificates \ ca-certificates \
pkg-config \ pkg-config \

View File

@@ -39,3 +39,131 @@ spec:
- podSelector: - podSelector:
matchLabels: matchLabels:
app.kubernetes.io/name: tempo app.kubernetes.io/name: tempo
---
# Compile workflow pods: need GitLab SSH, MinIO, k8s API, external HTTPS (cargo deps)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: argo-compile-workflow
namespace: foxhunt
labels:
app.kubernetes.io/part-of: foxhunt
spec:
podSelector:
matchLabels:
app.kubernetes.io/component: compile
policyTypes:
- Egress
egress:
# DNS — resolve external hostnames (crates.io, github.com)
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Kubernetes API — Argo executor
- ports:
- port: 443
protocol: TCP
- port: 6443
protocol: TCP
to:
- ipBlock:
cidr: 10.32.0.0/16
- ipBlock:
cidr: 172.16.0.4/32
# External HTTPS — cargo fetches crates.io, github.com (candle git dep)
- ports:
- port: 443
protocol: TCP
# GitLab SSH — git clone (Tailscale IP + cluster service)
- ports:
- port: 2222
protocol: TCP
to:
- ipBlock:
cidr: 100.90.76.85/32
- podSelector:
matchLabels:
app: gitlab-shell
# MinIO — binary upload
- ports:
- port: 9000
protocol: TCP
to:
- podSelector:
matchLabels:
app.kubernetes.io/name: minio
---
# CI pipeline pods (detect-changes + compile-service inline templates)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: argo-ci-pipeline
namespace: foxhunt
labels:
app.kubernetes.io/part-of: foxhunt
spec:
podSelector:
matchLabels:
app.kubernetes.io/component: ci-pipeline
policyTypes:
- Egress
egress:
# DNS — resolve external hostnames
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Kubernetes API — Argo executor
- ports:
- port: 443
protocol: TCP
- port: 6443
protocol: TCP
to:
- ipBlock:
cidr: 10.32.0.0/16
- ipBlock:
cidr: 172.16.0.4/32
# External HTTP/HTTPS — Kaniko base image pulls, apt-get, cargo fetches
- ports:
- port: 80
protocol: TCP
- port: 443
protocol: TCP
# GitLab SSH — git clone (compile-service uses ssh://git@git.fxhnt.ai)
- ports:
- port: 2222
protocol: TCP
to:
- ipBlock:
cidr: 100.90.76.85/32
- podSelector:
matchLabels:
app: gitlab-shell
# MinIO — binary upload from compile-service
- ports:
- port: 9000
protocol: TCP
to:
- podSelector:
matchLabels:
app.kubernetes.io/name: minio
# GitLab registry — Kaniko image push
- ports:
- port: 5000
protocol: TCP
to:
- podSelector:
matchLabels:
app: registry
# GitLab webservice — JWT auth for registry tokens
- ports:
- port: 8181
protocol: TCP
to:
- podSelector:
matchLabels:
app: webservice

View File

@@ -31,11 +31,21 @@ spec:
defaultMode: 256 defaultMode: 256
- name: registry-auth - name: registry-auth
secret: secret:
secretName: scw-registry secretName: gitlab-registry
optional: true
items: items:
- key: .dockerconfigjson - key: .dockerconfigjson
path: config.json path: config.json
volumeClaimTemplates:
- metadata:
name: workspace
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: scw-bssd
resources:
requests:
storage: 5Gi
templates: templates:
- name: build - name: build
inputs: inputs:
@@ -48,18 +58,24 @@ spec:
value: "{{workflow.parameters.image-name}}" value: "{{workflow.parameters.image-name}}"
dag: dag:
tasks: tasks:
- name: kaniko-build - name: git-clone
template: kaniko-build template: git-clone
arguments: arguments:
parameters: parameters:
- name: commit-sha - name: commit-sha
value: "{{inputs.parameters.commit-sha}}" value: "{{inputs.parameters.commit-sha}}"
- name: kaniko-build
template: kaniko-build
dependencies: [git-clone]
arguments:
parameters:
- name: dockerfile - name: dockerfile
value: "{{inputs.parameters.dockerfile}}" value: "{{inputs.parameters.dockerfile}}"
- name: image-name - name: image-name
value: "{{inputs.parameters.image-name}}" value: "{{inputs.parameters.image-name}}"
- name: kaniko-build # ── git-clone: fetch source code into shared PVC ──
- name: git-clone
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: ci-compile-cpu k8s.scaleway.com/pool-name: ci-compile-cpu
tolerations: tolerations:
@@ -69,6 +85,53 @@ spec:
inputs: inputs:
parameters: parameters:
- name: commit-sha - name: commit-sha
container:
image: alpine/git:latest
command: ["/bin/sh", "-c"]
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: "1"
memory: 512Mi
volumeMounts:
- name: git-ssh-key
mountPath: /etc/git-ssh
readOnly: true
- name: workspace
mountPath: /workspace
args:
- |
set -e
mkdir -p ~/.ssh
cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > ~/.ssh/config
chmod 600 ~/.ssh/config
SHA="{{inputs.parameters.commit-sha}}"
REPO="ssh://git@gitlab-gitlab-shell.foxhunt.svc.cluster.local:2222/root/foxhunt.git"
if [ "$SHA" = "HEAD" ]; then
git clone --depth=1 "$REPO" /workspace/src
else
git clone --depth=1 "$REPO" /workspace/src
cd /workspace/src
git fetch --depth=1 origin "$SHA"
git checkout "$SHA"
fi
echo "Checked out $(cd /workspace/src && git rev-parse --short HEAD)"
# ── kaniko-build: build and push image from cloned source ──
- name: kaniko-build
nodeSelector:
k8s.scaleway.com/pool-name: ci-compile-cpu
tolerations:
- key: node.cilium.io/agent-not-ready
operator: Exists
effect: NoSchedule
inputs:
parameters:
- name: dockerfile - name: dockerfile
- name: image-name - name: image-name
container: container:
@@ -85,29 +148,19 @@ spec:
cpu: "8" cpu: "8"
memory: 16Gi memory: 16Gi
volumeMounts: volumeMounts:
- name: git-ssh-key
mountPath: /etc/git-ssh
readOnly: true
- name: registry-auth - name: registry-auth
mountPath: /kaniko/.docker mountPath: /kaniko/.docker
readOnly: true readOnly: true
- name: workspace
mountPath: /workspace
args: args:
- | - |
mkdir -p ~/.ssh
cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
echo -e "Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null" > ~/.ssh/config
SHA="{{inputs.parameters.commit-sha}}"
git clone --depth=1 ssh://git@gitlab-gitlab-shell.foxhunt.svc.cluster.local:2222/root/foxhunt.git /workspace/src
if [ "$SHA" != "HEAD" ]; then
cd /workspace/src && git fetch --depth=1 origin "$SHA" && git checkout "$SHA"
fi
/kaniko/executor \ /kaniko/executor \
--context=/workspace/src \ --context=/workspace/src \
--dockerfile=/workspace/src/infra/docker/{{inputs.parameters.dockerfile}} \ --dockerfile=/workspace/src/infra/docker/{{inputs.parameters.dockerfile}} \
--destination=rg.fr-par.scw.cloud/foxhunt-ci/{{inputs.parameters.image-name}}:latest \ --destination=gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/{{inputs.parameters.image-name}}:latest \
--insecure-registry=gitlab-registry.foxhunt.svc.cluster.local:5000 \
--skip-tls-verify-registry=gitlab-registry.foxhunt.svc.cluster.local:5000 \
--cache=true \ --cache=true \
--cache-repo=rg.fr-par.scw.cloud/foxhunt-ci/cache \ --cache-repo=gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/cache \
--snapshot-mode=redo --snapshot-mode=redo

View File

@@ -23,11 +23,14 @@ spec:
defaultMode: 256 defaultMode: 256
- name: registry-auth - name: registry-auth
secret: secret:
secretName: scw-registry secretName: gitlab-registry
optional: true optional: true
items: items:
- key: .dockerconfigjson - key: .dockerconfigjson
path: config.json path: config.json
- name: minio-ca-cert
configMap:
name: minio-ca-cert
arguments: arguments:
parameters: parameters:
- name: commit-sha - name: commit-sha
@@ -45,7 +48,7 @@ spec:
template: detect-changes template: detect-changes
# Parallel: each compile step is self-contained (own git clone) # Parallel: each compile step is self-contained (own git clone)
# No shared PVC between nodes — sccache-pvc stays on platform only # sccache backed by MinIO — no PVC needed, shared across all nodes
- name: compile-services - name: compile-services
dependencies: [detect-changes] dependencies: [detect-changes]
template: compile-services template: compile-services
@@ -121,7 +124,7 @@ spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: platform
container: container:
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
env: env:
- name: COMMITS_JSON - name: COMMITS_JSON
@@ -212,17 +215,40 @@ spec:
path: /tmp/outputs/docker-images path: /tmp/outputs/docker-images
# ── compile-services: CPU-only, runs on platform (no CUDA needed) ── # ── compile-services: CPU-only, runs on platform (no CUDA needed) ──
# sccache backed by MinIO (s3://foxhunt-sccache/cpu/) — shared across nodes
- name: compile-services - name: compile-services
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: platform
container: container:
image: rg.fr-par.scw.cloud/foxhunt-ci/ci-builder-cpu:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder-cpu:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
env: env:
- name: SQLX_OFFLINE - name: SQLX_OFFLINE
value: "true" value: "true"
- name: CARGO_TERM_COLOR - name: CARGO_TERM_COLOR
value: always value: always
- name: SCCACHE_BUCKET
value: foxhunt-sccache
- name: SCCACHE_ENDPOINT
value: https://minio.foxhunt.svc.cluster.local:9000/
- name: SCCACHE_REGION
value: us-east-1
- name: SCCACHE_S3_KEY_PREFIX
value: cpu
- name: SCCACHE_S3_USE_SSL
value: "true"
- name: SCCACHE_S3_NO_CREDENTIALS
value: "false"
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: minio-credentials
key: access-key
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: minio-credentials
key: secret-key
- name: MINIO_ACCESS_KEY - name: MINIO_ACCESS_KEY
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
@@ -241,17 +267,21 @@ spec:
cpu: "3800m" cpu: "3800m"
memory: 6Gi memory: 6Gi
volumeMounts: volumeMounts:
- name: sccache
mountPath: /mnt/sccache
- name: git-ssh-key - name: git-ssh-key
mountPath: /etc/git-ssh mountPath: /etc/git-ssh
readOnly: true readOnly: true
- name: minio-ca-cert
mountPath: /etc/ssl/minio-ca
readOnly: true
args: args:
- | - |
set -e set -e
# Trust MinIO self-signed CA
cat /etc/ssl/minio-ca/ca.crt >> /etc/ssl/certs/ca-certificates.crt
SHA="{{workflow.parameters.commit-sha}}" SHA="{{workflow.parameters.commit-sha}}"
# Git clone (self-contained — no shared checkout step) # Git clone (self-contained)
mkdir -p ~/.ssh mkdir -p ~/.ssh
cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519 cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519
@@ -259,47 +289,45 @@ spec:
chmod 600 ~/.ssh/config chmod 600 ~/.ssh/config
REPO="ssh://git@gitlab-gitlab-shell.foxhunt.svc.cluster.local:2222/root/foxhunt.git" REPO="ssh://git@gitlab-gitlab-shell.foxhunt.svc.cluster.local:2222/root/foxhunt.git"
rm -rf /mnt/sccache/workspace WORKSPACE="/tmp/workspace"
if [ "$SHA" = "HEAD" ]; then if [ "$SHA" = "HEAD" ]; then
git clone --depth=1 "$REPO" /mnt/sccache/workspace git clone --depth=1 "$REPO" "$WORKSPACE"
else else
git clone --depth=1 "$REPO" /mnt/sccache/workspace git clone --depth=1 "$REPO" "$WORKSPACE"
cd /mnt/sccache/workspace cd "$WORKSPACE"
git fetch --depth=1 origin "$SHA" git fetch --depth=1 origin "$SHA"
git checkout "$SHA" git checkout "$SHA"
fi fi
cd /mnt/sccache/workspace cd "$WORKSPACE"
echo "Checked out $(git rev-parse --short HEAD)" echo "Checked out $(git rev-parse --short HEAD)"
YEAR=$(date +%Y) YEAR=$(date +%Y)
MONTH=$(date +%m) MONTH=$(date +%m)
export FOXHUNT_BUILD_VERSION="${YEAR}.${MONTH}.argo" export FOXHUNT_BUILD_VERSION="${YEAR}.${MONTH}.argo"
export RUSTC_WRAPPER=sccache export RUSTC_WRAPPER=sccache
export SCCACHE_DIR="/mnt/sccache/cpu"
mkdir -p "$SCCACHE_DIR"
sccache --zero-stats || true sccache --zero-stats || true
echo "=== Building service binaries (platform node, sccache) ===" echo "=== Building service binaries (sccache → MinIO s3://foxhunt-sccache/cpu/) ==="
cargo build --release \ cargo build --release \
-p api -p trading-service -p ml-training-service \ -p api -p trading-service -p ml-training-service \
-p backtesting-service -p trading-agent-service \ -p backtesting-service -p trading-agent-service \
-p broker-gateway -p data-acquisition-service -p broker-gateway -p data-acquisition-service
mkdir -p /mnt/sccache/workspace/bin/services mkdir -p "$WORKSPACE/bin/services"
for pkg in api trading-service ml-training-service backtesting-service trading-agent-service broker-gateway data-acquisition-service; do for pkg in api trading-service ml-training-service backtesting-service trading-agent-service broker-gateway data-acquisition-service; do
bin_name=$(echo "$pkg" | tr '-' '_') bin_name=$(echo "$pkg" | tr '-' '_')
cp "target/release/$pkg" "/mnt/sccache/workspace/bin/services/" 2>/dev/null \ cp "target/release/$pkg" "$WORKSPACE/bin/services/" 2>/dev/null \
|| cp "target/release/$bin_name" "/mnt/sccache/workspace/bin/services/" 2>/dev/null \ || cp "target/release/$bin_name" "$WORKSPACE/bin/services/" 2>/dev/null \
|| { echo "Binary not found for $pkg"; ls target/release/; exit 1; } || { echo "Binary not found for $pkg"; ls target/release/; exit 1; }
done done
strip /mnt/sccache/workspace/bin/services/* strip "$WORKSPACE/bin/services/"*
echo "=== Service binaries ===" echo "=== Service binaries ==="
ls -lh /mnt/sccache/workspace/bin/services/ ls -lh "$WORKSPACE/bin/services/"
sccache --show-stats || true sccache --show-stats || true
echo "=== Uploading service binaries ===" echo "=== Uploading service binaries ==="
rclone copy /mnt/sccache/workspace/bin/services/ :s3:foxhunt-binaries/services/ \ rclone copy "$WORKSPACE/bin/services/" :s3:foxhunt-binaries/services/ \
--s3-provider=Minio \ --s3-provider=Minio \
--s3-endpoint=https://minio.foxhunt.svc.cluster.local:9000 \ --s3-endpoint=https://minio.foxhunt.svc.cluster.local:9000 \
--s3-access-key-id="${MINIO_ACCESS_KEY}" \ --s3-access-key-id="${MINIO_ACCESS_KEY}" \
@@ -310,6 +338,7 @@ spec:
echo "=== Service compile + upload done ===" echo "=== Service compile + upload done ==="
# ── compile-training: CUDA build, needs POP2 for speed ── # ── compile-training: CUDA build, needs POP2 for speed ──
# sccache backed by MinIO (s3://foxhunt-sccache/cuda/sm_XX/) — persists across ephemeral nodes
- name: compile-training - name: compile-training
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: ci-compile-cpu k8s.scaleway.com/pool-name: ci-compile-cpu
@@ -318,13 +347,33 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
container: container:
image: rg.fr-par.scw.cloud/foxhunt-ci/ci-builder:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/ci-builder:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
env: env:
- name: SQLX_OFFLINE - name: SQLX_OFFLINE
value: "true" value: "true"
- name: CARGO_TERM_COLOR - name: CARGO_TERM_COLOR
value: always value: always
- name: SCCACHE_BUCKET
value: foxhunt-sccache
- name: SCCACHE_ENDPOINT
value: https://minio.foxhunt.svc.cluster.local:9000/
- name: SCCACHE_REGION
value: us-east-1
- name: SCCACHE_S3_USE_SSL
value: "true"
- name: SCCACHE_S3_NO_CREDENTIALS
value: "false"
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: minio-credentials
key: access-key
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: minio-credentials
key: secret-key
- name: MINIO_ACCESS_KEY - name: MINIO_ACCESS_KEY
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
@@ -346,12 +395,18 @@ spec:
- name: git-ssh-key - name: git-ssh-key
mountPath: /etc/git-ssh mountPath: /etc/git-ssh
readOnly: true readOnly: true
- name: minio-ca-cert
mountPath: /etc/ssl/minio-ca
readOnly: true
args: args:
- | - |
set -e set -e
# Trust MinIO self-signed CA
cat /etc/ssl/minio-ca/ca.crt >> /etc/ssl/certs/ca-certificates.crt
SHA="{{workflow.parameters.commit-sha}}" SHA="{{workflow.parameters.commit-sha}}"
# Git clone (self-contained — no shared PVC, ephemeral node) # Git clone (self-contained — ephemeral node)
mkdir -p ~/.ssh mkdir -p ~/.ssh
cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519 cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519
@@ -376,11 +431,10 @@ spec:
export FOXHUNT_BUILD_VERSION="${YEAR}.${MONTH}.argo" export FOXHUNT_BUILD_VERSION="${YEAR}.${MONTH}.argo"
export RUSTC_WRAPPER=sccache export RUSTC_WRAPPER=sccache
export CUDA_COMPUTE_CAP={{workflow.parameters.cuda-compute-cap}} export CUDA_COMPUTE_CAP={{workflow.parameters.cuda-compute-cap}}
export SCCACHE_DIR="/tmp/sccache/sm_${CUDA_COMPUTE_CAP}" export SCCACHE_S3_KEY_PREFIX="cuda/sm_${CUDA_COMPUTE_CAP}"
mkdir -p "$SCCACHE_DIR"
sccache --zero-stats || true sccache --zero-stats || true
echo "=== Building training binaries (CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP) ===" echo "=== Building training binaries (CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP, sccache → MinIO) ==="
cargo build --release -p ml --features ml/cuda \ cargo build --release -p ml --features ml/cuda \
--example train_baseline_rl --example train_baseline_supervised \ --example train_baseline_rl --example train_baseline_supervised \
--example evaluate_baseline --example evaluate_supervised \ --example evaluate_baseline --example evaluate_supervised \

View File

@@ -1,238 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: compile-training
namespace: foxhunt
labels:
app.kubernetes.io/name: compile-training
app.kubernetes.io/part-of: foxhunt
spec:
activeDeadlineSeconds: 3600
serviceAccountName: argo-workflow
entrypoint: compile
podMetadata:
labels:
app.kubernetes.io/component: compile
app.kubernetes.io/part-of: foxhunt
ttlStrategy:
secondsAfterCompletion: 3600
arguments:
parameters:
- name: commit-sha
value: HEAD
- name: cuda-compute-cap
value: "89"
volumeClaimTemplates:
- metadata:
name: workspace
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 20Gi
storageClassName: scw-bssd
volumes:
- name: sccache
persistentVolumeClaim:
claimName: sccache-pvc
- name: git-ssh-key
secret:
secretName: argo-git-ssh-key
defaultMode: 256
templates:
- name: compile
inputs:
parameters:
- name: commit-sha
value: "{{workflow.parameters.commit-sha}}"
- name: cuda-compute-cap
value: "{{workflow.parameters.cuda-compute-cap}}"
dag:
tasks:
- name: checkout
template: git-checkout
arguments:
parameters:
- name: commit-sha
value: "{{inputs.parameters.commit-sha}}"
- name: build
dependencies: [checkout]
template: build-training
arguments:
parameters:
- name: cuda-compute-cap
value: "{{inputs.parameters.cuda-compute-cap}}"
- name: upload
dependencies: [build]
template: upload-binaries
- name: git-checkout
nodeSelector:
k8s.scaleway.com/pool-name: ci-compile-cpu
tolerations:
- key: node.cilium.io/agent-not-ready
operator: Exists
effect: NoSchedule
inputs:
parameters:
- name: commit-sha
container:
image: rg.fr-par.scw.cloud/foxhunt-ci/ci-builder:latest
command: ["/bin/sh", "-c"]
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
volumeMounts:
- name: workspace
mountPath: /workspace
- name: git-ssh-key
mountPath: /etc/git-ssh
readOnly: true
args:
- |
set -e
mkdir -p ~/.ssh
cp /etc/git-ssh/ssh-privatekey ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > ~/.ssh/config
chmod 600 ~/.ssh/config
REPO="ssh://git@gitlab-gitlab-shell.foxhunt.svc.cluster.local:2222/root/foxhunt.git"
SHA="{{inputs.parameters.commit-sha}}"
echo "Cloning foxhunt at ${SHA}..."
if [ "$SHA" = "HEAD" ]; then
git clone --depth=1 "$REPO" /workspace/src
else
git clone "$REPO" /workspace/src
cd /workspace/src
git checkout "$SHA"
fi
cd /workspace/src
echo "Checked out $(git rev-parse --short HEAD)"
- name: build-training
nodeSelector:
k8s.scaleway.com/pool-name: ci-compile-cpu
tolerations:
- key: node.cilium.io/agent-not-ready
operator: Exists
effect: NoSchedule
inputs:
parameters:
- name: cuda-compute-cap
container:
image: rg.fr-par.scw.cloud/foxhunt-ci/ci-builder:latest
command: ["/bin/sh", "-c"]
env:
- name: SQLX_OFFLINE
value: "true"
- name: CARGO_TERM_COLOR
value: always
resources:
requests:
cpu: "14"
memory: 32Gi
limits:
cpu: "30"
memory: 64Gi
volumeMounts:
- name: workspace
mountPath: /workspace
- name: sccache
mountPath: /mnt/sccache
args:
- |
set -e
cd /workspace/src
export CUDA_COMPUTE_CAP={{inputs.parameters.cuda-compute-cap}}
export SCCACHE_DIR="/mnt/sccache/sm_${CUDA_COMPUTE_CAP}"
export RUSTC_WRAPPER=sccache
mkdir -p "$SCCACHE_DIR"
sccache --zero-stats || true
YEAR=$(date +%Y)
MONTH=$(date +%m)
export FOXHUNT_BUILD_VERSION="${YEAR}.${MONTH}.argo"
echo "=== Compiling training binaries (CUDA_COMPUTE_CAP=$CUDA_COMPUTE_CAP) ==="
cargo build --release -p ml --features ml/cuda \
--example train_baseline_rl \
--example train_baseline_supervised \
--example evaluate_baseline \
--example evaluate_supervised \
--example hyperopt_baseline_rl \
--example hyperopt_baseline_supervised
cargo build --release -p training_uploader
sccache --show-stats || true
echo "=== Copying and stripping binaries ==="
mkdir -p /workspace/bin
for bin in train_baseline_rl train_baseline_supervised evaluate_baseline evaluate_supervised hyperopt_baseline_rl hyperopt_baseline_supervised; do
cp target/release/examples/$bin /workspace/bin/
strip /workspace/bin/$bin
done
cp target/release/training_uploader /workspace/bin/
strip /workspace/bin/training_uploader
echo "=== Build complete ==="
ls -lh /workspace/bin/
- name: upload-binaries
nodeSelector:
k8s.scaleway.com/pool-name: platform
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
container:
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest
command: ["/bin/sh", "-c"]
env:
- name: MINIO_ACCESS_KEY
valueFrom:
secretKeyRef:
name: minio-credentials
key: access-key
- name: MINIO_SECRET_KEY
valueFrom:
secretKeyRef:
name: minio-credentials
key: secret-key
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
volumeMounts:
- name: workspace
mountPath: /workspace
args:
- |
set -e
echo "Uploading training binaries to MinIO..."
rclone copy /workspace/bin/ :s3:foxhunt-binaries/training/ \
--s3-provider=Minio \
--s3-endpoint=https://minio.foxhunt.svc.cluster.local:9000 \
--s3-access-key-id="${MINIO_ACCESS_KEY}" \
--s3-secret-access-key="${MINIO_SECRET_KEY}" \
--s3-no-check-bucket \
--no-check-certificate
echo "=== Uploaded binaries ==="
rclone ls :s3:foxhunt-binaries/training/ \
--s3-provider=Minio \
--s3-endpoint=https://minio.foxhunt.svc.cluster.local:9000 \
--s3-access-key-id="${MINIO_ACCESS_KEY}" \
--s3-secret-access-key="${MINIO_SECRET_KEY}" \
--s3-no-check-bucket \
--no-check-certificate

View File

@@ -0,0 +1,52 @@
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
name: ci-pipeline-trigger
namespace: foxhunt
labels:
app.kubernetes.io/name: ci-pipeline-trigger
app.kubernetes.io/part-of: foxhunt
spec:
template:
serviceAccountName: argo-workflow
eventBusName: default
dependencies:
- name: gitlab-push-dep
eventSourceName: gitlab-push
eventName: gitlab-push
filters:
data:
- path: body.ref
type: string
value:
- "refs/heads/main"
triggers:
- template:
name: ci-pipeline
argoWorkflow:
operation: submit
source:
resource:
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: ci-pipeline-
namespace: foxhunt
spec:
serviceAccountName: argo-workflow
workflowTemplateRef:
name: ci-pipeline
arguments:
parameters:
- name: commit-sha
- name: commits-json
parameters:
- src:
dependencyName: gitlab-push-dep
dataKey: body.checkout_sha
dest: spec.arguments.parameters.0.value
- src:
dependencyName: gitlab-push-dep
dataKey: body.commits
dataTemplate: "{{ toJson .Input }}"
dest: spec.arguments.parameters.1.value

View File

@@ -0,0 +1,10 @@
apiVersion: argoproj.io/v1alpha1
kind: EventBus
metadata:
name: default
namespace: foxhunt
spec:
nats:
native:
replicas: 3
auth: token

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: gitlab-push-eventsource-svc
namespace: foxhunt
labels:
app.kubernetes.io/name: gitlab-push-eventsource
app.kubernetes.io/part-of: foxhunt
spec:
type: ClusterIP
ports:
- port: 12000
targetPort: 12000
protocol: TCP
selector:
eventsource-name: gitlab-push

View File

@@ -0,0 +1,15 @@
apiVersion: argoproj.io/v1alpha1
kind: EventSource
metadata:
name: gitlab-push
namespace: foxhunt
labels:
app.kubernetes.io/name: gitlab-push-eventsource
app.kubernetes.io/part-of: foxhunt
spec:
eventBusName: default
webhook:
gitlab-push:
port: "12000"
endpoint: /push
method: POST

View File

@@ -5,12 +5,7 @@
# Controller runs on platform node (low overhead, ~100Mi idle) # Controller runs on platform node (low overhead, ~100Mi idle)
controller: controller:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
resources: resources:
requests: requests:
cpu: 50m cpu: 50m
@@ -25,12 +20,7 @@ controller:
# Argo Server — UI + API # Argo Server — UI + API
server: server:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
resources: resources:
requests: requests:
cpu: 25m cpu: 25m

View File

@@ -35,7 +35,7 @@ spec:
app.kubernetes.io/part-of: foxhunt app.kubernetes.io/part-of: foxhunt
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: postgres - name: postgres
image: timescale/timescaledb:latest-pg16 image: timescale/timescaledb:latest-pg16

View File

@@ -35,7 +35,7 @@ spec:
app.kubernetes.io/part-of: foxhunt app.kubernetes.io/part-of: foxhunt
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: questdb - name: questdb
image: questdb/questdb:8.2.3 image: questdb/questdb:8.2.3

View File

@@ -18,7 +18,7 @@ spec:
app.kubernetes.io/part-of: foxhunt app.kubernetes.io/part-of: foxhunt
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: redis - name: redis
image: redis:7-alpine image: redis:7-alpine

View File

@@ -4,13 +4,7 @@
replicas: 1 replicas: 1
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
resources: resources:
requests: requests:

View File

@@ -62,11 +62,7 @@ spec:
serviceAccountName: gitlab-pat-rotator serviceAccountName: gitlab-pat-rotator
restartPolicy: Never restartPolicy: Never
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: node.kubernetes.io/not-ready
operator: Exists
effect: NoSchedule
containers: containers:
- name: rotate - name: rotate
image: alpine:3.21 image: alpine:3.21

View File

@@ -12,7 +12,7 @@ spec:
template: template:
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
restartPolicy: Never restartPolicy: Never
containers: containers:
- name: init - name: init

View File

@@ -15,12 +15,7 @@ serviceAccount:
name: gitlab-runner name: gitlab-runner
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
runners: runners:
cloneUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181 cloneUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181
@@ -50,7 +45,7 @@ runners:
helper_cpu_limit = "500m" helper_cpu_limit = "500m"
helper_memory_request = "128Mi" helper_memory_request = "128Mi"
helper_memory_limit = "512Mi" helper_memory_limit = "512Mi"
image_pull_secrets = ["scw-registry", "gitlab-registry"] image_pull_secrets = ["gitlab-registry"]
[runners.kubernetes.node_selector] [runners.kubernetes.node_selector]
"k8s.scaleway.com/pool-name" = "ci-training-h100" "k8s.scaleway.com/pool-name" = "ci-training-h100"
[runners.kubernetes.node_tolerations] [runners.kubernetes.node_tolerations]

View File

@@ -13,12 +13,7 @@ serviceAccount:
name: gitlab-runner name: gitlab-runner
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
runners: runners:
cloneUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181 cloneUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181
@@ -47,7 +42,7 @@ runners:
helper_cpu_limit = "500m" helper_cpu_limit = "500m"
helper_memory_request = "128Mi" helper_memory_request = "128Mi"
helper_memory_limit = "512Mi" helper_memory_limit = "512Mi"
image_pull_secrets = ["scw-registry", "gitlab-registry"] image_pull_secrets = ["gitlab-registry"]
[runners.kubernetes.node_selector] [runners.kubernetes.node_selector]
"k8s.scaleway.com/pool-name" = "ci-training-h100x2" "k8s.scaleway.com/pool-name" = "ci-training-h100x2"
[runners.kubernetes.node_tolerations] [runners.kubernetes.node_tolerations]

View File

@@ -15,12 +15,7 @@ serviceAccount:
name: gitlab-runner name: gitlab-runner
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
runners: runners:
cloneUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181 cloneUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181
@@ -53,7 +48,7 @@ runners:
helper_cpu_limit = "500m" helper_cpu_limit = "500m"
helper_memory_request = "128Mi" helper_memory_request = "128Mi"
helper_memory_limit = "512Mi" helper_memory_limit = "512Mi"
image_pull_secrets = ["scw-registry", "gitlab-registry"] image_pull_secrets = ["gitlab-registry"]
[runners.kubernetes.node_selector] [runners.kubernetes.node_selector]
"k8s.scaleway.com/pool-name" = "ci-training" "k8s.scaleway.com/pool-name" = "ci-training"
[runners.kubernetes.node_tolerations] [runners.kubernetes.node_tolerations]

View File

@@ -9,12 +9,7 @@ gitlabUrl: http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181
replicas: 1 replicas: 1
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: platform
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
runners: runners:
# Override clone URL to internal service (pods can't reach Tailscale IPs) # Override clone URL to internal service (pods can't reach Tailscale IPs)
@@ -52,7 +47,7 @@ runners:
helper_cpu_limit = "500m" helper_cpu_limit = "500m"
helper_memory_request = "128Mi" helper_memory_request = "128Mi"
helper_memory_limit = "512Mi" helper_memory_limit = "512Mi"
image_pull_secrets = ["scw-registry", "gitlab-registry"] image_pull_secrets = ["gitlab-registry"]
# Sub-tables must come AFTER all scalar values (TOML rule) # Sub-tables must come AFTER all scalar values (TOML rule)
[runners.kubernetes.node_selector] [runners.kubernetes.node_selector]
"k8s.scaleway.com/pool-name" = "ci-compile-cpu" "k8s.scaleway.com/pool-name" = "ci-compile-cpu"
@@ -68,11 +63,6 @@ runners:
name = "training-data-pvc" name = "training-data-pvc"
mount_path = "/mnt/training-data" mount_path = "/mnt/training-data"
read_only = true read_only = true
# sccache on local block storage — faster than S3 for cache hits
[[runners.kubernetes.volumes.pvc]]
name = "sccache-pvc"
mount_path = "/mnt/sccache"
read_only = false
# MinIO CA cert for HTTPS S3 access (rclone uses RCLONE_CA_CERT env) # MinIO CA cert for HTTPS S3 access (rclone uses RCLONE_CA_CERT env)
[[runners.kubernetes.volumes.config_map]] [[runners.kubernetes.volumes.config_map]]
name = "minio-ca-cert" name = "minio-ca-cert"

View File

@@ -52,11 +52,6 @@ spec:
serviceAccountName: tailscale-gitlab serviceAccountName: tailscale-gitlab
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: platform
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
containers: containers:
- name: nginx - name: nginx
image: nginx:alpine image: nginx:alpine
@@ -70,9 +65,6 @@ spec:
- name: tls-certs - name: tls-certs
mountPath: /etc/nginx/certs mountPath: /etc/nginx/certs
readOnly: true readOnly: true
- name: argo-htpasswd
mountPath: /etc/nginx/auth
readOnly: true
resources: resources:
requests: requests:
cpu: 25m cpu: 25m
@@ -131,9 +123,6 @@ spec:
- name: tls-certs - name: tls-certs
secret: secret:
secretName: gitlab-tls-cert secretName: gitlab-tls-cert
- name: argo-htpasswd
secret:
secretName: argo-ui-htpasswd
--- ---
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -223,25 +212,6 @@ data:
} }
} }
# Prometheus — prometheus.fxhnt.ai
server {
listen 443 ssl;
server_name prometheus.fxhnt.ai;
ssl_certificate /etc/nginx/certs/tls.crt;
ssl_certificate_key /etc/nginx/certs/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://gitlab-prometheus-server.foxhunt.svc.cluster.local:80;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;
}
}
# API Gateway (gRPC) — api.fxhnt.ai # API Gateway (gRPC) — api.fxhnt.ai
server { server {
listen 443 ssl; listen 443 ssl;
@@ -260,28 +230,10 @@ data:
} }
} }
# Monitoring RPCs — monitor.fxhnt.ai (routed to API Gateway since monitoring_service absorbed) # MinIO S3 API — minio.fxhnt.ai
server { server {
listen 443 ssl; listen 443 ssl;
http2 on; server_name minio.fxhnt.ai;
server_name monitor.fxhnt.ai;
ssl_certificate /etc/nginx/certs/tls.crt;
ssl_certificate_key /etc/nginx/certs/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
grpc_pass grpc://api.foxhunt.svc.cluster.local:50051;
grpc_read_timeout 3600s;
grpc_send_timeout 3600s;
grpc_connect_timeout 30s;
}
}
# MinIO S3 API — s3.fxhnt.ai
server {
listen 443 ssl;
server_name s3.fxhnt.ai;
ssl_certificate /etc/nginx/certs/tls.crt; ssl_certificate /etc/nginx/certs/tls.crt;
ssl_certificate_key /etc/nginx/certs/tls.key; ssl_certificate_key /etc/nginx/certs/tls.key;
@@ -308,26 +260,3 @@ data:
} }
} }
# Argo Workflows UI — ci.fxhnt.ai
server {
listen 443 ssl;
server_name ci.fxhnt.ai;
ssl_certificate /etc/nginx/certs/tls.crt;
ssl_certificate_key /etc/nginx/certs/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
auth_basic "Argo Workflows";
auth_basic_user_file /etc/nginx/auth/htpasswd;
location / {
proxy_pass http://argo-workflows-server.foxhunt.svc.cluster.local:2746;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

View File

@@ -1,6 +1,6 @@
# GitLab CE - Foxhunt deployment # GitLab CE - Foxhunt deployment
# Runs on dedicated 'gitlab' node pool (DEV1-L) # Runs on 'infra' node pool alongside platform services
# External Postgres + Redis on services pool # External Postgres + Redis on same pool
global: global:
edition: ce edition: ce
@@ -80,12 +80,7 @@ prometheus:
enabled: false enabled: false
server: server:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
persistentVolume: persistentVolume:
enabled: false enabled: false
resources: resources:
@@ -108,14 +103,9 @@ registry:
secret: gitlab-s3-credentials secret: gitlab-s3-credentials
key: registry key: registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
# GitLab core components — all on gitlab node pool # GitLab core components — all on infra node pool
gitlab: gitlab:
webservice: webservice:
replicaCount: 1 replicaCount: 1
@@ -126,12 +116,7 @@ gitlab:
workhorse: workhorse:
extraArgs: "-apiLimit 0 -apiQueueLimit 0" extraArgs: "-apiLimit 0 -apiQueueLimit 0"
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
resources: resources:
requests: requests:
cpu: 500m cpu: 500m
@@ -149,12 +134,7 @@ gitlab:
maxReplicas: 1 maxReplicas: 1
concurrency: 10 concurrency: 10
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
resources: resources:
requests: requests:
cpu: 250m cpu: 250m
@@ -170,12 +150,7 @@ gitlab:
enabled: true enabled: true
size: 50Gi size: 50Gi
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
resources: resources:
requests: requests:
cpu: 200m cpu: 200m
@@ -190,12 +165,7 @@ gitlab:
minReplicas: 1 minReplicas: 1
maxReplicas: 1 maxReplicas: 1
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
service: service:
type: NodePort type: NodePort
nodePort: 32222 nodePort: 32222
@@ -207,12 +177,7 @@ gitlab:
secret: gitlab-s3-credentials secret: gitlab-s3-credentials
key: connection key: connection
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: gitlab k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
kas: kas:
enabled: false enabled: false

View File

@@ -46,10 +46,10 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -88,7 +88,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: ml-training-service - name: ml-training-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -45,10 +45,10 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -87,7 +87,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: trading-service - name: trading-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -12,7 +12,7 @@ spec:
spec: spec:
restartPolicy: Never restartPolicy: Never
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
containers: containers:
- name: migrate - name: migrate
image: rg.fr-par.scw.cloud/foxhunt/api:latest image: rg.fr-par.scw.cloud/foxhunt/api:latest

View File

@@ -54,7 +54,7 @@ spec:
app.kubernetes.io/part-of: foxhunt app.kubernetes.io/part-of: foxhunt
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: minio - name: minio
image: minio/minio:latest image: minio/minio:latest
@@ -94,11 +94,11 @@ spec:
failureThreshold: 5 failureThreshold: 5
resources: resources:
requests: requests:
cpu: 100m cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
volumes: volumes:
- name: data - name: data
persistentVolumeClaim: persistentVolumeClaim:
@@ -149,7 +149,7 @@ spec:
app.kubernetes.io/name: minio-init app.kubernetes.io/name: minio-init
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
restartPolicy: OnFailure restartPolicy: OnFailure
containers: containers:
- name: mc - name: mc

View File

@@ -115,12 +115,7 @@ spec:
spec: spec:
serviceAccountName: kube-state-metrics serviceAccountName: kube-state-metrics
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
tolerations:
- key: gitlab
operator: Equal
value: "true"
effect: NoSchedule
containers: containers:
- name: kube-state-metrics - name: kube-state-metrics
image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.14.0 image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.14.0

View File

@@ -61,7 +61,7 @@ spec:
app.kubernetes.io/name: loki app.kubernetes.io/name: loki
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: loki - name: loki
image: grafana/loki:3.4.2 image: grafana/loki:3.4.2

View File

@@ -17,7 +17,7 @@ spec:
app.kubernetes.io/name: pushgateway app.kubernetes.io/name: pushgateway
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: pushgateway - name: pushgateway
image: prom/pushgateway:v1.11.0 image: prom/pushgateway:v1.11.0

View File

@@ -57,7 +57,7 @@ spec:
app.kubernetes.io/name: tempo app.kubernetes.io/name: tempo
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
containers: containers:
- name: tempo - name: tempo
image: grafana/tempo:2.7.1 image: grafana/tempo:2.7.1

View File

@@ -35,12 +35,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -79,7 +79,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: api - name: api
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -34,12 +34,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -78,7 +78,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: backtesting-service - name: backtesting-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -34,12 +34,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -78,7 +78,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: broker-gateway - name: broker-gateway
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -34,12 +34,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -78,7 +78,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: data-acquisition-service - name: data-acquisition-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -23,7 +23,7 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
containers: containers:

View File

@@ -77,12 +77,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -121,7 +121,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: ml-training-service - name: ml-training-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -34,12 +34,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -78,7 +78,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: trading-agent-service - name: trading-agent-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -34,12 +34,12 @@ spec:
seccompProfile: seccompProfile:
type: RuntimeDefault type: RuntimeDefault
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: foxhunt k8s.scaleway.com/pool-name: foxhunt
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -78,7 +78,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: trading-service - name: trading-service
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-runtime:latest
securityContext: securityContext:
allowPrivilegeEscalation: false allowPrivilegeEscalation: false
readOnlyRootFilesystem: true readOnlyRootFilesystem: true

View File

@@ -17,7 +17,7 @@ spec:
app.kubernetes.io/name: tailscale-subnet-router app.kubernetes.io/name: tailscale-subnet-router
spec: spec:
nodeSelector: nodeSelector:
k8s.scaleway.com/pool-name: platform k8s.scaleway.com/pool-name: infra
serviceAccountName: tailscale serviceAccountName: tailscale
containers: containers:
- name: tailscale - name: tailscale

View File

@@ -36,10 +36,10 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
initContainers: initContainers:
- name: pull-training-runtime - name: pull-training-runtime
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-training-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-training-runtime:latest
command: ["echo", "foxhunt-training-runtime image pulled"] command: ["echo", "foxhunt-training-runtime image pulled"]
resources: resources:
requests: requests:

View File

@@ -32,13 +32,13 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
restartPolicy: Never restartPolicy: Never
# Fetch training binary from MinIO at job startup via rclone. # Fetch training binary from MinIO at job startup via rclone.
# Replaces PVC-based copy — no node affinity constraint, no L40S autoscale for writes. # Replaces PVC-based copy — no node affinity constraint, no L40S autoscale for writes.
initContainers: initContainers:
- name: fetch-binary - name: fetch-binary
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-training-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-training-runtime:latest
command: ["/bin/sh", "-c"] command: ["/bin/sh", "-c"]
args: args:
- | - |
@@ -79,7 +79,7 @@ spec:
memory: 128Mi memory: 128Mi
containers: containers:
- name: training - name: training
image: rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-training-runtime:latest image: gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-training-runtime:latest
# Available binaries (copied by initContainer): # Available binaries (copied by initContainer):
# train_baseline_rl (for dqn, ppo) # train_baseline_rl (for dqn, ppo)
# train_baseline_supervised (for tft, mamba2, tggn, tlob, liquid, kan, xlstm, diffusion) # train_baseline_supervised (for tft, mamba2, tggn, tlob, liquid, kan, xlstm, diffusion)

View File

@@ -1,11 +0,0 @@
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "../../../modules/object-storage"
}
inputs = {
bucket_name = "foxhunt-artifacts"
}

View File

@@ -1,11 +0,0 @@
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "../../../modules/registry"
}
inputs = {
namespace_name = "foxhunt"
}

View File

@@ -7,28 +7,19 @@ locals {
project_id = get_env("SCW_DEFAULT_PROJECT_ID") project_id = get_env("SCW_DEFAULT_PROJECT_ID")
} }
# Remote state in Scaleway Object Storage (S3-compatible) # Remote state in GitLab Terraform state backend (project root/foxhunt, ID=1)
# Bootstrap: scw object bucket create name=foxhunt-tfstate region=fr-par # Token stored in k8s secret gitlab-terraform-state-token
# Set TF_HTTP_USERNAME and TF_HTTP_PASSWORD env vars before running terragrunt.
remote_state { remote_state {
backend = "s3" backend = "http"
generate = { generate = {
path = "backend.tf" path = "backend.tf"
if_exists = "overwrite" if_exists = "overwrite"
} }
config = { config = {
bucket = "foxhunt-tfstate" address = "${get_env("GITLAB_TF_STATE_URL", "https://tf.fxhnt.ai")}/api/v4/projects/1/terraform/state/${path_relative_to_include()}"
key = "${path_relative_to_include()}/terraform.tfstate" lock_address = "${get_env("GITLAB_TF_STATE_URL", "https://tf.fxhnt.ai")}/api/v4/projects/1/terraform/state/${path_relative_to_include()}/lock"
region = "fr-par" unlock_address = "${get_env("GITLAB_TF_STATE_URL", "https://tf.fxhnt.ai")}/api/v4/projects/1/terraform/state/${path_relative_to_include()}/lock"
# Scaleway S3 endpoint
endpoints = {
s3 = "https://s3.fr-par.scw.cloud"
}
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
skip_region_validation = true
skip_s3_checksum = true
} }
} }

View File

@@ -1,13 +0,0 @@
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "../../../modules/secrets"
}
inputs = {
ibkr_account_id = get_env("IBKR_ACCOUNT_ID", "")
ibkr_username = get_env("IBKR_USERNAME", "")
ibkr_password = get_env("IBKR_PASSWORD", "")
}

View File

@@ -16,14 +16,6 @@ resource "scaleway_domain_record" "grafana" {
ttl = 300 ttl = 300
} }
resource "scaleway_domain_record" "prometheus" {
dns_zone = var.dns_zone
name = "prometheus"
type = "A"
data = var.git_ip
ttl = 300
}
resource "scaleway_domain_record" "dashboard" { resource "scaleway_domain_record" "dashboard" {
dns_zone = var.dns_zone dns_zone = var.dns_zone
name = "dashboard" name = "dashboard"
@@ -40,26 +32,11 @@ resource "scaleway_domain_record" "api" {
ttl = 300 ttl = 300
} }
resource "scaleway_domain_record" "monitor" { resource "scaleway_domain_record" "minio" {
dns_zone = var.dns_zone dns_zone = var.dns_zone
name = "monitor" name = "minio"
type = "A" type = "A"
data = var.git_ip data = var.git_ip
ttl = 300 ttl = 300
} }
resource "scaleway_domain_record" "s3" {
dns_zone = var.dns_zone
name = "s3"
type = "A"
data = var.git_ip
ttl = 300
}
resource "scaleway_domain_record" "ci" {
dns_zone = var.dns_zone
name = "ci"
type = "A"
data = var.git_ip
ttl = 300
}

View File

@@ -1,62 +0,0 @@
resource "scaleway_object_bucket" "artifacts" {
name = var.bucket_name
region = var.region
lifecycle_rule {
enabled = true
prefix = "sccache/"
expiration {
days = 30
}
}
versioning {
enabled = false
}
}
resource "scaleway_object_bucket" "gitlab_registry" {
name = "${var.bucket_name_prefix}-gitlab-registry"
region = var.region
versioning {
enabled = false
}
}
resource "scaleway_object_bucket" "gitlab_artifacts" {
name = "${var.bucket_name_prefix}-gitlab-artifacts"
region = var.region
lifecycle_rule {
enabled = true
prefix = "tmp/"
expiration {
days = 7
}
}
versioning {
enabled = false
}
}
resource "scaleway_object_bucket" "sccache" {
name = "${var.bucket_name_prefix}-sccache"
region = var.region
lifecycle_rule {
enabled = true
prefix = ""
expiration {
days = 14
}
}
versioning {
enabled = false
}
}

View File

@@ -1,29 +0,0 @@
output "bucket_name" {
description = "Name of the created object storage bucket"
value = scaleway_object_bucket.artifacts.name
}
output "endpoint" {
description = "S3-compatible endpoint URL for the bucket region"
value = "https://s3.${var.region}.scw.cloud"
}
output "artifacts_bucket_name" {
description = "Name of the main artifacts bucket"
value = scaleway_object_bucket.artifacts.name
}
output "gitlab_registry_bucket_name" {
description = "Name of the GitLab registry bucket"
value = scaleway_object_bucket.gitlab_registry.name
}
output "gitlab_artifacts_bucket_name" {
description = "Name of the GitLab artifacts bucket"
value = scaleway_object_bucket.gitlab_artifacts.name
}
output "sccache_bucket_name" {
description = "Name of the sccache bucket"
value = scaleway_object_bucket.sccache.name
}

View File

@@ -1,16 +0,0 @@
variable "region" {
description = "Scaleway region for the object storage bucket"
type = string
}
variable "bucket_name" {
description = "Name of the S3-compatible object storage bucket"
type = string
default = "foxhunt-artifacts"
}
variable "bucket_name_prefix" {
description = "Prefix for additional buckets (e.g., foxhunt)"
type = string
default = "foxhunt"
}

View File

@@ -1,11 +0,0 @@
resource "scaleway_registry_namespace" "foxhunt" {
name = var.namespace_name
region = var.region
is_public = false
}
resource "scaleway_registry_namespace" "foxhunt_ci" {
name = "${var.namespace_name}-ci"
region = var.region
is_public = false
}

View File

@@ -1,19 +0,0 @@
output "endpoint" {
description = "Registry endpoint URL"
value = scaleway_registry_namespace.foxhunt.endpoint
}
output "namespace_id" {
description = "Registry namespace ID"
value = scaleway_registry_namespace.foxhunt.id
}
output "ci_endpoint" {
description = "CI registry endpoint URL"
value = scaleway_registry_namespace.foxhunt_ci.endpoint
}
output "ci_namespace_id" {
description = "CI registry namespace ID"
value = scaleway_registry_namespace.foxhunt_ci.id
}

View File

@@ -1,10 +0,0 @@
variable "region" {
description = "Scaleway region for the container registry"
type = string
}
variable "namespace_name" {
description = "Name of the registry namespace"
type = string
default = "foxhunt"
}

View File

@@ -1,83 +0,0 @@
resource "random_password" "jwt_secret" {
length = 64
special = false
}
resource "random_password" "db_password" {
length = 32
special = false
}
resource "scaleway_secret" "jwt" {
name = "foxhunt-jwt-secret"
project_id = var.project_id
region = var.region
}
resource "scaleway_secret_version" "jwt" {
secret_id = scaleway_secret.jwt.id
data = base64encode(random_password.jwt_secret.result)
region = var.region
}
resource "scaleway_secret" "db_password" {
name = "foxhunt-db-password"
project_id = var.project_id
region = var.region
}
resource "scaleway_secret_version" "db_password" {
secret_id = scaleway_secret.db_password.id
data = base64encode(random_password.db_password.result)
region = var.region
}
resource "scaleway_secret" "tailscale_api_key" {
name = "foxhunt-tailscale-api-key"
project_id = var.project_id
region = var.region
}
resource "scaleway_secret_version" "tailscale_api_key" {
secret_id = scaleway_secret.tailscale_api_key.id
data = base64encode(var.tailscale_api_key)
region = var.region
}
# IBKR paper trading credentials (passed via environment variables, never hardcoded)
resource "scaleway_secret" "ibkr_account" {
name = "foxhunt-ibkr-account"
project_id = var.project_id
region = var.region
}
resource "scaleway_secret_version" "ibkr_account" {
secret_id = scaleway_secret.ibkr_account.id
data = base64encode(var.ibkr_account_id)
region = var.region
}
resource "scaleway_secret" "ibkr_username" {
name = "foxhunt-ibkr-username"
project_id = var.project_id
region = var.region
}
resource "scaleway_secret_version" "ibkr_username" {
secret_id = scaleway_secret.ibkr_username.id
data = base64encode(var.ibkr_username)
region = var.region
}
resource "scaleway_secret" "ibkr_password" {
name = "foxhunt-ibkr-password"
project_id = var.project_id
region = var.region
}
resource "scaleway_secret_version" "ibkr_password" {
secret_id = scaleway_secret.ibkr_password.id
data = base64encode(var.ibkr_password)
region = var.region
}

View File

@@ -1,36 +0,0 @@
output "jwt_secret_id" {
description = "ID of the JWT secret"
value = scaleway_secret.jwt.id
}
output "db_password_secret_id" {
description = "ID of the database password secret"
value = scaleway_secret.db_password.id
}
output "jwt_secret_value" {
description = "Generated JWT secret value"
value = random_password.jwt_secret.result
sensitive = true
}
output "db_password_value" {
description = "Generated database password value"
value = random_password.db_password.result
sensitive = true
}
output "ibkr_account_secret_id" {
description = "ID of the IBKR account secret"
value = scaleway_secret.ibkr_account.id
}
output "ibkr_username_secret_id" {
description = "ID of the IBKR username secret"
value = scaleway_secret.ibkr_username.id
}
output "ibkr_password_secret_id" {
description = "ID of the IBKR password secret"
value = scaleway_secret.ibkr_password.id
}

View File

@@ -1,36 +0,0 @@
variable "region" {
description = "Scaleway region for secret manager"
type = string
}
variable "project_id" {
description = "Scaleway project ID"
type = string
}
variable "tailscale_api_key" {
description = "Tailscale API key for generating pre-auth keys"
type = string
sensitive = true
}
variable "ibkr_account_id" {
description = "IBKR paper trading account ID"
type = string
sensitive = true
default = ""
}
variable "ibkr_username" {
description = "IBKR paper trading username"
type = string
sensitive = true
default = ""
}
variable "ibkr_password" {
description = "IBKR paper trading password"
type = string
sensitive = true
default = ""
}

View File

@@ -184,7 +184,7 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
containers: containers:
- name: training - name: training
image: ${IMAGE} image: ${IMAGE}
@@ -276,7 +276,7 @@ spec:
operator: Exists operator: Exists
effect: NoSchedule effect: NoSchedule
imagePullSecrets: imagePullSecrets:
- name: scw-registry - name: gitlab-registry
containers: containers:
- name: evaluate - name: evaluate
image: ${IMAGE} image: ${IMAGE}

View File

@@ -51,7 +51,7 @@ impl DispatcherConfig {
Self { Self {
namespace: std::env::var("K8S_NAMESPACE").unwrap_or_else(|_| "foxhunt".to_string()), namespace: std::env::var("K8S_NAMESPACE").unwrap_or_else(|_| "foxhunt".to_string()),
runtime_image: std::env::var("TRAINING_RUNTIME_IMAGE").unwrap_or_else(|_| { runtime_image: std::env::var("TRAINING_RUNTIME_IMAGE").unwrap_or_else(|_| {
"rg.fr-par.scw.cloud/foxhunt-ci/foxhunt-training-runtime:latest".to_string() "gitlab-registry.foxhunt.svc.cluster.local:5000/root/foxhunt/foxhunt-training-runtime:latest".to_string()
}), }),
data_pvc: "training-data-pvc".to_string(), data_pvc: "training-data-pvc".to_string(),
s3_bucket: std::env::var("S3_BUCKET") s3_bucket: std::env::var("S3_BUCKET")
@@ -478,7 +478,7 @@ pub fn build_job_spec(config: &DispatcherConfig, params: &TrainingJobParams) ->
}, },
]), ]),
image_pull_secrets: Some(vec![LocalObjectReference { image_pull_secrets: Some(vec![LocalObjectReference {
name: "scw-registry".to_string(), name: "gitlab-registry".to_string(),
}]), }]),
restart_policy: Some("Never".to_string()), restart_policy: Some("Never".to_string()),
..Default::default() ..Default::default()
@@ -640,7 +640,7 @@ mod tests {
// Image pull secrets // Image pull secrets
let ips = pod_spec.image_pull_secrets.as_ref().unwrap(); let ips = pod_spec.image_pull_secrets.as_ref().unwrap();
assert_eq!(ips[0].name, "scw-registry"); assert_eq!(ips[0].name, "gitlab-registry");
// Restart policy // Restart policy
assert_eq!(pod_spec.restart_policy.as_deref().unwrap(), "Never"); assert_eq!(pod_spec.restart_policy.as_deref().unwrap(), "Never");

View File

@@ -16,7 +16,7 @@ async fn watch_tuning_progress(
// Create gRPC client once (reuse connection) // Create gRPC client once (reuse connection)
let mut client = MlTrainingServiceClient::connect(api_url.to_string()) let mut client = MlTrainingServiceClient::connect(api_url.to_string())
.await .await
.context("Failed to connect to API Gateway")?; .context("Failed to connect to API")?;
loop { loop {
iteration += 1; iteration += 1;