# Ground warehouse segment (T3, docs/03 + docs/06) — the stationary, # long-lifecycle half of the system and therefore the most natural Terraform # territory. Runs in the same k3d cluster as the fleet, in its own namespace # and with its own state. locals { labels = { "app.kubernetes.io/part-of" = "swarm-ground" } } resource "kubernetes_namespace" "ground" { metadata { name = var.namespace labels = local.labels } } # --- MinIO object store ------------------------------------------------------- resource "kubernetes_secret" "minio" { metadata { name = "minio-credentials" namespace = kubernetes_namespace.ground.metadata[0].name } data = { MINIO_ROOT_USER = var.minio_root_user MINIO_ROOT_PASSWORD = var.minio_root_password } } resource "kubernetes_persistent_volume_claim" "minio" { metadata { name = "minio-data" namespace = kubernetes_namespace.ground.metadata[0].name } spec { access_modes = ["ReadWriteOnce"] resources { requests = { storage = var.minio_storage } } } } resource "kubernetes_deployment" "minio" { metadata { name = "minio" namespace = kubernetes_namespace.ground.metadata[0].name labels = local.labels } spec { replicas = 1 strategy { type = "Recreate" # RWO volume } selector { match_labels = { app = "minio" } } template { metadata { labels = merge(local.labels, { app = "minio" }) } spec { container { name = "minio" image = "minio/minio:RELEASE.2024-06-13T22-53-53Z" args = ["server", "/data", "--console-address", ":9001"] env_from { secret_ref { name = kubernetes_secret.minio.metadata[0].name } } # Air-gap hygiene: no update checks env { name = "MINIO_UPDATE" value = "off" } port { container_port = 9000 } port { container_port = 9001 } volume_mount { name = "store" mount_path = "/data" } } volume { name = "store" persistent_volume_claim { claim_name = kubernetes_persistent_volume_claim.minio.metadata[0].name } } } } } } resource "kubernetes_service" "minio" { metadata { name = "minio" namespace = kubernetes_namespace.ground.metadata[0].name } spec { type = "NodePort" selector = { app = "minio" } port { name = "api" port = 9000 target_port = 9000 } port { name = "console" port = 9001 target_port = 9001 node_port = var.node_ports.minio_console } } } # --- Post-flight offload: T1 lake -> T3 warehouse ------------------------------ # In production this runs on the docking station after a drone lands: only # sealed partitions move, checksums are verified, then the on-board lake is # pruned. The simulation compresses that into a periodic rsync-style copy # plus an object-store mirror. resource "kubernetes_cron_job_v1" "offload" { metadata { name = "offload" namespace = kubernetes_namespace.ground.metadata[0].name labels = local.labels } spec { schedule = var.offload_schedule concurrency_policy = "Forbid" successful_jobs_history_limit = 3 failed_jobs_history_limit = 3 job_template { metadata { labels = local.labels } spec { backoff_limit = 1 template { metadata { labels = local.labels } spec { restart_policy = "Never" # Step 1: copy Hive partitions verbatim (T1 layout == T3 layout) init_container { name = "copy" image = "busybox:1.36" command = ["sh", "-c", "cp -ru /lake/flight_id=* /warehouse/ 2>/dev/null; ls /warehouse | wc -l"] volume_mount { name = "lake" mount_path = "/lake" read_only = true } volume_mount { name = "warehouse" mount_path = "/warehouse" } } # Step 2: mirror the warehouse into the object store for # downstream consumers (training pipelines, replay tooling) container { name = "mirror" image = "minio/mc:RELEASE.2024-06-12T14-34-03Z" command = ["sh", "-c", "mc alias set store http://minio:9000 \"$MINIO_ROOT_USER\" \"$MINIO_ROOT_PASSWORD\" && mc mb -p store/warehouse && mc mirror --overwrite /warehouse store/warehouse"] env_from { secret_ref { name = kubernetes_secret.minio.metadata[0].name } } volume_mount { name = "warehouse" mount_path = "/warehouse" read_only = true } } volume { name = "lake" host_path { path = var.lake_host_path } } volume { name = "warehouse" host_path { path = var.warehouse_host_path type = "DirectoryOrCreate" } } } } } } } } # --- Warehouse explorer: historical read-only SQL over all flights ------------- resource "kubernetes_deployment" "warehouse_explorer" { metadata { name = "warehouse-explorer" namespace = kubernetes_namespace.ground.metadata[0].name labels = local.labels } spec { replicas = 1 selector { match_labels = { app = "warehouse-explorer" } } template { metadata { labels = merge(local.labels, { app = "warehouse-explorer" }) } spec { container { name = "explorer" image = var.simulator_image image_pull_policy = "Never" command = ["python", "explorer/server.py"] env { name = "DATA_DIR" value = "/warehouse" } port { container_port = 8088 } volume_mount { name = "warehouse" mount_path = "/warehouse" read_only = true } } volume { name = "warehouse" host_path { path = var.warehouse_host_path type = "DirectoryOrCreate" } } } } } } resource "kubernetes_service" "warehouse_explorer" { metadata { name = "warehouse-explorer" namespace = kubernetes_namespace.ground.metadata[0].name } spec { type = "NodePort" selector = { app = "warehouse-explorer" } port { port = 8088 target_port = 8088 node_port = var.node_ports.warehouse_explorer } } }