diff --git a/stacks/immich/main.tf b/stacks/immich/main.tf index 3ee56d1f..0555b653 100644 --- a/stacks/immich/main.tf +++ b/stacks/immich/main.tf @@ -121,7 +121,10 @@ resource "kubernetes_namespace" "immich" { metadata { name = "immich" labels = { - tier = local.tiers.gpu + # Opts immich out of kyverno's `quota-tier-2-gpu` generation rule + # so this stack can own the tier-quota with a higher memory cap. + "resource-governance/custom-quota" = "true" + tier = local.tiers.gpu } } lifecycle { @@ -130,6 +133,25 @@ resource "kubernetes_namespace" "immich" { } } +# Override the kyverno-generated tier-2-gpu quota (12Gi requests.memory). +# Immich-server needs 8Gi to absorb face-detection burst spikes (OOM 2026-04-26) +# without OOM. Plus immich-machine-learning (3.5Gi) + immich-postgresql (3Gi) + +# backup CronJobs ≈ 15.5Gi. 20Gi gives ~4.5Gi headroom. +resource "kubernetes_resource_quota" "immich" { + metadata { + name = "tier-quota" + namespace = kubernetes_namespace.immich.metadata[0].name + } + spec { + hard = { + "requests.cpu" = "8" + "requests.memory" = "20Gi" + "limits.memory" = "32Gi" + pods = "40" + } + } +} + resource "kubernetes_manifest" "external_secret" { manifest = { apiVersion = "external-secrets.io/v1beta1" @@ -311,10 +333,10 @@ resource "kubernetes_deployment" "immich_server" { resources { requests = { cpu = "100m" - memory = "4096Mi" + memory = "8Gi" } limits = { - memory = "4096Mi" + memory = "8Gi" } } }