improvement(helm): add internal ingress support and same-host path consolidation (#2960)

* improvement(helm): add internal ingress support and same-host path consolidation

* improvement(helm): clean up ingress template comments

Simplify verbose inline Helm comments and section dividers to match the
minimal style used in services.yaml.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(helm): add missing copilot path consolidation for realtime host

When copilot.host equals realtime.host but differs from app.host,
copilot paths were not being routed. Added logic to consolidate
copilot paths into the realtime rule for this scenario.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* improvement(helm): follow ingress best practices

- Remove orphan comments that appeared when services were disabled
- Add documentation about path ordering requirements
- Paths rendered in order: realtime, copilot, app (specific before catch-all)
- Clean template output matching industry Helm chart standards

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Waleed
2026-01-23 18:44:18 -08:00
committed by GitHub
parent f44594c380
commit f0ee67f3ed
4 changed files with 228 additions and 30 deletions

View File

@@ -172,29 +172,56 @@ ollama:
OLLAMA_KEEP_ALIVE: "-1"
OLLAMA_DEBUG: "1"
# Ingress configuration (NGINX ingress controller on Azure AKS)
# Ingress configuration
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# Main application
app:
host: simstudio.acme.com
paths:
- path: /
pathType: Prefix
# Realtime service
realtime:
host: simstudio-ws.acme.com
paths:
- path: /
pathType: Prefix
# TLS configuration
tls:
enabled: true
secretName: simstudio-tls-secret
secretName: simstudio-tls-secret
# Internal Ingress configuration
ingressInternal:
enabled: false
className: azure-application-gateway
annotations:
appgw.ingress.kubernetes.io/use-private-ip: "true"
# Main application
app:
host: simstudio-internal.acme.local
paths:
- path: /
pathType: Prefix
# Realtime service
realtime:
host: simstudio-internal.acme.local
paths:
- path: /socket.io
pathType: Prefix
# TLS configuration
tls:
enabled: true
secretName: simstudio-internal-tls-secret

View File

@@ -0,0 +1,105 @@
{{- if .Values.ingressInternal.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "sim.fullname" . }}-ingress-internal
namespace: {{ .Release.Namespace }}
labels:
{{- include "sim.labels" . | nindent 4 }}
{{- with .Values.ingressInternal.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingressInternal.className }}
ingressClassName: {{ .Values.ingressInternal.className }}
{{- end }}
{{- if .Values.ingressInternal.tls.enabled }}
tls:
- hosts:
- {{ .Values.ingressInternal.app.host | quote }}
{{- if and .Values.realtime.enabled (ne .Values.ingressInternal.realtime.host .Values.ingressInternal.app.host) }}
- {{ .Values.ingressInternal.realtime.host | quote }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingressInternal.copilot }}
{{- if and (ne .Values.ingressInternal.copilot.host .Values.ingressInternal.app.host) (ne .Values.ingressInternal.copilot.host .Values.ingressInternal.realtime.host) }}
- {{ .Values.ingressInternal.copilot.host | quote }}
{{- end }}
{{- end }}
secretName: {{ .Values.ingressInternal.tls.secretName }}
{{- end }}
rules:
- host: {{ .Values.ingressInternal.app.host | quote }}
http:
paths:
{{- if and .Values.realtime.enabled (eq .Values.ingressInternal.realtime.host .Values.ingressInternal.app.host) }}
{{- range .Values.ingressInternal.realtime.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-realtime
port:
number: {{ $.Values.realtime.service.port }}
{{- end }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingressInternal.copilot (eq .Values.ingressInternal.copilot.host .Values.ingressInternal.app.host) }}
{{- range .Values.ingressInternal.copilot.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-copilot
port:
number: {{ $.Values.copilot.server.service.port }}
{{- end }}
{{- end }}
{{- range .Values.ingressInternal.app.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-app
port:
number: {{ $.Values.app.service.port }}
{{- end }}
{{- if and .Values.realtime.enabled (ne .Values.ingressInternal.realtime.host .Values.ingressInternal.app.host) }}
- host: {{ .Values.ingressInternal.realtime.host | quote }}
http:
paths:
{{- range .Values.ingressInternal.realtime.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-realtime
port:
number: {{ $.Values.realtime.service.port }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingressInternal.copilot (eq .Values.ingressInternal.copilot.host .Values.ingressInternal.realtime.host) }}
{{- range .Values.ingressInternal.copilot.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-copilot
port:
number: {{ $.Values.copilot.server.service.port }}
{{- end }}
{{- end }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingressInternal.copilot (and (ne .Values.ingressInternal.copilot.host .Values.ingressInternal.app.host) (ne .Values.ingressInternal.copilot.host .Values.ingressInternal.realtime.host)) }}
- host: {{ .Values.ingressInternal.copilot.host | quote }}
http:
paths:
{{- range .Values.ingressInternal.copilot.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-copilot
port:
number: {{ $.Values.copilot.server.service.port }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -17,20 +17,43 @@ spec:
{{- if .Values.ingress.tls.enabled }}
tls:
- hosts:
- {{ .Values.ingress.app.host }}
{{- if .Values.realtime.enabled }}
- {{ .Values.ingress.realtime.host }}
- {{ .Values.ingress.app.host | quote }}
{{- if and .Values.realtime.enabled (ne .Values.ingress.realtime.host .Values.ingress.app.host) }}
- {{ .Values.ingress.realtime.host | quote }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingress.copilot }}
- {{ .Values.ingress.copilot.host }}
{{- if and (ne .Values.ingress.copilot.host .Values.ingress.app.host) (ne .Values.ingress.copilot.host .Values.ingress.realtime.host) }}
- {{ .Values.ingress.copilot.host | quote }}
{{- end }}
{{- end }}
secretName: {{ .Values.ingress.tls.secretName }}
{{- end }}
rules:
# Main application ingress rule
- host: {{ .Values.ingress.app.host }}
- host: {{ .Values.ingress.app.host | quote }}
http:
paths:
{{- if and .Values.realtime.enabled (eq .Values.ingress.realtime.host .Values.ingress.app.host) }}
{{- range .Values.ingress.realtime.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-realtime
port:
number: {{ $.Values.realtime.service.port }}
{{- end }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingress.copilot (eq .Values.ingress.copilot.host .Values.ingress.app.host) }}
{{- range .Values.ingress.copilot.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-copilot
port:
number: {{ $.Values.copilot.server.service.port }}
{{- end }}
{{- end }}
{{- range .Values.ingress.app.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
@@ -40,9 +63,8 @@ spec:
port:
number: {{ $.Values.app.service.port }}
{{- end }}
{{- if .Values.realtime.enabled }}
# Realtime service ingress rule
- host: {{ .Values.ingress.realtime.host }}
{{- if and .Values.realtime.enabled (ne .Values.ingress.realtime.host .Values.ingress.app.host) }}
- host: {{ .Values.ingress.realtime.host | quote }}
http:
paths:
{{- range .Values.ingress.realtime.paths }}
@@ -54,10 +76,20 @@ spec:
port:
number: {{ $.Values.realtime.service.port }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingress.copilot (eq .Values.ingress.copilot.host .Values.ingress.realtime.host) }}
{{- range .Values.ingress.copilot.paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "sim.fullname" $ }}-copilot
port:
number: {{ $.Values.copilot.server.service.port }}
{{- end }}
{{- end }}
{{- end }}
{{- if and .Values.copilot.enabled .Values.ingress.copilot }}
# Copilot service ingress rule
- host: {{ .Values.ingress.copilot.host }}
{{- if and .Values.copilot.enabled .Values.ingress.copilot (and (ne .Values.ingress.copilot.host .Values.ingress.app.host) (ne .Values.ingress.copilot.host .Values.ingress.realtime.host)) }}
- host: {{ .Values.ingress.copilot.host | quote }}
http:
paths:
{{- range .Values.ingress.copilot.paths }}
@@ -70,4 +102,4 @@ spec:
number: {{ $.Values.copilot.server.service.port }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -552,36 +552,70 @@ ollama:
extraVolumeMounts: []
# Ingress configuration
# When services share the same host, paths are consolidated into a single rule.
# Path order: realtime paths, copilot paths, then app paths (most specific first).
# Ensure specific paths (e.g., /socket.io, /copilot) come before catch-all paths (/).
ingress:
# Enable/disable ingress
enabled: false
# Ingress class name
className: nginx
# Annotations
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# Main application host configuration
# Main application (use / as catch-all)
app:
host: sim.local
paths:
- path: /
pathType: Prefix
# Realtime service host configuration
# Realtime service (use /socket.io when sharing host with app)
realtime:
host: sim-ws.local
paths:
- path: /
pathType: Prefix
# TLS configuration
# Copilot service (optional, use /copilot when sharing host)
# copilot:
# host: sim.local
# paths:
# - path: /copilot
# pathType: Prefix
tls:
enabled: false
secretName: sim-tls-secret
# Internal Ingress configuration
# Same path ordering rules apply as above.
ingressInternal:
enabled: false
className: nginx
annotations: {}
app:
host: sim-internal.local
paths:
- path: /
pathType: Prefix
realtime:
host: sim-internal.local
paths:
- path: /socket.io
pathType: Prefix
# copilot:
# host: sim-internal.local
# paths:
# - path: /copilot
# pathType: Prefix
tls:
enabled: false
secretName: sim-internal-tls-secret
# Service Account configuration
serviceAccount:
# Specifies whether a service account should be created