Files
OpenShell/deploy/helm/openshell/templates/_gateway-workload.tpl
Bryce Wilkinson 69ec36a68f feat(helm): expose priorityClassName and topologySpreadConstraints
The gateway pod template exposes nodeSelector, affinity and tolerations but
not priorityClassName or topologySpreadConstraints. Operators who need
either have to fork the chart or mutate the rendered output out-of-band.

Add two optional passthroughs:

- priorityClassName: the gateway is a control-plane component. When it shares
  nodes with the workloads it serves, the default priority gives it no
  advantage under node pressure, so a local capacity crunch can evict it and
  widen into a fleet-wide outage.
- topologySpreadConstraints: spread replicas across zones or nodes. Only
  affinity was available, which is a blunter tool for even spreading.

Both go in the shared gatewayPodTemplate, so they apply identically to the
statefulset and deployment workload shapes. Both render only when set; a
default render is byte-identical to before this change.

The data volume size/StorageClass passthroughs from the original revision are
dropped: upstream now provides them as server.dataStorageSize and
server.dataStorageClass.

Signed-off-by: Bryce Wilkinson <22760097+bjw123@users.noreply.github.com>
2026-10-22 14:16:41 +03:00

330 lines
13 KiB
Smarty

# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
{{/*
Gateway pod template shared by the StatefulSet and Deployment workload shapes.
*/}}
{{- define "openshell.gatewayPodTemplate" -}}
{{- $gatewayConfig := .Values.gatewayConfig | default dict -}}
{{- $oidcRuntimeConfig := get $gatewayConfig "openshell.gateway.oidc" | default dict -}}
{{- if not (get $oidcRuntimeConfig "issuer") -}}{{- $oidcRuntimeConfig = .Values.server.oidc | default dict -}}{{- end -}}
{{- $kubernetesRuntimeConfig := include "openshell.effectiveKubernetesConfig" . | fromYaml -}}
{{- $spiffeSocketPath := get $kubernetesRuntimeConfig "provider_spiffe_workload_api_socket_path" -}}
{{- $hasExternalCredentialDriver := or (eq (include "openshell.credentialDriverEnabled" (list . "kubernetes-secrets")) "true") (eq (include "openshell.credentialDriverEnabled" (list . "vault")) "true") -}}
{{- $vaultCredentialDriverEnabled := eq (include "openshell.credentialDriverEnabled" (list . "vault")) "true" -}}
{{- $credentialDrivers := .Values.credentialDrivers | default dict -}}
{{- $vaultResources := get $credentialDrivers "vault" | default dict -}}
{{- $legacyCredentialDrivers := .Values.server.credentialDrivers | default dict -}}
{{- $legacyVaultResources := get $legacyCredentialDrivers "vault" | default dict -}}
{{- $vaultCaConfigMapName := get $vaultResources "caConfigMapName" | default (get $legacyVaultResources "caConfigMapName") -}}
metadata:
annotations:
# Roll the gateway workload when the rendered gateway TOML changes - the
# gateway only reads /etc/openshell/gateway.toml at startup, so without
# this annotation a `helm upgrade` that only mutates the ConfigMap would
# leave pods running with stale config.
checksum/gateway-config: {{ include (print $.Template.BasePath "/gateway-config.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
{{- include "openshell.labels" . | nindent 4 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
terminationGracePeriodSeconds: {{ .Values.podLifecycle.terminationGracePeriodSeconds }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 4 }}
{{- end }}
serviceAccountName: {{ include "openshell.serviceAccountName" . }}
{{- if .Values.server.hostGatewayIP }}
hostAliases:
- ip: {{ .Values.server.hostGatewayIP | quote }}
hostnames:
- host.docker.internal
- host.openshell.internal
{{- end }}
{{- with .Values.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 4 }}
{{- end }}
containers:
- name: openshell-gateway
securityContext:
{{- toYaml .Values.securityContext | nindent 8 }}
image: {{ include "openshell.image" . | quote }}
imagePullPolicy: {{ .Values.gateway.image.pullPolicy | default .Values.global.image.pullPolicy }}
args:
- --config
- /etc/openshell/gateway.toml
{{- if not .Values.server.externalDbSecret }}
- --db-url
- {{ .Values.server.dbUrl | quote }}
{{- end }}
env:
- name: OPENSHELL_REPLICA_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OPENSHELL_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OPENSHELL_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- if eq (include "openshell.workloadKind" .) "deployment" }}
- name: OPENSHELL_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: OPENSHELL_PEER_ENDPOINT
value: {{ printf "%s://$(OPENSHELL_POD_IP):%d" (ternary "http" "https" (default false .Values.server.disableTls)) (int .Values.service.port) | quote }}
{{- end }}
- name: OPENSHELL_SERVICE_ACCOUNT_NAME
value: {{ include "openshell.serviceAccountName" . | quote }}
- name: OPENSHELL_PEER_SERVICE_NAME
value: {{ include "openshell.peerServiceName" . | quote }}
- name: OPENSHELL_PEER_TOKEN_AUDIENCE
value: "openshell-gateway-peer"
- name: OPENSHELL_PEER_SERVICE_ACCOUNT_TOKEN_FILE
value: /var/run/secrets/openshell-peer/token
- name: OPENSHELL_PEER_POD_LABELS
value: {{ printf "app.kubernetes.io/name=%s,app.kubernetes.io/instance=%s" (include "openshell.name" .) .Release.Name | quote }}
{{- if not .Values.server.disableTls }}
- name: OPENSHELL_PEER_TLS_SERVER_NAME
value: {{ printf "%s.%s.svc.cluster.local" (include "openshell.fullname" .) .Release.Namespace | quote }}
{{- if or .Values.pkiInitJob.enabled .Values.certManager.enabled }}
- name: OPENSHELL_PEER_TLS_CA_FILE
value: /etc/openshell-tls/server/ca.crt
{{- end }}
{{- if eq (include "openshell.gatewayClientCaEnabled" .) "true" }}
- name: OPENSHELL_PEER_TLS_CERT_FILE
value: /etc/openshell-tls/peer-client/tls.crt
- name: OPENSHELL_PEER_TLS_KEY_FILE
value: /etc/openshell-tls/peer-client/tls.key
{{- end }}
{{- end }}
{{- if not $hasExternalCredentialDriver }}
- name: {{ include "openshell.credentialStorageKeyEncryptionKeyEnvName" . }}
valueFrom:
secretKeyRef:
name: {{ include "openshell.credentialStorageKeyEncryptionKeySecretName" . }}
key: {{ include "openshell.credentialStorageKeyEncryptionKeySecretKey" . }}
{{- end }}
{{- if .Values.server.externalDbSecret }}
- name: OPENSHELL_DB_URL
valueFrom:
secretKeyRef:
name: {{ .Values.server.externalDbSecret }}
key: uri
{{- end }}
# Most gateway settings live in the ConfigMap-backed TOML file
# mounted at /etc/openshell/gateway.toml. Secret-bearing settings use
# env vars that the TOML references by name. Some process-level
# settings consumed by libraries outside gateway code also remain here.
{{- if and (get $oidcRuntimeConfig "issuer") .Values.server.oidc.caConfigMapName }}
# OIDC issuer custom-CA: rustls/reqwest read SSL_CERT_FILE for
# outbound TLS verification. This is a process-level env var
# consumed by the TLS stack itself, not by gateway code, so it
# cannot be represented in the gateway TOML schema.
- name: SSL_CERT_FILE
value: /etc/openshell-tls/oidc-ca/ca.crt
{{- end }}
- name: OPENSHELL_TELEMETRY_ENABLED
value: {{ .Values.server.telemetryEnabled | quote }}
{{- if $spiffeSocketPath }}
- name: OPENSHELL_GATEWAY_SPIFFE_WORKLOAD_API_SOCKET
value: {{ $spiffeSocketPath | quote }}
{{- end }}
volumeMounts:
{{- if eq (include "openshell.workloadKind" .) "statefulset" }}
- name: openshell-data
mountPath: /var/openshell
{{- end }}
# ConfigMap directory mounts expose keys through atomic-writer symlinks,
# while the gateway intentionally rejects symlinked configuration.
# The checksum annotation above rolls pods when this subPath changes.
- name: gateway-config
mountPath: /etc/openshell/gateway.toml
subPath: gateway.toml
readOnly: true
- name: sandbox-jwt
mountPath: /etc/openshell-jwt
readOnly: true
- name: gateway-peer-token
mountPath: /var/run/secrets/openshell-peer
readOnly: true
{{- if not .Values.server.disableTls }}
- name: tls-cert
mountPath: /etc/openshell-tls/server
readOnly: true
{{- if .Values.certManager.serverIssuerRef.name }}
- name: tls-external-cert
mountPath: /etc/openshell-tls/server-external
readOnly: true
{{- end }}
{{- if eq (include "openshell.gatewayClientCaEnabled" .) "true" }}
- name: peer-client-tls
mountPath: /etc/openshell-tls/peer-client
readOnly: true
- name: tls-client-ca
mountPath: /etc/openshell-tls/client-ca
readOnly: true
{{- end }}
{{- end }}
{{- if and (get $oidcRuntimeConfig "issuer") .Values.server.oidc.caConfigMapName }}
- name: oidc-ca
mountPath: /etc/openshell-tls/oidc-ca
readOnly: true
{{- end }}
{{- if and $vaultCredentialDriverEnabled $vaultCaConfigMapName }}
- name: vault-ca
mountPath: /etc/openshell-tls/vault-ca
readOnly: true
{{- end }}
{{- if .Values.upstreamProxy.caBundle.configMapName }}
- name: upstream-proxy-ca
mountPath: /etc/openshell-tls/proxy-ca
readOnly: true
{{- end }}
{{- if $spiffeSocketPath }}
- name: spiffe-workload-api
mountPath: {{ dir $spiffeSocketPath | quote }}
readOnly: true
{{- end }}
{{- with .Values.server.extraVolumeMounts }}
{{- toYaml . | nindent 8 }}
{{- end }}
ports:
- name: grpc
containerPort: {{ .Values.service.port }}
protocol: TCP
- name: health
containerPort: {{ .Values.service.healthPort }}
protocol: TCP
{{- if .Values.service.metricsPort }}
- name: metrics
containerPort: {{ .Values.service.metricsPort }}
protocol: TCP
{{- end }}
startupProbe:
httpGet:
path: /healthz
port: health
periodSeconds: {{ .Values.probes.startup.periodSeconds }}
timeoutSeconds: {{ .Values.probes.startup.timeoutSeconds }}
failureThreshold: {{ .Values.probes.startup.failureThreshold }}
livenessProbe:
httpGet:
path: /healthz
port: health
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
readinessProbe:
httpGet:
path: /readyz
port: health
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
resources:
{{- toYaml .Values.resources | nindent 8 }}
volumes:
- name: gateway-config
configMap:
name: {{ include "openshell.fullname" . }}-config
- name: sandbox-jwt
secret:
secretName: {{ include "openshell.sandboxJwtSecretName" . }}
defaultMode: {{ .Values.server.sandboxJwt.secretDefaultMode | default 0400 }}
- name: gateway-peer-token
projected:
defaultMode: 0400
sources:
- serviceAccountToken:
path: token
audience: openshell-gateway-peer
expirationSeconds: 3600
{{- if not .Values.server.disableTls }}
- name: tls-cert
secret:
secretName: {{ .Values.server.tls.certSecretName }}
{{- if .Values.certManager.serverIssuerRef.name }}
- name: tls-external-cert
secret:
secretName: {{ include "openshell.fullname" . }}-server-external-tls
{{- end }}
{{- if eq (include "openshell.gatewayClientCaEnabled" .) "true" }}
- name: peer-client-tls
secret:
secretName: {{ .Values.server.tls.clientTlsSecretName }}
- name: tls-client-ca
secret:
{{- if or (and .Values.pkiInitJob.enabled (not .Values.certManager.enabled)) (and .Values.certManager.enabled .Values.certManager.clientCaFromServerTlsSecret) }}
secretName: {{ .Values.server.tls.certSecretName }}
items:
- key: ca.crt
path: ca.crt
{{- else }}
secretName: {{ .Values.server.tls.clientCaSecretName }}
{{- end }}
{{- end }}
{{- end }}
{{- if and (get $oidcRuntimeConfig "issuer") .Values.server.oidc.caConfigMapName }}
- name: oidc-ca
configMap:
name: {{ .Values.server.oidc.caConfigMapName }}
{{- end }}
{{- if and $vaultCredentialDriverEnabled $vaultCaConfigMapName }}
- name: vault-ca
configMap:
name: {{ $vaultCaConfigMapName }}
items:
- key: ca.crt
path: ca.crt
{{- end }}
{{- if .Values.upstreamProxy.caBundle.configMapName }}
- name: upstream-proxy-ca
configMap:
name: {{ .Values.upstreamProxy.caBundle.configMapName | quote }}
items:
- key: {{ .Values.upstreamProxy.caBundle.key | default "ca.crt" | quote }}
path: ca.crt
{{- end }}
{{- if $spiffeSocketPath }}
- name: spiffe-workload-api
csi:
driver: csi.spiffe.io
readOnly: true
{{- end }}
{{- with .Values.server.extraVolumes }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}