diff --git a/charts/rhdh/Chart.yaml b/charts/rhdh/Chart.yaml index 6ffd719a7..8b407fa0e 100644 --- a/charts/rhdh/Chart.yaml +++ b/charts/rhdh/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: redhat-developer-hub type: application -version: 2.4.1 +version: 2.5.0 appVersion: 2.1.0 annotations: artifacthub.io/category: integration-delivery diff --git a/charts/rhdh/README.md b/charts/rhdh/README.md index 397ef5136..0d0a844a7 100644 --- a/charts/rhdh/README.md +++ b/charts/rhdh/README.md @@ -1,7 +1,7 @@ # RHDH Helm Chart for OpenShift and Kubernetes -![Version: 2.4.1](https://img.shields.io/badge/Version-2.4.1-informational?style=flat-square) +![Version: 2.5.0](https://img.shields.io/badge/Version-2.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) A Helm chart for deploying Red Hat Developer Hub, which is a Red Hat supported version of Backstage. @@ -36,7 +36,7 @@ For the **Generally Available** version of this chart, see: helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add redhat-developer https://redhat-developer.github.io/rhdh-chart -helm install my-rhdh redhat-developer/redhat-developer-hub --version 2.4.1 +helm install my-rhdh redhat-developer/redhat-developer-hub --version 2.5.0 ``` ## Introduction @@ -243,7 +243,7 @@ Kubernetes: `>= 1.31.0-0` | image.digest | Overrides the image tag with an image digest. | string | `""` | | imagePullSecrets | Secrets for pulling images from private registries (merged with global.imagePullSecrets). | list | `[]` | | ingress | Kubernetes Ingress configuration. | object | `{"annotations":{},"className":"","enabled":false,"hosts":[{"host":"{{ .Values.host }}","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}],"tls":[]}` | -| intelligentAssistant | Built-in Intelligent Assistant feature configuration. | object | `{"config":{"profile":{"existingConfigMap":{"key":"","name":""}},"stack":{"existingConfigMap":{"key":"","name":""}}},"core":{"argsOverride":[],"commandOverride":[],"extraArgs":[],"extraEnv":[],"extraVolumeMounts":[],"image":{"digest":"","registry":"quay.io","repository":"lightspeed-core/lightspeed-stack","tag":"dev-20260824-cbd182b"},"imagePullPolicy":"IfNotPresent","resources":{"limits":{"cpu":"1000m","memory":"2Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}},"enabled":true,"existingSecret":"","okp":{"affinity":{},"httpd":{"compressed":"true","encrypt":"false","serverName":"localhost"},"image":{"digest":"","pullPolicy":"IfNotPresent","registry":"registry.redhat.io","repository":"offline-knowledge-portal/rhokp-rhel9","tag":"1.2.12-1788274041"},"imagePullSecrets":[],"ingress":{"annotations":{},"className":"","enabled":true,"host":"","tls":{"enabled":false,"secretName":""}},"livenessProbe":{"initialDelaySeconds":30,"periodSeconds":30},"nodeSelector":{},"readinessProbe":{"initialDelaySeconds":10,"periodSeconds":10},"replicaCount":1,"resources":{"limits":{"cpu":"2","memory":"4Gi"},"requests":{"cpu":"200m","memory":"2Gi"}},"route":{"enabled":true,"tls":{"insecureEdgeTerminationPolicy":"Redirect","termination":"edge"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}},"service":{"type":"ClusterIP"},"solr":{"hostBind":"0.0.0.0","memory":"1g"},"tolerations":[],"topologySpreadConstraints":[]},"plugins":[{"enabled":true,"package":"ref://red-hat-developer-hub-backstage-plugin-intelligent-assistant"},{"enabled":true,"package":"ref://red-hat-developer-hub-backstage-plugin-intelligent-assistant-backend"}],"runtimeVolume":{"emptyDir":{},"persistentVolumeClaim":{},"type":"emptyDir"}}` | +| intelligentAssistant | Built-in Intelligent Assistant feature configuration. | object | `{"config":{"profile":{"existingConfigMap":{"key":"","name":""}},"stack":{"existingConfigMap":{"key":"","name":""}}},"core":{"argsOverride":[],"commandOverride":[],"extraArgs":[],"extraEnv":[],"extraVolumeMounts":[],"image":{"digest":"","registry":"quay.io","repository":"lightspeed-core/lightspeed-stack","tag":"dev-20260824-cbd182b"},"imagePullPolicy":"IfNotPresent","resources":{"limits":{"cpu":"1000m","memory":"2Gi"},"requests":{"cpu":"100m","memory":"512Mi"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}},"enabled":true,"existingSecret":"","okp":{"affinity":{},"enabled":false,"httpd":{"compressed":"true","encrypt":"false","serverName":"localhost"},"image":{"digest":"","pullPolicy":"IfNotPresent","registry":"registry.redhat.io","repository":"offline-knowledge-portal/rhokp-rhel9","tag":"1.2.12-1788274041"},"imagePullSecrets":[],"ingress":{"annotations":{},"className":"","enabled":true,"host":"","tls":{"enabled":false,"secretName":""}},"livenessProbe":{"initialDelaySeconds":30,"periodSeconds":30},"nodeSelector":{},"readinessProbe":{"initialDelaySeconds":10,"periodSeconds":10},"replicaCount":1,"resources":{"limits":{"cpu":"2","memory":"4Gi"},"requests":{"cpu":"200m","memory":"2Gi"}},"route":{"enabled":true,"tls":{"insecureEdgeTerminationPolicy":"Redirect","termination":"edge"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}},"service":{"type":"ClusterIP"},"solr":{"hostBind":"0.0.0.0","memory":"1g"},"tolerations":[],"topologySpreadConstraints":[]},"plugins":[{"enabled":true,"package":"ref://red-hat-developer-hub-backstage-plugin-intelligent-assistant"},{"enabled":true,"package":"ref://red-hat-developer-hub-backstage-plugin-intelligent-assistant-backend"}],"runtimeVolume":{"emptyDir":{},"persistentVolumeClaim":{},"type":"emptyDir"}}` | | intelligentAssistant.config | Configuration files mounted into the sidecar. By default, the chart creates ConfigMaps from bundled source files. Set existingConfigMap to use a pre-existing ConfigMap instead. | object | `{"profile":{"existingConfigMap":{"key":"","name":""}},"stack":{"existingConfigMap":{"key":"","name":""}}}` | | intelligentAssistant.config.profile | Python profile with prompt templates (rhdh-profile.py). | object | `{"existingConfigMap":{"key":"","name":""}}` | | intelligentAssistant.config.profile.existingConfigMap | Use an existing ConfigMap instead of the bundled default. | object | Created from bundled rhdh-profile.py | @@ -258,8 +258,9 @@ Kubernetes: `>= 1.31.0-0` | intelligentAssistant.core.commandOverride | Override the container's default command. Leave empty to use the image entrypoint. | list | `[]` | | intelligentAssistant.core.extraArgs | Extra arguments appended after the default arguments. Ignored when argsOverride is set. | list | `[]` | | intelligentAssistant.existingSecret | Name of an existing Secret that supplies credentials and settings to the lightspeed-core container. Configure the provider itself in lightspeed-stack.yaml. If empty, no Secret is loaded. Expected keys (all optional; include only keys used by the configured provider): VLLM_URL, VLLM_API_KEY, VLLM_MAX_TOKENS, VLLM_TLS_VERIFY, OPENAI_API_KEY, VERTEX_AI_PROJECT, VERTEX_AI_LOCATION, GOOGLE_APPLICATION_CREDENTIALS, ENABLE_VALIDATION, VALIDATION_PROVIDER, VALIDATION_MODEL_NAME Set ENABLE_VALIDATION to question_validity to enable validation. GOOGLE_APPLICATION_CREDENTIALS must be a path to a credentials file mounted in the sidecar. See files/intelligent-assistant/secret.example.yaml for a reference template. | string | `""` | -| intelligentAssistant.okp | OKP (Offline Knowledge Portal) configuration. Deploys an OKP instance for document retrieval when Intelligent Assistant is enabled. | object | `{"affinity":{},"httpd":{"compressed":"true","encrypt":"false","serverName":"localhost"},"image":{"digest":"","pullPolicy":"IfNotPresent","registry":"registry.redhat.io","repository":"offline-knowledge-portal/rhokp-rhel9","tag":"1.2.12-1788274041"},"imagePullSecrets":[],"ingress":{"annotations":{},"className":"","enabled":true,"host":"","tls":{"enabled":false,"secretName":""}},"livenessProbe":{"initialDelaySeconds":30,"periodSeconds":30},"nodeSelector":{},"readinessProbe":{"initialDelaySeconds":10,"periodSeconds":10},"replicaCount":1,"resources":{"limits":{"cpu":"2","memory":"4Gi"},"requests":{"cpu":"200m","memory":"2Gi"}},"route":{"enabled":true,"tls":{"insecureEdgeTerminationPolicy":"Redirect","termination":"edge"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}},"service":{"type":"ClusterIP"},"solr":{"hostBind":"0.0.0.0","memory":"1g"},"tolerations":[],"topologySpreadConstraints":[]}` | +| intelligentAssistant.okp | OKP (Offline Knowledge Portal) configuration. Deploys an OKP instance for RHDH documentation retrieval when explicitly enabled. The image is large and can significantly increase initial installation time. | object | `{"affinity":{},"enabled":false,"httpd":{"compressed":"true","encrypt":"false","serverName":"localhost"},"image":{"digest":"","pullPolicy":"IfNotPresent","registry":"registry.redhat.io","repository":"offline-knowledge-portal/rhokp-rhel9","tag":"1.2.12-1788274041"},"imagePullSecrets":[],"ingress":{"annotations":{},"className":"","enabled":true,"host":"","tls":{"enabled":false,"secretName":""}},"livenessProbe":{"initialDelaySeconds":30,"periodSeconds":30},"nodeSelector":{},"readinessProbe":{"initialDelaySeconds":10,"periodSeconds":10},"replicaCount":1,"resources":{"limits":{"cpu":"2","memory":"4Gi"},"requests":{"cpu":"200m","memory":"2Gi"}},"route":{"enabled":true,"tls":{"insecureEdgeTerminationPolicy":"Redirect","termination":"edge"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}},"service":{"type":"ClusterIP"},"solr":{"hostBind":"0.0.0.0","memory":"1g"},"tolerations":[],"topologySpreadConstraints":[]}` | | intelligentAssistant.okp.affinity | Pod scheduling: affinity rules for the OKP pod. | object | `{}` | +| intelligentAssistant.okp.enabled | Enable OKP-backed RHDH documentation retrieval. Disabled by default on all platforms. | bool | `false` | | intelligentAssistant.okp.imagePullSecrets | Image pull secrets for the OKP container image. Required on vanilla Kubernetes to authenticate with registry.redhat.io. Not needed on OpenShift where the cluster-wide pull secret covers Red Hat registries. | list | `[]` | | intelligentAssistant.okp.livenessProbe | Liveness probe configuration for the OKP container. | object | `{"initialDelaySeconds":30,"periodSeconds":30}` | | intelligentAssistant.okp.nodeSelector | Pod scheduling: node selector for the OKP pod. | object | `{}` | @@ -412,7 +413,7 @@ For detailed information on configuring the catalog index, including how to over ### NetworkPolicies -This chart deploys a **default-deny** NetworkPolicy for the RHDH backend pod, blocking all ingress and egress traffic that is not explicitly allowed. When the built-in PostgreSQL is enabled (`postgresql.enabled=true`), the database pods also get their own default-deny policy with selective allow rules. +This chart deploys a **default-deny** NetworkPolicy for the RHDH backend pod, blocking all ingress and egress traffic that is not explicitly allowed. When the built-in PostgreSQL is enabled (`postgresql.enabled=true`), the database pods also get their own default-deny policy with selective allow rules. When OKP is active, its pods receive a separate default-deny ingress and egress policy with rules allowing only the required HTTP ingress. The following traffic is allowed out of the box: @@ -422,9 +423,16 @@ The following traffic is allowed out of the box: | Egress | 443 (TCP) | Any | HTTPS (Git forges, auth providers, external APIs) | | Egress | 5432 (TCP) | Built-in PostgreSQL pods (scoped) or any (external DB) | Database access | | Egress | 6379 (TCP) | Any | Redis (BYO — no pod/namespace selector) | +| Egress | 80 (TCP) | Any destination | LCORE access to an HTTP OKP Ingress | +| Egress | 8080 (TCP) | OKP pods | LCORE access to the internal OKP Service fallback | | Ingress | 7007 (TCP) | OpenShift router namespace or any namespace (non-OCP) | User traffic via Route / Ingress | +| Ingress | 8080 (TCP) | RHDH pods and the OpenShift router namespace or any namespace (non-OCP) | OKP queries and product-document citations via Route / Ingress | | Ingress | 9464 (TCP) | `openshift-monitoring`, `openshift-user-workload-monitoring`, `gmp-system`, `gke-gmp-system`, `monitoring` | Prometheus metrics scraping | +OKP initiates no outbound connections: its HTTP server and Solr process run in the same pod and serve the documentation embedded in the image. Its default-deny policy therefore blocks all new egress connections. NetworkPolicy is stateful, so response traffic for allowed ingress connections remains permitted. + +RHDH already permits HTTPS egress on port 443. When OKP uses HTTP instead, the chart permits RHDH egress on port 80 for a Kubernetes Ingress or restricts port 8080 egress to OKP pods for the internal Service fallback. No additional RHDH egress policy is created when `OKP_SERVICE_URL` uses HTTPS. + **Redis egress is intentionally unscoped.** RHDH does not deploy Redis; users bring their own instance, which may live in the same namespace, a different namespace, or an external managed service. The rule therefore allows egress on port 6379 to any destination. **Bitnami subchart NetworkPolicies are disabled** (`postgresql.primary.networkPolicy.enabled=false`, `postgresql.readReplicas.networkPolicy.enabled=false`) because this chart provides its own tighter policies for the built-in database pods. @@ -453,6 +461,8 @@ When using the built-in Intelligent Assistant feature, do not also keep those pl The Lightspeed Core sidecar loads `intelligentAssistant.existingSecret` as environment variables. If you update that Secret outside of Helm, Kubernetes does not guarantee that the Backstage Pod restarts automatically. Use a no-op `helm upgrade` or manually restart the Backstage deployment after changing the secret data. +RHDH documentation retrieval is disabled by default in Intelligent Assistant. To enable it, set `intelligentAssistant.okp.enabled=true`. This deploys the OKP workload and uses the OKP-enabled Lightspeed Stack configuration. The OKP container image is large, so enabling it can significantly increase the initial installation time while the image is downloaded. On vanilla Kubernetes, you must also configure the OKP Ingress and Red Hat registry credentials. See [Intelligent Assistant and OKP integration](../../docs/intelligent-assistant.md) for platform-specific configuration. + ### Vanilla Kubernetes compatibility mode To deploy this chart on vanilla Kubernetes or any other non-OCP platform, apply the following changes. Note that further customizations might be required, depending on your exact Kubernetes setup: diff --git a/charts/rhdh/README.md.gotmpl b/charts/rhdh/README.md.gotmpl index 77060edb1..9d05ac15b 100644 --- a/charts/rhdh/README.md.gotmpl +++ b/charts/rhdh/README.md.gotmpl @@ -257,7 +257,7 @@ For detailed information on configuring the catalog index, including how to over ### NetworkPolicies -This chart deploys a **default-deny** NetworkPolicy for the RHDH backend pod, blocking all ingress and egress traffic that is not explicitly allowed. When the built-in PostgreSQL is enabled (`postgresql.enabled=true`), the database pods also get their own default-deny policy with selective allow rules. +This chart deploys a **default-deny** NetworkPolicy for the RHDH backend pod, blocking all ingress and egress traffic that is not explicitly allowed. When the built-in PostgreSQL is enabled (`postgresql.enabled=true`), the database pods also get their own default-deny policy with selective allow rules. When OKP is active, its pods receive a separate default-deny ingress and egress policy with rules allowing only the required HTTP ingress. The following traffic is allowed out of the box: @@ -267,9 +267,16 @@ The following traffic is allowed out of the box: | Egress | 443 (TCP) | Any | HTTPS (Git forges, auth providers, external APIs) | | Egress | 5432 (TCP) | Built-in PostgreSQL pods (scoped) or any (external DB) | Database access | | Egress | 6379 (TCP) | Any | Redis (BYO — no pod/namespace selector) | +| Egress | 80 (TCP) | Any destination | LCORE access to an HTTP OKP Ingress | +| Egress | 8080 (TCP) | OKP pods | LCORE access to the internal OKP Service fallback | | Ingress | 7007 (TCP) | OpenShift router namespace or any namespace (non-OCP) | User traffic via Route / Ingress | +| Ingress | 8080 (TCP) | RHDH pods and the OpenShift router namespace or any namespace (non-OCP) | OKP queries and product-document citations via Route / Ingress | | Ingress | 9464 (TCP) | `openshift-monitoring`, `openshift-user-workload-monitoring`, `gmp-system`, `gke-gmp-system`, `monitoring` | Prometheus metrics scraping | +OKP initiates no outbound connections: its HTTP server and Solr process run in the same pod and serve the documentation embedded in the image. Its default-deny policy therefore blocks all new egress connections. NetworkPolicy is stateful, so response traffic for allowed ingress connections remains permitted. + +RHDH already permits HTTPS egress on port 443. When OKP uses HTTP instead, the chart permits RHDH egress on port 80 for a Kubernetes Ingress or restricts port 8080 egress to OKP pods for the internal Service fallback. No additional RHDH egress policy is created when `OKP_SERVICE_URL` uses HTTPS. + **Redis egress is intentionally unscoped.** RHDH does not deploy Redis; users bring their own instance, which may live in the same namespace, a different namespace, or an external managed service. The rule therefore allows egress on port 6379 to any destination. **Bitnami subchart NetworkPolicies are disabled** (`postgresql.primary.networkPolicy.enabled=false`, `postgresql.readReplicas.networkPolicy.enabled=false`) because this chart provides its own tighter policies for the built-in database pods. @@ -298,6 +305,8 @@ When using the built-in Intelligent Assistant feature, do not also keep those pl The Lightspeed Core sidecar loads `intelligentAssistant.existingSecret` as environment variables. If you update that Secret outside of Helm, Kubernetes does not guarantee that the Backstage Pod restarts automatically. Use a no-op `helm upgrade` or manually restart the Backstage deployment after changing the secret data. +RHDH documentation retrieval is disabled by default in Intelligent Assistant. To enable it, set `intelligentAssistant.okp.enabled=true`. This deploys the OKP workload and uses the OKP-enabled Lightspeed Stack configuration. The OKP container image is large, so enabling it can significantly increase the initial installation time while the image is downloaded. On vanilla Kubernetes, you must also configure the OKP Ingress and Red Hat registry credentials. See [Intelligent Assistant and OKP integration](../../docs/intelligent-assistant.md) for platform-specific configuration. + ### Vanilla Kubernetes compatibility mode To deploy this chart on vanilla Kubernetes or any other non-OCP platform, apply the following changes. Note that further customizations might be required, depending on your exact Kubernetes setup: diff --git a/charts/rhdh/templates/_helpers.tpl b/charts/rhdh/templates/_helpers.tpl index 74ffdc2c2..de88be3d9 100644 --- a/charts/rhdh/templates/_helpers.tpl +++ b/charts/rhdh/templates/_helpers.tpl @@ -320,12 +320,13 @@ imagePullSecrets: {{/* Return whether OKP should be deployed. -On OpenShift (openshift.route.enabled): active when IA is enabled and okp.route.enabled is true. -On vanilla K8s: only active when okp.ingress.enabled is true and okp.ingress.host is set. +OKP must be explicitly enabled on every platform. +On OpenShift (openshift.route.enabled): also requires okp.route.enabled. +On vanilla K8s: also requires okp.ingress.enabled and a non-empty okp.ingress.host. */}} {{- define "rhdh.intelligentAssistant.okp.active" -}} {{- $ia := include "rhdh.intelligentAssistant" . | fromYaml -}} -{{- if and $ia.enabled (or (and .Values.openshift.route.enabled $ia.okp.route.enabled) (and (not .Values.openshift.route.enabled) $ia.okp.ingress.enabled $ia.okp.ingress.host)) -}} +{{- if and $ia.enabled $ia.okp.enabled (or (and .Values.openshift.route.enabled $ia.okp.route.enabled) (and (not .Values.openshift.route.enabled) $ia.okp.ingress.enabled $ia.okp.ingress.host)) -}} true {{- end -}} {{- end -}} diff --git a/charts/rhdh/templates/intelligent-assistant/okp-network-policies.yaml b/charts/rhdh/templates/intelligent-assistant/okp-network-policies.yaml new file mode 100644 index 000000000..89420c5e5 --- /dev/null +++ b/charts/rhdh/templates/intelligent-assistant/okp-network-policies.yaml @@ -0,0 +1,130 @@ +{{- $ia := include "rhdh.intelligentAssistant" . | fromYaml -}} +{{- if include "rhdh.intelligentAssistant.okp.active" . }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-okp-default-deny + labels: + {{- include "rhdh.intelligentAssistant.okp.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.intelligentAssistant.okp.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + +{{- $usesHttpIngress := and (not .Values.openshift.route.enabled) (not $ia.okp.ingress.tls.enabled) -}} +{{- $usesInternalService := and .Values.openshift.route.enabled (not .Values.openshift.clusterRouterBase) -}} +{{- if $usesHttpIngress }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-okp-allow-http-egress + labels: + {{- include "rhdh.intelligentAssistant.okp.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + - port: 80 + protocol: TCP +{{- end }} + +{{- if $usesInternalService }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-okp-allow-internal-service-egress + labels: + {{- include "rhdh.intelligentAssistant.okp.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - to: + - podSelector: + matchLabels: + {{- include "rhdh.intelligentAssistant.okp.selectorLabels" . | nindent 14 }} + ports: + - port: 8080 + protocol: TCP +{{- end }} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-okp-allow-backstage-ingress + labels: + {{- include "rhdh.intelligentAssistant.okp.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.intelligentAssistant.okp.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + {{- include "rhdh.selectorLabels" . | nindent 14 }} + ports: + - port: 8080 + protocol: TCP + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "rhdh.fullname" . }}-okp-allow-router-ingress + labels: + {{- include "rhdh.intelligentAssistant.okp.labels" . | nindent 4 }} + {{- with .Values.commonAnnotations }} + annotations: + {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + {{- include "rhdh.intelligentAssistant.okp.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + {{- if .Values.openshift.route.enabled }} + matchLabels: + policy-group.network.openshift.io/ingress: "" + {{- else }} + {} + {{- end }} + ports: + - port: 8080 + protocol: TCP +{{- end }} diff --git a/charts/rhdh/values.schema.json b/charts/rhdh/values.schema.json index 45f2d7945..ddaaab14e 100644 --- a/charts/rhdh/values.schema.json +++ b/charts/rhdh/values.schema.json @@ -772,6 +772,7 @@ "existingSecret": "", "okp": { "affinity": {}, + "enabled": false, "httpd": { "compressed": "true", "encrypt": "false", @@ -1220,6 +1221,11 @@ "default": {}, "type": "object" }, + "enabled": { + "default": false, + "title": "Enable OKP-backed RHDH documentation retrieval. The large OKP image can significantly increase initial installation time.", + "type": "boolean" + }, "httpd": { "additionalProperties": false, "properties": { @@ -1635,7 +1641,7 @@ "type": "array" } }, - "title": "OKP (Offline Knowledge Portal) configuration. Deploys an OKP instance for document retrieval.", + "title": "OKP (Offline Knowledge Portal) configuration. Deploys an OKP instance for RHDH documentation retrieval when explicitly enabled.", "type": "object" }, "plugins": { diff --git a/charts/rhdh/values.schema.tmpl.json b/charts/rhdh/values.schema.tmpl.json index 121f839ba..fde40d693 100644 --- a/charts/rhdh/values.schema.tmpl.json +++ b/charts/rhdh/values.schema.tmpl.json @@ -956,10 +956,15 @@ } }, "okp": { - "title": "OKP (Offline Knowledge Portal) configuration. Deploys an OKP instance for document retrieval.", + "title": "OKP (Offline Knowledge Portal) configuration. Deploys an OKP instance for RHDH documentation retrieval when explicitly enabled.", "type": "object", "additionalProperties": false, "properties": { + "enabled": { + "title": "Enable OKP-backed RHDH documentation retrieval. The large OKP image can significantly increase initial installation time.", + "type": "boolean", + "default": false + }, "image": { "type": "object", "additionalProperties": false, diff --git a/charts/rhdh/values.yaml b/charts/rhdh/values.yaml index 1f86f067c..1446aa1eb 100644 --- a/charts/rhdh/values.yaml +++ b/charts/rhdh/values.yaml @@ -571,8 +571,11 @@ intelligentAssistant: seccompProfile: type: "RuntimeDefault" # -- OKP (Offline Knowledge Portal) configuration. - # Deploys an OKP instance for document retrieval when Intelligent Assistant is enabled. + # Deploys an OKP instance for RHDH documentation retrieval when explicitly enabled. + # The image is large and can significantly increase initial installation time. okp: + # -- Enable OKP-backed RHDH documentation retrieval. Disabled by default on all platforms. + enabled: false image: registry: "registry.redhat.io" repository: "offline-knowledge-portal/rhokp-rhel9" diff --git a/docs/intelligent-assistant.md b/docs/intelligent-assistant.md index 7e5d818ea..e8808cd6d 100644 --- a/docs/intelligent-assistant.md +++ b/docs/intelligent-assistant.md @@ -14,22 +14,39 @@ The Intelligent Assistant integration deploys two components alongside the RHDH OKP is **not** part of the RHDH Deployment — it is a separate workload that LCORE talks to via `OKP_SERVICE_URL`. +> **Important:** RHDH documentation retrieval is disabled by default in Intelligent Assistant +> on both OpenShift and vanilla Kubernetes. Enable OKP explicitly to ground responses in the +> bundled Red Hat product documentation and provide clickable citations. The OKP container +> image is large, so enabling it can significantly increase the initial installation time while +> the image is downloaded. + ## Deployment Scenarios | Scenario | OKP deployed? | Config used | RAG sources? | |---|---|---|---| -| **OpenShift (auto)** | Yes — automatic when `intelligentAssistant.enabled=true` | `lightspeed-stack.yaml` (with OKP RAG configuration) | Yes | -| **Vanilla K8s (default)** | No — unless OKP Ingress is enabled and `okp.ingress.host` is set | `lightspeed-stack-no-okp.yaml` | No | -| **Vanilla K8s (opt-in)** | Yes — when `okp.ingress.enabled=true` and `okp.ingress.host` is provided | `lightspeed-stack.yaml` (with OKP RAG configuration) | Yes | +| **OpenShift (default)** | No | `lightspeed-stack-no-okp.yaml` | No | +| **OpenShift (opt-in)** | Yes — when `okp.enabled=true` | `lightspeed-stack.yaml` (with OKP RAG configuration) | Yes | +| **Vanilla K8s (default)** | No | `lightspeed-stack-no-okp.yaml` | No | +| **Vanilla K8s (opt-in)** | Yes — when `okp.enabled=true`, `okp.ingress.enabled=true`, and `okp.ingress.host` is provided | `lightspeed-stack.yaml` (with OKP RAG configuration) | Yes | ## Helm Install Flags -### OpenShift (OKP auto-enabled) +### OpenShift — No OKP (default) + +```bash +helm install rhdh ./charts/rhdh \ + --set intelligentAssistant.enabled=true \ + --set intelligentAssistant.existingSecret=lightspeed-secret \ + --set openshift.clusterRouterBase=$(oc get ingresses.config/cluster -o jsonpath='{.spec.domain}') +``` + +### OpenShift — OKP Opt-in ```bash helm install rhdh ./charts/rhdh \ --set intelligentAssistant.enabled=true \ --set intelligentAssistant.existingSecret=lightspeed-secret \ + --set intelligentAssistant.okp.enabled=true \ --set openshift.clusterRouterBase=$(oc get ingresses.config/cluster -o jsonpath='{.spec.domain}') ``` @@ -38,6 +55,7 @@ helm install rhdh ./charts/rhdh \ ```bash helm install rhdh ./charts/rhdh \ --namespace rhdh \ + --set host=rhdh.mydomain.com \ --set intelligentAssistant.enabled=true \ --set intelligentAssistant.existingSecret=lightspeed-secret \ --set openshift.route.enabled=false \ @@ -53,6 +71,7 @@ helm install rhdh ./charts/rhdh \ ```bash helm install rhdh ./charts/rhdh \ --namespace rhdh \ + --set host=rhdh.mydomain.com \ --set intelligentAssistant.enabled=true \ --set intelligentAssistant.existingSecret=lightspeed-secret \ --set openshift.route.enabled=false \ @@ -61,6 +80,7 @@ helm install rhdh ./charts/rhdh \ --set 'ingress.hosts[0].paths[0].path=/' \ --set 'ingress.hosts[0].paths[0].pathType=Prefix' \ --set ingress.className=nginx \ + --set intelligentAssistant.okp.enabled=true \ --set intelligentAssistant.okp.ingress.enabled=true \ --set intelligentAssistant.okp.ingress.host=okp.mydomain.com \ --set intelligentAssistant.okp.ingress.className=nginx \ @@ -73,6 +93,7 @@ helm install rhdh ./charts/rhdh \ ```bash helm install rhdh ./charts/rhdh \ --namespace rhdh \ + --set host=rhdh.mydomain.com \ --set intelligentAssistant.enabled=true \ --set intelligentAssistant.existingSecret=lightspeed-secret \ --set openshift.route.enabled=false \ @@ -81,6 +102,7 @@ helm install rhdh ./charts/rhdh \ --set 'ingress.hosts[0].paths[0].path=/' \ --set 'ingress.hosts[0].paths[0].pathType=Prefix' \ --set ingress.className=nginx \ + --set intelligentAssistant.okp.enabled=true \ --set intelligentAssistant.okp.ingress.enabled=true \ --set intelligentAssistant.okp.ingress.host=okp.mydomain.com \ --set intelligentAssistant.okp.ingress.className=nginx \ @@ -111,7 +133,8 @@ On vanilla Kubernetes (unlike OpenShift), the chart requires additional setup: 2. **Enable Ingress** — set `ingress.enabled=true` with a hostname and ingress class. An ingress controller (e.g. [ingress-nginx](https://kubernetes.github.io/ingress-nginx/)) must be installed in the cluster. To opt in to OKP, also set - `intelligentAssistant.okp.ingress.enabled=true` and provide a non-empty + `intelligentAssistant.okp.enabled=true`, set + `intelligentAssistant.okp.ingress.enabled=true`, and provide a non-empty `intelligentAssistant.okp.ingress.host`. 3. **OKP image pull secret** — the OKP image is hosted on `registry.redhat.io`, which requires authentication. Create a pull secret from your Red Hat registry credentials @@ -200,6 +223,7 @@ kubectl create secret tls okp-tls -n \ # Then set TLS on the OKP Ingress helm install rhdh ./charts/rhdh \ ... \ + --set intelligentAssistant.okp.enabled=true \ --set intelligentAssistant.okp.ingress.enabled=true \ --set intelligentAssistant.okp.ingress.host=okp.mydomain.com \ --set intelligentAssistant.okp.ingress.tls.enabled=true \ @@ -223,6 +247,7 @@ OKP values are under `intelligentAssistant.okp.*`: | Value | Default | Description | |---|---|---| +| `okp.enabled` | `false` | Enable OKP-backed RHDH documentation retrieval. Enabling it downloads and runs the large OKP image. | | `okp.image.registry` | `registry.redhat.io` | OKP container image registry | | `okp.image.repository` | `offline-knowledge-portal/rhokp-rhel9` | OKP image repository | | `okp.image.tag` | `1.2.12-1788274041` | Pinned OKP image tag | @@ -232,9 +257,9 @@ OKP values are under `intelligentAssistant.okp.*`: | `okp.resources.limits.memory` | `4Gi` | Memory limit | | `okp.securityContext` | restricted | Security context for the OKP container | | `okp.imagePullSecrets` | `[]` | Image pull secrets (merged with `global.imagePullSecrets`) | -| `okp.route.enabled` | `true` | Create OpenShift Route | -| `okp.ingress.enabled` | `true` | Create K8s Ingress (requires `host`) | -| `okp.ingress.host` | `""` | Ingress hostname (required with `okp.ingress.enabled=true` to opt in on K8s) | +| `okp.route.enabled` | `true` | Create an OpenShift Route when OKP is enabled | +| `okp.ingress.enabled` | `true` | Create a K8s Ingress when OKP is enabled (requires `host`) | +| `okp.ingress.host` | `""` | Ingress hostname (required with `okp.enabled=true` on K8s) | | `okp.ingress.className` | `""` | Ingress class (e.g. `nginx`) | | `okp.ingress.tls.enabled` | `false` | Enable TLS on the OKP Ingress | | `okp.ingress.tls.secretName` | `""` | TLS secret name (cert+key) |