Two 9-quarter precompute_features runs OOM-killed on the existing
ci-compile-cpu pool (POP2-HC-32C-64G, 56Gi cgroup limit):
- train-wq8b8: exit 137 ~12s after "OFI computed" at ~57Gi
- train-2l6p4: exit 137 ~12s after "OFI computed" at ~52Gi peak
(despite the into_iter + drop(feature_vectors) +
normalize_in_place refactors landed in a27cb40a9 + 623ebfcf7,
which trimmed ~12GB of avoidable retention)
The remaining ~52-60GB peak is the irreducible working set at the
post-OFI / pre-alpha-pipeline step:
- 9-quarter MBP-10 snapshots (~10GB)
- 199M front-month trades as Mbp10Trade (~13GB)
- 17.8M bars × features + targets + OFI buffers (~14GB)
- alpha_snapshots (move-handoff from all_snapshots, ~10GB)
- feature/target Vecs (~7GB) + Rust allocator overhead
Adds a dedicated high-memory pool sized for this rare path:
- New scaleway_k8s_pool.ci_compile_cpu_hm (POP2-HM-32C-256G,
32 vCPU + 256GB RAM) with size=0 + min_size=0 autoscaling. Costs
zero when idle; autoscaler provisions one node when a pod targets
`nodeSelector: ci-compile-cpu-hm`.
- New variables: enable_ci_compile_cpu_hm_pool,
ci_compile_cpu_hm_type (default POP2-HM-32C-256G),
ci_compile_cpu_hm_max_size (default 1).
- terragrunt.hcl: enable the pool, max_size=1.
- train-template.yaml: ensure-fxcache nodeSelector pinned to
ci-compile-cpu-hm; memory limit raised 56Gi → 200Gi. The
ci-compile-cpu pool stays as the standard CI compile target for
ensure-binary + every other CPU-heavy task.
Apply with:
cd infra/live/production/kapsule
terragrunt apply -target=module.kapsule.scaleway_k8s_pool.ci_compile_cpu_hm
kubectl apply -n foxhunt -f ../../../../infra/k8s/argo/train-template.yaml
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
190 lines
5.9 KiB
HCL
190 lines
5.9 KiB
HCL
resource "scaleway_vpc_private_network" "foxhunt" {
|
||
name = "${var.cluster_name}-pn"
|
||
region = var.region
|
||
}
|
||
|
||
# VPC Public Gateway — provides NAT (masquerade) for private nodes
|
||
# and DHCP with default route propagation to prevent DNS deadlock.
|
||
# See incident_dns_deadlock.md for why this is critical.
|
||
resource "scaleway_vpc_public_gateway" "foxhunt" {
|
||
name = "${var.cluster_name}-gw"
|
||
type = "VPC-GW-S"
|
||
zone = "${var.region}-2"
|
||
bastion_enabled = true
|
||
bastion_port = 61000
|
||
}
|
||
|
||
resource "scaleway_vpc_public_gateway_dhcp" "foxhunt" {
|
||
subnet = "172.16.0.0/22"
|
||
push_default_route = true
|
||
push_dns_server = true
|
||
zone = "${var.region}-2"
|
||
}
|
||
|
||
resource "scaleway_vpc_gateway_network" "foxhunt" {
|
||
gateway_id = scaleway_vpc_public_gateway.foxhunt.id
|
||
private_network_id = scaleway_vpc_private_network.foxhunt.id
|
||
dhcp_id = scaleway_vpc_public_gateway_dhcp.foxhunt.id
|
||
enable_masquerade = true
|
||
zone = "${var.region}-2"
|
||
}
|
||
|
||
resource "scaleway_k8s_cluster" "foxhunt" {
|
||
name = var.cluster_name
|
||
version = var.k8s_version
|
||
cni = "cilium"
|
||
region = var.region
|
||
delete_additional_resources = true
|
||
private_network_id = scaleway_vpc_private_network.foxhunt.id
|
||
|
||
auto_upgrade {
|
||
enable = true
|
||
maintenance_window_start_hour = 4
|
||
maintenance_window_day = "sunday"
|
||
}
|
||
|
||
autoscaler_config {
|
||
disable_scale_down = false
|
||
scale_down_delay_after_add = "10m"
|
||
scale_down_unneeded_time = "10m"
|
||
estimator = "binpacking"
|
||
ignore_daemonsets_utilization = true
|
||
}
|
||
}
|
||
|
||
# Platform pool — runs everything: app services, databases, GitLab, monitoring
|
||
resource "scaleway_k8s_pool" "platform" {
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "platform"
|
||
node_type = var.platform_type
|
||
size = 1
|
||
min_size = 1
|
||
max_size = var.platform_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|
||
|
||
# L40S training pool (48GB VRAM, CUDA CC 89 — hyperopt + supervised training)
|
||
resource "scaleway_k8s_pool" "ci_training_l40s" {
|
||
count = var.enable_ci_training_l40s_pool ? 1 : 0
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "ci-training-l40s"
|
||
node_type = var.ci_training_l40s_type
|
||
size = 1
|
||
min_size = 0
|
||
max_size = var.ci_training_l40s_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|
||
|
||
# H100 training pool (80GB VRAM, CUDA CC 90 — RL hyperopt)
|
||
resource "scaleway_k8s_pool" "ci_training_h100" {
|
||
count = var.enable_ci_training_h100_pool ? 1 : 0
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "ci-training-h100"
|
||
node_type = var.ci_training_h100_type
|
||
size = 1
|
||
min_size = 0 # Scale to zero when idle. Cold start: ~15 min NVIDIA driver install.
|
||
max_size = var.ci_training_h100_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|
||
|
||
# H100x2 training pool (2x 80GB VRAM — multi-GPU parallel hyperopt)
|
||
resource "scaleway_k8s_pool" "ci_training_h100x2" {
|
||
count = var.enable_ci_training_h100x2_pool ? 1 : 0
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "ci-training-h100x2"
|
||
node_type = var.ci_training_h100x2_type
|
||
size = 1
|
||
min_size = 0
|
||
max_size = var.ci_training_h100x2_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|
||
|
||
# H100-SXM training pool (2x 80GB SXM VRAM — NVLink multi-GPU)
|
||
resource "scaleway_k8s_pool" "ci_training_h100_sxm" {
|
||
count = var.enable_ci_training_h100_sxm_pool ? 1 : 0
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "ci-training-h100-sxm"
|
||
node_type = var.ci_training_h100_sxm_type
|
||
size = 1
|
||
min_size = 0
|
||
max_size = var.ci_training_h100_sxm_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|
||
|
||
# CPU compile pool (POP2-HC — high CPU, no GPU, for cargo check/build)
|
||
resource "scaleway_k8s_pool" "ci_compile_cpu" {
|
||
count = var.enable_ci_compile_cpu_pool ? 1 : 0
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "ci-compile-cpu"
|
||
node_type = var.ci_compile_cpu_type
|
||
size = 1
|
||
min_size = 0
|
||
max_size = var.ci_compile_cpu_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|
||
|
||
# High-memory CPU compile pool (POP2-HM — same CPU count as ci-compile-cpu
|
||
# but 4× the RAM; reserved for rare full-rebuild precompute_features runs
|
||
# that can't fit on the standard 64GB nodes). min_size=0 + size=0 initial
|
||
# so the pool costs nothing when idle — autoscaler provisions one node
|
||
# only when a pod targets `nodeSelector: ci-compile-cpu-hm`.
|
||
resource "scaleway_k8s_pool" "ci_compile_cpu_hm" {
|
||
count = var.enable_ci_compile_cpu_hm_pool ? 1 : 0
|
||
cluster_id = scaleway_k8s_cluster.foxhunt.id
|
||
name = "ci-compile-cpu-hm"
|
||
node_type = var.ci_compile_cpu_hm_type
|
||
size = 0
|
||
min_size = 0
|
||
max_size = var.ci_compile_cpu_hm_max_size
|
||
autoscaling = true
|
||
autohealing = true
|
||
public_ip_disabled = var.public_ip_disabled
|
||
region = var.region
|
||
|
||
lifecycle {
|
||
ignore_changes = [size]
|
||
}
|
||
}
|