Files
foxhunt/infra/modules/kapsule/main.tf
jgrusewski 4afaa5e248 fix(infra): resolve double-declared NAT gateway (kapsule vs public-gateway)
The real gateway foxhunt-gw (42653780) was an unmanaged orphan: kapsule state never had a gateway,
public-gateway state referenced a deleted gateway (7a7ffaa5) -> BOTH modules' terragrunt apply would
have created a duplicate gateway (risking cluster egress). Fix:
- kapsule module: removed the legacy gateway/dhcp/gateway_network resources (pre-refactor duplicate,
  never in kapsule state; cluster only needs the private_network which stays). kapsule plan now clean.
- public-gateway module (canonical, IPAM mode): state rm the stale 7a7ffaa5 refs + imported the real
  gateway/gateway_network/IP (42653780 / 661c8543 / dc419a10); set bastion_enabled=true to match the
  live gw. public-gateway plan now 'No changes'. Live gateway untouched throughout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 14:05:50 +02:00

139 lines
4.7 KiB
HCL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
resource "scaleway_vpc_private_network" "foxhunt" {
name = "${var.cluster_name}-pn"
region = var.region
}
# NAT gateway (foxhunt-gw) is owned by the dedicated `public-gateway` module (IPAM mode +
# dedicated IP), which depends on this module's private_network_id output. The legacy
# gateway/dhcp/gateway_network resources that used to live here were a pre-refactor duplicate
# (never in this module's state) and were removed 2026-06-21 to stop `terragrunt apply` here
# from trying to create a second gateway. See reference_ci_pool_and_tfstate / incident_dns_deadlock.
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]
}
}
# NOTE: ci-training-h100x2 and ci-training-h100-sxm pools removed
# 2026-05-16 — Scaleway account doesn't have quota for the SXM variant
# (cp_servers_type_H100_SXM_2_80G 0/0), and the H100x2 variant is
# more expensive than our actual usage justifies. Keeping the regular
# single-GPU H100 pool (ci_training_h100) + the L40S pool covers
# every current training workload.
# 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]
}
}