Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions charts/llm-d-async/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
llm-d-async {{ .Chart.AppVersion }} has been installed as {{ include "llm-d-async.fullname" . }}.

Transport: {{ include "llm-d-async.transport" . }}

The processor is configured through the unified transport surface
(--transport / --transport-config); no deprecated CLI flags are emitted.
{{- if include "llm-d-async.usingDeprecatedTransport" . }}

WARNING: deprecated chart values in use.
You configured the transport with the deprecated per-backend values
(ap.redis.enabled / ap.gcpPubSub.enabled / ap.messageQueueImpl and the
per-backend ap.redis.* / ap.gcpPubSub.* request/queue fields, ap.otel.redisTracing).
They still work — the chart translates them into the transport config — but
will be removed in a future release. Migrate to the unified surface:

ap:
transport: {{ include "llm-d-async.transport" . }}
transportConfig:
# transport-specific JSON document; see the chart README and the
# "Transport Configuration" section of the project README.
{{- end }}
{{- if include "llm-d-async.usingDeprecatedRedisConn" . }}

WARNING: deprecated Redis connection values in use.
ap.redis.url / ap.redis.secretName are deprecated. Provide the Redis/Valkey
connection on the transport surface instead — the chart injects it as REDIS_URL
and keeps it out of the pod args:

ap:
transportConfig:
urlSecret:
name: <existing-secret> # reference a Secret, OR
key: url
# or have the chart create the Secret from a literal URL:
# urlSecret:
# url: redis://...
{{- end }}
122 changes: 113 additions & 9 deletions charts/llm-d-async/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,109 @@ Create the name of the service account to use
{{- end }}

{{/*
Render gate params as JSON with all values as strings.
The gate params parser expects map[string]string, so numeric values must be quoted.
Effective transport type. Prefers the new ap.transport; otherwise derives it from
the deprecated ap.redis.enabled / ap.gcpPubSub.enabled / ap.messageQueueImpl values.
Renders empty when no backend is selected.
*/}}
{{- define "llm-d-async.gateParamsJson" -}}
{{- $out := dict -}}
{{- range $k, $v := .Values.ap.redis.gateParams -}}
{{- $_ := set $out $k ($v | toString) -}}
{{- define "llm-d-async.transport" -}}
{{- if .Values.ap.transport -}}
{{- .Values.ap.transport -}}
{{- else if .Values.ap.redis.enabled -}}
{{- if eq (.Values.ap.messageQueueImpl | default "redis-pubsub") "redis-sortedset" -}}
redis-sortedset
{{- else -}}
redis-pubsub
{{- end -}}
{{- else if .Values.ap.gcpPubSub.enabled -}}
gcp-pubsub
{{- end -}}
{{- end }}

{{/*
Transport config JSON document passed via --transport-config. On the new surface
it is ap.transportConfig verbatim; otherwise it is synthesized from the deprecated
per-backend values so existing values files keep working.
*/}}
{{- define "llm-d-async.transportConfig" -}}
{{- if .Values.ap.transport -}}
{{- /* urlSecret is a chart-only directive (it wires REDIS_URL from a Secret);
strip it so it is never passed to the processor or rendered into args. */ -}}
{{- omit .Values.ap.transportConfig "urlSecret" | toJson -}}
{{- else -}}
{{- include "llm-d-async.legacyTransportConfig" . -}}
{{- end -}}
{{- end }}

{{/*
Synthesize a transport config JSON document from the deprecated per-backend chart
values (ap.redis.* / ap.gcpPubSub.* / ap.otel.redisTracing). The Redis "url" is
deliberately left unset so the injected REDIS_URL env var supplies it.
*/}}
{{- define "llm-d-async.legacyTransportConfig" -}}
{{- $ap := .Values.ap -}}
{{- $transport := include "llm-d-async.transport" . -}}
{{- $cfg := dict -}}
{{- if eq $transport "redis-pubsub" -}}
{{- if and $ap.otel.redisTracing $ap.otel.endpoint -}}{{- $_ := set $cfg "enable_tracing" true -}}{{- end -}}
{{- if $ap.redis.queuesConfig -}}
{{- $_ := set $cfg "queues" $ap.redis.queuesConfig -}}
{{- else -}}
{{- $_ := set $cfg "queues" (list (dict "queue_name" "request-queue" "igw_base_url" $ap.igwBaseURL "request_path_url" $ap.redis.requestPathURL)) -}}
{{- end -}}
{{- else if eq $transport "redis-sortedset" -}}
{{- $_ := set $cfg "result_queue_name" ($ap.redis.resultQueueName | default "result-list") -}}
{{- $_ := set $cfg "poll_interval_ms" (int ($ap.redis.pollIntervalMs | default 1000)) -}}
{{- $_ := set $cfg "batch_size" (int ($ap.redis.batchSize | default 10)) -}}
{{- if and $ap.otel.redisTracing $ap.otel.endpoint -}}{{- $_ := set $cfg "enable_tracing" true -}}{{- end -}}
{{- if $ap.redis.queuesConfig -}}
{{- $_ := set $cfg "queues" $ap.redis.queuesConfig -}}
{{- else -}}
{{- $q := dict "queue_name" ($ap.redis.requestQueueName | default "request-sortedset") "igw_base_url" $ap.igwBaseURL "request_path_url" $ap.redis.requestPathURL -}}
{{- if $ap.redis.gateType -}}
{{- $_ := set $q "gate_type" $ap.redis.gateType -}}
{{- $gp := dict -}}
{{- range $k, $v := $ap.redis.gateParams -}}{{- $_ := set $gp $k ($v | toString) -}}{{- end -}}
{{- $_ := set $q "gate_params" $gp -}}
{{- end -}}
{{- $_ := set $cfg "queues" (list $q) -}}
{{- end -}}
{{- else if eq $transport "gcp-pubsub" -}}
{{- $_ := set $cfg "project_id" $ap.gcpPubSub.projectId -}}
{{- $_ := set $cfg "result_topic_id" $ap.gcpPubSub.resultTopicId -}}
{{- if $ap.gcpPubSub.topicsConfig -}}
{{- $_ := set $cfg "topics" $ap.gcpPubSub.topicsConfig -}}
{{- else -}}
{{- $_ := set $cfg "topics" (list (dict "subscriber_id" $ap.gcpPubSub.requestSubscriberId "igw_base_url" $ap.igwBaseURL "request_path_url" $ap.gcpPubSub.requestPathURL)) -}}
{{- end -}}
{{- end -}}
{{- $cfg | toJson -}}
{{- end }}

{{/*
Report whether any deprecated per-backend transport value is in use. Drives the
migration warning in NOTES.txt.
*/}}
{{- define "llm-d-async.usingDeprecatedTransport" -}}
{{- if and (not .Values.ap.transport) (or .Values.ap.redis.enabled .Values.ap.gcpPubSub.enabled) -}}
true
{{- end -}}
{{- end }}

{{/*
Report whether the deprecated ap.redis.* connection inputs are in use. On the new
surface the Redis connection belongs in ap.transportConfig.urlSecret; ap.redis.url
and ap.redis.secretName are retained for backwards compatibility only. Only warn
when the effective transport is Redis and the connection actually comes from
ap.redis.* (i.e. the new urlSecret surface is not configured), so the migration
notice never fires for a non-Redis backend or when urlSecret already supersedes it.
*/}}
{{- define "llm-d-async.usingDeprecatedRedisConn" -}}
{{- $transport := include "llm-d-async.transport" . -}}
{{- $ts := .Values.ap.transportConfig | default dict -}}
{{- $hasUrlSecret := or (dig "urlSecret" "url" "" $ts) (dig "urlSecret" "name" "" $ts) -}}
{{- if and (hasPrefix "redis" $transport) (not $hasUrlSecret) (or .Values.ap.redis.url .Values.ap.redis.secretName) -}}
true
{{- end -}}
{{- $out | toJson -}}
{{- end }}
Comment on lines +157 to 164

{{/*
Expand All @@ -75,7 +169,12 @@ If redis.url is set, the chart creates a Secret named <fullname>-redis.
Otherwise, use the user-provided redis.secretName.
*/}}
{{- define "llm-d-async.redisSecretName" -}}
{{- if .Values.ap.redis.url -}}
{{- $ts := .Values.ap.transportConfig | default dict -}}
{{- if and .Values.ap.transport (dig "urlSecret" "url" "" $ts) -}}
{{- printf "%s-redis" (include "llm-d-async.fullname" .) -}}
{{- else if and .Values.ap.transport (dig "urlSecret" "name" "" $ts) -}}
{{- dig "urlSecret" "name" "" $ts -}}
{{- else if .Values.ap.redis.url -}}
{{- printf "%s-redis" (include "llm-d-async.fullname" .) -}}
{{- else -}}
{{- .Values.ap.redis.secretName -}}
Expand All @@ -87,7 +186,12 @@ Resolve the Redis secret key.
When the chart creates the Secret, the key is always "url".
*/}}
{{- define "llm-d-async.redisSecretKey" -}}
{{- if .Values.ap.redis.url -}}
{{- $ts := .Values.ap.transportConfig | default dict -}}
{{- if and .Values.ap.transport (dig "urlSecret" "url" "" $ts) -}}
url
{{- else if and .Values.ap.transport (dig "urlSecret" "name" "" $ts) -}}
{{- dig "urlSecret" "key" "url" $ts | default "url" -}}
{{- else if .Values.ap.redis.url -}}
url
{{- else -}}
{{- .Values.ap.redis.secretKey -}}
Expand Down
5 changes: 1 addition & 4 deletions charts/llm-d-async/templates/ap-configmap.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- if or .Values.ap.workerPools .Values.ap.gcpPubSub.topicsConfig .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig }}
{{- if or .Values.ap.workerPools .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig }}
apiVersion: v1
kind: ConfigMap
metadata:
Expand All @@ -10,9 +10,6 @@ data:
{{- if .Values.ap.workerPools }}
worker-pools.json: {{ .Values.ap.workerPools | toJson | quote }}
{{- end }}
{{- if .Values.ap.gcpPubSub.topicsConfig }}
pubsub-topics.json: {{ .Values.ap.gcpPubSub.topicsConfig | toJson | quote }}
{{- end }}
{{- if .Values.ap.transformConfig }}
transform-config.json: {{ .Values.ap.transformConfig | toJson | quote }}
{{- end }}
Expand Down
102 changes: 30 additions & 72 deletions charts/llm-d-async/templates/ap-deployments.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
{{- /* ---- Fail-fast configuration validation ----
Turn common misconfigurations into clear install-time errors instead of
runtime crash-loops or silently dropped requests. */ -}}
{{- if not (include "llm-d-async.transport" .) }}
{{- fail "No transport configured: set ap.transport (redis-pubsub|redis-sortedset|gcp-pubsub) with ap.transportConfig, or enable a backend via ap.redis.enabled / ap.gcpPubSub.enabled (deprecated)." }}
{{- end }}
{{- if .Values.ap.transport }}
{{- /* New transport surface. */ -}}
{{- if not .Values.ap.transportConfig }}
{{- fail "ap.transport is set but ap.transportConfig is empty: provide the transport configuration document (see the README 'Transport Configuration' section)." }}
{{- end }}
{{- if and (hasPrefix "redis" .Values.ap.transport) (not (hasKey .Values.ap.transportConfig "url")) (not (include "llm-d-async.redisSecretName" .)) }}
{{- fail "redis transport has no connection: set ap.transportConfig.urlSecret.url (chart creates a Secret) or ap.transportConfig.urlSecret.name/key (reference an existing Secret), or an inline url in ap.transportConfig (dev only). The deprecated ap.redis.url / ap.redis.secretName still work. The resolved Secret is injected as REDIS_URL." }}
{{- end }}
{{- else }}
{{- /* Deprecated per-backend surface. */ -}}
{{- if .Values.ap.redis.enabled }}
{{- if and (not .Values.ap.redis.url) (not .Values.ap.redis.secretName) }}
{{- fail "ap.redis is enabled but no connection is configured: set ap.redis.url, or set ap.redis.secretName/ap.redis.secretKey to reference an existing Secret." }}
Expand All @@ -17,6 +30,10 @@
{{- fail "ap.igwBaseURL is required: set it to your inference gateway base URL, or provide per-topic igw_base_url entries via ap.gcpPubSub.topicsConfig." }}
{{- end }}
{{- end }}
{{- if and .Values.ap.redis.enabled (eq (.Values.ap.messageQueueImpl | default "redis-pubsub") "redis-sortedset") .Values.ap.redis.queuesConfig .Values.ap.redis.gateType }}
{{- fail "Cannot set both queuesConfig and gateType. Use queuesConfig with per-queue gate_type instead." }}
{{- end }}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
Expand All @@ -43,69 +60,13 @@ spec:
# Must match the binary produced by the Dockerfile (ENTRYPOINT /llm-d-async).
- /llm-d-async
args:
{{- if .Values.ap.redis.enabled }}
{{- if eq (.Values.ap.messageQueueImpl | default "redis-pubsub") "redis-sortedset" }}
- --message-queue-impl=redis-sortedset
{{- if and .Values.ap.redis.queuesConfig .Values.ap.redis.gateType }}
{{- fail "Cannot set both queuesConfig and gateType. Use queuesConfig with per-queue gate_type instead." }}
{{- end }}
{{- if .Values.ap.redis.queuesConfig }}
- --redis.ss.queues-config
- {{ .Values.ap.redis.queuesConfig | toJson | quote }}
{{- else }}
- --redis.ss.igw-base-url={{ .Values.ap.igwBaseURL }}
- --redis.ss.request-path-url
- "{{ .Values.ap.redis.requestPathURL }}"
- --redis.ss.request-queue-name
- "{{ .Values.ap.redis.requestQueueName | default "request-sortedset" }}"
{{- if .Values.ap.redis.gateType }}
- --redis.ss.gate-type={{ .Values.ap.redis.gateType }}
- --redis.ss.gate-params={{ include "llm-d-async.gateParamsJson" . }}
{{- end }}
{{- end }}
- --redis.ss.result-queue-name
- "{{ .Values.ap.redis.resultQueueName | default "result-list" }}"
- --redis.ss.poll-interval-ms
- "{{ .Values.ap.redis.pollIntervalMs | default 1000 }}"
- --redis.ss.batch-size
- "{{ .Values.ap.redis.batchSize | default 10 }}"
{{- else }}
- --message-queue-impl=redis-pubsub
{{- if .Values.ap.redis.queuesConfig }}
- --redis.queues-config
- {{ .Values.ap.redis.queuesConfig | toJson | quote }}
{{- else }}
- --redis.igw-base-url={{ .Values.ap.igwBaseURL }}
- --redis.request-path-url
- "{{ .Values.ap.redis.requestPathURL }}"
{{- end }}
{{- end }}
{{- else if .Values.ap.gcpPubSub.enabled }}
{{- /* Honor an explicit gcp-pubsub* messageQueueImpl; otherwise auto-select
gcp-pubsub-gated when any topic declares a gate_type (per-topic gates
only take effect in gated mode). */}}
{{- $mqImpl := "gcp-pubsub" }}
{{- if and .Values.ap.messageQueueImpl (hasPrefix "gcp-pubsub" .Values.ap.messageQueueImpl) }}
{{- $mqImpl = .Values.ap.messageQueueImpl }}
{{- else }}
{{- range .Values.ap.gcpPubSub.topicsConfig }}
{{- if .gate_type }}{{- $mqImpl = "gcp-pubsub-gated" }}{{- end }}
{{- end }}
{{- end }}
- --message-queue-impl={{ $mqImpl }}
{{- if .Values.ap.gcpPubSub.projectId }}
- --pubsub.project-id={{ .Values.ap.gcpPubSub.projectId }}
{{- end }}
- --pubsub.result-topic-id={{ .Values.ap.gcpPubSub.resultTopicId }}
{{- if .Values.ap.gcpPubSub.topicsConfig }}
- --pubsub.topics-config-file=/etc/llm-d-async/config/pubsub-topics.json
{{- else }}
- --pubsub.igw-base-url={{ .Values.ap.igwBaseURL }}
- --pubsub.request-subscriber-id={{ .Values.ap.gcpPubSub.requestSubscriberId }}
- --pubsub.request-path-url
- "{{ .Values.ap.gcpPubSub.requestPathURL }}"
{{- end }}
{{- end }}
{{- /* Unified transport surface. On the deprecated per-backend values the
config is synthesized from them (see _helpers.tpl), so the processor
never receives the retired --message-queue-impl / --redis.* / --pubsub.*
flags regardless of which values the operator sets. */}}
- --transport={{ include "llm-d-async.transport" . }}
- --transport-config
- {{ include "llm-d-async.transportConfig" . | quote }}
{{- if .Values.ap.prometheusURL }}
- --prometheus-url={{ .Values.ap.prometheusURL }}
{{- end }}
Expand All @@ -119,16 +80,13 @@ spec:
- --transform-config-file=/etc/llm-d-async/config/transform-config.json
{{- end }}
{{- if .Values.ap.requestMergePolicyConfig }}
- --request-merge-policy-config=/etc/llm-d-async/config/request-merge-policy.json
- --request-merge-policy-config-file=/etc/llm-d-async/config/request-merge-policy.json
{{- end }}
- --concurrency={{ .Values.ap.concurrency | default 64 }}
- --drain-timeout={{ .Values.ap.drainTimeout | default "2m" }}
- --health-port={{ .Values.ap.health.port | default 8081 }}
- --metrics-endpoint-auth={{ .Values.ap.metrics.secure }}
- --metrics-port={{ .Values.ap.metrics.port | default 9090 }}
{{- if and .Values.ap.otel.redisTracing .Values.ap.otel.endpoint }}
- --redis-tracing=true
{{- end }}
{{- if .Values.ap.tls.insecureSkipVerify }}
- --tls-insecure-skip-verify=true
{{- end }}
Expand Down Expand Up @@ -166,7 +124,7 @@ spec:
- name: OTEL_RESOURCE_ATTRIBUTES
value: "k8s.namespace.name=$(NAMESPACE),k8s.pod.name=$(POD_NAME),service.version={{ .Chart.AppVersion }}"
{{- end }}
{{- if .Values.ap.redis.enabled }}
{{- if and (hasPrefix "redis" (include "llm-d-async.transport" .)) (include "llm-d-async.redisSecretName" .) }}
- name: REDIS_URL
valueFrom:
secretKeyRef:
Expand Down Expand Up @@ -213,9 +171,9 @@ spec:
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if or .Values.ap.workerPools .Values.ap.gcpPubSub.topicsConfig .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig .Values.ap.tls.secretName }}
{{- if or .Values.ap.workerPools .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig .Values.ap.tls.secretName }}
volumeMounts:
{{- if or .Values.ap.workerPools .Values.ap.gcpPubSub.topicsConfig .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig }}
{{- if or .Values.ap.workerPools .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig }}
- name: ap-config
mountPath: /etc/llm-d-async/config
readOnly: true
Expand All @@ -228,9 +186,9 @@ spec:
{{- end }}
serviceAccountName: {{ include "llm-d-async.fullname" . }}
terminationGracePeriodSeconds: 130
{{- if or .Values.ap.workerPools .Values.ap.gcpPubSub.topicsConfig .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig .Values.ap.tls.secretName }}
{{- if or .Values.ap.workerPools .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig .Values.ap.tls.secretName }}
volumes:
{{- if or .Values.ap.workerPools .Values.ap.gcpPubSub.topicsConfig .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig }}
{{- if or .Values.ap.workerPools .Values.ap.transformConfig .Values.ap.requestMergePolicyConfig }}
- name: ap-config
configMap:
name: {{ include "llm-d-async.fullname" . }}-config
Expand Down
13 changes: 11 additions & 2 deletions charts/llm-d-async/templates/redis-secret.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
{{- if and .Values.ap.redis.enabled .Values.ap.redis.url }}
{{- /* Create the connection Secret when a literal URL is supplied, either on the
new surface (ap.transportConfig.urlSecret.url) or via the deprecated
ap.redis.url. A referenced Secret (urlSecret.name / redis.secretName) is
not created here. Only emit it when the effective transport is Redis so a
non-Redis backend (e.g. gcp-pubsub) never stores an unused Redis URL. */ -}}
{{- $transport := include "llm-d-async.transport" . -}}
{{- $newURL := "" -}}
{{- if .Values.ap.transport -}}{{- $newURL = dig "urlSecret" "url" "" (.Values.ap.transportConfig | default dict) -}}{{- end -}}
{{- $url := $newURL | default .Values.ap.redis.url -}}
{{- if and (hasPrefix "redis" $transport) $url }}
apiVersion: v1
kind: Secret
metadata:
Expand All @@ -8,5 +17,5 @@ metadata:
{{- include "llm-d-async.labels" . | nindent 4 }}
type: Opaque
stringData:
url: {{ .Values.ap.redis.url | quote }}
url: {{ $url | quote }}
{{- end }}
Loading
Loading