diff --git a/charts/eduide-cluster/README.md b/charts/eduide-cluster/README.md index 1c1f450..be06d4c 100644 --- a/charts/eduide-cluster/README.md +++ b/charts/eduide-cluster/README.md @@ -22,6 +22,7 @@ cert-manager issuers. Install once per cluster, before any eduide release. | envoyProxy.labels | object | `{}` | | | envoyProxy.name | string | `"theia-shared-gateway"` | | | envoyProxy.namespace | string | `"envoy-gateway-system"` | | +| envoyProxy.replicas | int | `1` | Data plane replica count, rendered into the spec at `provider.kubernetes.envoyDeployment.replicas`. Envoy Gateway stops reconciling that field when the EnvoyProxy leaves it out, which makes a manual scale to zero permanent and the Gateway unreachable for good. A `spec` that names its own replicas wins over this, and `null` leaves the field out entirely. Ignored for a spec that scales some other way - an `envoyHpa`, an `envoyDaemonSet`, or a `Host` provider. | | envoyProxy.spec | object | `{}` | | | gateway | object | `{"addresses":[],"allowedRoutes":{"namespaces":{"from":"All"}},"annotations":{},"className":"envoy","create":true,"labels":{},"listeners":[],"name":"theia-shared-gateway","namespace":"eduide-system","redirects":[]}` | ------------------------------------------------------------------------ | | gateway.create | bool | `true` | Create the shared Gateway. Set false only if you terminate and route traffic some other way; EduIDE then has no ingress of its own. | diff --git a/charts/eduide-cluster/templates/gateway/envoyproxy.yaml b/charts/eduide-cluster/templates/gateway/envoyproxy.yaml index 8671814..8750d0c 100644 --- a/charts/eduide-cluster/templates/gateway/envoyproxy.yaml +++ b/charts/eduide-cluster/templates/gateway/envoyproxy.yaml @@ -1,4 +1,26 @@ {{- if .Values.envoyProxy.create }} +{{- /* +Envoy Gateway only owns the data plane Deployment's replica count while the +EnvoyProxy states it. Omit it and the controller writes the field once at +creation and never looks at it again, so a single `kubectl scale --replicas=0` +- or a stray click in a cluster UI - takes every Gateway on the class down +until somebody scales it back by hand. Default it here, and let a spec that +sets its own replicas (an HPA-driven cluster, say) win. + +Three specs must be left alone. A DaemonSet data plane rejects the resource +outright - the CRD permits envoyDeployment or envoyDaemonSet, never both - an +HPA already owns the field, and a `Host` provider has no Deployment to scale. +`type` comes along with the default because the CRD requires it as soon as +`provider` exists at all, and a spec of `{}` is a valid install. +*/}} +{{- $spec := deepCopy (default (dict) .Values.envoyProxy.spec) }} +{{- $kubernetes := default (dict) (dig "provider" "kubernetes" (dict) $spec) }} +{{- $onKubernetes := eq (dig "provider" "type" "Kubernetes" $spec) "Kubernetes" }} +{{- $ownsReplicas := or (hasKey $kubernetes "envoyDaemonSet") (hasKey $kubernetes "envoyHpa") }} +{{- if and (not (kindIs "invalid" .Values.envoyProxy.replicas)) $onKubernetes (not $ownsReplicas) }} +{{- $default := dict "provider" (dict "type" "Kubernetes" "kubernetes" (dict "envoyDeployment" (dict "replicas" .Values.envoyProxy.replicas))) }} +{{- $spec = mergeOverwrite $default $spec }} +{{- end }} apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: @@ -13,5 +35,5 @@ metadata: {{ toYaml . | nindent 4 }} {{- end }} spec: -{{ toYaml .Values.envoyProxy.spec | nindent 2 }} +{{ toYaml $spec | nindent 2 }} {{- end }} diff --git a/charts/eduide-cluster/values.yaml b/charts/eduide-cluster/values.yaml index 5844360..3365899 100644 --- a/charts/eduide-cluster/values.yaml +++ b/charts/eduide-cluster/values.yaml @@ -133,6 +133,14 @@ envoyProxy: namespace: envoy-gateway-system labels: {} annotations: {} + # -- Data plane replica count, rendered into the spec at + # `provider.kubernetes.envoyDeployment.replicas`. Envoy Gateway stops + # reconciling that field when the EnvoyProxy leaves it out, which makes a + # manual scale to zero permanent and the Gateway unreachable for good. A + # `spec` that names its own replicas wins over this, and `null` leaves the + # field out entirely. Ignored for a spec that scales some other way - an + # `envoyHpa`, an `envoyDaemonSet`, or a `Host` provider. + replicas: 1 spec: {} managedCertificates: enabled: false