Phase 1: Prerequisites

Install the operator subscriptions required by Red Hat OpenShift AI 3.4 Models as a Service.

All file paths and oc apply commands in this guide are relative to the rhoai-maas-guide repository root. Make sure you have cloned it and are working from its root directory (see Getting Started).
This guide is not a replacement for the official Red Hat OpenShift AI Models as a Service documentation. It is a companion resource with opinionated Kustomize manifests and automation scripts to accelerate deployment.

Operator Overview

Operator Namespace Purpose

Red Hat OpenShift AI (rhods-operator)

redhat-ods-operator

Core RHOAI platform, model serving, dashboards, pipelines

Red Hat Connectivity Link (rhcl-operator)

openshift-operators

API gateway policies, authentication (Authorino) and rate limiting (Limitador) for MaaS endpoints

cert-manager (openshift-cert-manager-operator)

cert-manager-operator

TLS certificate lifecycle management for serving endpoints

Leader Worker Set (leader-worker-set)

openshift-lws-operator

Coordinates multi-replica workloads for distributed inference and training

Optional GPU Operators

Operator Namespace Purpose

Node Feature Discovery (nfd)

openshift-nfd

Detects hardware features (GPUs, CPU flags) and labels nodes accordingly

NVIDIA GPU Operator (gpu-operator-certified)

nvidia-gpu-operator

Installs NVIDIA drivers, device plugin, and monitoring for GPU workloads

Optional MetalLB Operator (Non-Cloud Clusters)

Operator Namespace Purpose

MetalLB Operator (metallb-operator)

metallb-system

Provides LoadBalancer IP addresses for the MaaS Gateway on baremetal, OpenStack, or SNO clusters

On non-cloud clusters (baremetal, OpenStack, RHPDS, SNO), there is no cloud load-balancer controller to provision external IPs for LoadBalancer Services. MetalLB fills this role, assigning IPs from a configured pool so the MaaS Gateway can reach Programmed=True.

The setup-maas.sh script auto-detects non-cloud platforms and installs MetalLB automatically if needed.

Installation

Step 0: Clone the Repository

git clone https://github.com/rh-aiservices-bu/rhoai-maas-guide.git
cd rhoai-maas-guide

All commands in this guide are run from the repository root.

Step 1: Install Required Operators

oc apply -k manifests/01-prerequisites/operators/

This installs all four required operator subscriptions. OLM will resolve and install each operator automatically.

Step 2 (Optional): Install GPU Operators

If your cluster has GPU nodes (or you plan to add them), install the GPU operators:

oc apply -k manifests/01-prerequisites/gpu/

Step 2b (Optional): Create GPU Operand Instances

After the GPU operator CSVs have succeeded (see Verification below), create the operand instances that configure NFD and the GPU driver stack.

The operators must be fully installed before applying these resources - the CRDs they define do not exist until the operators are ready. Wait for both CSVs to succeed first.
# Wait for GPU operator CSVs to succeed
oc wait csv -n openshift-nfd -l operators.coreos.com/nfd.openshift-nfd="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

oc wait csv -n nvidia-gpu-operator -l operators.coreos.com/gpu-operator-certified.nvidia-gpu-operator="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

Create the NFD NodeFeatureDiscovery instance (scans nodes for GPU hardware) and the NVIDIA ClusterPolicy (installs drivers, device plugin, monitoring):

oc apply -k manifests/01-prerequisites/gpu/instances/

Wait for the ClusterPolicy to reach ready state (this takes 5-10 minutes as the GPU operator installs NVIDIA drivers on GPU nodes):

oc wait clusterpolicy gpu-cluster-policy \
  --for=jsonpath='{.status.state}'=ready --timeout=600s

Verify GPU resources are available:

# Check NFD labeled GPU nodes
oc get nodes -l feature.node.kubernetes.io/pci-10de.present=true

# Check GPU operator pods
oc get pods -n nvidia-gpu-operator

# Check nvidia.com/gpu resources on GPU nodes
oc get nodes -l nvidia.com/gpu.present=true

Step 3: Install MetalLB (Non-Cloud Platforms Only)

Read this section carefully!

If your cluster has no cloud load-balancer controller (baremetal, OpenStack, RHPDS/SNO), you need MetalLB to make the Gateway accessible externally.

First, determine your platform type:

oc get infrastructure cluster -o jsonpath='{.status.platform}'
Platform output What to do

AWS, Azure, GCP (cloud)

Skip to Verification below — no extra configuration needed.

None, BareMetal, OpenStack

Continue with the steps below — MetalLB and a passthrough Route are required.

Install the MetalLB operator:

oc apply -k manifests/01-prerequisites/metallb/

Wait for the MetalLB CSV to succeed, then create the MetalLB CR and configure an IP pool:

oc wait csv -n metallb-system -l operators.coreos.com/metallb-operator.metallb-system="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=120s

Create MetalLB instance

oc apply -f manifests/01-prerequisites/metallb/metallb.yaml

Create IPAddressPool + L2Advertisement.

Do not use the node’s own IP for the MetalLB pool. When a LoadBalancer service shares the node IP on port 443, kube-proxy iptables rules intercept internal cluster traffic meant for the OpenShift router (which serves *.apps routes on the same IP:port via hostNetwork). This breaks OAuth callbacks, console access, and any in-cluster traffic to routes.

The command below derives an IP one address above the first node’s InternalIP. For multi-node clusters or complex networks, adjust METALLB_IP_RANGE to an unused IP on the same L2 subnet.

NODE_IP=$(oc get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
METALLB_IP=$(echo "$NODE_IP" | awk -F. '{printf "%s.%s.%s.%d", $1, $2, $3, $4+1}')
export METALLB_IP_RANGE="${METALLB_IP}-${METALLB_IP}"

echo "Node IP: $NODE_IP  ->  MetalLB IP: $METALLB_IP_RANGE"

envsubst < manifests/03-maas-platform/openshift-gateway-setup/metallb-config.yaml | oc apply -f -

Verification

Wait for Operator CSVs to Succeed

After applying the subscriptions, wait for each operator’s ClusterServiceVersion to reach the Succeeded phase.

Operator CSVs take 30-60 seconds to appear after applying subscriptions. If oc wait returns "no matching resources found", wait a minute and retry.

Required operators:

oc wait csv -n redhat-ods-operator -l operators.coreos.com/rhods-operator.redhat-ods-operator="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

oc wait csv -n openshift-operators -l operators.coreos.com/rhcl-operator.openshift-operators="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

oc wait csv -n cert-manager-operator -l operators.coreos.com/openshift-cert-manager-operator.cert-manager-operator="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

oc wait csv -n openshift-lws-operator -l operators.coreos.com/leader-worker-set.openshift-lws-operator="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

GPU operators (if installed):

oc wait csv -n openshift-nfd -l operators.coreos.com/nfd.openshift-nfd="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

oc wait csv -n nvidia-gpu-operator -l operators.coreos.com/gpu-operator-certified.nvidia-gpu-operator="" \
  --for=jsonpath='{.status.phase}'=Succeeded --timeout=600s

Verify CRDs Are Available

Check that the key CRDs have been registered:

# RHOAI
oc get crd datascienceclusters.datasciencecluster.opendatahub.io

# Connectivity Link / Kuadrant
oc get crd kuadrants.kuadrant.io

# cert-manager
oc get crd certificates.cert-manager.io

# Leader Worker Set
oc get crd leaderworkersetoperators.operator.openshift.io

Quick Status Check

List all operator subscriptions and their current CSVs:

oc get subscriptions.operators.coreos.com -A \
  -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,CSV:.status.currentCSV,STATE:.status.state'

Expected Results:

Exact CSV versions will vary depending on when you install. The versions below were current as of June 2026.
NAMESPACE                NAME                                                                                   CSV                                                STATE
cert-manager-operator    openshift-cert-manager-operator                                                        cert-manager-operator.v1.19.0                      AtLatestKnown
metallb-system           metallb-operator                                                                       metallb-operator.v4.20.0-...                       AtLatestKnown
openshift-lws-operator   leader-worker-set                                                                      leader-worker-set.v1.0.0                           AtLatestKnown
openshift-operators      authorino-operator-stable-redhat-operators-openshift-marketplace                       authorino-operator.v1.3.1                          AtLatestKnown
openshift-operators      dns-operator-stable-redhat-operators-openshift-marketplace                             dns-operator.v1.3.1                                AtLatestKnown
openshift-operators      limitador-operator-stable-redhat-operators-openshift-marketplace                       limitador-operator.v1.3.1                          AtLatestKnown
openshift-operators      rhcl-operator                                                                          rhcl-operator.v1.4.2                               AtLatestKnown
redhat-ods-operator      rhods-operator                                                                         rhods-operator.3.4.0                               AtLatestKnown

Appendix

Directory Structure

manifests/01-prerequisites/
  operators/
    kustomization.yaml          # aggregates all operator subdirectories
    cert-manager/
    connectivity-link/
    leader-worker-set/
    rhoai-operator/
  gpu/
    kustomization.yaml          # aggregates NFD + NVIDIA operator subscriptions
    nfd/
    nvidia-operator/
    instances/
      kustomization.yaml        # aggregates NFD + GPU operand instances
      nodefeaturediscovery.yaml  # NFD NodeFeatureDiscovery CR
      cluster-policy.yaml       # NVIDIA GPU ClusterPolicy CR
  metallb/
    kustomization.yaml          # MetalLB namespace + operatorgroup + subscription
    namespace.yaml
    operatorgroup.yaml
    subscription.yaml
    metallb.yaml                # MetalLB CR (applied after CSV succeeds)

Next step