Skip to content

Commit 532e9d6

Browse files
luis5tbclaude
andcommitted
feat: add OpenShift deployment via Helm chart
Add a Helm chart under deploy/openshift/ with configurable values for deploying the Lightspeed Agent on OpenShift without the Google Cloud Marketplace handler. Introduces SKIP_ORDER_VALIDATION setting to bypass marketplace order-id checks while preserving JWT token introspection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 703c996 commit 532e9d6

File tree

15 files changed

+932
-4
lines changed

15 files changed

+932
-4
lines changed

deploy/openshift/Chart.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: v2
2+
name: lightspeed-agent
3+
description: Red Hat Lightspeed Agent for OpenShift
4+
type: application
5+
version: 0.1.0
6+
appVersion: "latest"
7+
keywords:
8+
- lightspeed
9+
- agent
10+
- a2a
11+
- redhat
12+
- gemini

deploy/openshift/README.md

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
# Red Hat Lightspeed Agent - OpenShift Deployment (Helm)
2+
3+
This guide covers deploying the Red Hat Lightspeed Agent on OpenShift using Helm.
4+
5+
Unlike the Cloud Run and Podman deployments, the OpenShift deployment does **not**
6+
include the Google Cloud Marketplace handler. Order-id validation is skipped
7+
(`SKIP_ORDER_VALIDATION=true`), while JWT token introspection against Red Hat SSO
8+
is still enforced.
9+
10+
## Architecture
11+
12+
```
13+
┌─────────────────────────────────┐
14+
│ OpenShift Route │
15+
│ (TLS edge termination) │
16+
└──────────────┬──────────────────┘
17+
18+
┌──────────────▼──────────────────┐
19+
│ lightspeed-agent (Pod) │
20+
│ │
21+
│ ┌─────────────────────────┐ │
22+
│ │ lightspeed-agent │ │
23+
│ │ (port 8000) │──────────▶ console.redhat.com
24+
│ │ A2A / JSON-RPC 2.0 │ │ (via MCP)
25+
│ │ OAuth 2.0 (Red Hat SSO)│ │
26+
│ └────────┬────────────────┘ │
27+
│ │ localhost:8081 │
28+
│ ┌────────▼────────────────┐ │
29+
│ │ lightspeed-mcp │ │
30+
│ │ (sidecar) │ │
31+
│ │ Red Hat Lightspeed MCP │ │
32+
│ └──────────────────────────┘ │
33+
└──────────────────────────────────┘
34+
│ │
35+
┌──────────────▼───┐ ┌──────────▼──────────┐
36+
│ PostgreSQL │ │ Redis │
37+
│ (sessions) │ │ (rate limiting) │
38+
│ Port 5432 │ │ Port 6379 │
39+
└──────────────────┘ └─────────────────────┘
40+
```
41+
42+
## Components
43+
44+
| Component | Description |
45+
|---|---|
46+
| **lightspeed-agent** | Main A2A agent (Gemini + Google ADK) |
47+
| **lightspeed-mcp** | Red Hat Lightspeed MCP server (sidecar in agent pod) providing tools for console.redhat.com APIs |
48+
| **postgresql** | PostgreSQL 16 for ADK session persistence |
49+
| **redis** | Redis 7 for distributed rate limiting |
50+
51+
## Prerequisites
52+
53+
- OpenShift 4.x cluster with `oc` and `helm` CLIs configured
54+
- Access to pull container images from:
55+
- `quay.io/ecosystem-appeng/lightspeed-agent` (or your own registry)
56+
- `quay.io/redhat-services-prod/insights-management-tenant/insights-mcp/red-hat-lightspeed-mcp`
57+
- `registry.redhat.io/rhel9/postgresql-16`
58+
- `quay.io/fedora/redis-7`
59+
- A Google AI Studio API key or Vertex AI project
60+
- Red Hat SSO OAuth credentials (client ID and secret)
61+
62+
## Deployment Steps
63+
64+
### 1. Create a project (namespace)
65+
66+
```bash
67+
oc new-project lightspeed-agent
68+
```
69+
70+
### 2. Build and push the agent image
71+
72+
Build the container image from the repository root and push it to an accessible
73+
registry:
74+
75+
```bash
76+
podman build -t quay.io/<your-org>/lightspeed-agent:latest -f Containerfile .
77+
podman push quay.io/<your-org>/lightspeed-agent:latest
78+
```
79+
80+
If using a different registry or tag, set the image in `values.yaml` or pass it
81+
as an override (see step 4).
82+
83+
### 3. Configure values
84+
85+
Copy `values.yaml` and edit it with your settings:
86+
87+
```bash
88+
cp deploy/openshift/values.yaml deploy/openshift/my-values.yaml
89+
```
90+
91+
At minimum, update the `secrets` section with real credentials:
92+
93+
```yaml
94+
secrets:
95+
create: true
96+
googleApiKey: "your-real-api-key"
97+
redHatSsoClientId: "your-real-client-id"
98+
redHatSsoClientSecret: "your-real-client-secret"
99+
sessionDbPassword: "a-strong-password"
100+
sessionDatabaseUrl: "postgresql+asyncpg://sessions:a-strong-password@lightspeed-agent-postgresql:5432/agent_sessions"
101+
```
102+
103+
> **Note**: If you prefer to manage the Secret externally (e.g., via Vault or
104+
> sealed-secrets), set `secrets.create: false` and create a Secret named
105+
> `<release>-lightspeed-agent-secrets` with the same keys.
106+
107+
### Key configurable values
108+
109+
| Value | Description | Default |
110+
|---|---|---|
111+
| `agent.image.repository` | Agent container image | `quay.io/ecosystem-appeng/lightspeed-agent` |
112+
| `agent.image.tag` | Agent image tag | `latest` |
113+
| `agent.replicas` | Number of agent replicas | `1` |
114+
| `mcp.image.repository` | Lightspeed MCP server image | `quay.io/.../red-hat-lightspeed-mcp` |
115+
| `google.geminiModel` | Gemini model name | `gemini-2.5-flash` |
116+
| `google.useVertexAI` | Use Vertex AI instead of AI Studio | `false` |
117+
| `postgresql.storage.size` | PostgreSQL PVC size | `1Gi` |
118+
| `redis.storage.size` | Redis PVC size | `1Gi` |
119+
| `route.enabled` | Create an OpenShift Route | `true` |
120+
| `auth.skipOrderValidation` | Skip marketplace order checks | `true` |
121+
122+
See `values.yaml` for the full list of configurable options.
123+
124+
### 4. Install the chart
125+
126+
```bash
127+
helm install lightspeed-agent deploy/openshift/ \
128+
-f deploy/openshift/my-values.yaml \
129+
-n lightspeed-agent
130+
```
131+
132+
Or override individual values directly:
133+
134+
```bash
135+
helm install lightspeed-agent deploy/openshift/ \
136+
-f deploy/openshift/my-values.yaml \
137+
--set agent.image.repository=my-registry.example.com/lightspeed-agent \
138+
--set agent.image.tag=v1.0.0 \
139+
--set google.geminiModel=gemini-2.5-pro \
140+
--set postgresql.storage.size=5Gi \
141+
-n lightspeed-agent
142+
```
143+
144+
### 5. Update the agent provider URL
145+
146+
After the Route is created, update `AGENT_PROVIDER_URL` to match the route
147+
hostname:
148+
149+
```bash
150+
ROUTE_HOST=$(oc get route lightspeed-agent -n lightspeed-agent -o jsonpath='{.spec.host}')
151+
helm upgrade lightspeed-agent deploy/openshift/ \
152+
-f deploy/openshift/my-values.yaml \
153+
--set agent.providerUrl=https://${ROUTE_HOST} \
154+
-n lightspeed-agent
155+
```
156+
157+
### 6. Verify the deployment
158+
159+
```bash
160+
# Check all pods are running
161+
oc get pods -n lightspeed-agent
162+
163+
# Check the agent health endpoint
164+
ROUTE_HOST=$(oc get route lightspeed-agent -n lightspeed-agent -o jsonpath='{.spec.host}')
165+
curl -s https://${ROUTE_HOST}/health
166+
167+
# Check the agent card
168+
curl -s https://${ROUTE_HOST}/.well-known/agent.json | python -m json.tool
169+
```
170+
171+
## Authentication
172+
173+
The agent authenticates requests via Red Hat SSO token introspection:
174+
175+
1. Clients obtain a Bearer token from Red Hat SSO
176+
2. The agent validates the token via the SSO introspection endpoint
177+
3. The required scope (`agent:insights` by default) is checked
178+
179+
Since there is no marketplace handler in this deployment, order-id validation
180+
is disabled (`SKIP_ORDER_VALIDATION=true`). The agent does not need a marketplace
181+
database or DCR client registrations.
182+
183+
## Scaling
184+
185+
To scale the agent horizontally:
186+
187+
```bash
188+
oc scale deployment/lightspeed-agent --replicas=3 -n lightspeed-agent
189+
```
190+
191+
Rate limiting state is shared across replicas through Redis.
192+
193+
For automatic scaling, create a HorizontalPodAutoscaler:
194+
195+
```bash
196+
oc autoscale deployment/lightspeed-agent --min=1 --max=5 --cpu-percent=80 -n lightspeed-agent
197+
```
198+
199+
## Upgrading
200+
201+
```bash
202+
helm upgrade lightspeed-agent deploy/openshift/ \
203+
-f deploy/openshift/my-values.yaml \
204+
-n lightspeed-agent
205+
```
206+
207+
## Troubleshooting
208+
209+
### View logs
210+
211+
```bash
212+
# Agent logs
213+
oc logs deployment/lightspeed-agent -c lightspeed-agent -n lightspeed-agent
214+
215+
# Lightspeed MCP server logs
216+
oc logs deployment/lightspeed-agent -c lightspeed-mcp -n lightspeed-agent
217+
218+
# PostgreSQL logs
219+
oc logs deployment/lightspeed-agent-postgresql -n lightspeed-agent
220+
221+
# Redis logs
222+
oc logs deployment/lightspeed-agent-redis -n lightspeed-agent
223+
```
224+
225+
### Common issues
226+
227+
**Pod stuck in `ImagePullBackOff`**: Verify the image registry is accessible and
228+
credentials are configured if pulling from a private registry:
229+
230+
```bash
231+
oc create secret docker-registry my-registry-secret \
232+
--docker-server=quay.io \
233+
--docker-username=<user> \
234+
--docker-password=<password> \
235+
-n lightspeed-agent
236+
oc secrets link default my-registry-secret --for=pull -n lightspeed-agent
237+
```
238+
239+
**Agent cannot connect to PostgreSQL**: Verify the PostgreSQL pod is running and
240+
the `SESSION_DATABASE_URL` in the secret matches the service name and port.
241+
242+
**Agent cannot connect to Redis**: Verify the Redis pod is running and the
243+
`RATE_LIMIT_REDIS_URL` in the ConfigMap points to the correct Redis service.
244+
245+
**Health check failing**: Check agent logs for startup errors. Common causes
246+
include missing secrets or unreachable database/Redis services.
247+
248+
## Cleanup
249+
250+
Uninstall the Helm release to remove all deployed resources:
251+
252+
```bash
253+
helm uninstall lightspeed-agent -n lightspeed-agent
254+
```
255+
256+
PersistentVolumeClaims are not deleted by `helm uninstall`. Remove them manually
257+
if needed:
258+
259+
```bash
260+
oc delete pvc -l app.kubernetes.io/part-of=lightspeed-agent -n lightspeed-agent
261+
```
262+
263+
Or delete the entire project:
264+
265+
```bash
266+
oc delete project lightspeed-agent
267+
```
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "lightspeed-agent.name" -}}
5+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
*/}}
11+
{{- define "lightspeed-agent.fullname" -}}
12+
{{- if .Values.fullnameOverride }}
13+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
14+
{{- else }}
15+
{{- $name := default .Chart.Name .Values.nameOverride }}
16+
{{- if contains $name .Release.Name }}
17+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
18+
{{- else }}
19+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
20+
{{- end }}
21+
{{- end }}
22+
{{- end }}
23+
24+
{{/*
25+
Common labels
26+
*/}}
27+
{{- define "lightspeed-agent.labels" -}}
28+
app.kubernetes.io/name: {{ include "lightspeed-agent.name" . }}
29+
app.kubernetes.io/instance: {{ .Release.Name }}
30+
app.kubernetes.io/version: {{ .Values.agent.image.tag | default .Chart.AppVersion | quote }}
31+
app.kubernetes.io/managed-by: {{ .Release.Service }}
32+
app.kubernetes.io/part-of: lightspeed-agent
33+
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
34+
{{- end }}
35+
36+
{{/*
37+
Selector labels for the agent
38+
*/}}
39+
{{- define "lightspeed-agent.agentSelectorLabels" -}}
40+
app.kubernetes.io/name: {{ include "lightspeed-agent.fullname" . }}
41+
app.kubernetes.io/component: agent
42+
{{- end }}
43+
44+
{{/*
45+
Selector labels for PostgreSQL
46+
*/}}
47+
{{- define "lightspeed-agent.postgresqlSelectorLabels" -}}
48+
app.kubernetes.io/name: {{ include "lightspeed-agent.fullname" . }}-postgresql
49+
app.kubernetes.io/component: database
50+
{{- end }}
51+
52+
{{/*
53+
Selector labels for Redis
54+
*/}}
55+
{{- define "lightspeed-agent.redisSelectorLabels" -}}
56+
app.kubernetes.io/name: {{ include "lightspeed-agent.fullname" . }}-redis
57+
app.kubernetes.io/component: ratelimit
58+
{{- end }}
59+
60+
{{/*
61+
PostgreSQL service name
62+
*/}}
63+
{{- define "lightspeed-agent.postgresqlServiceName" -}}
64+
{{- include "lightspeed-agent.fullname" . }}-postgresql
65+
{{- end }}
66+
67+
{{/*
68+
Redis service name
69+
*/}}
70+
{{- define "lightspeed-agent.redisServiceName" -}}
71+
{{- include "lightspeed-agent.fullname" . }}-redis
72+
{{- end }}

0 commit comments

Comments
 (0)