fix(deploy): scope the Helm Rust switch to the proxy container and type it
Some checks failed
Cost map pins recheck / rerun-cost-map-guard (push) Has been cancelled
LiteLLM Rust DB / db-queries (push) Has been cancelled
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
LiteLLM Rust / rust-wheel (push) Has been cancelled
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled

Rename the value to rust.enabled and gateway.rust.enabled, since it sets the
process-wide LITELLM_RUST. In litellm-helm it moves out of the shared
proxyEnv helper so the collector sidecar no longer receives it, matching the
component chart. A values.schema.json entry rejects non-boolean values at
install time, and an extraEnvVars entry now suppresses the chart value
instead of producing a duplicate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yujong Lee 2026-11-06 04:13:10 +09:00
parent 6720140bc9
commit 30cd152748
10 changed files with 176 additions and 78 deletions

View file

@ -285,10 +285,6 @@ and the same spend transaction buffer.
- name: LITELLM_LOG
value: {{ .Values.logLevel | quote }}
{{- end }}
{{- if and (not (kindIs "invalid" .Values.rustGateway.enabled)) (not (hasKey (default dict .Values.envVars) "LITELLM_RUST")) }}
- name: LITELLM_RUST
value: {{ .Values.rustGateway.enabled | toString | quote }}
{{- end }}
{{- if .Values.envVars }}
{{- range $key, $val := .Values.envVars }}
- name: {{ $key }}

View file

@ -58,6 +58,14 @@ spec:
env:
{{- include "litellm.lensConnectionEnv" . | nindent 12 }}
{{- include "litellm.proxyEnv" . | nindent 12 }}
{{- $userSetsRust := hasKey (default dict .Values.envVars) "LITELLM_RUST" }}
{{- range .Values.extraEnvVars }}
{{- if eq .name "LITELLM_RUST" }}{{ $userSetsRust = true }}{{ end }}
{{- end }}
{{- if and (kindIs "bool" .Values.rust.enabled) (not $userSetsRust) }}
- name: LITELLM_RUST
value: {{ .Values.rust.enabled | quote }}
{{- end }}
{{- if .Values.liteadmin.enabled }}
- name: LITELLM_ADMIN_AGENT_URL
value: {{ printf "http://%s-liteadmin:10000" (include "litellm.fullname" . | trunc 53 | trimSuffix "-") | quote }}

View file

@ -1,52 +0,0 @@
suite: Rust forwarding gateway
templates:
- deployment.yaml
- configmap-litellm.yaml
tests:
- it: leaves the image default in place when unset
template: deployment.yaml
asserts:
- notContains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
any: true
- it: turns forwarding off explicitly
template: deployment.yaml
set:
rustGateway.enabled: false
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "false"
- it: enables forwarding without changing command or probes
template: deployment.yaml
set:
rustGateway.enabled: true
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "true"
- equal:
path: spec.template.spec.containers[0].livenessProbe.httpGet.port
value: http
- it: respects an explicit environment override
template: deployment.yaml
set:
rustGateway.enabled: true
envVars.LITELLM_RUST: "false"
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "false"
- notContains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "true"

View file

@ -0,0 +1,87 @@
suite: Rust switch
templates:
- deployment.yaml
- configmap-litellm.yaml
tests:
- it: leaves LITELLM_RUST unset by default
template: deployment.yaml
asserts:
- notContains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
any: true
- it: sets LITELLM_RUST to false
template: deployment.yaml
set:
rust.enabled: false
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "false"
- it: sets LITELLM_RUST to true
template: deployment.yaml
set:
rust.enabled: true
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "true"
- it: keeps LITELLM_RUST off the collector sidecar
template: deployment.yaml
set:
rust.enabled: true
collector.enabled: true
asserts:
- equal:
path: spec.template.spec.containers[1].name
value: litellm-collector
- notContains:
path: spec.template.spec.containers[1].env
content:
name: LITELLM_RUST
any: true
- it: lets envVars override the value
template: deployment.yaml
set:
rust.enabled: true
envVars.LITELLM_RUST: "false"
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "false"
- notContains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "true"
- it: lets extraEnvVars override the value without a duplicate entry
template: deployment.yaml
set:
rust.enabled: true
extraEnvVars:
- name: LITELLM_RUST
value: "false"
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "false"
- notContains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "true"
- it: rejects a value that is not a boolean
template: deployment.yaml
set:
rust.enabled: "yes"
asserts:
- failedTemplate: {}

View file

@ -0,0 +1,16 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"rust": {
"properties": {
"enabled": {
"type": [
"boolean",
"null"
]
}
}
}
}
}

View file

@ -4,9 +4,14 @@
replicaCount: 1
rustGateway:
# null inherits the image default; true or false sets LITELLM_RUST
rust:
# Sets LITELLM_RUST on the proxy container. null leaves it unset. true runs the
# Rust forwarding server on the public port in front of the Python workers and
# turns on the opt-in Rust routes, false keeps every switchable route on Python.
# A LITELLM_RUST in envVars or extraEnvVars wins, and this wins over one from
# environmentSecrets or environmentConfigMaps
enabled:
liteadmin:
enabled: false
existingSecret: ""

View file

@ -60,16 +60,13 @@ spec:
- name: LITELLM_CORS_ORIGINS
value: {{ include "litellm.ui.publicOrigin" . | quote }}
{{- end }}
{{- $rustGateway := .Values.gateway.rustGateway | default dict }}
{{- $rustGatewayOverridden := false }}
{{- $userSetsRust := false }}
{{- range .Values.gateway.extraEnv }}
{{- if eq .name "LITELLM_RUST" }}
{{- $rustGatewayOverridden = true }}
{{- if eq .name "LITELLM_RUST" }}{{ $userSetsRust = true }}{{ end }}
{{- end }}
{{- end }}
{{- if and (not (kindIs "invalid" $rustGateway.enabled)) (not $rustGatewayOverridden) }}
{{- if and (kindIs "bool" .Values.gateway.rust.enabled) (not $userSetsRust) }}
- name: LITELLM_RUST
value: {{ $rustGateway.enabled | toString | quote }}
value: {{ .Values.gateway.rust.enabled | quote }}
{{- end }}
{{- include "litellm.serverEnv" (dict "root" $ "component" .Values.gateway) | nindent 12 }}
{{- if .Values.gateway.config.create }}

View file

@ -1,11 +1,11 @@
suite: Rust forwarding gateway
suite: Rust switch
templates:
- gateway/deployment.yaml
- gateway/configmap.yaml
values:
- ./values/required.yaml
tests:
- it: leaves the image default in place when unset
- it: leaves LITELLM_RUST unset by default
template: gateway/deployment.yaml
asserts:
- notContains:
@ -13,33 +13,44 @@ tests:
content:
name: LITELLM_RUST
any: true
- it: turns forwarding off explicitly
- it: sets LITELLM_RUST to false
template: gateway/deployment.yaml
set:
gateway.rustGateway.enabled: false
gateway.rust.enabled: false
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "false"
- it: enables forwarding without changing command or probes
- it: sets LITELLM_RUST to true
template: gateway/deployment.yaml
set:
gateway.rustGateway.enabled: true
gateway.rust.enabled: true
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: LITELLM_RUST
value: "true"
- equal:
path: spec.template.spec.containers[0].livenessProbe.httpGet.port
value: http
- it: respects an explicit extraEnv override
- it: keeps LITELLM_RUST off the collector sidecar
template: gateway/deployment.yaml
set:
gateway.rustGateway.enabled: true
gateway.rust.enabled: true
gateway.collector.enabled: true
asserts:
- equal:
path: spec.template.spec.containers[1].name
value: collector
- notContains:
path: spec.template.spec.containers[1].env
content:
name: LITELLM_RUST
any: true
- it: lets extraEnv override the value
template: gateway/deployment.yaml
set:
gateway.rust.enabled: true
gateway.extraEnv:
- name: LITELLM_RUST
value: "false"
@ -54,3 +65,9 @@ tests:
content:
name: LITELLM_RUST
value: "true"
- it: rejects a value that is not a boolean
template: gateway/deployment.yaml
set:
gateway.rust.enabled: "yes"
asserts:
- failedTemplate: {}

View file

@ -0,0 +1,20 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"gateway": {
"properties": {
"rust": {
"properties": {
"enabled": {
"type": [
"boolean",
"null"
]
}
}
}
}
}
}
}

View file

@ -294,8 +294,12 @@ gateway:
# Number of uvicorn worker processes per gateway pod. Sets NUM_WORKERS,
# consumed by the gateway image entrypoint. Default is 1.
numWorkers: 1
rustGateway:
# null inherits the image default; true or false sets LITELLM_RUST
rust:
# Sets LITELLM_RUST on the gateway container. null leaves it unset. true runs
# the Rust forwarding server on the public port in front of the Python workers
# and turns on the opt-in Rust routes, false keeps every switchable route on
# Python. A LITELLM_RUST in extraEnv wins, and this wins over one from
# envConfigMaps or envSecrets
enabled:
extraEnv: [] # Add extra environment variables to the gateway
envConfigMaps: [] # Add extra environment variables to the gateway from config maps