adding openshift template#12
Conversation
WalkthroughA new OpenShift template named Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant OpenShift
participant ConfigMaps
participant assisted-chat Deployment
participant Service
User->>OpenShift: Instantiate assisted-chat template
OpenShift->>ConfigMaps: Create lightspeed-stack and llama-stack-client ConfigMaps
OpenShift->>assisted-chat Deployment: Deploy container with configs and secrets
assisted-chat Deployment->>Service: Expose service on configured port
User->>Service: Access assisted-chat application
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
7236d54 to
84f6233
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
template.yaml (3)
82-82: Trim trailing whitespaceYAML linters flag the blank space at the end of this line.
- api-key: "" + api-key: ""
317-324:ReadWriteManymay not be available; make the access mode configurableMost default storage classes (e.g., gp2 on AWS or standard on GCP) only support
ReadWriteOnce. Hard-codingReadWriteManywill cause the PVC to remain Pending on those platforms.- accessModes: - - ReadWriteMany + accessModes: + - ${STORAGE_ACCESS_MODE}Add
STORAGE_ACCESS_MODEto the parameters list with a sane default (ReadWriteOnce).
2-30: Parameters lack descriptions and display namesProviding
description(and optionallydisplayName) for each parameter greatly improvesoc explain templateoutput and the Web Console form generation.Example:
- name: IMAGE value: "quay.io/lightspeed-core/lightspeed-stack" + description: Container image for the Lightspeed stackAdding these fields is low-effort and boosts template usability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
template.yaml(1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
template.yaml
[error] 83-83: trailing spaces
(trailing-spaces)
84f6233 to
4f99995
Compare
|
@coderabbitai review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 8938 @eranco74, I've reviewed the OpenShift template for the assisted-chat service. Here's my comprehensive analysis: ✅ Strengths
|
86816bc to
d1fa864
Compare
template.yaml
Outdated
| description: "Size of the persistent volume for storing feedback, transcripts, and SQLite databases" | ||
| - name: STORAGE_MOUNT_PATH | ||
| value: "/tmp/data" | ||
| description: "Container path where the persistent volume will be mounted" |
There was a problem hiding this comment.
Is this temporary or does it really need to be persisted between restarts of the pods? If it is temporary, can we use an emptyDir instead of a PVC?
If we really need to use a PVC, then the access mode of the PVC below would need to be ReadWriteMany, and we will need to ensure that multiple pods know how to coordinate access to that storage.
I'd very much prefer if we use an emptyDir, as then these concerns go away and the deployment is simpler.
template.yaml
Outdated
| insecureEdgeTerminationPolicy: Redirect | ||
|
|
||
| - apiVersion: v1 | ||
| kind: PersistentVolumeClaim |
There was a problem hiding this comment.
As I commented above I think it is better if we use an emptyDir, if possible, at least initially.
d1fa864 to
6fd2459
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
template.yaml(1 hunks)
🔇 Additional comments (1)
template.yaml (1)
272-294: Good move: swapped PVC for emptyDirSwitching to
emptyDireliminates multi-writer storage complexity and matches the feedback from previous reviews.
| - name: REPLICAS_COUNT | ||
| value: "1" | ||
| description: "Number of pod replicas to deploy for high availability" | ||
| - name: SERVICE_PORT | ||
| value: "8090" | ||
| description: "Port number on which the lightspeed-stack service listens" |
There was a problem hiding this comment.
Unquoted numeric parameters break Kubernetes type-validation
Values for REPLICAS_COUNT, SERVICE_PORT, and LIGHTSPEED_SERVICE_WORKERS are wrapped in quotes, so after substitution fields like spec.replicas, containerPort, and port end up as strings ("1", "8090" …). Kubernetes expects integers and will reject the Deployment/Service.
- value: "1" # REPLICAS_COUNT
+ value: 1
- value: "8090" # SERVICE_PORT
+ value: 8090
- value: "1" # LIGHTSPEED_SERVICE_WORKERS
+ value: 1Apply the same pattern to any other purely-numeric parameters.
Also applies to: 43-45
🤖 Prompt for AI Agents
In template.yaml lines 15 to 20, the numeric values for REPLICAS_COUNT and
SERVICE_PORT are quoted strings, which causes Kubernetes to reject them due to
type mismatch. Remove the quotes around these numeric values to ensure they are
treated as integers. Also, apply this fix to any other numeric parameters in the
file, including lines 43 to 45, to maintain consistent type validation.
| spec: | ||
| containers: | ||
| - name: lightspeed-stack | ||
| image: ${IMAGE}:${IMAGE_TAG} | ||
| imagePullPolicy: IfNotPresent | ||
| ports: | ||
| - name: http | ||
| containerPort: ${SERVICE_PORT} | ||
| protocol: TCP | ||
| env: | ||
| - name: GEMINI_API_KEY | ||
| valueFrom: | ||
| secretKeyRef: | ||
| name: ${GEMINI_API_SECRET_NAME} | ||
| key: api-key | ||
| - name: LLAMA_STACK_SQLITE_STORE_DIR | ||
| value: ${STORAGE_MOUNT_PATH}/sqlite | ||
| - name: LLAMA_STACK_OTEL_SERVICE_NAME | ||
| value: ${LLAMA_STACK_OTEL_SERVICE_NAME} | ||
| - name: LLAMA_STACK_TELEMETRY_SINKS | ||
| value: ${LLAMA_STACK_TELEMETRY_SINKS} | ||
| resources: | ||
| limits: | ||
| memory: ${MEMORY_LIMIT} | ||
| cpu: ${CPU_LIMIT} | ||
| requests: | ||
| memory: ${MEMORY_REQUEST} | ||
| cpu: ${CPU_REQUEST} | ||
| volumeMounts: | ||
| - name: lightspeed-config | ||
| mountPath: /app-root/lightspeed-stack.yaml | ||
| subPath: lightspeed-stack.yaml | ||
| - name: llama-stack-config | ||
| mountPath: /app-root/llama_stack_client_config.yaml | ||
| subPath: llama_stack_client_config.yaml | ||
| - name: data-storage | ||
| mountPath: ${STORAGE_MOUNT_PATH} | ||
| livenessProbe: | ||
| httpGet: | ||
| path: /v1/liveness | ||
| port: ${SERVICE_PORT} | ||
| initialDelaySeconds: 30 | ||
| periodSeconds: 10 | ||
| readinessProbe: | ||
| httpGet: | ||
| path: /v1/readiness | ||
| port: ${SERVICE_PORT} | ||
| initialDelaySeconds: 5 | ||
| periodSeconds: 5 | ||
| volumes: |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Harden the pod with a securityContext
The container currently runs without any explicit restrictions. Add a pod-level security context to enforce non-root execution and a default seccomp profile.
spec:
+ securityContext:
+ runAsUser: 10001
+ runAsGroup: 10001
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
containers:
- name: lightspeed-stackThis is a low-effort win for compliance and cluster policy alignment.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| spec: | |
| containers: | |
| - name: lightspeed-stack | |
| image: ${IMAGE}:${IMAGE_TAG} | |
| imagePullPolicy: IfNotPresent | |
| ports: | |
| - name: http | |
| containerPort: ${SERVICE_PORT} | |
| protocol: TCP | |
| env: | |
| - name: GEMINI_API_KEY | |
| valueFrom: | |
| secretKeyRef: | |
| name: ${GEMINI_API_SECRET_NAME} | |
| key: api-key | |
| - name: LLAMA_STACK_SQLITE_STORE_DIR | |
| value: ${STORAGE_MOUNT_PATH}/sqlite | |
| - name: LLAMA_STACK_OTEL_SERVICE_NAME | |
| value: ${LLAMA_STACK_OTEL_SERVICE_NAME} | |
| - name: LLAMA_STACK_TELEMETRY_SINKS | |
| value: ${LLAMA_STACK_TELEMETRY_SINKS} | |
| resources: | |
| limits: | |
| memory: ${MEMORY_LIMIT} | |
| cpu: ${CPU_LIMIT} | |
| requests: | |
| memory: ${MEMORY_REQUEST} | |
| cpu: ${CPU_REQUEST} | |
| volumeMounts: | |
| - name: lightspeed-config | |
| mountPath: /app-root/lightspeed-stack.yaml | |
| subPath: lightspeed-stack.yaml | |
| - name: llama-stack-config | |
| mountPath: /app-root/llama_stack_client_config.yaml | |
| subPath: llama_stack_client_config.yaml | |
| - name: data-storage | |
| mountPath: ${STORAGE_MOUNT_PATH} | |
| livenessProbe: | |
| httpGet: | |
| path: /v1/liveness | |
| port: ${SERVICE_PORT} | |
| initialDelaySeconds: 30 | |
| periodSeconds: 10 | |
| readinessProbe: | |
| httpGet: | |
| path: /v1/readiness | |
| port: ${SERVICE_PORT} | |
| initialDelaySeconds: 5 | |
| periodSeconds: 5 | |
| volumes: | |
| spec: | |
| securityContext: | |
| runAsUser: 10001 | |
| runAsGroup: 10001 | |
| runAsNonRoot: true | |
| seccompProfile: | |
| type: RuntimeDefault | |
| containers: | |
| - name: lightspeed-stack | |
| image: ${IMAGE}:${IMAGE_TAG} | |
| imagePullPolicy: IfNotPresent | |
| ports: | |
| - name: http | |
| containerPort: ${SERVICE_PORT} | |
| protocol: TCP | |
| env: | |
| - name: GEMINI_API_KEY | |
| valueFrom: | |
| secretKeyRef: | |
| name: ${GEMINI_API_SECRET_NAME} | |
| key: api-key | |
| - name: LLAMA_STACK_SQLITE_STORE_DIR | |
| value: ${STORAGE_MOUNT_PATH}/sqlite | |
| - name: LLAMA_STACK_OTEL_SERVICE_NAME | |
| value: ${LLAMA_STACK_OTEL_SERVICE_NAME} | |
| - name: LLAMA_STACK_TELEMETRY_SINKS | |
| value: ${LLAMA_STACK_TELEMETRY_SINKS} | |
| resources: | |
| limits: | |
| memory: ${MEMORY_LIMIT} | |
| cpu: ${CPU_LIMIT} | |
| requests: | |
| memory: ${MEMORY_REQUEST} | |
| cpu: ${CPU_REQUEST} | |
| volumeMounts: | |
| - name: lightspeed-config | |
| mountPath: /app-root/lightspeed-stack.yaml | |
| subPath: lightspeed-stack.yaml | |
| - name: llama-stack-config | |
| mountPath: /app-root/llama_stack_client_config.yaml | |
| subPath: llama_stack_client_config.yaml | |
| - name: data-storage | |
| mountPath: ${STORAGE_MOUNT_PATH} | |
| livenessProbe: | |
| httpGet: | |
| path: /v1/liveness | |
| port: ${SERVICE_PORT} | |
| initialDelaySeconds: 30 | |
| periodSeconds: 10 | |
| readinessProbe: | |
| httpGet: | |
| path: /v1/readiness | |
| port: ${SERVICE_PORT} | |
| initialDelaySeconds: 5 | |
| periodSeconds: 5 | |
| volumes: |
🤖 Prompt for AI Agents
In template.yaml around lines 236 to 285, the container spec lacks a pod-level
securityContext to enforce security best practices. Add a securityContext at the
pod level that sets runAsNonRoot to true and specifies a default seccompProfile
(e.g., type: RuntimeDefault) to ensure the container does not run as root and
uses a secure syscall filter. This will harden the pod with minimal changes and
improve compliance.
37fc7e0 to
1c63b50
Compare
1c63b50 to
84aad60
Compare
Openshift template for Lightspeed stack (+llama stack)
Creates Route, Service, Deployment, PVC (for persistent data like sqlite, feedback and transcript) , and ConfigMap (lightspeed stack yamls) objects.
GEMINI_API_KEY is replaced with a k8s Secret, which needs to be created first before applying this template:
oc create secret generic assisted-chat-gemini-secret --from-literal=api-key="your-actual-gemini-api-key"Summary by CodeRabbit