mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
feat(helm): route extra ingress paths to custom services (#48674)
This commit is contained in:
parent
21ab2cb87b
commit
e101449816
3 changed files with 180 additions and 3 deletions
|
|
@ -23,3 +23,23 @@ ui:
|
|||
backend:
|
||||
gatewayUrl: https://gateway.example.com
|
||||
```
|
||||
|
||||
## Routes to another Service
|
||||
|
||||
For a shared hostname, `ingress.extraPaths` can route to a Service in the same namespace using `serviceName` and `servicePort`. The port can be a number or a named Service port. Omit `service` when using these fields
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
className: alb
|
||||
host: gateway.example.com
|
||||
extraPaths:
|
||||
- path: /moyai
|
||||
pathType: Prefix
|
||||
serviceName: moyai-ingress
|
||||
servicePort: 8080
|
||||
```
|
||||
|
||||
The Service and application must already support the path prefix. The chart adds the path to the existing Ingress and leaves its built-in routes in place. It does not create the target Service or rewrite requests
|
||||
|
||||
For AWS ALB, configure the target Service's `alb.ingress.kubernetes.io/healthcheck-path` annotation when the application needs a different health check from LiteLLM. Existing `service` aliases (`gateway`, `backend`, `ui`) remain supported
|
||||
|
|
|
|||
|
|
@ -277,11 +277,34 @@ spec:
|
|||
{{- if not $extra.path }}
|
||||
{{- fail (printf "ingress.extraPaths[%d]: 'path' is required" $idx) }}
|
||||
{{- end }}
|
||||
{{- $target := dict }}
|
||||
{{- $port := dict }}
|
||||
{{- if or (hasKey $extra "serviceName") (hasKey $extra "servicePort") }}
|
||||
{{- if hasKey $extra "service" }}
|
||||
{{- fail (printf "ingress.extraPaths[%d]: service cannot be combined with serviceName or servicePort" $idx) }}
|
||||
{{- end }}
|
||||
{{- if not (and (kindIs "string" $extra.serviceName) $extra.serviceName $extra.servicePort) }}
|
||||
{{- fail (printf "ingress.extraPaths[%d]: a non-empty serviceName and servicePort are required for a custom Service" $idx) }}
|
||||
{{- end }}
|
||||
{{- $target = dict "name" $extra.serviceName }}
|
||||
{{- if kindIs "string" $extra.servicePort }}
|
||||
{{- $port = dict "name" $extra.servicePort }}
|
||||
{{- else if or (kindIs "float64" $extra.servicePort) (kindIs "int64" $extra.servicePort) (kindIs "int" $extra.servicePort) }}
|
||||
{{- if or (lt (float64 $extra.servicePort) 1.0) (gt (float64 $extra.servicePort) 65535.0) (ne (float64 $extra.servicePort) (float64 (int $extra.servicePort))) }}
|
||||
{{- fail (printf "ingress.extraPaths[%d]: numeric servicePort must be an integer from 1 to 65535" $idx) }}
|
||||
{{- end }}
|
||||
{{- $port = dict "number" (int $extra.servicePort) }}
|
||||
{{- else }}
|
||||
{{- fail (printf "ingress.extraPaths[%d]: servicePort must be a port number or name" $idx) }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- $service := $extra.service | default "gateway" }}
|
||||
{{- $target := get $extraPathBackends $service }}
|
||||
{{- $target = get $extraPathBackends $service }}
|
||||
{{- if not $target }}
|
||||
{{- fail (printf "ingress.extraPaths[%d] (path %s): unknown service %q, expected one of backend, gateway, ui" $idx $extra.path $service) }}
|
||||
{{- end }}
|
||||
{{- $port = dict "number" $target.port }}
|
||||
{{- end }}
|
||||
{{- $requestedPathType := $extra.pathType | default "Prefix" }}
|
||||
{{- if not (has $requestedPathType (list "Prefix" "Exact" "ImplementationSpecific")) }}
|
||||
{{- fail (printf "ingress.extraPaths[%d] (path %s): unknown pathType %q, expected one of Exact, ImplementationSpecific, Prefix" $idx $extra.path $requestedPathType) }}
|
||||
|
|
@ -297,9 +320,9 @@ spec:
|
|||
pathType: {{ $pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ $target.name }}
|
||||
name: {{ $target.name | quote }}
|
||||
port:
|
||||
number: {{ $target.port }}
|
||||
{{- toYaml $port | nindent 18 }}
|
||||
{{- end }}
|
||||
# --- Catch-all → backend (management API: /key/*, /user/*, /team/*, ...) ---
|
||||
- path: /
|
||||
|
|
|
|||
|
|
@ -326,3 +326,137 @@ tests:
|
|||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "ingress.extraPaths[0]: each entry must be a mapping with a 'path' key"
|
||||
|
||||
- it: routes a custom Service by number without replacing the existing ingress
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.className: alb
|
||||
ingress.host: gateway.example.com
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
serviceName: moyai-ingress
|
||||
servicePort: 8080
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: RELEASE-NAME-litellm
|
||||
- equal:
|
||||
path: spec.ingressClassName
|
||||
value: alb
|
||||
- equal:
|
||||
path: spec.rules[0].host
|
||||
value: gateway.example.com
|
||||
- equal:
|
||||
path: spec.rules[0].http.paths[-2]
|
||||
value:
|
||||
path: /moyai
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: moyai-ingress
|
||||
port:
|
||||
number: 8080
|
||||
- equal:
|
||||
path: spec.rules[0].http.paths[-1].backend.service.name
|
||||
value: RELEASE-NAME-litellm-backend
|
||||
- equal:
|
||||
path: spec.rules[0].http.paths[0].backend.service.name
|
||||
value: RELEASE-NAME-litellm-ui
|
||||
|
||||
- it: routes a custom Service by named port alongside a component alias
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
serviceName: moyai-ingress
|
||||
servicePort: http
|
||||
- path: /watsonx
|
||||
service: gateway
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.rules[0].http.paths[-3].backend.service
|
||||
value:
|
||||
name: moyai-ingress
|
||||
port:
|
||||
name: http
|
||||
- equal:
|
||||
path: spec.rules[0].http.paths[-2].backend.service.name
|
||||
value: RELEASE-NAME-litellm-gateway
|
||||
|
||||
- it: rejects ambiguous component and custom Service selectors
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
service: gateway
|
||||
serviceName: moyai-ingress
|
||||
servicePort: 8080
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: service cannot be combined with serviceName or servicePort'
|
||||
|
||||
- it: rejects a custom Service without its port
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
serviceName: moyai-ingress
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: a non-empty serviceName and servicePort are required for a custom Service'
|
||||
|
||||
- it: rejects a custom Service port without its name
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
servicePort: 8080
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: a non-empty serviceName and servicePort are required for a custom Service'
|
||||
|
||||
- it: rejects a non scalar port
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
serviceName: moyai-ingress
|
||||
servicePort: {number: 8080}
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: servicePort must be a port number or name'
|
||||
|
||||
- it: rejects a fractional port
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
serviceName: moyai-ingress
|
||||
servicePort: 8080.5
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: numeric servicePort must be an integer from 1 to 65535'
|
||||
|
||||
- it: rejects an out of range port
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /moyai
|
||||
serviceName: moyai-ingress
|
||||
servicePort: 65536
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: numeric servicePort must be an integer from 1 to 65535'
|
||||
|
||||
- it: rejects a custom Service taking over a built in path
|
||||
set:
|
||||
ingress.enabled: true
|
||||
ingress.extraPaths:
|
||||
- path: /v1/chat
|
||||
serviceName: moyai-ingress
|
||||
servicePort: 8080
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: 'ingress.extraPaths[0]: path /v1/chat with pathType Prefix is already routed by this chart, and a duplicate would take it over rather than add to it'
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue