Files
Will Anderson 53f2ad3c16 Fix Cloud Run probe ports and LB timeout_sec
- accounts: add ACCOUNTS_PORT=8080 env var (service defaults to 7753)
- api: add SERVER_PORT=8080 env var, change probe path to /actuator/health
- LB backends: remove timeout_sec (not supported for serverless NEG backends)
2026-04-26 00:28:33 -05:00

309 lines
7.0 KiB
Terraform

# ── REST API (neuron-rest) — Cloud Run ────────────────────────────────────────
# Stateless API layer. Validates JWTs from accounts service.
# No database connection — reads user context from accounts service.
# cpu_idle=false: always-hot, no cold-start latency for API calls.
locals {
api_labels = {
"managed-by" = "terraform"
"service" = "neuron-api"
}
}
# ── Prod — us-central1 ────────────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "api_us" {
name = "api-prod-us"
location = "us-central1"
project = var.project_id
ingress = "INGRESS_TRAFFIC_ALL"
labels = local.api_labels
template {
service_account = google_service_account.api.email
scaling {
min_instance_count = 1
max_instance_count = 100
}
containers {
image = local.api_image
resources {
limits = {
cpu = "2"
memory = "1Gi"
}
cpu_idle = false
}
env {
name = "ENV"
value = "production"
}
env {
name = "SERVER_PORT"
value = "8080"
}
env {
name = "ACCOUNTS_SERVICE_URL"
value = "https://accounts.neurontechnologies.ai"
}
env {
name = "JWT_SECRET"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.jwt_secret.secret_id
version = "latest"
}
}
}
env {
name = "LICENSE_ADMIN_TOKEN"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.license_admin_token.secret_id
version = "latest"
}
}
}
ports {
container_port = 8080
name = "http1"
}
startup_probe {
http_get {
path = "/actuator/health"
port = 8080
}
initial_delay_seconds = 2
timeout_seconds = 5
period_seconds = 5
failure_threshold = 6
}
liveness_probe {
http_get {
path = "/actuator/health"
port = 8080
}
timeout_seconds = 5
period_seconds = 30
failure_threshold = 3
}
}
max_instance_request_concurrency = 1000
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [
google_project_iam_member.api_secret_accessor,
google_secret_manager_secret_version.jwt_secret,
]
}
# ── Prod — europe-west1 ───────────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "api_eu" {
name = "api-prod-eu"
location = "europe-west1"
project = var.project_id
ingress = "INGRESS_TRAFFIC_ALL"
labels = local.api_labels
template {
service_account = google_service_account.api.email
scaling {
min_instance_count = 1
max_instance_count = 100
}
containers {
image = local.api_image
resources {
limits = {
cpu = "2"
memory = "1Gi"
}
cpu_idle = false
}
env {
name = "ENV"
value = "production"
}
env {
name = "SERVER_PORT"
value = "8080"
}
env {
name = "ACCOUNTS_SERVICE_URL"
value = "https://accounts.neurontechnologies.ai"
}
env {
name = "JWT_SECRET"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.jwt_secret.secret_id
version = "latest"
}
}
}
env {
name = "LICENSE_ADMIN_TOKEN"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.license_admin_token.secret_id
version = "latest"
}
}
}
ports {
container_port = 8080
name = "http1"
}
startup_probe {
http_get {
path = "/actuator/health"
port = 8080
}
initial_delay_seconds = 2
timeout_seconds = 5
period_seconds = 5
failure_threshold = 6
}
liveness_probe {
http_get {
path = "/actuator/health"
port = 8080
}
timeout_seconds = 5
period_seconds = 30
failure_threshold = 3
}
}
max_instance_request_concurrency = 1000
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [google_project_iam_member.api_secret_accessor]
}
# ── Prod — asia-northeast1 ────────────────────────────────────────────────────
resource "google_cloud_run_v2_service" "api_apac" {
name = "api-prod-apac"
location = "asia-northeast1"
project = var.project_id
ingress = "INGRESS_TRAFFIC_ALL"
labels = local.api_labels
template {
service_account = google_service_account.api.email
scaling {
min_instance_count = 1
max_instance_count = 100
}
containers {
image = local.api_image
resources {
limits = {
cpu = "2"
memory = "1Gi"
}
cpu_idle = false
}
env {
name = "ENV"
value = "production"
}
env {
name = "SERVER_PORT"
value = "8080"
}
env {
name = "ACCOUNTS_SERVICE_URL"
value = "https://accounts.neurontechnologies.ai"
}
env {
name = "JWT_SECRET"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.jwt_secret.secret_id
version = "latest"
}
}
}
env {
name = "LICENSE_ADMIN_TOKEN"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.license_admin_token.secret_id
version = "latest"
}
}
}
ports {
container_port = 8080
name = "http1"
}
startup_probe {
http_get {
path = "/actuator/health"
port = 8080
}
initial_delay_seconds = 2
timeout_seconds = 5
period_seconds = 5
failure_threshold = 6
}
liveness_probe {
http_get {
path = "/actuator/health"
port = 8080
}
timeout_seconds = 5
period_seconds = 30
failure_threshold = 3
}
}
max_instance_request_concurrency = 1000
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [google_project_iam_member.api_secret_accessor]
}