This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-5272-531d79ff226acba9d5f8d1d13d57564359ba0cec in repository https://gitbox.apache.org/repos/asf/texera.git
commit d08645529119db0d12cf4f1466f6b5a2db6d5eb5 Author: Jiadong Bai <[email protected]> AuthorDate: Mon Jun 1 17:34:37 2026 -0700 feat(k8s): add agent service and LiteLLM to the Helm chart (#5272) ### What changes were proposed in this PR? The agent-service image is built and runs under single-node compose but had no Helm deployment, and the chart had no in-cluster LLM gateway. This adds both, mirroring the proven preview/production chart while aligning the agent service's env to what the code on `main` actually reads. **Agent service** (gated on `agentService.enabled`) - `agent-service-deployment.yaml` + `agent-service-service.yaml`, wired to in-cluster service DNS using the env names from `agent-service/src/config/env.ts`: `TEXERA_DASHBOARD_SERVICE_ENDPOINT` (webserver), `LLM_ENDPOINT` (access-control-service), `WORKFLOW_COMPILING_SERVICE_ENDPOINT`, and a per-CU `EXECUTION_ENDPOINT_TEMPLATE`. - A dedicated `/api/agents` HTTPRoute (REST + the `/api/agents/:id/react` WebSocket) plus a **`BackendTrafficPolicy` that consistent-hashes on `X-Agent-Workflow-Id`** — agents are held in memory per pod, so a workflow's requests must always reach the same replica (the client already stamps that header). - Readiness/liveness on `/api/healthcheck`. **LiteLLM — in-cluster LLM gateway** (gated on `litellm.enabled`) - `litellm-deployment.yaml` + `litellm-service.yaml` + `litellm-config.yaml` (ConfigMap). - **Postgres persistence on by default**: a `texera_litellm` database is created by the Postgres init script, and the deployment sets `DATABASE_URL` + `STORE_MODEL_IN_DB=true` so keys, spend, and model config survive restarts. - `access-control-service` wired to LiteLLM (`LITELLM_BASE_URL`, `LITELLM_MASTER_KEY`, copilot enabled). A shared Opaque `Secret` holds the agent gateway key, the LiteLLM master key, and the provider API keys (supply via `--set`/override; none committed). ### Any related issues, documentation, discussions? Closes #5269 ### How was this PR tested? Tested locally by `helm install`. Worked end 2 end. `helm lint` and `helm template` against the chart (subchart `dependencies:` stripped locally so the render needs no remote charts): ``` helm lint . # 1 chart(s) linted, 0 chart(s) failed helm template texera . -f values-development.yaml # RC=0, 50 objects, no errors ``` ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.8 (1M context) --------- Co-authored-by: Bob Bai <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> Co-authored-by: ali risheh <[email protected]> --- .../access-control-service-deployment.yaml | 12 ++- .../templates/access-control-service-service.yaml | 4 +- ...l => agent-service-backend-traffic-policy.yaml} | 29 ++++---- bin/k8s/templates/agent-service-deployment.yaml | 79 ++++++++++++++++++++ ...vice-service.yaml => agent-service-secret.yaml} | 24 +++--- ...ice-service.yaml => agent-service-service.yaml} | 12 +-- bin/k8s/templates/gateway-routes.yaml | 37 ++++++++++ bin/k8s/templates/gateway-security-policy.yaml | 2 +- ...ol-service-service.yaml => litellm-config.yaml} | 17 ++--- bin/k8s/templates/litellm-deployment.yaml | 85 ++++++++++++++++++++++ ...l-service-service.yaml => litellm-service.yaml} | 12 +-- .../templates/postgresql-init-script-config.yaml | 7 ++ bin/k8s/templates/pylsp.yaml | 2 +- bin/k8s/values-development.yaml | 64 +++++++++++++++- bin/k8s/values.yaml | 56 +++++++++++++- 15 files changed, 388 insertions(+), 54 deletions(-) diff --git a/bin/k8s/templates/access-control-service-deployment.yaml b/bin/k8s/templates/access-control-service-deployment.yaml index f4d4405d33..99713e7071 100644 --- a/bin/k8s/templates/access-control-service-deployment.yaml +++ b/bin/k8s/templates/access-control-service-deployment.yaml @@ -50,6 +50,16 @@ spec: value: {{ .Values.workflowComputingUnitPool.name }} - name: KUBERNETES_COMPUTE_UNIT_POOL_NAMESPACE value: {{ .Values.workflowComputingUnitPool.namespace }} + {{- if .Values.litellm.enabled }} + # LLM gateway used to serve /api/chat and /api/models to the agent service. + - name: LITELLM_BASE_URL + value: http://{{ .Values.litellm.name }}-svc:{{ .Values.litellm.service.port }} + - name: LITELLM_MASTER_KEY + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-agent-service-secret + key: litellm-master-key + {{- end }} {{- range .Values.texeraEnvVars }} - name: {{ .name }} value: "{{ .value }}" @@ -65,4 +75,4 @@ spec: path: /api/healthcheck port: {{ .Values.accessControlService.service.port }} initialDelaySeconds: 5 - periodSeconds: 5 \ No newline at end of file + periodSeconds: 5 diff --git a/bin/k8s/templates/access-control-service-service.yaml b/bin/k8s/templates/access-control-service-service.yaml index 25f0390566..4c2137456a 100644 --- a/bin/k8s/templates/access-control-service-service.yaml +++ b/bin/k8s/templates/access-control-service-service.yaml @@ -18,7 +18,7 @@ apiVersion: v1 kind: Service metadata: - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc + name: {{ .Values.accessControlService.name }}-svc namespace: {{ .Release.Namespace }} spec: type: {{ .Values.accessControlService.service.type }} @@ -27,4 +27,4 @@ spec: ports: - protocol: TCP port: {{ .Values.accessControlService.service.port }} - targetPort: {{ .Values.accessControlService.service.port }} \ No newline at end of file + targetPort: {{ .Values.accessControlService.service.port }} diff --git a/bin/k8s/templates/gateway-security-policy.yaml b/bin/k8s/templates/agent-service-backend-traffic-policy.yaml similarity index 64% copy from bin/k8s/templates/gateway-security-policy.yaml copy to bin/k8s/templates/agent-service-backend-traffic-policy.yaml index 4128b5f3d8..dffecbfb60 100644 --- a/bin/k8s/templates/gateway-security-policy.yaml +++ b/bin/k8s/templates/agent-service-backend-traffic-policy.yaml @@ -15,25 +15,24 @@ # specific language governing permissions and limitations # under the License. +# Agents are stateful and held in memory per pod, so all requests for a given +# workflow must reach the same replica. The client stamps X-Agent-Workflow-Id on +# every agent request; pin routing to it with a consistent hash. +{{- if .Values.agentService.enabled }} apiVersion: gateway.envoyproxy.io/v1alpha1 -kind: SecurityPolicy +kind: BackendTrafficPolicy metadata: - name: {{ .Release.Name }}-ext-auth + name: {{ .Release.Name }}-agent-service-traffic-policy namespace: {{ .Release.Namespace }} spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute - name: {{ .Release.Name }}-dynamic-routes - extAuth: - http: - backendRefs: - - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc - port: {{ .Values.accessControlService.service.port }} - path: /api/auth - headersToBackend: - - x-user-computing-unit-access - - x-user-id - - x-user-name - - x-user-email - - Host + name: {{ .Release.Name }}-agent-service-route + loadBalancer: + type: ConsistentHash + consistentHash: + type: Header + header: + name: X-Agent-Workflow-Id +{{- end }} diff --git a/bin/k8s/templates/agent-service-deployment.yaml b/bin/k8s/templates/agent-service-deployment.yaml new file mode 100644 index 0000000000..5437cd7d9c --- /dev/null +++ b/bin/k8s/templates/agent-service-deployment.yaml @@ -0,0 +1,79 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +{{- if .Values.agentService.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Values.agentService.name }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ .Release.Name }}-{{ .Values.agentService.name }} +spec: + replicas: {{ .Values.agentService.numOfPods | default 1 }} + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Values.agentService.name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Values.agentService.name }} + spec: + containers: + - name: {{ .Values.agentService.name }} + image: {{ .Values.texera.imageRegistry }}/{{ .Values.agentService.imageName }}:{{ .Values.texera.imageTag }} + imagePullPolicy: {{ .Values.texeraImages.pullPolicy }} + ports: + - containerPort: {{ .Values.agentService.service.port }} + # Env names match the agent service's config schema (agent-service/src/config/env.ts). + env: + - name: PORT + value: "{{ .Values.agentService.service.port }}" + # Dashboard service: workflow CRUD + operator metadata. + - name: TEXERA_DASHBOARD_SERVICE_ENDPOINT + value: http://{{ .Values.webserver.name }}-svc:{{ .Values.webserver.service.port }} + # LLM gateway: access-control-service serves /api/chat and /api/models, + # forwarding to LiteLLM (mirrors the single-node nginx routing). + - name: LLM_ENDPOINT + value: http://{{ .Values.accessControlService.name }}-svc:{{ .Values.accessControlService.service.port }} + - name: WORKFLOW_COMPILING_SERVICE_ENDPOINT + value: http://{{ .Values.workflowCompilingService.name }}-svc:{{ .Values.workflowCompilingService.service.port }} + # Per-computing-unit execution endpoint; "{cuid}" is substituted with the + # computing unit id at request time. + - name: EXECUTION_ENDPOINT_TEMPLATE + value: http://computing-unit-{cuid}.{{ .Values.workflowComputingUnitPool.name }}-svc.{{ .Values.workflowComputingUnitPool.namespace }}.svc.cluster.local:{{ .Values.workflowComputingUnitPool.service.port }} + - name: LLM_API_KEY + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-agent-service-secret + key: llm-api-key + # The service loads operator metadata from the dashboard service on + # startup, so gate readiness on its health endpoint before the gateway + # routes traffic here. /api/healthcheck needs no auth. + readinessProbe: + httpGet: + path: /api/healthcheck + port: {{ .Values.agentService.service.port }} + initialDelaySeconds: 5 + periodSeconds: 5 + livenessProbe: + httpGet: + path: /api/healthcheck + port: {{ .Values.agentService.service.port }} + initialDelaySeconds: 15 + periodSeconds: 10 +{{- end }} diff --git a/bin/k8s/templates/access-control-service-service.yaml b/bin/k8s/templates/agent-service-secret.yaml similarity index 58% copy from bin/k8s/templates/access-control-service-service.yaml copy to bin/k8s/templates/agent-service-secret.yaml index 25f0390566..61746a0aeb 100644 --- a/bin/k8s/templates/access-control-service-service.yaml +++ b/bin/k8s/templates/agent-service-secret.yaml @@ -15,16 +15,20 @@ # specific language governing permissions and limitations # under the License. +# Shared secret for the agent service and LiteLLM. Holds the agent's gateway +# key, LiteLLM's master key, and the upstream provider API keys. Provide real +# values via `--set` or a values override file; do not commit them. +{{- if or .Values.agentService.enabled .Values.litellm.enabled }} apiVersion: v1 -kind: Service +kind: Secret metadata: - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc + name: {{ .Release.Name }}-agent-service-secret namespace: {{ .Release.Namespace }} -spec: - type: {{ .Values.accessControlService.service.type }} - selector: - app: {{ .Release.Name }}-{{ .Values.accessControlService.name }} - ports: - - protocol: TCP - port: {{ .Values.accessControlService.service.port }} - targetPort: {{ .Values.accessControlService.service.port }} \ No newline at end of file +type: Opaque +stringData: + llm-api-key: "{{ .Values.agentService.env.llmApiKey }}" + litellm-master-key: "{{ .Values.litellm.masterKey }}" + {{- range $key, $value := .Values.litellm.providerApiKeys }} + {{ $key }}: "{{ $value }}" + {{- end }} +{{- end }} diff --git a/bin/k8s/templates/access-control-service-service.yaml b/bin/k8s/templates/agent-service-service.yaml similarity index 73% copy from bin/k8s/templates/access-control-service-service.yaml copy to bin/k8s/templates/agent-service-service.yaml index 25f0390566..581716bf80 100644 --- a/bin/k8s/templates/access-control-service-service.yaml +++ b/bin/k8s/templates/agent-service-service.yaml @@ -15,16 +15,18 @@ # specific language governing permissions and limitations # under the License. +{{- if .Values.agentService.enabled }} apiVersion: v1 kind: Service metadata: - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc + name: {{ .Values.agentService.name }}-svc namespace: {{ .Release.Namespace }} spec: - type: {{ .Values.accessControlService.service.type }} + type: {{ .Values.agentService.service.type }} selector: - app: {{ .Release.Name }}-{{ .Values.accessControlService.name }} + app: {{ .Release.Name }}-{{ .Values.agentService.name }} ports: - protocol: TCP - port: {{ .Values.accessControlService.service.port }} - targetPort: {{ .Values.accessControlService.service.port }} \ No newline at end of file + port: {{ .Values.agentService.service.port }} + targetPort: {{ .Values.agentService.service.port }} +{{- end }} diff --git a/bin/k8s/templates/gateway-routes.yaml b/bin/k8s/templates/gateway-routes.yaml index ab53c184e8..ac8096aa21 100644 --- a/bin/k8s/templates/gateway-routes.yaml +++ b/bin/k8s/templates/gateway-routes.yaml @@ -66,6 +66,16 @@ spec: backendRefs: - name: config-service-svc port: 9094 + - matches: + - path: + type: PathPrefix + value: /api/models + - path: + type: PathPrefix + value: /api/chat + backendRefs: + - name: access-control-service-svc + port: 9096 - matches: - path: type: PathPrefix @@ -133,6 +143,33 @@ spec: kind: Backend name: texera-dynamic-backend --- +# Agent Service Route (a separate HTTPRoute so the BackendTrafficPolicy can +# target it for consistent-hash routing). Covers REST and the +# /api/agents/:id/react WebSocket. Longest-prefix matching gives /api/agents +# priority over the /api catch-all in the static routes above. +{{- if .Values.agentService.enabled }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .Release.Name }}-agent-service-route + namespace: {{ .Release.Namespace }} +spec: + parentRefs: + - name: {{ .Release.Name }}-gateway + {{- if and .Values.gatewayConfig .Values.gatewayConfig.hostname }} + hostnames: + - {{ .Values.gatewayConfig.hostname }} + {{- end }} + rules: + - matches: + - path: + type: PathPrefix + value: /api/agents + backendRefs: + - name: agent-service-svc + port: 3001 +{{- end }} +--- # MinIO Route {{- if .Values.minio.gateway.enabled }} apiVersion: gateway.networking.k8s.io/v1 diff --git a/bin/k8s/templates/gateway-security-policy.yaml b/bin/k8s/templates/gateway-security-policy.yaml index 4128b5f3d8..47a67532d8 100644 --- a/bin/k8s/templates/gateway-security-policy.yaml +++ b/bin/k8s/templates/gateway-security-policy.yaml @@ -28,7 +28,7 @@ spec: extAuth: http: backendRefs: - - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc + - name: {{ .Values.accessControlService.name }}-svc port: {{ .Values.accessControlService.service.port }} path: /api/auth headersToBackend: diff --git a/bin/k8s/templates/access-control-service-service.yaml b/bin/k8s/templates/litellm-config.yaml similarity index 68% copy from bin/k8s/templates/access-control-service-service.yaml copy to bin/k8s/templates/litellm-config.yaml index 25f0390566..c4c2aa136d 100644 --- a/bin/k8s/templates/access-control-service-service.yaml +++ b/bin/k8s/templates/litellm-config.yaml @@ -15,16 +15,13 @@ # specific language governing permissions and limitations # under the License. +{{- if .Values.litellm.enabled }} apiVersion: v1 -kind: Service +kind: ConfigMap metadata: - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc + name: {{ .Release.Name }}-litellm-config namespace: {{ .Release.Namespace }} -spec: - type: {{ .Values.accessControlService.service.type }} - selector: - app: {{ .Release.Name }}-{{ .Values.accessControlService.name }} - ports: - - protocol: TCP - port: {{ .Values.accessControlService.service.port }} - targetPort: {{ .Values.accessControlService.service.port }} \ No newline at end of file +data: + litellm-config.yaml: | +{{ .Values.litellm.config | indent 4 }} +{{- end }} diff --git a/bin/k8s/templates/litellm-deployment.yaml b/bin/k8s/templates/litellm-deployment.yaml new file mode 100644 index 0000000000..ba681da7d1 --- /dev/null +++ b/bin/k8s/templates/litellm-deployment.yaml @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +{{- if .Values.litellm.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-{{ .Values.litellm.name }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ .Release.Name }}-{{ .Values.litellm.name }} +spec: + replicas: {{ .Values.litellm.numOfPods | default 1 }} + selector: + matchLabels: + app: {{ .Release.Name }}-{{ .Values.litellm.name }} + template: + metadata: + labels: + app: {{ .Release.Name }}-{{ .Values.litellm.name }} + spec: + containers: + - name: {{ .Values.litellm.name }} + image: {{ .Values.litellm.image }} + imagePullPolicy: Always + args: + - "--config" + - "/app/config/litellm-config.yaml" + ports: + - containerPort: {{ .Values.litellm.service.port }} + env: + - name: LITELLM_MASTER_KEY + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-agent-service-secret + key: litellm-master-key + # Postgres persistence: LiteLLM runs its Prisma migrations against this + # database on startup and stores keys, spend, and (with STORE_MODEL_IN_DB) + # model config there, so state survives pod restarts. Defaults to the + # in-cluster Postgres; set litellm.databaseUrl to point at an external one. + - name: DATABASE_URL + value: {{ .Values.litellm.databaseUrl | default (printf "postgresql://postgres:%s@%s-postgresql:5432/%s" .Values.postgresql.auth.postgresPassword .Release.Name .Values.litellm.databaseName) | quote }} + - name: STORE_MODEL_IN_DB + value: "{{ .Values.litellm.storeModelInDb }}" + {{- range $key, $value := .Values.litellm.providerApiKeys }} + - name: {{ $key }} + valueFrom: + secretKeyRef: + name: {{ $.Release.Name }}-agent-service-secret + key: {{ $key }} + {{- end }} + volumeMounts: + - name: litellm-config + mountPath: /app/config + livenessProbe: + httpGet: + path: /health/liveliness + port: {{ .Values.litellm.service.port }} + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /health/liveliness + port: {{ .Values.litellm.service.port }} + initialDelaySeconds: 15 + periodSeconds: 5 + volumes: + - name: litellm-config + configMap: + name: {{ .Release.Name }}-litellm-config +{{- end }} diff --git a/bin/k8s/templates/access-control-service-service.yaml b/bin/k8s/templates/litellm-service.yaml similarity index 73% copy from bin/k8s/templates/access-control-service-service.yaml copy to bin/k8s/templates/litellm-service.yaml index 25f0390566..875bdd08f1 100644 --- a/bin/k8s/templates/access-control-service-service.yaml +++ b/bin/k8s/templates/litellm-service.yaml @@ -15,16 +15,18 @@ # specific language governing permissions and limitations # under the License. +{{- if .Values.litellm.enabled }} apiVersion: v1 kind: Service metadata: - name: {{ .Release.Name }}-{{ .Values.accessControlService.name }}-svc + name: {{ .Values.litellm.name }}-svc namespace: {{ .Release.Namespace }} spec: - type: {{ .Values.accessControlService.service.type }} + type: {{ .Values.litellm.service.type }} selector: - app: {{ .Release.Name }}-{{ .Values.accessControlService.name }} + app: {{ .Release.Name }}-{{ .Values.litellm.name }} ports: - protocol: TCP - port: {{ .Values.accessControlService.service.port }} - targetPort: {{ .Values.accessControlService.service.port }} \ No newline at end of file + port: {{ .Values.litellm.service.port }} + targetPort: {{ .Values.litellm.service.port }} +{{- end }} diff --git a/bin/k8s/templates/postgresql-init-script-config.yaml b/bin/k8s/templates/postgresql-init-script-config.yaml index 9b7e5488b5..f9bb8c4b52 100644 --- a/bin/k8s/templates/postgresql-init-script-config.yaml +++ b/bin/k8s/templates/postgresql-init-script-config.yaml @@ -52,5 +52,12 @@ data: {{ .Files.Get "files/texera_ddl.sql" | indent 6 }} EOF psql -U postgres -f /tmp/texera_ddl.sql +{{- if .Values.litellm.enabled }} + + echo "Initializing LiteLLM database..." + # LiteLLM (Prisma) creates its own tables on startup but the database must exist. + psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = '{{ .Values.litellm.databaseName }}'" | grep -q 1 \ + || psql -U postgres -c "CREATE DATABASE {{ .Values.litellm.databaseName }}" +{{- end }} echo "Schema initialization complete." \ No newline at end of file diff --git a/bin/k8s/templates/pylsp.yaml b/bin/k8s/templates/pylsp.yaml index ee6a3e59a5..89f3fd1b48 100644 --- a/bin/k8s/templates/pylsp.yaml +++ b/bin/k8s/templates/pylsp.yaml @@ -35,7 +35,7 @@ spec: containers: - name: {{ .Values.pythonLanguageServer.name }} image: {{ .Values.pythonLanguageServer.image | quote }} - imagePullPolicy: Always + imagePullPolicy: {{ .Values.pythonLanguageServer.imagePullPolicy | quote }} ports: - containerPort: 3000 resources: diff --git a/bin/k8s/values-development.yaml b/bin/k8s/values-development.yaml index cbf0183f00..5537b39acc 100644 --- a/bin/k8s/values-development.yaml +++ b/bin/k8s/values-development.yaml @@ -56,10 +56,10 @@ postgresql: resources: requests: cpu: "0.25" - memory: "256Mi" + memory: "512Mi" limits: cpu: "1" - memory: "256Mi" + memory: "1Gi" persistence: enabled: true size: 10Gi @@ -225,6 +225,63 @@ accessControlService: cpu: 1000m memory: 256Mi +agentService: + enabled: true + name: agent-service + numOfPods: 1 + imageName: texera-agent-service + service: + type: ClusterIP + port: 3001 + env: + # Authenticates the agent service to the in-cluster LLM gateway + # (access-control-service / LiteLLM), not to the upstream provider. + llmApiKey: "dummy" + +litellm: + enabled: true + name: litellm + image: litellm/litellm:main-stable + numOfPods: 1 + service: + type: ClusterIP + port: 4000 + masterKey: "sk-texera-litellm-key" + # Postgres persistence: the database is created by the postgres init script and + # LiteLLM stores keys/spend (and model config when storeModelInDb is true) there. + databaseName: texera_litellm + # Full Postgres connection string for LiteLLM. Leave empty to use the in-cluster + # Postgres (composed from postgresql.auth + databaseName); set it to point at an + # external database, e.g. postgresql://user:pass@host:5432/dbname. + databaseUrl: "" + storeModelInDb: true + # Provider API keys - injected as env vars into the LiteLLM pod and stored in a + # Secret. Set these via --set or a values override file (do NOT commit real keys). + # The config below references them via "os.environ/KEY_NAME". + providerApiKeys: + OPENAI_API_KEY: "" + ANTHROPIC_API_KEY: "" + config: | + litellm_settings: + drop_params: true + model_list: + - model_name: claude-sonnet-4 + litellm_params: + model: claude-sonnet-4-20250514 + api_key: "os.environ/ANTHROPIC_API_KEY" + - model_name: claude-haiku-4.5 + litellm_params: + model: claude-haiku-4-5-20251001 + api_key: "os.environ/ANTHROPIC_API_KEY" + - model_name: gpt-4.1 + litellm_params: + model: gpt-4.1 + api_key: "os.environ/OPENAI_API_KEY" + - model_name: gpt-4.1-mini + litellm_params: + model: gpt-4.1-mini + api_key: "os.environ/OPENAI_API_KEY" + # headless service for the access of computing units workflowComputingUnitPool: createNamespaces: true @@ -285,6 +342,8 @@ texeraEnvVars: value: "true" - name: GUI_WORKFLOW_WORKSPACE_ASYNC_RENDERING_ENABLED value: "true" + - name: GUI_WORKFLOW_WORKSPACE_COPILOT_ENABLED + value: "true" - name: COMPUTING_UNIT_SHARING_ENABLED value: "true" - name: USER_SYS_INVITE_ONLY @@ -308,6 +367,7 @@ pythonLanguageServer: name: python-language-server replicaCount: 1 image: texera/pylsp:latest + imagePullPolicy: IfNotPresent imagePullSecret: regcred resources: limits: diff --git a/bin/k8s/values.yaml b/bin/k8s/values.yaml index 2d7c520ff7..4f708b6da1 100644 --- a/bin/k8s/values.yaml +++ b/bin/k8s/values.yaml @@ -18,8 +18,8 @@ texera: # Container image registry and tag for all Texera services # Override these to use a different registry or version - imageRegistry: ghcr.io/apache - imageTag: latest + imageRegistry: docker.io/apache + imageTag: 1.1.0-incubating global: # Required by Bitnami sub-charts (postgresql, minio) to allow custom images @@ -207,6 +207,55 @@ accessControlService: type: ClusterIP port: 9096 +agentService: + enabled: true + name: agent-service + numOfPods: 1 + imageName: texera-agent-service + service: + type: ClusterIP + port: 3001 + env: + # Authenticates the agent service to the in-cluster LLM gateway + # (access-control-service / LiteLLM), not to the upstream provider. + llmApiKey: "dummy" + +litellm: + enabled: true + name: litellm + image: litellm/litellm:main-stable + numOfPods: 1 + service: + type: ClusterIP + port: 4000 + masterKey: "sk-texera-litellm-key" + # Postgres persistence: the database is created by the postgres init script and + # LiteLLM stores keys/spend (and model config when storeModelInDb is true) there. + databaseName: texera_litellm + # Full Postgres connection string for LiteLLM. Leave empty to use the in-cluster + # Postgres (composed from postgresql.auth + databaseName); set it to point at an + # external database, e.g. postgresql://user:pass@host:5432/dbname. + databaseUrl: "" + storeModelInDb: true + # Provider API keys - injected as env vars into the LiteLLM pod and stored in a + # Secret. Set these via --set or a values override file (do NOT commit real keys). + # The config below references them via "os.environ/KEY_NAME". + providerApiKeys: + OPENAI_API_KEY: "" + ANTHROPIC_API_KEY: "" + config: | + litellm_settings: + drop_params: true + model_list: + - model_name: claude-haiku-4.5 + litellm_params: + model: claude-haiku-4-5-20251001 + api_key: "os.environ/ANTHROPIC_API_KEY" + - model_name: gpt-5-mini + litellm_params: + model: gpt-5-mini + api_key: "os.environ/OPENAI_API_KEY" + # headless service for the access of computing units workflowComputingUnitPool: createNamespaces: true @@ -267,6 +316,8 @@ texeraEnvVars: value: "true" - name: GUI_WORKFLOW_WORKSPACE_ASYNC_RENDERING_ENABLED value: "true" + - name: GUI_WORKFLOW_WORKSPACE_COPILOT_ENABLED + value: "true" - name: COMPUTING_UNIT_SHARING_ENABLED value: "true" - name: USER_SYS_INVITE_ONLY @@ -293,6 +344,7 @@ pythonLanguageServer: name: python-language-server replicaCount: 1 image: texera/pylsp:latest + imagePullPolicy: IfNotPresent imagePullSecret: regcred resources: limits:
