OpenShift deployment
- Overview
- Prerequisites
- Requirements
- Getting Started
- Configuration Setup
- Security Context Constraints
- Database Deployment
- Deploy PostgreSQL SSL Certificate
- Kueue Deployment
- OpenShift Service Mesh 3 Deployment
- OpenShift Route TLS Configuration
- Next steps
Overview
This guide describes deploying SAS Retrieval Agent Manager on an OpenShift cluster.
Complete Get started first. It covers the common prerequisites, tools, and license retrieval for every platform.
Prerequisites
In addition to the common prerequisites:
- Ability to create resources in the OpenShift environment for the SAS Retrieval Agent Manager project
- A PostgreSQL database server with bidirectional connectivity to the cluster
Requirements
Hardware Requirements
Cluster sizing is platform-independent. Small, Medium, and Large worker node requirements are the same as on AKS and EKS. See Cluster sizing.
This example shows a Small cluster with a highly available control plane:
| Node Type | Count | CPUs | RAM | Disk | Notes |
|---|---|---|---|---|---|
| Control Plane Node (tainted) | 3 | 4 | 8GB | 50GB | |
| Worker Nodes | 2 | 8 | 32GB | 200GB | Use 64GB for embedding or vectorization workloads |
| NFS Server Node | 1 | 8 | 16GB | 200GB | Optional if using CSI storage; can also serve as a worker node |
For Medium and Large clusters, keep this control plane and NFS configuration and scale the worker nodes to the tier requirements.
Postgres Database Sizing
Follow the PostgreSQL sizing recommendations here.
Infrastructure Requirements
- OpenShift version: 4.19.1
Getting Started
We do not support the entire infrastructure deployment process for OpenShift like we do with AWS, Azure, and Open Source Kubernetes. You will need an already functioning OpenShift cluster. If you’re interested in deploying an OpenShift cluster, please refer to Red Hat documentation here.
Configuration Setup
For the OpenShift deployment, all of the necessary deployment changes will occur if you set the platform key in the Values file to openshift as seen here:
# @schema
# enum:
# - "azure"
# - "aws"
# - "kubernetes"
# - "openshift"
# required: true
# default: "azure"
# @schema
# -- Platform we are deploying on. (azure, aws, kubernetes, openshift)
platform: openshift
Setting platform: openshift changes three things:
- It creates a
SecurityContextConstraintsobject and aClusterRoleBindingthat grants it to the SAS Retrieval Agent Manager ServiceAccounts. - It removes
runAsUser,runAsGroup, andrunAsNonRootfrom the pod and container security contexts, so OpenShift assigns a UID from the namespace range. - It defaults
ingress.classTypetoroute, so the chart creates OpenShiftRouteobjects instead ofIngressobjects.
Security Context Constraints
By default, an OpenShift installation creates two cluster-scoped objects: a
SecurityContextConstraintsobject and aClusterRoleBinding. Installing the chart therefore requires cluster administrator privileges. If you must keep all role bindings inside your namespace, use the namespace-scoped alternative below.
The chart creates a dedicated SCC named <release-name>-scc rather than using the built-in anyuid or privileged SCCs. It grants only what the application needs:
SYS_NICEcapability, for process priorityrunAsUser: RunAsAnyandfsGroup: RunAsAnyMKNODdropped, no privileged containers, no host network, IPC, PID, ports, or host paths
The accompanying ClusterRoleBinding binds the ServiceAccounts to the ClusterRole that OpenShift generates for the SCC (system:openshift:scc:<release-name>-scc).
Namespace-scoped alternative
A SecurityContextConstraints object is cluster-scoped and cannot be namespaced. However, the binding can be. A RoleBinding that references a ClusterRole grants that role only within its own namespace, which avoids the cluster-wide grant.
Use this approach when your OpenShift administrator does not permit ClusterRoleBinding objects for application workloads.
Step 1. Set the platform to kubernetes.
This stops the chart from rendering its own SCC and ClusterRoleBinding:
platform: kubernetes
ingress:
# Required. Keeps OpenShift Routes, which platform "openshift" would otherwise select for you.
classType: route
Important: With
platform: kubernetes, the chart keeps the explicitrunAsUser,runAsGroup, andrunAsNonRootvalues instead of letting OpenShift assign a UID. The SCC below usesrunAsUser: RunAsAny, which permits them. Do not remove that setting.
Step 2. Apply the SCC and the RoleBinding.
Use the example manifests. Edit the namespace and release name if you do not use the defaults, then apply the file. A cluster administrator must apply it, because the SCC itself is cluster-scoped:
oc apply -f scc-namespace-scoped.yaml
The manifests create:
| Object | Scope | Purpose |
|---|---|---|
SecurityContextConstraints | Cluster | Identical to the one the chart would create, but with an empty users list |
RoleBinding | Namespace | Grants system:openshift:scc:retrieval-agent-manager-scc to the ServiceAccounts in your namespace only |
Step 3. Verify the binding before you install.
# Confirm the SCC exists
oc get scc retrieval-agent-manager-scc
# Confirm the RoleBinding is namespaced, not cluster-wide
oc get rolebinding retrieval-agent-manager-scc-binding -n retagentmgr
# Confirm a ServiceAccount can use the SCC
oc adm policy who-can use scc retrieval-agent-manager-scc -n retagentmgr
Step 4. Install the chart.
The ServiceAccounts must exist for the binding to take effect, but a RoleBinding may reference a ServiceAccount that does not exist yet. You can apply the manifests before or after the Helm install; the subjects resolve once the chart creates the ServiceAccounts.
Note: If you change the Helm release name or any
serviceAccount.namevalue, update the subject names in the manifests to match.
Database Deployment
SAS Retrieval Agent Manager requires a PostgreSQL 15+ database. On OpenShift, the Crunchy Postgres for Kubernetes operator provides a quick and convenient way to deploy PostgreSQL directly on the cluster. However, running PostgreSQL inside the cluster shares resources with the application workloads and will result in degraded performance compared to a dedicated external PostgreSQL installation. A dedicated external PostgreSQL database is the preferred approach for production deployments.
Note: Follow the PostgreSQL sizing recommendations to determine your required database size before deploying.
Install the Crunchy Postgres Operator
The Crunchy Postgres operator can be installed via the OpenShift web console or via the CLI using an OperatorGroup and Subscription.
Via the OpenShift Web Console
- Log in to the OpenShift web console.
- Navigate to Operators → OperatorHub.
- Search for “Crunchy Postgres for Kubernetes”.
- Select the operator and click Install.
- Choose the target namespace (e.g.,
postgres-operator) and click Install.
Via CLI
Create the namespace and operator resources using the following commands:
# Create the namespace for the Postgres Operator
oc new-project postgres-operator
# Create an OperatorGroup scoped to the namespace
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: postgres-operator-group
namespace: postgres-operator
spec:
targetNamespaces:
- postgres-operator
EOF
# Create a Subscription for the Crunchy Postgres Operator
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: crunchy-postgres-operator
namespace: postgres-operator
spec:
channel: v5
name: crunchy-postgres-operator
source: certified-operators
sourceNamespace: openshift-marketplace
EOF
Verify the operator is running:
oc -n postgres-operator get pods --selector=postgres-operator.crunchydata.com/control-plane=postgres-operator
Deploy a PostgresCluster
Once the operator is running, create a PostgresCluster resource. The spec.openshift: true flag is required for OpenShift environments.
cat <<EOF | oc apply -f -
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: sas-ram-db
namespace: postgres-operator
spec:
openshift: true
postgresVersion: 15
instances:
- name: instance1
replicas: 1
dataVolumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 128Gi
backups:
pgbackrest:
repos:
- name: repo1
volume:
volumeClaimSpec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 128Gi
users:
- name: sasramadmin
databases:
- sasram
options: "SUPERUSER"
EOF
Track the status of your cluster:
oc -n postgres-operator describe postgresclusters.postgres-operator.crunchydata.com sas-ram-db
Once running, retrieve the connection credentials from the generated secret:
# The secret is named <clusterName>-pguser-<userName>
oc -n postgres-operator get secret sas-ram-db-pguser-sasramadmin -o jsonpath='{.data.uri}' | base64 -d
Note: For more details on cluster configuration, user management, and high availability, refer to the Crunchy Postgres for Kubernetes documentation.
Deploy PostgreSQL SSL Certificate
PGO sets up a PKI and enables TLS for all connections by default. You must extract the CA and TLS certificates from the cluster-generated secrets and build a combined cert.pem bundle for SAS Retrieval Agent Manager to use.
Extract the Certificate Components
PGO stores the cluster certificates in a secret named <clusterName>-cluster-cert. Extract the required files:
# Extract the CA certificate (used as trustedcerts.pem and ca.crt)
oc -n postgres-operator get secret sas-ram-db-cluster-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
# Extract the server TLS certificate
oc -n postgres-operator get secret sas-ram-db-cluster-cert -o jsonpath='{.data.tls\.crt}' | base64 -d > tls.crt
# Extract the server TLS private key
oc -n postgres-operator get secret sas-ram-db-cluster-cert -o jsonpath='{.data.tls\.key}' | base64 -d > tls.key
Construct the Certificate Bundle
Follow Secure the database connection to build the combined cert.pem bundle and create the Kubernetes secret. On OpenShift, use the files extracted above:
cat ca.crt ca.crt tls.crt tls.key > combined-cert.pem
Note: When using PGO’s built-in PKI, the chain cert and intermediate cert are the same
ca.crt. If you have configuredspec.customTLSSecretwith your own PKI, use your owntrustedcerts.pemin place of the firstca.crt.
Create the Kubernetes Secret
On OpenShift, use oc to create the project and the secret:
# The correct namespace to store all SAS Retrieval Agent Manager Resources
oc new-project retagentmgr
# Create a secret with the PostgreSQL SSL bundle
oc create secret generic postgres-ssl-cert --from-file=cert.pem=combined-cert.pem -n retagentmgr
Note: It is critical to enter the name of the secret in the
postgreSQLCertSecretkey in the ram-values under global.configuration.vhub. For example, with this secret name, it would be:postgreSQLCertSecret: 'postgres-ssl-cert'
Kueue Deployment
On OpenShift, Kueue is installed via the OpenShift Kueue Operator rather than the upstream Helm chart used on other platforms.
Install the OpenShift Kueue Operator
- Log in to the OpenShift web console.
- Navigate to Operators → OperatorHub.
- Search for “Kueue” and select the OpenShift Kueue Operator.
- Click Install and accept the defaults.
Alternatively, install via CLI:
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: openshift-kueue-operator
namespace: openshift-operators
spec:
channel: stable
name: openshift-kueue-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
EOF
Create the Kueue Instance
Once the operator is running, create a Kueue cluster resource to enable Kueue with the BatchJob integration framework:
cat <<EOF | oc apply -f -
apiVersion: kueue.openshift.io/v1
kind: Kueue
metadata:
name: cluster
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: kueue-operator
spec:
config:
integrations:
frameworks:
- BatchJob
logLevel: Normal
managementState: Managed
operatorLogLevel: Normal
EOF
Verify that Kueue is available:
oc get kueue cluster -o jsonpath='{.status.conditions}'
The Available condition should show status: "True" before proceeding.
Label the SAS Retrieval Agent Manager Namespace
For Kueue to manage workloads in the retagentmgr namespace on OpenShift, the following label must be applied to the namespace:
oc label namespace retagentmgr kueue.openshift.io/managed=true
Note: Without this label, Kueue will not intercept and manage vectorization jobs in the
retagentmgrnamespace and those jobs will fail to be queued correctly.
Deploy Kueue Queue Objects Manually
By default, the SAS Retrieval Agent Manager Helm chart deploys the Kueue queue objects when integrations.kueue.enabled is true. If you set integrations.kueue.enabled to false, you must create the queue objects manually before SAS Retrieval Agent Manager starts vectorization jobs.
Use only one method to create these objects. If the Helm chart creates them, do not apply these manifests manually. If you apply these manifests manually, keep integrations.kueue.enabled set to false.
Use the example queue manifests. They declare the same ResourceFlavor, ClusterQueue, and LocalQueue objects with the default values from the Helm chart. Edit the namespace and the quotas to match your cluster, then apply the file:
oc apply -f kueue-queues.yaml
Note: Match the
ClusterQueuequotas to the capacity of the cluster you built. See Job scheduling quotas.
Verify that the objects are created:
oc get resourceflavor retrieval-agent-manager
oc get clusterqueue cluster-queue
oc -n retagentmgr get localqueue genai-queue
OpenShift Service Mesh 3 Deployment
Red Hat OpenShift Service Mesh 3 (OSSM3) is an optional integration that enables L7 traffic management for the SAS Retrieval Agent Manager. When enabled, the Helm chart deploys an Istio ambient-mode waypoint proxy into the release namespace. The waypoint is an Envoy sidecar-free proxy that processes all HTTP traffic and injects the X-Forwarded-For header with the real source pod IP.
Note: This section requires an OpenShift cluster with the Kubernetes Gateway API CRDs installed (see below). OSSM3 is based on the Sail Operator and uses a fundamentally different resource model from OSSM 1/2 —
ServiceMeshControlPlaneis not used here.
Install the Kubernetes Gateway API CRDs
OSSM3 ambient mode relies on the Kubernetes Gateway API. Install the standard channel CRDs before installing the operator:
oc apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
Verify the CRDs are established:
oc get crd gateways.gateway.networking.k8s.io httproutes.gateway.networking.k8s.io \
referencegrants.gateway.networking.k8s.io grpcroutes.gateway.networking.k8s.io
Install the OpenShift Service Mesh 3 Operator
Via the OpenShift Web Console
- Log in to the OpenShift web console.
- Navigate to Operators → OperatorHub.
- Search for “OpenShift Service Mesh” and select the Red Hat OpenShift Service Mesh operator (version 3.x).
- Click Install, select All namespaces scope, and accept the defaults.
- Wait for the operator status to show Succeeded.
Via CLI
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: servicemeshoperator3
namespace: openshift-operators
spec:
channel: stable
name: servicemeshoperator3
source: redhat-operators
sourceNamespace: openshift-marketplace
EOF
Wait for the operator to be ready:
oc -n openshift-operators wait --for=condition=Ready pod \
-l name=sailoperator --timeout=120s
Deploy the IstioCNI Resource
Ambient mode requires the Istio CNI plugin to redirect traffic at the node level without injecting sidecars. Create an IstioCNI resource in the istio-cni namespace:
oc new-project istio-cni
cat <<EOF | oc apply -f -
apiVersion: sailoperator.io/v1
kind: IstioCNI
metadata:
name: default
spec:
version: v1.24.3
namespace: istio-cni
profile: openshift-ambient
EOF
Verify the CNI daemonset is running on all nodes:
oc -n istio-cni wait --for=condition=Ready pod \
-l k8s-app=istio-cni-node --timeout=180s
Deploy the Istio Control Plane
Create the Istio resource that provisions the istiod control plane:
oc new-project istio-system
cat <<EOF | oc apply -f -
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: default
spec:
version: v1.24.3
namespace: istio-system
profile: openshift-ambient
EOF
Monitor the control plane until it reaches Healthy status:
oc -n istio-system wait --for=condition=Ready istio default --timeout=180s
You can also inspect the status in detail:
oc -n istio-system get istio default -o jsonpath='{.status}' | jq
Enroll the Release Namespace in Ambient Mesh
Label the retagentmgr namespace to opt it into ambient-mode data-plane processing. This must be done before installing the SAS Retrieval Agent Manager Helm chart so that the waypoint Gateway is created in an ambient-enabled namespace.
# Enroll the namespace in Istio ambient mode
oc label namespace retagentmgr istio.io/dataplane-mode=ambient
# Instruct all pods/services in the namespace to route through the waypoint
oc label namespace retagentmgr istio.io/use-waypoint=waypoint
Note: The
istio.io/use-waypointlabel value must match theintegrations.istio.waypoint.namevalue in yourram-values.yaml(default:waypoint).
Configure SAS Retrieval Agent Manager to Use the Waypoint
Enable the Istio integration in your ram-values.yaml:
integrations:
istio:
enabled: true
waypoint:
# Must match the value used in the istio.io/use-waypoint namespace label
name: waypoint
# "all" processes both east-west service traffic and ingress workload traffic
waypointFor: all
When enabled: true, the chart creates a Gateway resource with gatewayClassName: istio-waypoint in the release namespace. The Istio gateway controller detects this and deploys an Envoy waypoint deployment.
Verify the Waypoint Is Running
After the Helm chart is installed, confirm the waypoint deployment is healthy:
# Check the waypoint Gateway resource
oc -n retagentmgr get gateway waypoint
# Check the Envoy waypoint pod deployed by the Istio gateway controller
oc -n retagentmgr get pods -l gateway.istio.io/managed=istio.io-mesh-controller
# Confirm the waypoint is programmed (PROGRAMMED=True)
oc -n retagentmgr get gateway waypoint -o jsonpath='{.status.conditions}' | jq
The Programmed condition should show status: "True" before proceeding to the Application Deployment step.
OpenShift Route TLS Configuration
SAS Retrieval Agent Manager exposes services on OpenShift via Route resources, which need to be secured with TLS certificates. OpenShift’s Route API does not support referencing a Secret by name (unlike Kubernetes Ingress); instead, the certificate and private key must be embedded directly in the Route’s spec.tls section.
This section explains how to configure TLS for OpenShift Routes using two approaches:
- Inline certificates — provide PEM-encoded certificate and key directly in Helm values
- cert-manager integration — use cert-manager to automate certificate issuance and renewal
Option 1: Inline Certificates (Manual)
The simplest approach is to provide your certificate and private key as PEM-encoded text in the Helm values file.
Prerequisites
- A valid TLS certificate (
.crtfile) in PEM format - A corresponding private key (
.keyfile) in PEM format - Optionally, a CA certificate (
.crtfile) for certificate chains
Obtain Your Certificate
Get or generate your certificate through any means (commercial CA, self-signed, Let’s Encrypt, etc.). For example:
# Self-signed example (valid for testing; do NOT use in production)
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt -days 365 -nodes \
-subj "/CN=aiagent.sasram.kh.asegroup.com"
Encode as Base64
Encode the certificate and key for use in Helm values:
# Display certificate content as base64 (for the values file)
cat tls.crt | base64 -w 0
# Display key content as base64 (for the values file)
cat tls.key | base64 -w 0
# Optional: display CA certificate if you have a certificate chain
cat ca.crt | base64 -w 0
Configure in Helm Values
In your ram-values.yaml:
ingress:
enabled: true
classType: route # "route" for OpenShift
domain: aiagent.sasram.kh.asegroup.com
tls:
enabled: true
secretName: ingress-tls # Name for the Kubernetes secret created by the chart
certificate: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJC1...
...
-----END CERTIFICATE-----
key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA2Z3x4...
...
-----END RSA PRIVATE KEY-----
caCertificate: |
-----BEGIN CERTIFICATE-----
MIIDgTCCAmkCAQAwDQYJ...
...
-----END CERTIFICATE-----
Note: The chart will create a Kubernetes
Secretnamedingress-tlsfrom these values. This secret is used by nginx/contour ingress resources (if configured), and for cert-manager CertificateRequest objects when needed.
Option 2: cert-manager Integration (Automated)
For automated certificate issuance and renewal, integrate with cert-manager using the OpenShift Routes controller add-on. This approach uses annotations on the Route to request and manage certificates from a cert-manager Issuer or ClusterIssuer.
Prerequisites
- cert-manager installed in the cluster (e.g., via Red Hat’s cert-manager Operator for OpenShift)
- openshift-routes controller installed separately (NOT included with standard cert-manager)
- A cert-manager
IssuerorClusterIssuerconfigured in your cluster (e.g., ACME-based, self-signed, or corporate PKI)
Install the openshift-routes Controller
The openshift-routes controller is a separate add-on from the cert-manager project. It watches Route resources for cert-manager annotations and patches their spec.tls section with certificate and key data.
# Install openshift-routes in the cert-manager namespace
helm install openshift-routes -n cert-manager \
oci://ghcr.io/cert-manager/charts/openshift-routes \
--version v0.10.0
Verify the controller is running:
oc -n cert-manager get pods -l app.kubernetes.io/name=openshift-routes
Create a cert-manager Issuer or ClusterIssuer
If you don’t already have an Issuer configured, create one. This example uses ACME with Let’s Encrypt:
cat <<EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress: {}
EOF
For self-signed or corporate CA Issuers, refer to the cert-manager documentation.
Configure in Helm Values
In your ram-values.yaml:
ingress:
enabled: true
classType: route # "route" for OpenShift
domain: aiagent.sasram.kh.asegroup.com
tls:
enabled: true
secretName: ingress-tls
# Leave certificate/key/caCertificate empty when using cert-manager
certificate: ""
key: ""
caCertificate: ""
certManager:
enabled: true
issuerRef:
name: letsencrypt-prod # Name of your ClusterIssuer or Issuer
kind: ClusterIssuer # Use "Issuer" for namespace-scoped, "ClusterIssuer" for cluster-scoped
dnsNames:
- aiagent.example.com # Additional DNS names (optional; ingress.domain is always included)
duration: 2160h # Certificate lifetime (optional; defaults to cert-manager default)
renewBefore: 360h # How long before expiry to renew (optional; defaults to 1/3 of duration)
When certManager.enabled: true, the chart:
- Adds cert-manager annotations (
cert-manager.io/issuer-name, etc.) to all Route resources - The openshift-routes controller detects these annotations and creates a
CertificateRequestthrough cert-manager - The Issuer issues a certificate and signs the request
- The openshift-routes controller patches the Route’s
spec.tls.certificateandspec.tls.keywith the signed certificate - On renewal (default: 2/3 through the certificate lifetime), the process repeats automatically
Verify the Routes have certificates:
# List routes in the retagentmgr namespace
oc -n retagentmgr get routes
# Inspect a specific route's TLS section
oc -n retagentmgr get route <route-name> -o jsonpath='{.spec.tls}' | jq
Security Considerations
The openshift-routes controller is designed for single-tenant clusters. Important caveats:
- Multi-tenant risk: Any user who can edit a
Routecan request certificates for any domain via the annotations. This grants cluster-wide certificate request capability to Route editors. On shared clusters, use one or more of:- RBAC to restrict who can edit Routes
- Domain-validating (ACME) Issuers to prevent arbitrary domains
- cert-manager’s approver-policy to gate issuance
- Namespace isolation: The controller reconciles Routes across all namespaces using a single service account, so consider applying namespace-level RBAC as well.
For more details, see the openshift-routes project README.
Next steps
- Configure the database — install and enable the
pgcryptoandvectorextensions. - GPG keys — generate and back up the encryption keys.
- Install and upgrade — deploy the application.
Note: OpenShift installs Kueue and the service mesh through operators, as described above, rather than through the Helm charts listed on the Install dependencies page.