From ba5408f7f90d26c20ef29be20fcfacbec340ad1f Mon Sep 17 00:00:00 2001 From: OdooSky v3 Date: Sat, 9 May 2026 22:53:37 +0300 Subject: [PATCH] =?UTF-8?q?chart=200.7.4=20=E2=80=94=20install=20KEDA=20co?= =?UTF-8?q?re=20+=20HTTP=20add-on=20for=20AI=20Studio=20scale-to-zero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two subchart deps: - keda v2.15.1 (event-driven autoscaler, ScaledObject CRD) - keda-add-ons-http v0.8.0 (HTTPScaledObject CRD + interceptor-proxy) Both gated by enabled flags (keda.enabled, kedaHttpAddon.enabled), default true so all clusters can host AI Studio (per-instance OpenCode pods that scale 0↔1 on URL hit). Idle cost ~300 MB RAM total — small relative to typical customer cluster (7+ GB allocatable). Charts mirrored to registry.odoosky.cloud/odoosky/docker-mirror/charts following the existing mirror-first pattern used by cert-manager, traefik, longhorn, external-secrets. Studio chart (studio-template-v3) created in monorepo as part of the same feature; chart-side IngressRoute will be updated in 0.1.1 to point at keda-add-ons-http-interceptor-proxy.keda.svc instead of the per-instance Service (KEDA HTTP routing pattern). Tower handlers for deploy/get/write-mode-toggle/delete already shipped in 0.76.47 behind a studioChartReady=false feature flag. --- Chart.yaml | 41 +++++++++++++++++++++++---- values.yaml | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/Chart.yaml b/Chart.yaml index 6e8b5ea..2afa6df 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -23,19 +23,22 @@ description: | Git). type: application -version: 0.7.3 -appVersion: "0.7.3" +version: 0.7.4 +appVersion: "0.7.4" -# All 4 subcharts now resolve from registry.odoosky.cloud (mirrored -# 2026-05-08). Mirror-first discipline + China-region readiness: a -# Jetstack / Traefik / Longhorn / external-secrets-io outage no longer -# blocks new tenant cluster bootstrap. +# All 6 subcharts now resolve from registry.odoosky.cloud (mirrored +# 2026-05-08, KEDA stack added 2026-05-09). Mirror-first discipline +# + China-region readiness: a Jetstack / Traefik / Longhorn / +# external-secrets-io / KEDA outage no longer blocks new tenant +# cluster bootstrap. # # Original upstream sources (for re-sync if a chart bumps): # cert-manager → https://charts.jetstack.io # traefik → https://traefik.github.io/charts # longhorn → https://charts.longhorn.io # external-secrets → https://charts.external-secrets.io +# keda → https://kedacore.github.io/charts +# keda-add-ons-http→ https://kedacore.github.io/charts # # Re-sync recipe: `helm pull --repo --version ` # then `helm push oci://registry.odoosky.cloud/odoosky/docker-mirror/charts`. @@ -64,3 +67,29 @@ dependencies: version: "0.10.7" repository: "oci://registry.odoosky.cloud/odoosky/docker-mirror/charts" condition: externalSecrets.enabled + # KEDA core — event-driven autoscaler. Owns the ScaledObject CRD + # and the metrics-server adapter that K8s' HPA reads from. Required + # by KEDA HTTP add-on below; declared here so the install order is + # correct (sync-wave 0 default; HTTP add-on at wave 1). + # + # Currently consumed by AI Studio (per-instance OpenCode pods that + # scale 0↔1 on URL hit, see studio-template-v3). Enabled by default + # because Studio is opt-in per-instance — clusters without any + # Studio pay only for the KEDA control plane (~50 MB RAM). + - name: keda + version: "2.15.1" + repository: "oci://registry.odoosky.cloud/odoosky/docker-mirror/charts" + condition: keda.enabled + # KEDA HTTP add-on — separate component that owns the + # HTTPScaledObject CRD + the interceptor-proxy. Traefik routes + # public traffic to the interceptor (in keda namespace), which + # holds the request while it scales the target Deployment 0→1, + # then forwards. After scaledownPeriod of no traffic, scales 1→0. + # + # AI Studio is the only current consumer; the add-on is harmless + # idle (interceptor is just a small Go service). Studio chart + # creates one HTTPScaledObject per (tenant, instance). + - name: keda-add-ons-http + version: "0.8.0" + repository: "oci://registry.odoosky.cloud/odoosky/docker-mirror/charts" + condition: kedaHttpAddon.enabled diff --git a/values.yaml b/values.yaml index fe42ad2..e17463f 100644 --- a/values.yaml +++ b/values.yaml @@ -305,3 +305,82 @@ externalSecrets: # correctly per-cluster. external-secrets: installCRDs: true + +# keda — event-driven autoscaler. Gate for the conditional in +# Chart.yaml dependencies. Enabled by default so all clusters can +# host AI Studio (per-instance OpenCode pods that scale 0↔1 via the +# HTTP add-on below). KEDA's control plane is ~50 MB RAM idle — +# negligible for clusters that never spawn a Studio. +# +# Subchart values pass through under the dep name (`keda:`) below. +keda: + enabled: true + # operator + adapter + webhook — keep CPU/RAM modest. KEDA polls + # event sources every pollingInterval (default 30s); on a cluster + # with no ScaledObjects it does no work. + operator: + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 500m + memory: 256Mi + metricsServer: + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 500m + memory: 256Mi + webhooks: + resources: + requests: + cpu: 50m + memory: 50Mi + limits: + cpu: 200m + memory: 128Mi + +# kedaHttpAddon — gate for the HTTP add-on subchart. Same +# enabled-by-default rationale: idle interceptor is small, and only +# clusters with active Studios route traffic through it. +# +# The add-on installs the HTTPScaledObject CRD + an interceptor Service +# in the `keda` namespace at `keda-add-ons-http-interceptor-proxy`. +# Studio-template-v3's IngressRoute targets that interceptor by name +# (it figures out which Studio Deployment to wake by Host header +# matched against HTTPScaledObject.spec.hosts). +kedaHttpAddon: + enabled: true + +# keda-add-ons-http — values passed THROUGH to the HTTP add-on +# subchart. The interceptor is the request-handling hot path; it +# buffers each cold-start request until the target pod is Ready. +# The scaler is the control loop watching HTTPScaledObject status. +keda-add-ons-http: + interceptor: + replicas: + # Scale the interceptor itself with HPA on its own metrics — + # not zero (it must always be reachable to wake other pods). + # 1 replica is fine for OdooSky's per-customer-cluster load + # (single-digit Studios per cluster); upstream's own HPA + # handles bursts above that. + min: 1 + max: 3 + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 500m + memory: 256Mi + scaler: + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi