Build AI/Agentic Applications with OGX
Working with OGX in Red Hat OpenShift AI Self-Managed
Abstract
Chapter 1. Llama Stack to OGX migration
Starting in OpenShift AI version 3.5EA1, Llama Stack is being fully renamed to OGX. This creates breaking changes in any applications created with the Llama Stack Operator.
The following charts show the naming changes of the components, environment variables, and field changes.
Table 1.1. Name Mapping
| Component | Previous name | New name |
|---|---|---|
| API Group |
|
|
| API Version |
|
|
| Kind |
|
|
| Plural |
|
|
| Short Name |
|
|
| Container Name |
|
|
| App Label |
|
|
| Managed-by |
|
|
| Watch Label |
|
|
| Mount Path |
|
|
| Leader Election ID |
|
|
Table 1.2. Environment Variables
| Previous name | New name | Additional details |
|---|---|---|
|
|
| Container port for the server |
|
|
| Number of uvicorn worker processes |
|
|
| Path to the server config file |
Table 1.3. Status Field Changes
| Old Path | New Path |
|---|---|
|
|
|
|
|
|
The following YAML examples display the changes in specifications. For example: OGXServer CRs, network configurations, and workload configurations.
Workload Configuration
Previous workload configuration (flat on spec):
spec:
replicas: 2
server:
distribution:
name: rh-dev
containerSpec:
env:
- name: MY_VAR
value: "hello"
storage:
size: "20Gi"
New workload configuration (grouped under spec.workload):
spec:
distribution:
name: rh-dev
workload:
replicas: 2
storage:
size: "20Gi"
overrides:
env:
- name: MY_VAR
value: "hello"Network Configurations
Previous network configurations (spec.network):
spec:
network:
exposeRoute: true
allowedFrom:
namespaces: ["my-app"]
labels: ["team=frontend"]
New network configurations(spec.network):
spec:
network:
externalAccess:
enabled: true
policy:
enabled: true
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: my-app
- namespaceSelector:
matchLabels:
team: frontend
ports:
- protocol: TCP
port: 83211.1. Migrating from Llama Stack to OGX
In order to migrate to the newly named ogx-operator, you must remove the Llama Stack Operator and create new OGXServer custom resources (CRs).
Prerequisites
- You have the Llama Stack Operator installed on your OpenShift AI cluster.
-
You have custom
LlamaStackDistributionapplications. - You have cluster administrator permissions.
-
You have installed the OpenShift CLI (
oc).
Procedure
Remove the Llama Stack Operator from your environment. You can remove the Llama Stack Operator by setting the component spec:
$ dsc.spec.components.lls = "Removed"
Install the new OGX operator by setting the component spec:
$ dsc.spec.components.ogx = "Managed"
Create the
OGXServercustom resource (CR).apiVersion: ogx.io/v1beta1 kind: OGXServer metadata: name: my-server spec: distribution: name: rh-dev workload: replicas: 1 storage: size: "20Gi" overrides: env: - name: OLLAMA_INFERENCE_MODEL value: "llama3.2:1b" - name: OLLAMA_URL value: "http://ollama-server-service.ollama-dist.svc.cluster.local:11434"Apply the
OGXServerCR to the cluster:$ oc apply -f ogxserver.yaml
Verification
Verify the pod deployment with the following command:
# Check the new CRD is registered $ oc get crd ogxservers.ogx.io # List OGXServer resources $ oc get ogxserver # Check conditions for adoption status $ oc get ogxserver my-server -o jsonpath='{.status.conditions}' # Verify the server is ready $ oc get ogxserver my-server -o jsonpath='{.status.phase}'You can then clean up the legacy resources when the new OGXServer is verified.
Remove the
LlamaStackDistributionCR resources:$ oc delete llamastackdistribution <old-llsd-name> -n <namespace>
(Optional) Adopting existing PVC.
To preserve existing data by adopting the PVC from the old
LlamaStackDistribution, set theannotationsparameter similar to the following:metadata: annotations: ogx.io/adopt-storage: "<old-llsd-name>"The operator strips the old
ownerReffrom the PVC and labels it for discovery. The adopted PVC intentionally has noownerReferenceto the OGXServer.
(Optional) Adopting existing Service and Ingress
To preserve ClusterIP and external endpoints, set the
annotationssimilar to the following:metadata: annotations: ogx.io/adopt-storage: "<old-llsd-name>" ogx.io/adopt-networking: "<old-llsd-name>"
The operator adopts the orphaned Service + Ingress, replaces Service selectors with new pod labels: app: ogx, app.kubernetes.io/instance: <name>, and sets ownerReferences.
Chapter 2. Overview of OGX
OGX is a unified AI runtime environment designed to simplify the deployment and management of generative AI workloads on OpenShift AI. In OpenShift, the OGX Operator manages the deployment lifecycle of these components, ensuring scalability, consistency, and integration with OpenShift AI projects. OGX integrates model inference, embedding generation, vector storage, and retrieval services into a single stack that is optimized for retrieval-augmented generation (RAG) and agent-based AI workflows.
OGX concepts
- OGX Operator Installs and manages OGX server instances in OpenShift AI, handling lifecycle operations such as deployment, scaling, and updates.
-
The
run.yamlfile Defines which APIs are enabled and how backend providers are configured for a OGX server. Red Hat ships a defaultrun.yamlthat supports common deployment scenarios. You can provide a customrun.yamlto enable advanced workflows or integrate additional providers. -
OGXServercustom resource Declares the runtime configuration for a OGX server, including model providers, embedding configuration, vector storage, and persistence settings.
OpenShift AI ships with a OGX Distribution that runs the OGX server in a containerized environment. For the OGX Operator version included in this release of OpenShift AI, see Supported Configurations for 3.x.
OGX integration is currently available in Red Hat OpenShift AI 3.5 as a Technology Preview feature. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production.
These features provide early access to upcoming product capabilities, enabling customers to test functionality and provide feedback during development.
For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.
OGX includes the following core components:
-
Integration with OpenShift AI Uses the
OGXServercustom resource to simplify configuration and deployment of AI workloads. - Inference model connections Acts as a proxy between OGX APIs and model inference servers, such as vLLM deployments.
- Embedding generation Generates vector embeddings used for retrieval. In OpenShift AI 3.2, remote embedding models are the recommended and default option for production deployments. Inline embedding models remain available for development and testing scenarios.
- Vector storage Stores and indexes embeddings by using supported vector databases, such as Milvus or PostgreSQL with the pgvector extension.
- Metadata persistence Stores vector store metadata, file references, and configuration state. In OpenShift AI 3.2, PostgreSQL is the default backend for production-grade deployments.
- Retrieval workflows Manages ingestion, chunking, embedding, and similarity search to support RAG workflows.
- Agentic workflows Enables agent-based interactions through supported APIs, such as OpenAI-compatible Responses and Chat Completions.
For information about deploying OGX in OpenShift AI, see Deploying a RAG stack in a project.
The OGX Operator is not currently supported on IBM Z platform.
OGX is supported on IBM Power (ppc64le) with limited functionality:
- The GenAI playground is supported and available on the IBM Power architecture.
-
milvus-liteis supported and available as a vector store option on the IBM Power architecture. -
Although
PostgreSQLwith thepgvectorextension is listed as a supported vector store, it is not currently available on the IBM Power ppc64le architecture.
Additional resources
2.1. OGX APIs
You can use the following APIs from OGX for AI actions.
2.1.1. Supported OGX APIs in OpenShift AI
2.1.1.1. File Processors API
-
Endpoint:
/v1alpha/file-processors. - Providers: All file processor backends deployed through OpenShift AI.
- Support level: Developer Preview
The File Processors API converts various document types into vector-ready chunks using configurable extraction backends, including Docling, PyPDF, and others. You can upload a document in your file storage and the API returns structured chunks.
2.1.1.2. Datasets_IO API
-
Endpoint:
/v1alpha/datasetio. - Providers: All dataset_io backends deployed through OpenShift AI.
- Support level: Technology Preview.
The Dataset_IO API manages the input and output of datasets and their content.
2.1.1.3. Inference API
-
Endpoint:
/v1alpha/inference. - Providers: All inference backends deployed through OpenShift AI.
- Support level: Developer Preview.
The majority of the Inference API is deprecated. The Inference providers use the Completions and Chat Completions APIs now.
The Inference API enables conversational, message-based interactions with models served by OGX in OpenShift AI.
2.1.1.4. Tool Runtime API
-
Endpoint:
/v1/tool-runtime. - Providers: All tool runtime backends deployed through OpenShift AI.
- Support level: Developer Preview.
The Tool Runtime API allows a model to dynamically call a tool at runtime.
2.1.1.5. Vector_IO API
-
Endpoint:
/v1/vector-io. - Providers: All vector_io backends deployed through OpenShift AI.
- Support level: Developer Preview.
The Vector_IO API allows you to manage and query vector embeddings: numeric representations of data.
2.2. OpenAI-compatible APIs in OGX
OpenShift AI includes a OGX component that exposes OpenAI-compatible APIs. These APIs enable you to reuse existing OpenAI SDKs, tools, and workflows directly within your OpenShift environment, without changing your client code. This compatibility layer supports retrieval-augmented generation (RAG), inference, and embedding workloads by using OpenAI-compatible endpoints, schemas, and authentication patterns.
This compatibility layer has the following capabilities:
- Standardized endpoints: REST API paths align with OpenAI specifications.
- Schema parity: Request and response fields follow OpenAI data structures.
When connecting OpenAI SDKs or third-party tools to OpenShift AI, you must update the client configuration to use your deployment’s OGX route as the base_url.
When you use OpenAI-compatible SDKs, the base_url must include the /v1 path suffix so that requests are routed to the OpenAI-compatible API surface exposed by OGX.
When you use OpenAI SDKs or send raw HTTP requests to OGX, always include the /v1 path suffix in the base URL.
For example: http://ogx-service:8321/v1
Using the service endpoint without /v1 results in request failures.
These endpoints are exposed under the OpenAI compatibility layer and are distinct from the native OGX APIs.
2.2.1. Supported OpenAI-compatible APIs in OpenShift AI
Before running the following examples, ensure you have:
-
The OpenAI Python SDK installed:
pip install -q openai rich - A configured client pointing to your OGX endpoint
- Model IDs from your deployment (see Models API section)
from openai import OpenAI
import rich
# We'll be using a ogx server deployed in {productname-short}.
# Once all pods associated to the OGXServer are running,
# create the base_url using the ogx service hostname (with /v1 at the end when using openai sdk)
base_url = "http://ogx-distribution-service.my-project.svc.cluster.local:8321/v1"
client = OpenAI(
api_key="your-ogx-key",
base_url=base_url
)For more information, see Deploying a OGX server.
2.2.1.1. Models API
-
Endpoint:
/v1/models. - Providers: All model-serving back ends configured within OpenShift AI.
- Support level: Technology Preview.
The Models API lists and retrieves available model resources from the OGX deployment running on OpenShift AI. By using the Models API, you can enumerate models, view their capabilities, and verify deployment status through a standardized OpenAI-compatible interface.
Example code in Python:
# List models available in the ogx server
models = client.models.list()
rich.print(models)
# Select the first LLM and first embedding model
model_id = next(m for m in models if m.custom_metadata["model_type"] == "llm").id
embedding_model_id = (
em := next(m for m in models if m.custom_metadata["model_type"] == "embedding")
).id
embedding_dimension = em.custom_metadata["embedding_dimension"]
2.2.1.2. Chat Completions API
-
Endpoint:
/v1/chat/completions. - Providers: All inference back ends deployed through OpenShift AI.
- Support level: Technology Preview.
The Chat Completions API enables conversational, message-based interactions with models served by OGX in OpenShift AI.
Example code in Python:
# Test chat completion functionality with a simple question
response = client.chat.completions.create(
model=model_id,
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"},
],
temperature=0,
)
# Optional verification check
assert len(response.choices) > 0, "No response after basic inference on ogx server"
content = response.choices[0].message.content
rich.print(content)
2.2.1.3. Completions API
-
Endpoint:
/v1/completions. - Providers: All inference back ends managed by OpenShift AI.
- Support level: Technology Preview.
The Completions API supports single-turn text generation and prompt completion.
Example code in Python:
# Test completion functionality with a simple question
response = client.completions.create(
model=model_id,
prompt="Answer with one word only: What is the capital of France?",
max_tokens=64,
temperature=0.1
)
# Optional verification check
assert len(response.choices) > 0, "No response after basic inference on ogx server"
content = response.choices[0].text
rich.print(content)
2.2.1.4. Embeddings API
-
Endpoint:
/v1/embeddings. - Providers: All embedding models enabled in OpenShift AI.
The Embeddings API generates numerical embeddings for text or documents that can be used in downstream semantic search or RAG applications.
Example code in Python:
# Create text embeddings
response = client.embeddings.create(
input="Your text string goes here",
model=embedding_model_id
)
embedding = response.data[0].embedding
rich.print(embedding[:5] + ["..."] + embedding[-5:])
2.2.1.5. Files API
-
Endpoint:
/v1/files. - Providers: File system-based file storage provider for managing files and documents stored locally in your cluster.
- Support level: Technology Preview.
The Files API manages file uploads for use in embedding and retrieval workflows.
The Files API handles file storage only. Indexing files for retrieval requires a vector store, which is a separate provider managed through the Vector Stores API. The following example demonstrates a complete file-upload-and-index workflow that uses both APIs together.
Example code in Python:
import requests
from rich import print
from rich.rule import Rule
import time
# -----------------------------
# Download the PDF from url
# -----------------------------
print(Rule("[bold cyan]Downloading PDF[/bold cyan]"))
# We'll use IBM 2025-Q4 report to test RAG, as models don't have that info
pdf_url = "https://www.ibm.com/downloads/documents/us-en/1550f7eea8c0ded6"
filename = "ibm-Q4-2025-4q25-press-release.pdf"
title = "IBM-4Q25-Earnings-Press-Release"
print("📥 Fetching PDF from URL...")
response = requests.get(pdf_url)
response.raise_for_status()
print("✅ PDF fetched successfully")
print(f"💾 Saving PDF as [bold]{filename}[/bold]...")
with open(filename, "wb") as f:
f.write(response.content)
print(f"✅ Downloaded and saved: [green]{filename}[/green]")
# -----------------------------
# Upload the PDF
# -----------------------------
print(Rule("[bold cyan]Uploading File[/bold cyan]"))
print("☁️ Uploading file to Files API...")
with open(filename, "rb") as f:
file_info = client.files.create(
file=(filename, f),
purpose="assistants"
)
print("✅ File uploaded successfully")
print(file_info)
# -----------------------------
# Create vector store
# -----------------------------
print(Rule("[bold cyan]Creating Vector Store[/bold cyan]"))
provider_id = "milvus-remote"
print("🧠 Creating vector store with Milvus provider...")
vector_store = client.vector_stores.create(
name="test_vector_store",
extra_body={
"embedding_model": embedding_model_id,
"embedding_dimension": embedding_dimension,
"provider_id": provider_id,
},
)
print("✅ Vector store created")
print(vector_store)
# -----------------------------
# Add file to vector store
# -----------------------------
print(Rule("[bold cyan]Indexing File[/bold cyan]"))
print("📎 Adding uploaded file to vector store...")
vector_store_file = client.vector_stores.files.create(
vector_store_id=vector_store.id,
file_id=file_info.id,
chunking_strategy={
"type": "static",
"static": {
"max_chunk_size_tokens": 700,
"chunk_overlap_tokens": 100,
}
},
attributes={
"title": title,
},
)
print("✅ File added to vector store")
print(vector_store_file)
# -----------------------------
# Verify file is completed
# -----------------------------
print(Rule("[bold cyan]Waiting until file status is complete[/bold cyan]"))
# Wait for file processing to complete
print("Waiting for file processing to complete...")
max_wait_time = 300 # 5 minutes
start_time = time.time()
while time.time() - start_time < max_wait_time:
files = client.vector_stores.files.list(vector_store_id=vector_store.id)
if files.data:
file_status = files.data[0].status
print(f"File status: {file_status}")
if file_status == "completed":
print("✅ File processing completed!")
break
elif file_status == "failed":
print("✗ File processing failed!")
break
time.sleep(5)
else:
print("⚠ Timeout waiting for file processing")
# Verify file is completed
files = client.vector_stores.files.list(vector_store_id=vector_store.id)
if files.data:
print(f"\nFinal file status: {files.data[0].status}")
print(f"File details: {files.data[0]}")
else:
print("No files found in vector store")
print(Rule("[bold green]All tasks completed successfully ✔[/bold green]"))
2.2.1.6. Vector Stores API
-
Endpoint:
/v1/vector_stores. - Providers: Remote vector store providers configured in OpenShift AI.
- Support level: Technology Preview.
The Vector Stores API manages the creation, configuration, and lifecycle of vector store resources in OGX. Through this API, you can create new vector stores, list existing ones, delete unused stores, and query their metadata, all using OpenAI-compatible request and response formats.
2.2.1.7. Vector Store Files API
-
Endpoint:
/v1/vector_stores/{vector_store_id}/files. - Providers: Local inline provider configured for file storage and retrieval.
- Support level: Developer Preview.
The Vector Store Files API implements the OpenAI Vector Store Files interface and manages the association between document files and vector stores used for RAG workflows.
2.2.1.8. Responses API
-
Endpoint:
/v1/responses. - Providers: All agents, inference, and vector providers configured in OpenShift AI.
- Support level: Generally Available
The Responses API generates model outputs by combining inference, file search, and tool-calling capabilities through a single OpenAI-compatible endpoint. It is particularly useful for retrieval-augmented generation (RAG) workflows that rely on the file_search tool to retrieve context from vector stores.
The Responses API orchestrates inference and retrieval but relies on separate providers for file storage (Files API) and vector indexing (Vector Stores API). The following example demonstrates a complete RAG workflow that uses the Files API, Vector Stores API, and Responses API together.
Example code in Python:
from rich import print
from rich.table import Table
system_instructions = """You are a financial document analysis assistant specialized in quarterly earnings reports, annual filings, press releases, and earnings call transcripts.
You are designed to answer questions in a concise and professional manner.
Answer questions strictly using only the provided documents.
Base every answer strictly on the retrieved document content and cite the relevant section or excerpt ID.
Do not use outside knowledge.
Do not guess, infer missing data, or fabricate numbers.
If the answer is not found in the retrieved content, reply: "I couldn't find relevant information in the available files or my own knowledge."
Be concise, precise, and factual."""
examples = [
{
"input_query": "What do you know about IBM earnings in Q4, 2025? Summarize in one sentence",
"expected_answer": "IBM reported strong fourth-quarter results with revenue rising 12% to $19.7 billion, driven by double-digit growth in its Software and Infrastructure segments and a generative AI book of business that has now surpassed $12.5 billion"
},
{
"input_query": "What was the total value of IBM's generative AI book of business as reported in the fourth quarter of 2025?",
"expected_answer": "IBM reported that its generative AI book of business now stands at more than $12.5 billion."
},
{
"input_query": "What was IBM's reported free cash flow for the full year of 2025?",
"expected_answer": (
"IBM reported a full-year free cash flow of $14.7 billion, which was an increase of $2.0 billion year-over-year"
)
},
{
"input_query": "How did the Software segment perform in terms of revenue during the fourth quarter of 2025?",
"expected_answer": (
"The Software segment generated $9.0 billion in revenue, representing an increase of 14 percent (or 11 percent at constant currency)"
)
},
]
# Use the Responses API to create a results table comparing not using vs using
# the vector_store
table = Table(
title="Answer Comparison (With vs Without Vector Store)",
show_lines=True,
)
table.add_column("Question", style="cyan", no_wrap=False)
table.add_column("Expected Answer", style="magenta", no_wrap=False)
table.add_column("Answer (No Vector Store)", style="yellow", no_wrap=False)
table.add_column("Answer (With Vector Store)", style="green", no_wrap=False)
for example in examples:
question = example["input_query"]
expected_answer = example["expected_answer"]
# Ask question without vector_store
response_no_vs = client.responses.create(
model=model_id,
input=question,
instructions=system_instructions,
)
answer_no_vs = response_no_vs.output_text.strip()
# Ask question with vector_store
response_vs = client.responses.create(
model=model_id,
input=question,
instructions=system_instructions,
tools=[
{
"type": "file_search",
"vector_store_ids": [vector_store.id],
}
],
)
answer_vs = response_vs.output_text.strip()
table.add_row(
question,
expected_answer,
answer_no_vs,
answer_vs,
)
# The table will take a while to be printed, as multiple queries to the responses API will be done
print(table)
2.2.1.9. Conversations API
-
Endpoint:
/v1/conversations. - Providers: All agents and inference providers configured in OpenShift AI.
- Support level: Technology Preview.
The Conversations API enables multi-turn, context-aware chats by managing server-side conversation state. Instead of manually passing previous_response_id between Responses API calls, you can create a conversation that automatically accumulates message history across multiple turns. This simplifies building AI applications where each turn in the conversation can reference context from all previous turns.
The Conversations API provides the following operations:
-
Create a conversation:
POST /v1/conversations- Creates a new conversation container with optional metadata. -
Retrieve a conversation:
GET /v1/conversations/\{id}- Retrieves a conversation by ID. -
Update a conversation:
POST /v1/conversations/\{id}- Updates a conversation’s metadata. -
Delete a conversation:
DELETE /v1/conversations/\{id}- Removes a conversation and its history. -
Create conversation items:
POST /v1/conversations/\{id}/items- Adds items to a conversation. -
List conversation items:
GET /v1/conversations/\{id}/items- Retrieves all messages stored in a conversation. -
Retrieve a conversation item:
GET /v1/conversations/\{id}/items/\{item_id}- Retrieves a specific item. -
Delete a conversation item:
DELETE /v1/conversations/\{id}/items/\{item_id}- Removes an item from a conversation.
To use a conversation with the Responses API, pass the conversation parameter instead of previous_response_id when calling /v1/responses.
Example code in Python:
model_id = "your-model-id"
# Step 1: Create a conversation
conversation = client.conversations.create(
metadata={"topic": "pet-care", "user": "demo-user"}
)
conversation_id = conversation.id
# Step 2: Send messages using the Responses API with conversation_id
# Turn 1
response1 = client.responses.create(
model=model_id,
input="I have a rabbit. What is its living quarters called?",
conversation=conversation_id,
store=True, # Persist each response as a conversation item
instructions="You are a helpful assistant. Keep responses brief.",
)
print(response1.output_text)
# Turn 2: The response can use context from Turn 1
response2 = client.responses.create(
model=model_id,
input="I also have a dog. What are its living quarters called?",
conversation=conversation_id,
store=True,
)
print(response2.output_text)
# Turn 3: The response can use context from previous turns
response3 = client.responses.create(
model=model_id,
input="List the living quarters I need for all my pets.",
conversation=conversation_id,
store=True,
)
print(response3.output_text)
# Step 3: List all messages in the conversation
items = client.conversations.items.list(conversation_id, order="asc")
for item in items.data:
print(f"{item.role}: {item.content}")
# Step 4: Clean up
client.conversations.delete(conversation_id)The Conversations API is a Technology Preview feature in OpenShift AI. While functional and suitable for evaluation, some endpoints and parameters might change in future releases. This API is not recommended for production use.
Additional resources
2.2.2. OpenAI compatibility for RAG APIs in OGX
OpenShift AI supports OpenAI-compatible request and response schemas for OGX retrieval-augmented generation (RAG) workflows. This compatibility allows you to use OpenAI clients, tools, and schemas with OGX for managing files, vector stores, and executing RAG queries through the Responses API.
OpenAI compatibility enables the following capabilities:
- You can use OpenAI SDKs and tools with OGX by pointing the client to the OGX OpenAI-compatible API path.
-
You can manage files and vector stores by using OpenAI-compatible endpoints and invoke RAG workflows by using the Responses API with the
file_searchtool.
When configuring clients, the required base_url depends on the SDK that you use:
OpenAI SDKs When you use an OpenAI-compatible SDK (for example, the OpenAI Python client), you must include the
/v1path suffix in the base URL. For example:`http://ogx-service:8321/v1`
OGX SDK (
ogx_client) When you use the native OGX SDK, set the base URL to the OGX service endpoint without the/v1suffix. The SDK automatically appends the correct API paths. For example:`http://ogx-service:8321`
When you use OpenAI-compatible SDKs or send raw HTTP requests to OGX, always include the /v1 path suffix in the base URL.
Using the service endpoint without /v1 results in request failures.
2.3. OGX API provider support
You can use OGX to enable various Provider APIs and providers in OpenShift AI. The following table lists the supported providers included in OpenShift AI, enablement environment variables, disconnected environment support, and its current support status.
The support status of the OGX API providers has shifted between Technology Preview and Developer Preview across OpenShift AI versions.
| Provider API | Providers | How to Enable | Disconnected support | Support status |
|---|---|---|---|---|
| Responses |
| Enabled by default | Yes | Developer Preview |
| Messages |
| Enabled by default | Yes | Developer Preview |
| Dataset_IO |
| Enabled by default | Yes | Technology Preview |
|
| Enabled by default | No | Technology Preview | |
| Files |
| Enabled by default | No | Technology Preview |
|
|
Set the | Yes | Developer Preview | |
| Inference |
|
Set the | Yes | Technology Preview |
|
|
Set the | Yes | Technology Preview | |
|
|
Set the | No | Technology Preview | |
|
|
Set the | No | Developer Preview | |
|
|
Set the | No | Developer Preview | |
|
|
Set the | No | Technology Preview | |
|
|
Set the | No | Technology Preview | |
|
|
Set the | No | Technology Preview | |
|
|
Set the | No | Technology Preview | Tool_Runtime |
|
| Enabled by default | No | Developer Preview | |
|
| Enabled by default | No | Developer Preview | |
|
| Enabled by default | No | Developer Preview | |
|
| Enabled by default | No | Developer Preview | Vector_IO |
|
|
Set the | No | Technology Preview | |
|
|
Set the | Yes | Technology Preview | |
|
|
Set the | Yes | Technology Preview | |
|
|
Set the | Yes | Technology Preview | |
|
|
Set the | Yes | Technology Preview | File Processors |
|
| Enabled by default | No | Developer Preview | |
|
|
Dependency only. Requires a custom | No | Developer Preview | |
|
|
Dependency only. Requires a custom | No | Developer Preview | |
|
|
Dependency only. Requires a custom | No | Developer Preview |
Any providers labeled as Dependency only are not included in the default runtime config.yaml file, but their dependencies are pre-installed in the container image. To use those providers, pass a custom config.yaml at runtime that includes the provider definitions.
2.4. OpenAI-compatible file citation annotations
OGX supports OpenAI-compatible file citation annotations in Responses API outputs when using the file_search tool. These annotations enable applications to trace generated responses back to source documents without requiring changes to existing OpenAI client code.
2.4.1. OpenAI-compatible file citation annotations in OGX
OpenShift AI provides OpenAI-compatible file citation annotations in Responses API outputs when using retrieval-augmented generation (RAG) with the file_search tool. These annotations enable applications to trace generated responses back to the source files used during retrieval without requiring changes to existing OpenAI client code. When you use the Responses API with the file_search tool, OGX returns citation metadata that references the source file used to generate the response. Annotations are enabled by default.
Citation annotations have the following characteristics:
- They follow the same response structure defined by OpenAI.
-
They appear in the
annotationsfield ofoutput_textresponse content. - They identify the source file by ID and filename.
- They provide document-level attribution.
This feature improves transparency for RAG workflows while maintaining schema compatibility with OpenAI request and response formats.
In OpenShift AI, the following annotation capabilities are supported:
- Annotations are returned only through the Responses API.
-
Annotations are returned only when using the
file_searchtool. -
The
file_citationannotation type is supported. - Attribution is provided at the document level.
Additional resources
2.4.2. Viewing file citation annotations in Responses API output
When you query ingested content by using the file_search tool with the Responses API, OGX returns OpenAI-compatible file_citation annotations. These annotations identify the source files used during retrieval.
Prerequisites
- You have deployed a OGX server.
- You have configured at least one inference model.
- You have created a vector store and ingested content into it.
-
You can successfully execute a RAG query by using the
file_searchtool, as described in Querying ingested content in a Llama model. - You have access to a client environment, such as a Jupyter notebook or an OpenAI SDK client, that is correctly configured to send authenticated requests to the OGX server.
This procedure requires that content has already been ingested into a vector store. If no content is available, RAG queries return empty or non-contextual responses.
Procedure
In a Jupyter notebook cell or other configured client environment, run a RAG query by using the
file_searchtool.response = client.responses.create( model=model_id, input=query, instructions=system_instructions, tools=[ { "type": "file_search", "vector_store_ids": [vector_store_id], } ], )Inspect the full response object rather than only the
output_textproperty.response.output
Access the
annotationsarray.annotations = response.output[0].content[0].annotations print(annotations)
Review the
file_citationannotation fields.Example output:
[ { "type": "file_citation", "file_id": "file-57610eaac6364459bfefae60377837b7", "filename": "redbankfinancial_about.pdf", "index": 139 } ]
Each file_citation annotation includes the following fields:
-
file_id: The identifier of the retrieved file. -
filename: The name of the source file. -
index: The index of the cited file in the list of files.
Multiple annotations can reference the same index position.
Optional: Using the OpenAI-compatible HTTP endpoint
If you use raw HTTP requests or an OpenAI SDK, send requests to the following endpoint:
/v1/responses
Ensure that your base URL includes the /v1 path suffix, as described in OpenAI compatibility for RAG APIs in OGX.
The accuracy and consistency of citation annotations depend on the capabilities of the underlying language model. Smaller or less capable models might produce less precise attributions, even when retrieval is functioning correctly. If citation results are incomplete or inconsistent, verify the model configuration and consider using a larger or more capable model.
Optional: Using the OpenAI-compatible endpoint
When you use an OpenAI SDK, configure the client base_url to include the /v1 path suffix. The SDK automatically appends the appropriate endpoint path, such as /responses.
For example:
http://ogx-service:8321/v1
When you send raw HTTP requests, include both the /v1 path suffix and the /responses endpoint in the full request URL.
For example:
http://ogx-service:8321/v1/responses
Ensure that /v1 is included only once in the base URL. Do not append /v1 multiple times.
For more information, see OpenAI compatibility for RAG APIs in OGX.
The accuracy and consistency of citation annotations depend on the capabilities of the underlying language model. Smaller or less capable models might produce less precise attributions, even when retrieval is functioning correctly. If citation results are incomplete or inconsistent, verify the model configuration and consider using a larger or more capable model.
Verification
-
The response includes an
annotationsarray underoutput[].content[]. -
Each annotation has
"type": "file_citation". -
The
file_idandfilenamecorrespond to files stored in the specified vector store.
2.4.3. File citation annotation reference
This reference describes the file_citation annotation type returned by OGX through the OpenAI-compatible Responses API.
2.4.3.1. Annotation location
Annotations are returned in the annotations field of output_text content items within the output[].content[] structure of the Responses API response.
"output": [
{
"content": [
{
"type": "output_text",
"text": "Example generated response.",
"annotations": [ ... ]
}
]
}
]2.4.3.2. Supported annotation type
In OpenShift AI, OGX returns the file_citation annotation type when using the file_search tool.
URL citation annotations
The url_citation type is defined in the OpenAI schema but is not produced by OGX in OpenShift AI 3.3.
2.4.3.3. File citation fields
The file_citation annotation includes the following fields:
| Field | Type | Description |
|---|---|---|
| type | string |
Always |
| file_id | string | Identifier of the source file used during retrieval |
| filename | string | Name of the source file |
| index | integer | Index of the cited file in the list of files. |
2.4.3.4. Annotation behavior
- Attribution is provided at the document level.
- Multiple annotations can reference the same index position.
- Chunk-level and token-level attribution are not supported.
- Annotations follow the OpenAI response schema without modification.
Chapter 3. Activating the OGX Operator
You can activate the OGX Operator on your OpenShift cluster by setting its managementState to Managed in the OpenShift AI Operator DataScienceCluster custom resource (CR). This setting enables Llama-based model serving without reinstalling or directly editing Operator subscriptions. You can edit the CR in the OpenShift web console or by using the OpenShift CLI (oc).
As an alternative to following the steps in this procedure, you can activate the OGX Operator from the OpenShift CLI (oc) by running the following command:
$ oc patch datasciencecluster <name> --type=merge -p {"spec":{"components":{"ogx":{"managementState":"Managed"}}}}
Replace <name> with your DataScienceCluster name, for example, default-dsc.
Prerequisites
- You have installed OpenShift 4.19 or newer.
- You have cluster administrator privileges.
You have installed the OpenShift CLI (
oc) as described in the appropriate documentation for your cluster:- Installing the OpenShift CLI for OpenShift Container Platform
- Installing the OpenShift CLI for Red Hat OpenShift Service on AWS
- You have installed the Red Hat OpenShift AI Operator on your cluster.
-
You have a
DataScienceClustercustom resource in your environment; the default isdefault-dsc. -
Your infrastructure supports GPU-enabled instance types, for example,
g4dn.xlargeon AWS. - You have enabled GPU support in OpenShift AI, including installing the Node Feature Discovery Operator and NVIDIA GPU Operator. For more information, see Installing the Node Feature Discovery Operator and Enabling NVIDIA GPUs.
-
You have created a
NodeFeatureDiscoveryresource instance on your cluster, as described in Content from docs.nvidia.com is not included.Installing the Node Feature Discovery Operator and creating a NodeFeatureDiscovery instance in the NVIDIA documentation. -
You have created a
ClusterPolicyresource instance with default values on your cluster, as described in Content from docs.nvidia.com is not included.Creating the ClusterPolicy instance in the NVIDIA documentation.
For IBM Power, ppc64le architectures, CPU-only deployments are fully supported.
Procedure
- Log in to the OpenShift web console as a cluster administrator.
Go to the Installed Operators page. The navigation path depends on your OpenShift version:
- On OpenShift 4.20 and later, click Ecosystem → Installed Operators.
- On OpenShift 4.19, click Operators → Installed Operators.
- Click the Red Hat OpenShift AI Operator to open its details.
- Click the Data Science Cluster tab.
-
On the DataScienceClusters page, click the
default-dscobject. Click the YAML tab.
An embedded YAML editor opens, displaying the configuration for the
DataScienceClustercustom resource.In the YAML editor, locate the
spec.componentssection. If theogxfield does not exist, add it. Then, set themanagementStatefield toManaged:spec: components: ogx: managementState: Managed- Click Save to apply your changes.
Verification
After you activate the OGX Operator, verify that it is running in your cluster:
- In the OpenShift web console, click Workloads → Pods.
-
From the Project list, select the
redhat-ods-applicationsnamespace. -
Confirm that a pod with the label
name=ogx-k8s-operatoris displayed and has a status of Running.
Chapter 4. Deploying a OGX server
OGX allows you to create and deploy a server that enables various APIs for accessing AI services in your OpenShift AI cluster. You can create a OGXServer custom resource for your desired use cases. You are responsible for provisioning and managing the PostgreSQL instance. The PostgreSQL database can be deployed in-cluster or hosted externally, as long as it is reachable from the cluster network.
The included procedure provides an example OGXServer CR that deploys a OGX server that enables the following setup:
-
A connection to a vLLM inference service with a
llama32-3bmodel. - A connection to a remote vector database.
- Allocated persistent storage.
- Orchestration endpoints.
Prerequisites
- You have installed OpenShift 4.19 or newer.
- You have logged in to Red Hat OpenShift AI.
- You have cluster administrator privileges for your OpenShift cluster.
- You have activated the OGX Operator in your cluster.
- You have access to a PostgreSQL version 14 or later instance that is reachable from the OpenShift cluster network.
- You have PostgreSQL credentials for that instance that allow OGX to create the database and tables.
-
You know the PostgreSQL hostname and database port to use for the
POSTGRES_HOSTandPOSTGRES_PORTenvironment variables. You have installed the OpenShift CLI (
oc) as described in the appropriate documentation for your cluster:- Installing the OpenShift CLI for OpenShift Container Platform
- Installing the OpenShift CLI for Red Hat OpenShift Service on AWS
Procedure
In the OpenShift web console, select Administrator → Quick Create (
) → Import YAML, and create a CR similar to the following example ogx-custom-server.yamlfile:Example ogx-custom-server.yaml
apiVersion: ogx.io/v1beta1 kind: OGXServer metadata: name: ogx-custom-server namespace: <project-name> # Replace with your OpenShift project spec: distribution: name: rh-dev workload: replicas: 1 overrides: env: - name: VLLM_URL value: 'https://llama32-3b.ogx.svc.cluster.local/v1' - name: INFERENCE_MODEL value: llama32-3b - name: VLLM_TLS_VERIFY value: 'false' - name: POSTGRES_HOST value: <postgres-host> - name: POSTGRES_PORT value: '<postgres-port>' # Default PostgreSQL port is 5432 - name: POSTGRES_DB value: ogx - name: POSTGRES_USER value: ogx - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: key: password name: postgres-secret 1 name: ogx port: 8321 distribution: name: 'rh-dev' storage: size: 20Gi mountPath: <custom-mount-path> ## Defaults to /opt/app-root/src/.ogx/distributions/rh/- 1
- Create the secret in the same namespace as the
OGXServerresource. Avoid placing passwords directly on the command line, as they can be stored in shell history. Instead, create a file that contains only the database password and use that file to create the secret, or create the secret by using the OpenShift web console.
For example:
$ oc create secret generic postgres-secret --from-file=password=pg-password.txt -n <project-name> $ rm -f pg-password.txt
For more information about creating and managing Secrets, see Providing sensitive data to pods by using secrets.
Ensure that the file
pg-password.txtcontains only the database password and is deleted after the secret is created.OGX automatically creates the metadata database specified by the
POSTGRES_DBenvironment variable if it does not already exist, provided that the PostgreSQL user has sufficient privileges.
Verification
Check that the custom resource was created with the following command:
$ oc get ogxserver -n ogx
Check the running pods with the following command:
$ oc get pods -n ogx | grep ogx-custom-server
Check the logs with the following command:
$ oc logs -n ogx -l app=ogx
Example output
INFO: Started server process INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://['::', '0.0.0.0']:8321
Chapter 5. Deploying a Llama model with KServe
To use OGX and retrieval-augmented generation (RAG) workloads in OpenShift AI, you must deploy a Llama model with a vLLM model server and configure KServe in KServe RawDeployment mode.
When deploying models using KServe on IBM Power (ppc64le), ensure that you use only supported parameters for the model configuration.
Half (FP16) precision is not currently supported on this architecture. Attempting to use FP16 may result in a NotImplementedError: "rotary_embedding_impl" not implemented for 'Half' error.
Prerequisites
- You have installed OpenShift 4.19 or newer.
- You have logged in to Red Hat OpenShift AI.
- You have cluster administrator privileges for your OpenShift cluster.
- You have activated the OGX Operator.
- You have installed KServe.
- You have enabled the model serving platform. For more information about enabling the model serving platform, see Enabling the model serving platform.
- You can access the model serving platform in the dashboard configuration. For more information about setting dashboard configuration options, see Customizing the dashboard.
- You have enabled GPU support in OpenShift AI, including installing the Node Feature Discovery Operator and NVIDIA GPU Operator. For more information, see Installing the Node Feature Discovery Operator and Enabling NVIDIA GPUs.
You have installed the OpenShift CLI (
oc) as described in the appropriate documentation for your cluster:- Installing the OpenShift CLI for OpenShift Container Platform
- Installing the OpenShift CLI for Red Hat OpenShift Service on AWS
- You have created a project.
- The vLLM serving runtime is installed and available in your environment.
-
You have created a storage connection for your model that contains a
URI - v1connection type. This storage connection must define the location of your Llama 3.2 model artifacts. For example,oci://quay.io/redhat-ai-services/modelcar-catalog:llama-3.2-3b-instruct. For more information about creating storage connections, see This content is not included.Adding a connection to your project.
These steps are only supported in OpenShift AI versions 2.19 and later.
- In the OpenShift AI dashboard, navigate to the project details page and click the Deployments tab.
- In the Model serving platform tile, click Select model.
Click the Deploy model button.
The Deploy model dialog opens.
Configure the deployment properties for your model:
- In the Model deployment name field, enter a unique name for your deployment.
-
In the Serving runtime field, select
vLLM NVIDIA GPU serving runtime for KServefrom the drop-down list. - In the Deployment mode field, select KServe RawDeployment from the drop-down list.
-
Set Number of model server replicas to deploy to
1. In the Model server size field, select
Customfrom the drop-down list.-
Set CPUs requested to
1 core. -
Set Memory requested to
10 GiB. -
Set CPU limit to
2 core. -
Set Memory limit to
14 GiB. -
Set Accelerator to
NVIDIA GPUs. -
Set Accelerator count to
1.
-
Set CPUs requested to
- From the Connection type, select a relevant data connection from the drop-down list.
In the Additional serving runtime arguments field, specify the following recommended arguments:
--dtype=half --max-model-len=20000 --gpu-memory-utilization=0.95 --enable-chunked-prefill --enable-auto-tool-choice --tool-call-parser=llama3_json --chat-template=/app/data/template/tool_chat_template_llama3.2_json.jinja
Click Deploy.
NoteModel deployment can take several minutes, especially for the first model that is deployed on the cluster. Initial deployment may take more than 10 minutes while the relevant images download.
Verification
Verify that the
kserve-controller-managerandodh-model-controllerpods are running:- Open a new terminal window.
- Log in to your OpenShift cluster from the CLI:
- In the upper-right corner of the OpenShift web console, click your user name and select Copy login command.
- After you have logged in, click Display token.
Copy the Log in with this token command and paste it in the OpenShift CLI (
oc).$ oc login --token=<token> --server=<openshift_cluster_url>
Enter the following command to verify that the
kserve-controller-managerandodh-model-controllerpods are running:$ oc get pods -n redhat-ods-applications | grep -E 'kserve-controller-manager|odh-model-controller'
Confirm that you see output similar to the following example:
kserve-controller-manager-7c865c9c9f-xyz12 1/1 Running 0 4m21s odh-model-controller-7b7d5fd9cc-wxy34 1/1 Running 0 3m55s
If you do not see either of the
kserve-controller-managerandodh-model-controllerpods, there could be a problem with your deployment. In addition, if the pods appear in the list, but theirStatusis not set toRunning, check the pod logs for errors:$ oc logs <pod-name> -n redhat-ods-applications
Check the status of the inference service:
$ oc get inferenceservice -n ogx $ oc get pods -n <project name> | grep llama
The deployment automatically creates the following resources:
-
A
ServingRuntimeresource. -
An
InferenceServiceresource, aDeployment, a pod, and a service pointing to the pod.
-
A
Verify that the server is running. For example:
$ oc logs llama-32-3b-instruct-predictor-77f6574f76-8nl4r -n <project name>
Check for output similar to the following example log:
INFO 2025-05-15 11:23:52,750 __main__:498 server: Listening on ['::', '0.0.0.0']:8321 INFO: Started server process [1] INFO: Waiting for application startup. INFO 2025-05-15 11:23:52,765 __main__:151 server: Starting up INFO: Application startup complete. INFO: Uvicorn running on http://['::', '0.0.0.0']:8321 (Press CTRL+C to quit)
- The deployed model displays in the Deployments tab on the project details page for the project it was deployed under.
If you see a
ConvertTritonGPUToLLVMerror in the pod logs when querying the/v1/chat/completionsAPI, and the vLLM server restarts or returns a500 Internal Servererror, apply the following workaround:Before deploying the model, remove the
--enable-chunked-prefillargument from the Additional serving runtime arguments field in the deployment dialog.The error is displayed similar to the following:
/opt/vllm/lib64/python3.12/site-packages/vllm/attention/ops/prefix_prefill.py:36:0: error: Failures have been detected while processing an MLIR pass pipeline /opt/vllm/lib64/python3.12/site-packages/vllm/attention/ops/prefix_prefill.py:36:0: note: Pipeline failed while executing [`ConvertTritonGPUToLLVM` on 'builtin.module' operation]: reproducer generated at `std::errs, please share the reproducer above with Triton project.` INFO: 10.129.2.8:0 - "POST /v1/chat/completions HTTP/1.1" 500 Internal Server Error
Chapter 6. Testing your vLLM model endpoints
To verify that your deployed Llama 3.2 model is accessible externally, ensure that your vLLM model server is exposed as a network endpoint. You can then test access to the model from outside both the OpenShift cluster and the OpenShift AI interface.
If you selected Make deployed models available through an external route during deployment, your vLLM model endpoint is already accessible outside the cluster. You do not need to manually expose the model server. Manually exposing vLLM model endpoints, for example, by using oc expose, creates an unsecured route unless you configure authentication. Avoid exposing endpoints without security controls to prevent unauthorized access.
Prerequisites
- You have cluster administrator privileges for your OpenShift cluster.
- You have logged in to Red Hat OpenShift AI.
- You have activated the OGX Operator in OpenShift AI.
- You have deployed an inference model, for example, the llama-3.2-3b-instruct model.
You have installed the OpenShift CLI (
oc) as described in the appropriate documentation for your cluster:- Installing the OpenShift CLI for OpenShift Container Platform
- Installing the OpenShift CLI for Red Hat OpenShift Service on AWS
Procedure
Open a new terminal window.
- Log in to your OpenShift cluster from the CLI:
- In the upper-right corner of the OpenShift web console, click your user name and select Copy login command.
- After you have logged in, click Display token.
Copy the Log in with this token command and paste it in the OpenShift CLI (
oc).$ oc login --token=<token> --server=<openshift_cluster_url>
If you enabled Require token authentication during model deployment, retrieve your token:
$ export MODEL_TOKEN=$(oc get secret default-name-llama-32-3b-instruct-sa -n <project name> --template={{ .data.token }} | base64 -d)Obtain your model endpoint URL:
- If you enabled Make deployed models available through an external route during model deployment, click Endpoint details on the Deployments page in the OpenShift AI dashboard to obtain your model endpoint URL.
In addition, if you did not enable Require token authentication during model deployment, you can also enter the following command to retrieve the endpoint URL:
$ export MODEL_ENDPOINT="https://$(oc get route llama-32-3b-instruct -n <project name> --template={{ .spec.host }})"
Test the endpoint with a sample chat completion request:
If you did not enable Require token authentication during model deployment, enter a chat completion request. For example:
$ curl -X POST $MODEL_ENDPOINT/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "llama-32-3b-instruct", "messages": [ { "role": "user", "content": "Hello" } ] }'If you enabled Require token authentication during model deployment, include a token in your request. For example:
curl -s -k $MODEL_ENDPOINT/v1/chat/completions \ --header "Authorization: Bearer $MODEL_TOKEN" \ --header 'Content-Type: application/json' \ -d '{ "model": "llama-32-3b-instruct", "messages": [ { "role": "user", "content": "can you tell me a funny joke?" } ] }' | jq .NoteThe
-kflag disables SSL verification and should only be used in test environments or with self-signed certificates.
Verification
Confirm that you received a JSON response containing a chat completion. For example:
{
"id": "chatcmpl-05d24b91b08a4b78b0e084d4cc91dd7e",
"object": "chat.completion",
"created": 1747279170,
"model": "llama-32-3b-instruct",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"reasoning_content": null,
"content": "Hello! It's nice to meet you. Is there something I can help you with or would you like to chat?",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null
}],
"usage": {
"prompt_tokens": 37,
"total_tokens": 62,
"completion_tokens": 25,
"prompt_tokens_details": null
},
"prompt_logprobs": null
}If you do not receive a response similar to the example, verify that the endpoint URL and token are correct, and ensure your model deployment is running.
Chapter 7. Select and deploy a vector database
When your application requires retrieval-augmented generation (RAG), choose and configure a vector store so that you can store and query document embeddings for retrieval during inference. OGX in OpenShift AI supports remote Milvus, PostgreSQL with the pgvector extension, and Qdrant as vector store providers. After configuring a vector store, you can build a RAG application, as described in Deploying a RAG stack in a project.
7.1. Overview of vector databases
Vector databases are a core component of retrieval-augmented generation (RAG) in OpenShift AI. They store and index vector embeddings that represent the semantic meaning of text or other data. When integrated with OGX, vector databases enable applications to retrieve relevant context and combine it with large language model (LLM) inference.
Vector databases provide the following capabilities:
- Store vector embeddings generated by embedding models.
- Support efficient similarity search to retrieve semantically related content.
- Enable RAG workflows by supplying the LLM with contextually relevant data.
In OpenShift AI, vector databases are configured and managed through the OGX Operator as part of a OGXServer. PostgreSQL is the default and recommended metadata store for OGX, supporting production-ready persistence, concurrency, and scalability.
The following vector database options are supported in OpenShift AI:
- Remote Milvus Remote Milvus runs as a standalone vector database service, either within the cluster or as an external managed deployment. This option is suitable for large-scale or production-grade RAG workloads that require high availability, horizontal scalability, and isolation from the OGX server. In OpenShift environments, Milvus typically requires an accompanying etcd service for coordination. For more information, see Providing redundancy with etcd.
- Remote PostgreSQL with pgvector PostgreSQL with the pgvector extension provides a production-ready vector database option that integrates vector similarity search directly into PostgreSQL. This option is well suited for environments that already operate PostgreSQL and require durable storage, transactional consistency, and centralized management. pgvector enables OGX to store embeddings and perform similarity search without deploying a separate vector database service.
Consider the following guidance when choosing a vector database for your RAG workloads:
- Use Remote Milvus when you require large-scale vector indexing and high-throughput similarity search.
- Use PostgreSQL with pgvector when you want production-ready persistence and integration with existing PostgreSQL-based data platforms.
SQLite-based storage is no longer recommended for production deployments. PostgreSQL-based backends provide improved reliability, concurrency, and scalability as OGX moves toward general availability.
7.1.1. Overview of Milvus vector databases
Milvus is an open source vector database designed for high-performance similarity search across large volumes of embedding data. In OpenShift AI, Milvus is supported as a vector store provider for OGX and enables retrieval-augmented generation (RAG) workloads that require efficient vector indexing, scalable search, and durable storage.
Production-grade OGX deployments default to PostgreSQL for metadata persistence. When Milvus is used as the vector store, PostgreSQL is typically used for OGX metadata, while Milvus manages vector indexes and similarity search.
Milvus vector databases provide the following capabilities in OpenShift AI:
- High-performance similarity search using Approximate Nearest Neighbor (ANN) algorithms
- Efficient indexing and query optimization for dense embeddings
- Persistent storage of vector data
- Integration with OGX through an OpenAI-compatible Vector Stores API
In a typical RAG workflow in OpenShift AI, the following responsibilities are separated:
- Embedding generation Embeddings are generated by the configured embedding provider. Remote embedding models are the recommended and default option for production deployments.
- Vector storage and retrieval Milvus stores embedding vectors and performs similarity search operations.
- Metadata persistence OGX stores vector store metadata, file references, and configuration state using PostgreSQL in production deployments.
- OGX server Coordinates ingestion, retrieval, and model inference through a unified API surface.
In OpenShift AI, Milvus can be used in the following operational modes:
- Remote Milvus Runs as a standalone service within your OpenShift project or as an external managed Milvus deployment. Remote Milvus is recommended for production-grade RAG workloads.
A remote Milvus deployment typically includes the following components:
- A Milvus service that exposes a gRPC endpoint (port 19530) for client traffic
- An etcd service that Milvus uses for metadata coordination, collection state, and index management
- Persistent storage for durable vector data
Milvus requires a dedicated etcd instance for metadata coordination, even when running in standalone mode. Do not use the OpenShift control plane etcd for this purpose. For more information about etcd, see Providing redundancy with etcd.
You must deploy a dedicated etcd service for Milvus or connect Milvus to an external etcd instance. Do not share the OpenShift control plane etcd with application workloads.
Use Remote Milvus when you require scalable vector search, high-performance retrieval, and integration with production-grade OGX deployments in OpenShift AI.
For instructions on deploying Milvus as a remote vector database, see Deploying a remote Milvus vector database.
7.1.2. Overview of pgvector vector databases
pgvector is an open source PostgreSQL extension that enables vector similarity search on embedding data stored in relational tables. In OpenShift AI, PostgreSQL with the pgvector extension is supported as a remote vector database provider for the OGX Operator. pgvector supports retrieval augmented generation workflows that require persistent vector storage while integrating with existing PostgreSQL environments.
pgvector vector databases provide the following capabilities in OpenShift AI:
- Storage of vector embeddings in PostgreSQL tables.
- Similarity search across embeddings by using pgvector distance metrics.
- Persistent storage of vectors alongside structured relational data.
- Integration with existing PostgreSQL security and operational tooling.
In a typical retrieval augmented generation workflow in OpenShift AI, your application uses the following components:
- Inference provider Generates embeddings and model responses.
- Vector store provider Stores embeddings and performs similarity search. When you use pgvector, PostgreSQL provides this capability as a remote vector store.
- File storage provider Stores the source files that are ingested into vector stores.
- OGX server Provides a unified API surface, including an OpenAI compatible Vector Stores API.
When you ingest content, OGX splits source material into chunks, generates embeddings, and stores them in PostgreSQL through the pgvector extension. When you query a vector store, OGX performs similarity search and returns the most relevant chunks for use in prompts.
In OpenShift AI, pgvector is used in the following operational mode:
- Remote PostgreSQL with pgvector, which runs as a standalone PostgreSQL database service accessed by the OGX server. This mode is suitable for development and production workloads that require persistent storage and integration with existing PostgreSQL infrastructure.
When you deploy PostgreSQL with the pgvector extension, you typically manage the following components:
- Secrets for PostgreSQL connection credentials.
- Persistent storage for durable database data.
- A PostgreSQL service that exposes a network endpoint.
PostgreSQL with pgvector does not require an external coordination service. Vector data, indexes, and metadata are stored directly in PostgreSQL tables and managed through standard database mechanisms.
Use PostgreSQL with pgvector when you require persistent vector storage and want to integrate vector search into existing PostgreSQL based data platforms within OpenShift AI. Deploying a PostgreSQL instance with pgvector.
7.2. Deploying a remote Milvus vector database
To use Milvus as a remote vector database provider for OGX in OpenShift AI, you must deploy Milvus and its required etcd service in your OpenShift project. This procedure shows how to deploy Milvus in standalone mode without the Milvus Operator.
The following example configuration is intended for testing or evaluation environments. For production-grade deployments, see Content from milvus.io is not included.https://milvus.io/docs in the Milvus documentation.
Prerequisites
- You have installed OpenShift 4.19 or newer.
- You have enabled GPU support in OpenShift AI. This includes installing the Node Feature Discovery operator and NVIDIA GPU Operators. For more information, see Installing the Node Feature Discovery operator and Enabling NVIDIA GPUs.
- You have cluster administrator privileges for your OpenShift cluster.
- You are logged in to Red Hat OpenShift AI.
- You have a StorageClass available that can provision persistent volumes.
- You created a root password to secure your Milvus service.
- You have deployed an inference model with vLLM, for example, the llama-3.2-3b-instruct model, and you have selected Make deployed models available through an external route and Require token authentication during model deployment.
- You have the correct inference model identifier, for example, llama-3-2-3b.
-
You have the model endpoint URL, ending with
/v1, such ashttps://llama-32-3b-instruct-predictor:8443/v1. - You have the API token required to access the model endpoint.
-
You have installed the OpenShift command line interface (
oc) as described in Installing the OpenShift CLI.
Procedure
-
In the OpenShift console, click the Quick Create (
) icon and then click the Import YAML option.
- Verify that your project is the selected project.
In the Import YAML editor, paste the following manifest and click Create:
apiVersion: v1 kind: Secret metadata: name: milvus-secret type: Opaque stringData: root-password: "MyStr0ngP@ssw0rd" --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: milvus-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi volumeMode: Filesystem --- apiVersion: apps/v1 kind: Deployment metadata: name: etcd-deployment labels: app: etcd spec: replicas: 1 selector: matchLabels: app: etcd strategy: type: Recreate template: metadata: labels: app: etcd spec: containers: - name: etcd image: quay.io/coreos/etcd:v3.5.5 command: - etcd - --advertise-client-urls=http://127.0.0.1:2379 - --listen-client-urls=http://0.0.0.0:2379 - --data-dir=/etcd ports: - containerPort: 2379 volumeMounts: - name: etcd-data mountPath: /etcd env: - name: ETCD_AUTO_COMPACTION_MODE value: revision - name: ETCD_AUTO_COMPACTION_RETENTION value: "1000" - name: ETCD_QUOTA_BACKEND_BYTES value: "4294967296" - name: ETCD_SNAPSHOT_COUNT value: "50000" volumes: - name: etcd-data emptyDir: {} restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: etcd-service spec: ports: - port: 2379 targetPort: 2379 selector: app: etcd --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: milvus-standalone name: milvus-standalone spec: replicas: 1 selector: matchLabels: app: milvus-standalone strategy: type: Recreate template: metadata: labels: app: milvus-standalone spec: containers: - name: milvus-standalone image: milvusdb/milvus:v2.6.0 args: ["milvus", "run", "standalone"] env: - name: DEPLOY_MODE value: standalone - name: ETCD_ENDPOINTS value: etcd-service:2379 - name: COMMON_STORAGETYPE value: local - name: MILVUS_ROOT_PASSWORD valueFrom: secretKeyRef: name: milvus-secret key: root-password livenessProbe: exec: command: ["curl", "-f", "http://localhost:9091/healthz"] initialDelaySeconds: 90 periodSeconds: 30 timeoutSeconds: 20 failureThreshold: 5 ports: - containerPort: 19530 protocol: TCP - containerPort: 9091 protocol: TCP volumeMounts: - name: milvus-data mountPath: /var/lib/milvus restartPolicy: Always volumes: - name: milvus-data persistentVolumeClaim: claimName: milvus-pvc --- apiVersion: v1 kind: Service metadata: name: milvus-service spec: selector: app: milvus-standalone ports: - name: grpc port: 19530 targetPort: 19530 - name: http port: 9091 targetPort: 9091Note-
Use the gRPC port (
19530) for theMILVUS_ENDPOINTsetting in OGX. -
The HTTP port (
9091) is reserved for health checks. -
If you deploy Milvus in a different namespace, use the fully qualified service name in your OGX configuration. For example:
http://milvus-service.<namespace>.svc.cluster.local:19530
-
Use the gRPC port (
Verification
- In the OpenShift web console, click Workloads → Deployments.
-
Verify that both
etcd-deploymentandmilvus-standaloneshow a status of 1 of 1 pods available. - Click Pods in the navigation panel and confirm that pods for both deployments are Running.
-
Click the
milvus-standalonepod name, then select the Logs tab. Verify that Milvus reports a healthy startup with output similar to:
Milvus Standalone is ready to serve ... Listening on 0.0.0.0:19530 (gRPC)
-
Click Networking → Services and confirm that the
milvus-serviceandetcd-serviceresources exist and are exposed on ports19530and2379, respectively. (Optional) Click Pods → milvus-standalone → Terminal and run the following health check:
curl http://localhost:9091/healthz
A response of
{"status": "healthy"}confirms that Milvus is running correctly.
7.3. Using PostgreSQL in OGX
PostgreSQL is a dependency for OGX deployments in OpenShift AI, where it serves as the mandatory metadata storage backend for supported vector storage configurations. Additionally, you can configure PostgreSQL as a remote vector database provider by enabling the pgvector extension.
In OpenShift AI, PostgreSQL serves the following roles in OGX deployments:
- Required metadata storage for OGX APIs and orchestration services.
- An optional remote vector database when the pgvector provider is enabled.
Depending on your deployment requirements, these roles can be fulfilled by the same PostgreSQL instance or separate instances. For example, you might use a single instance for development and testing environments, and separate instances for production deployments that require independent scaling or isolation.
The procedures provide basic configuration suitable for development and testing. Production deployments require additional planning, including the following considerations:
- High availability and replication
- Backup and disaster recovery
- Security hardening and encryption
- Performance tuning and monitoring
7.3.1. Understanding PostgreSQL in OGX
7.3.1.1. Understanding OGX metadata storage
In OpenShift AI, OGX requires PostgreSQL as a metadata storage backend to persist state and configuration data across multiple components. Metadata storage provides durable persistence for vector stores, file management, agent state, conversation history, and other OGX services.
PostgreSQL is required as a metadata storage backend for all OpenShift AI deployments.
7.3.1.1.1. Role of metadata storage in OGX
OGX components require persistent storage beyond in-memory data structures. Without metadata storage, component state would be lost on pod restarts or application failures.
OGX uses metadata storage to persist:
- Vector store metadata, such as collection identifiers and document mappings.
- File metadata, including file locations, identifiers, and attributes.
- Agent state and conversation history.
- Dataset configurations and batch processing state.
- Model registry information and prompt templates.
This persistent storage allows OGX to maintain operational state across pod restarts, rescheduling, and application updates.
7.3.1.1.2. PostgreSQL metadata storage backends
OGX uses PostgreSQL to store multiple categories of metadata, including vector store metadata, file records, agent state, conversation history, and configuration data. These data types have different storage characteristics but are managed automatically within a single PostgreSQL instance.
PostgreSQL version 14 or later is required for all OGX deployments, including development, testing, and production environments.
If validation errors occur, confirm that the deployed OGX image version matches the configuration schema referenced by your run.yaml.
OGX does not provision or manage the PostgreSQL instance used for metadata storage. You must deploy and manage the PostgreSQL database and supply its connection details when deploying OGX.
7.3.2. Deploying and Configuring PostgreSQL
7.3.2.1. Deploying a PostgreSQL instance with pgvector
You can connect OGX in OpenShift AI to an existing PostgreSQL instance that has the pgvector extension enabled. For development or evaluation, you can also deploy a PostgreSQL instance with the pgvector extension directly in your OpenShift project by creating Kubernetes resources through the OpenShift web console. This procedure focuses on deploying PostgreSQL with the pgvector extension for use as a remote vector store. It does not cover preparing a PostgreSQL database for use as OGX metadata storage.
Prerequisites
- You have installed OpenShift 4.19 or newer.
- You have permissions to create resources in a project in your OpenShift cluster.
- You have PostgreSQL connection details available, including the database name, user name, and password.
- If you plan to deploy PostgreSQL in-cluster, you have a StorageClass that can provision persistent volumes.
- If you are using an existing PostgreSQL instance, the pgvector extension is installed and enabled on the target database.
Procedure
- Log in to the OpenShift web console.
- Select the project where you want to deploy the PostgreSQL instance.
-
Click the Quick Create (
) icon, and then click Import YAML.
- Verify that the correct project is selected.
Copy the following YAML, replace the placeholder values, paste it into the YAML editor, and then click Create.
ImportantThis example deploys a standalone PostgreSQL service with the pgvector extension enabled.
OGX does not automatically use this database. To use this PostgreSQL instance as a vector store, you must explicitly configure the pgvector provider in a
OGXServer.This example is intended for development or evaluation purposes. For production deployments, review and adapt the configuration to meet your organization’s security, availability, backup, and lifecycle requirements.
Example PostgreSQL deployment with pgvector (development or evaluation)
apiVersion: v1 kind: Secret metadata: name: <pgvector-postgresql-credentials-secret> type: Opaque stringData: POSTGRES_DB: "<database-name>" POSTGRES_USER: "<database-username>" POSTGRES_PASSWORD: "<database-password>" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: <pgvector-postgresql-pvc> spec: accessModes: - ReadWriteOnce resources: requests: storage: <storage-size> --- apiVersion: apps/v1 kind: Deployment metadata: name: <pgvector-postgresql-deployment> spec: replicas: 1 selector: matchLabels: app: <pgvector-postgresql-app-label> template: metadata: labels: app: <pgvector-postgresql-app-label> spec: containers: - name: postgres image: pgvector/pgvector:pg16 ports: - name: postgres containerPort: 5432 env: - name: POSTGRES_DB valueFrom: secretKeyRef: name: <pgvector-postgresql-credentials-secret> key: POSTGRES_DB - name: POSTGRES_USER valueFrom: secretKeyRef: name: <pgvector-postgresql-credentials-secret> key: POSTGRES_USER - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: <pgvector-postgresql-credentials-secret> key: POSTGRES_PASSWORD volumeMounts: - name: pgdata mountPath: /var/lib/postgresql/data # Replace TCP socket probes with exec probes that validate SQL readiness. readinessProbe: exec: command: - /bin/sh - -c - pg_isready -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 6 livenessProbe: exec: command: - /bin/sh - -c - pg_isready -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" initialDelaySeconds: 30 periodSeconds: 20 timeoutSeconds: 5 failureThreshold: 6 # Create the pgvector extension after PostgreSQL is actually accepting SQL. lifecycle: postStart: exec: command: - /bin/sh - -c - | set -e echo "Waiting for PostgreSQL to be ready before enabling pgvector..." until PGPASSWORD="$POSTGRES_PASSWORD" psql -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 1" >/dev/null 2>&1; do sleep 2 done PGPASSWORD="$POSTGRES_PASSWORD" psql -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE EXTENSION IF NOT EXISTS vector;" volumes: - name: pgdata persistentVolumeClaim: claimName: <pgvector-postgresql-pvc> --- apiVersion: v1 kind: Service metadata: name: <pgvector-postgresql-service> spec: selector: app: <pgvector-postgresql-app-label> ports: - name: postgres port: 5432 targetPort: 5432 type: ClusterIP- Click Create.
Verification
- Navigate to Networking → Services.
-
Confirm that the PostgreSQL Service is listed and exposes port
5432. - Navigate to Workloads → Pods.
- Confirm that the PostgreSQL pod is running.
This procedure verifies only that PostgreSQL with pgvector is deployed and reachable within the project. It does not verify integration with OGX.
7.3.2.2. Configuring the pgvector remote provider in OGX
To use PostgreSQL with the pgvector extension as a remote vector store, configure pgvector in your existing OGXServer and provide PostgreSQL connection details as environment variables. Ensure that your OGXServer already includes the PostgreSQL metadata storage configuration. This setup enables retrieval augmented generation (RAG) workflows in OpenShift AI by using PostgreSQL-based vector storage.
Prerequisites
- You have installed and enabled the OGX Operator in OpenShift AI.
- You have a PostgreSQL database with the pgvector extension enabled. OGX uses PostgreSQL for two purposes: metadata storage and the optional pgvector remote vector store. You can use a single PostgreSQL instance for both roles or deploy separate instances.
- You have the PostgreSQL connection details, including the host name, port number, database name, user name, and password.
- You have permissions to create Secrets and edit custom resources in your project.
Procedure
- In the OpenShift web console, switch to the Administrator perspective.
Create a Secret that stores the PostgreSQL connection details.
- Ensure that the correct project is selected.
- Click Workloads → Secrets.
- Click Create → From YAML.
Paste the following YAML, update the placeholder values, and then click Create.
Example Secret for pgvector connection details
apiVersion: v1 kind: Secret metadata: name: pgvector-connection type: Opaque stringData: PGVECTOR_HOST: "<pgvector-hostname>" PGVECTOR_PORT: "<pgvector-port>" PGVECTOR_DB: "<database-name>" PGVECTOR_USER: "<database-username>" PGVECTOR_PASSWORD: "<database-password>"
ImportantThe pgvector provider is not enabled automatically.
You must explicitly enable pgvector and supply its connection details through environment variables in your
OGXServer.In OpenShift AI, the pgvector provider is enabled when the
ENABLE_PGVECTORenvironment variable is set.
Update your
OGXServercustom resource to enable pgvector and reference the Secret.- Select the OGX Operator.
- Click the OGXServer tab.
-
Select your
OGXServerresource. - Click YAML.
Update the resource to include the following fields, and then click Save.
Before you enable pgvector, deploy a OGX server and configure the PostgreSQL metadata store.
For more information, see Deploying a OGX server.
Then update your existing OGXServer to add the pgvector configuration shown in the following example. The example shows only the additional environment variables required to enable the pgvector provider.
Example OGXServer configuration for pgvector
apiVersion: ogx.io/v1beta1
kind: OGXServer
metadata:
name: ogx
spec:
distribution:
name: rh-dev
workload:
overrides:
env:
- name: ENABLE_PGVECTOR
value: "true"
- name: PGVECTOR_HOST
valueFrom:
secretKeyRef:
name: pgvector-connection
key: PGVECTOR_HOST
- name: PGVECTOR_PORT
valueFrom:
secretKeyRef:
name: pgvector-connection
key: PGVECTOR_PORT
- name: PGVECTOR_DB
valueFrom:
secretKeyRef:
name: pgvector-connection
key: PGVECTOR_DB
- name: PGVECTOR_USER
valueFrom:
secretKeyRef:
name: pgvector-connection
key: PGVECTOR_USER
- name: PGVECTOR_PASSWORD
valueFrom:
secretKeyRef:
name: pgvector-connection
key: PGVECTOR_PASSWORDVerification
- Click Workloads → Pods.
- Confirm that the OGX pod restarts and reaches the Running state.
- Open the pod logs and confirm that the server starts successfully and initializes the pgvector provider without errors.
7.4. Using Qdrant in OGX
Qdrant is a supported remote vector store provider for OGX in OpenShift AI. You can deploy Qdrant in your OpenShift project or connect to an existing Qdrant instance, and configure OGX to use Qdrant for retrieval-augmented generation (RAG) workloads.
To use Qdrant with OGX, complete the following tasks:
- Review how Qdrant integrates with OGX.
- Deploy a Qdrant instance or connect to an existing deployment.
-
Configure your
OGXServerto use Qdrant as the vector store provider. - Perform vector operations through the OpenAI-compatible Vector Stores API.
7.4.1. Overview of Qdrant vector databases
Qdrant is an open source vector database optimized for high-performance similarity search and advanced filtering. In OpenShift AI, Qdrant is supported as a remote vector store provider for OGX and can be used in retrieval-augmented generation (RAG) workloads that require efficient vector indexing and durable storage.
When used with OGX in OpenShift AI, Qdrant provides:
- High-performance similarity search using Hierarchical Navigable Small World (HNSW) indexing
- Filtering based on stored metadata during vector search
- Persistent storage of vector data
- Integration through the OpenAI-compatible Vector Stores API
In a RAG workflow:
- Embeddings are generated by the configured embedding provider.
- Qdrant stores embedding vectors and performs similarity search.
- OGX manages ingestion, retrieval, and model inference through a unified API.
In OpenShift AI, you must deploy Qdrant as a remote service, either within your OpenShift project or as an externally managed deployment.
Inline Qdrant is not supported. To use Qdrant with OGX in OpenShift AI, deploy Qdrant as a remote service.
A typical remote deployment includes:
- A Qdrant service exposing HTTP (port 6333) and gRPC (port 6334) endpoints
- Persistent storage for vector data
- Optional API key authentication
For deployment and configuration instructions, see Using Qdrant in OGX.
7.4.2. Deploying a Qdrant vector database
You can connect OGX in OpenShift AI to an existing Qdrant instance or deploy a Qdrant vector database in your OpenShift project. For development or evaluation purposes, you can deploy Qdrant by creating Kubernetes resources in the OpenShift web console.
Prerequisites
- You have installed OpenShift 4.19 or later.
- You have permission to create resources in a project.
A StorageClass is available that can provision a PersistentVolume for the PersistentVolumeClaim used by this deployment.
NoteThis example uses a single PersistentVolumeClaim. If your cluster uses dynamic provisioning, the StorageClass provisions the required PersistentVolume automatically.
-
Optional: You have an API key for Qdrant authentication. If your Qdrant instance does not require authentication, remove the Secret and the
QDRANT__SERVICE__API_KEYenvironment variable from the deployment example.
Procedure
- Log in to the OpenShift web console.
- From the Project list, select the project where you want to deploy Qdrant.
- Click Import YAML.
Paste the following YAML:
ImportantThis example deploys a standalone Qdrant service for development or evaluation. For production deployments, review and adapt the configuration to meet your organization’s security, availability, backup, and lifecycle requirements.
apiVersion: v1 kind: Secret metadata: name: <qdrant_credentials_secret> type: Opaque stringData: QDRANT_API_KEY: "<api_key>" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: <qdrant_pvc> spec: accessModes: - ReadWriteOnce resources: requests: storage: <storage_size> --- apiVersion: apps/v1 kind: Deployment metadata: name: <qdrant_deployment> spec: replicas: 1 selector: matchLabels: app: <qdrant_app_label> template: metadata: labels: app: <qdrant_app_label> spec: containers: - name: qdrant image: qdrant/qdrant:v1.12.0 ports: - name: http containerPort: 6333 - name: grpc containerPort: 6334 env: - name: QDRANT__SERVICE__API_KEY valueFrom: secretKeyRef: name: <qdrant_credentials_secret> key: QDRANT_API_KEY volumeMounts: - name: qdrant-storage mountPath: /qdrant/storage - name: qdrant-storage mountPath: /qdrant/snapshots subPath: snapshots readinessProbe: httpGet: path: /readyz port: 6333 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 6333 initialDelaySeconds: 10 periodSeconds: 20 volumes: - name: qdrant-storage persistentVolumeClaim: claimName: <qdrant_pvc> --- apiVersion: v1 kind: Service metadata: name: <qdrant_service> spec: selector: app: <qdrant_app_label> ports: - name: http port: 6333 targetPort: 6333 - name: grpc port: 6334 targetPort: 6334 type: ClusterIPNoteIf your Qdrant instance does not require authentication, remove the Secret and the
QDRANT__SERVICE__API_KEYenvironment variable from the Deployment configuration.Replace the placeholder values as follows:
-
<qdrant_credentials_secret>: A name for the Secret that stores the Qdrant API key, for exampleqdrant-credentials. -
<api_key>: An API key for authenticating with Qdrant. If authentication is not required, remove the Secret and theQDRANT__SERVICE__API_KEYenvironment variable from the Deployment. -
<qdrant_pvc>: A name for the PersistentVolumeClaim, for exampleqdrant-pvc. -
<storage_size>: The storage capacity to request, for example10Gi. -
<qdrant_deployment>: A name for the Deployment, for exampleqdrant. -
<qdrant_app_label>: A label for the application, for exampleqdrant. -
<qdrant_service>: A name for the Service, for exampleqdrant-service.
-
- Click Create.
Verification
-
The Qdrant Service is present in the project and exposes ports
6333(HTTP) and6334(gRPC). You can confirm this on the Networking → Services page in the OpenShift web console. - The Qdrant pod reaches the Running state. You can confirm this on the Workloads → Pods page in the OpenShift web console.
This verification confirms only that Qdrant is deployed and reachable within the project. To use this Qdrant instance with OGX, configure the Qdrant provider in a OGXServer.
7.4.3. Configuring the Qdrant remote provider in OGX
To use Qdrant as a remote vector store, configure your OGXServer resource with the connection details for your Qdrant service. This configuration enables OGX to store and retrieve embedding vectors using Qdrant in OpenShift AI.
Prerequisites
- You have installed and enabled the OGX Operator in OpenShift AI.
- You have a running Qdrant instance that is accessible from your OpenShift cluster.
- You have the Qdrant connection details, including the service URL and, if required, an API key.
- You have permission to create Secrets and modify custom resources in your project.
Procedure
- In the OpenShift web console, switch to the Administrator perspective.
Create a Secret that stores the Qdrant connection details used by OGX. This Secret must contain the URL of the Qdrant service and, if required, the API key.
NoteIf you deployed Qdrant by using the procedure in Deploying a Qdrant vector database, create this Secret separately for the OGX configuration. The Secret created during the Qdrant deployment does not contain the
QDRANT_URLvalue required by the OGX provider.-
From the Project list, select the project where the
OGXServerresource is deployed. - Click Workloads → Secrets.
- Click Create → From YAML.
Paste the following YAML:
apiVersion: v1 kind: Secret metadata: name: qdrant-connection type: Opaque stringData: QDRANT_URL: "<qdrant_url>" QDRANT_API_KEY: "<api_key>"
Replace the placeholder values as follows:
-
<qdrant_url>: The full URL to the Qdrant service, for examplehttp://qdrant-service:6333. For in-cluster deployments, use the Service name and port. For external deployments, use the external URL. -
<api_key>: The API key for authenticating with Qdrant. If authentication is not enabled for your Qdrant instance, remove theQDRANT_API_KEYentry from both the Secret and theenvsection in theOGXServerconfiguration.
-
- Click Create.
-
From the Project list, select the project where the
-
Update your
OGXServercustom resource to reference the Secret and supply the required environment variables. Go to the Installed Operators page. The navigation path depends on your OpenShift version:
- On OpenShift 4.20 and later, click Ecosystem → Installed Operators.
- On OpenShift 4.19, click Operators → Installed Operators.
- Select the OGX Operator.
- Click the OGXServer tab.
-
Select your
OGXServerresource. - Click YAML.
Update the resource to include the following fields.
NoteThe environment variable names and configuration fields used by the Qdrant provider can vary depending on the OGX version included with OpenShift AI. Before applying this configuration, verify that the variables and fields match the supported versions listed in Supported Configurations for 3.x.
apiVersion: ogx.io/v1beta1 kind: OGXServer metadata: name: ogx spec: server: containerSpec: env: - name: ENABLE_QDRANT value: "true" - name: QDRANT_URL valueFrom: secretKeyRef: name: qdrant-connection key: QDRANT_URL - name: QDRANT_API_KEY valueFrom: secretKeyRef: name: qdrant-connection key: QDRANT_API_KEY- Click Save.
Verification
- The OGX pod reaches the Running state. You can confirm this on the Workloads → Pods page in the OpenShift web console.
- The pod logs show that the Qdrant provider initializes successfully and does not report connection errors.
Vector operations executed through the OGX API complete successfully, confirming that OGX can communicate with Qdrant.
For information about performing vector operations, see:
7.4.4. Performing vector operations with Qdrant
After configuring Qdrant as the vector store provider in OGX, you can perform vector operations by using the OpenAI-compatible Vector Stores API exposed by OGX. These operations include creating vector stores, adding documents, performing similarity search, and deleting vector stores. You interact with the OGX API rather than connecting directly to Qdrant. OGX manages collection creation, embedding generation, and query execution on your behalf.
Prerequisites
- You have installed and enabled the OGX Operator in OpenShift AI.
-
You have configured Qdrant as the vector store provider in your
OGXServer. - You have an embedding model available through a configured inference provider.
- You have network access to the OGX API endpoint.
You have installed the
jqcommand-line utility.For installation instructions, see Content from jqlang.org is not included.jq.
-
You have the
curlcommand-line tool installed.
Procedure
Determine how you will access the OGX API.
You can access the API from within the cluster or from outside the cluster.
-
In-cluster access: Run the
curlcommands from a pod in the same project, or from a workstation that has network access to the OGX Service. External access: Expose the OGX Service by creating a Route, and then use the Route URL from your local workstation.
For this procedure, set
OGX_URLto the service or route root URL without the/v1suffix. The example commands append/v1as part of the endpoint path.For more information about API compatibility and base URL requirements, see
OpenAI compatibility for RAG APIs in OGX.
Example base URL for in-cluster access
OGX_URL="http://ogx-service:8321"
Example base URL for external access through a Route
OGX_URL="https://ogx-route.example.com"
-
In-cluster access: Run the
Create a vector store and capture its ID.
CREATE_RESPONSE=$(curl -s -X POST "${OGX_URL}/v1/vector_stores" \ -H "Content-Type: application/json" \ -d '{ "name": "my-rag-store", "embedding_model": "vllm/ibm-granite/granite-embedding-125m-english", "embedding_dimension": 768, "provider_id": "qdrant-remote" }') VECTOR_STORE_ID=$(echo "$CREATE_RESPONSE" | jq -r '.id') echo "Vector store ID: ${VECTOR_STORE_ID}"Ensure that the
VECTOR_STORE_IDvariable contains a valid value before continuing.
7.4.4.1. Add files to a vector store
Upload files to the vector store for ingestion. OGX automatically splits the content into chunks, generates embeddings, and stores them in Qdrant.
Example using curl
FILE_RESPONSE=$(curl -s -X POST "${OGX_URL}/v1/vector_stores/${VECTOR_STORE_ID}/files" \
-F "file=@/path/to/document.pdf" \
-F "purpose=assistants")
FILE_ID=$(echo "$FILE_RESPONSE" | jq -r '.id')
echo "File ID: ${FILE_ID}"7.4.4.2. Query a vector store
Perform similarity search to retrieve relevant content from the vector store. The search query is converted into an embedding and compared with stored vectors in Qdrant.
Example using curl
curl -X POST "${OGX_URL}/v1/vector_stores/${VECTOR_STORE_ID}/search" \
-H "Content-Type: application/json" \
-d '{
"query": "What is retrieval-augmented generation?",
"max_results": 5
}'7.4.4.3. Delete a vector store
Delete a vector store when it is no longer required. This removes the vector store and its associated data from Qdrant.
Example using curl
curl -X DELETE "${OGX_URL}/v1/vector_stores/${VECTOR_STORE_ID}"Verification
- Creating a vector store returns a valid vector store ID.
- File uploads complete successfully and are accepted by the API.
- Search queries return results from the ingested content.
Chapter 8. Deploying OGX for multi-tenancy
As an OpenShift cluster administrator, you can use OGX to deploy a single server or cluster that manages multiple tenant deployments.
8.1. Overview of multi-tenancy on OGX
Multi-tenancy allows teams to share infrastructure while isolating data and access. Without multi-tenancy controls, any authenticated user can view, modify or delete any other user’s resources or applications.
8.1.1. Single-server vs Multi-server environments
Single-server: A single OGX server serves all tenants. Tenant administrators manage the configurations on the shared server and provision resources to tenant users. Isolation is enforced at the application layer with JSON Web Token (JWT) validation and Attribute-Based Access Control (ABAC).
When to use single-server multi-tenancy
Single-server multi-tenancy is recommended when:
- Teams share a cluster and trust the platform, but require data separation.
- Environments where teams can share a single database, a single set of models, and a unified pod.
- Fast deployment is necessary without the overhead of provisioning new infrastructure.
Multi-server: The OGX Operator deploys multiple OGXServer custom resources (CRs) within tenant admin namespaces. Isolation is enforced at the infrastructure level with Role-Based Access Control (RBAC), NetworkPolicies, and ResourceQuotas.
When to use multi-server multi-tenancy
Multi-server multi-tenancy is recommended when:
- Tenant admins need full infrastructure isolation including, separate pods, databases, and storage.
- Environments with strict compliance where process-level separation is mandated.
- Tenant admins need different OGX configurations including different providers, models, and policies.
-
Tenant admins want to manage their own
OGXServerCR and the operator reconciles into a dedicated deployment, service, and storage.
8.1.2. Roles for multi-tenancy environments
In OpenShift AI, there are various roles that manage or interact with the resources the single or multi server provides. A tenant consists of one or more namespaces that own OGXServer custom resources (CRs). By default, resources are isolated within the tenants designated namespace.
-
Platform Admin: Operates at the cluster or multi-server level, the platform admin installs the operator, provisions tenant namespaces, configures Role-Based Access Control (RBAC),
ResourceQuotasCRs, and manages CRDs. -
Tenant Admin: Operates at the namespace or single-server level, the tenant admin creates and manages
OGXServerCRs, configures OGX providers, secrets, and networking configurations. - Tenant User: Operates at the API level, the tenant user makes requests to an API endpoint without OpenShift cluster access.
8.1.3. Operator-enforced isolation
The OGX Operator enforces security and administrative boundaries. By default, the operator enforces the following isolation boundaries:
-
Namespace-scoped resources: All resources created by the operator, including
Deployment,Service,ServiceAccount,RoleBinding,NetworkPolicy, orPersistentVolumeClaim, are created in the CR namespace. -
ConfigMap/ Secret references: All
ConfigMapand secret references in the custom resource specifications are restricted to the CR’s namespace. Network Isolation: The
NetworkPolicyspecification is created for each distribution with the following defaults:Table 8.1. Network Isolation Rules
Direction Default Rule Configurable Ingress
Allow from same namespace
Yes, with the
allowedFromparameterIngress
Allow from operator namespace
No, required for operator health checks
Ingress
Deny all other
Yes, with the
allowedFromparameterEgress
Unrestricted or no policy
Yes, via egress rules
Egress
Auto-include DNS (port 53)
No, always injected when egress rules are present
-
Server pod permissions: The server
ServiceAccounthas no Kubernetes API permissions. Secrets are injected as environment variables viasecretKeyRef, not read at runtime by the server.
8.2. Creating a single-server multi-tenant environment
A single-server multi-tenant environment allows you to run a single OGX server with multiple users connecting to a single namespace.
As a tenant admin, you need to configure security boundaries, mapping identities, and networking configurations.
Supported authentication providers
- OAuth2 JWKS: Validates JWT with a JWKS endpoint, best used for Kubernetes OIDC, Keycloak and standard OIDC providers.
- OAuth2 Introspection: Validates tokens via RFC 7662, best used for legacy OAuth servers.
-
Kubernetes: Validates via the K8s
SelfSubjectReviewAPI, best used for native in-cluster service accounts. - GitHub: Validates GitHub PATs with the GitHub API, best used for open-source or deployments in GitHub environments.
- Upstream Header: Reads identity from gateway headers, best used for authorino, istio or API gateway setups.
- Custom: Forwards the token to a user-provided HTTP endpoint, best used for specific proprietary integrations.
Authorization Layers
OGX enforces security through two distinct authorization mechanisms:
Access Policy (ABAC) - This policy controls which specific resources a tenant user can create, read, update, and delete. This policy can be modified to allow team-based sharing.
Optional: Route Policy (RBAC) - OGX checks if the tenant users role is allowed to use the requested URL. For example, some tenant users can be restricted to inference endpoints while admins maintain full access
Route policy capability is available in OpenShift AI but is not included in the default distribution configuration. Utilization requires deploying custom config.yaml configuration.
Each OGX resource has different Isolation levels.
Table 8.2. Resource Isolation Matrix
| Resource Name | Isolation Level | Sharing / Access Model |
|---|---|---|
| Responses | Isolated (ABAC) | Fully private, each tenant sees only their own data. |
| Files | Isolated (ABAC) | Fully private, each tenant sees only their own data. |
| Vector Stores | Isolated (ABAC) | Fully private, each tenant sees only their own data. |
| Batches | Isolated (ABAC) | Fully private, each tenant sees only their own data. |
| Interactions | Isolated (ABAC) | Fully private, each tenant sees only their own data. |
| Inference Store | Isolated (ABAC) | Fully private, each tenant sees only their own data. |
| Models | Shared (Configurable) | Infrastructure resource, available to all tenants by default. |
| Tool Groups | Shared (Configurable) | Available to all tenants by default, but can be restricted per-team via access policy. |
The following procedures describe how to set up an OGX server with custom authentication and routing
Prerequisites
-
You have installed the OpenShift CLI (
oc) - You have installed the OGX Operator on your OpenShift AI cluster.
Procedure
-
Deploy an
OGXServerCR with your custom configuration. For more information, see "Deploying an OGX Server". Configure claims mapping in the
config.yamlfileserver: auth: provider_config: claims_mapping: realm_access.roles: roles groups: teams tenant_id: namespacesYou now need to enable authentication on your server. You can enable Kubernetes OIDC, which is recommended for in-cluster workloads, or Keycloak for basic users and external clients.
Enabling authorization with Kubernetes OIDC
Get the clusters OIDC endpoints with the following command:
$ AUTH_ISSUER=$(oc get --raw /.well-known/openid-configuration | jq .issuer -r) $ AUTH_JWKS_URI=$(oc get --raw /.well-known/openid-configuration | jq .jwks_uri -r)
Set the following additional environment variables:
AUTH_AUDIENCE=ogx AUTH_VERIFY_TLS=true
The default distribution configuration activates when you set the necessary environment variables.
Default auth configuration YAML
auth: provider_config: type: ${env.AUTH_ISSUER:+oauth2_token} # activates only when AUTH_ISSUER is set audience: ${env.AUTH_AUDIENCE:=ogx} issuer: ${env.AUTH_ISSUER:=} jwks: uri: ${env.AUTH_JWKS_URI:=} verify_tls: ${env.AUTH_VERIFY_TLS:=true}
Enabling authorization with Keycloak
Set your Keycloak details in the
OGXServercustom resourceapiVersion: ogx.io/v1beta1 kind: OGXServer metadata: name: ogx-shared-server namespace: ogx-system spec: env: - name: AUTH_ISSUER value: "https://keycloak.example.com/realms/my-org" - name: AUTH_JWKS_URI value: "https://keycloak.example.com/realms/my-org/protocol/openid-connect/certs" - name: AUTH_AUDIENCE value: "ogx-api"
You then need to configure the access policy of your server. OpenShift AI ships a default access policy that provides owner-based isolation.
Default access policy YAML
auth: access_policy: # System resources are readable by all - permit: actions: [read] when: resource is unowned description: "All users can read system resources" # Any authenticated user can create resources - permit: actions: [create] description: "Authenticated users can create resources" # Only the owner can read, update, or delete resources - permit: actions: [read, update, delete] when: user is owner description: "Owners can manage their own resources"For team-based sharing where users can see the resources of users on the same team, use the following example
access_policyconfig:auth: access_policy: - permit: actions: [read] when: resource is unowned description: "All users can read system resources" - permit: actions: [create] description: "Authenticated users can create resources" - permit: actions: [read, update, delete] when: user is owner description: "Owners can manage their own resources" - permit: actions: [read] when: user in owners teams description: "Team members can read each others resources"For permissions where an admin can access everything, use the following example
access_policyconfig:auth: access_policy: # Admin bypass: full access to all resources - permit: actions: [create, read, update, delete] when: user with admin in roles description: "Admins have full access" # Standard user policies - permit: actions: [read] when: resource is unowned - permit: actions: [create] - permit: actions: [read, update, delete] when: user is owner
Create the project namespaces, for example:
$ oc new-project <project-a> $ oc new-project <project-b>
Set the service accounts for each role, for example
$ oc create serviceaccount ogx-developer -n <project-a> $ oc create serviceaccount ogx-agent -n <project-b>
The tenant admin is responsible for provisioning auth tokens for the tenant users. You can generate the tokens using Kubernetes OIDC, which is recommended for cluster workloads, or Keycloak for basic users or external clients.
Accessing a Kubernetes OIDC token
You can create a token based on team roles and project names:
$ TOKEN=$(oc create token ogx-developer -n <project-a> --audience ogx --duration=3600s)
Accessing a Keycloak token
Configure your
config.yamlfile to trust KeyCloakauth.provider_config.issuer: https://keycloak.example.com/realms/ai-platform auth.provider_config.jwks.uri: https://keycloak.example.com/realms/ai-platform/protocol/openid-connect/certs
Access and set the token environment variable:
TOKEN=$(curl -s -X POST \ "https://keycloak.example.com/realms/ai-platform/protocol/openid-connect/token" \ -d "grant_type=password&client_id=ogx&username=alice&password=***" \ | jq -r .access_token)
- Your tenant users can now access the resources on the namespace. For more information, see "Using APIs as a tenant user".
8.3. Creating a multi-server multi-tenant environment
In OpenShift AI, the platform administrator can set up a multi-server multi-tenant environment, enabling tenant admins to manage namespaces for their respective tenant users.
Platform admin responsibilities
- Namespace Provisioning: Create and label tenant namespaces before CR creation.
-
RBAC: Create
RolesandRoleBindingsper tenant namespace - ResourceQuota/ LimitRange: Set per-namespace compute and object quotas.
- Monitoring: Monitor tenant resource usage and set alerts for quota pressure.
- (Optional) Network enforcement: Enable network isolation requirements.
Tenant admin responsibilities
-
Distribution configuration: Create and manage
OGXServerCRs in their namespaces. -
Resource limits: Configure
resources.requests,resources.limits, andmaxReplicason CRs. TheResourceQuotaCR provisioned by the platform admin enforces that these configurations stay within their namespace quota. - Secrets: Create and manage Secrets including, API keys and provider credentials, in their namespace.
-
Network ingress: Configure
spec.network.policy.ingressto allow access from specific users. -
Network egress: Configure
spec.network.policy.egressto restrict outbound traffic from server pods.
The following procedure displays the necessary CR configurations that the platform admin needs to enable for the tenant admin.
Prerequisites
- You have cluster administrator permissions.
-
You have installed the OpenShift CLI (
oc) - You have installed the OGX Operator on your OpenShift AI cluster.
Procedure
Create a
ClusterRolecustom resource for configuring the platform admin permissions.Example platform admin
ClusterRoleCRapiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: ogx-platform-admin rules: - apiGroups: ["ogx.io"] resources: ["ogxservers"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - apiGroups: [""] resources: ["namespaces"] verbs: ["get", "list", "watch", "create"] - apiGroups: ["rbac.authorization.k8s.io"] resources: ["roles", "rolebindings"] verbs: ["get", "list", "watch", "create", "update", "patch"]
Grant the tenant admin permissions to manage CR in their namespace with the following example
Roleconfigurations:apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: ogx-tenant-admin namespace: tenant-a rules: - apiGroups: ["ogx.io"] resources: ["ogxservers"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - apiGroups: [""] resources: ["secrets", "configmaps"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: ogx-tenant-admin namespace: tenant-a subjects: - kind: Group name: tenant-a-admins apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: ogx-tenant-admin apiGroup: rbac.authorization.k8s.io
Enable
ResourceQuotaCR using the following configurations as an example:apiVersion: v1 kind: ResourceQuota metadata: name: ogx-tenant-quota namespace: tenant-a spec: hard: requests.cpu: "8" requests.memory: 32Gi limits.cpu: "16" limits.memory: 64Gi pods: "10"Enable preferred
NetworkPolicyCR configurations:Allow specific namespace
spec: network: policy: ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: frontend-ns ports: - port: 8321 protocol: TCPAllow namespace by label
spec: network: policy: ingress: - from: - namespaceSelector: matchLabels: tenant: customer-a ports: - port: 8321 protocol: TCPAllow specific pods in a namespace
spec: network: policy: ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: frontend-ns podSelector: matchLabels: app: api-gateway ports: - port: 8321 protocol: TCPAllow external CIDR
spec: network: policy: ingress: - from: - ipBlock: cidr: 10.0.0.0/8 except: - 10.0.1.0/24 ports: - port: 8321 protocol: TCP
Verification
- Log in to the cluster as a tenant administrator and verify that you can manage resources in your designated namespace.
8.4. Using APIs as a tenant user
You can access and use various APIs configured by a platform or tenant admin.
Procedure
Obtain your credentials from the tenant admin. Your tenant admin will provide you with:
An OGX endpoint URL, for example:
https://ogx.apps.cluster.example.com/v1
An API Key or token. You can obtain the keys in various ways:
-
An environment variable: The
OGX_API_KEYis already set by the platform admin when you open the notebook. - Keycloak login: You login to keycloak and the OGX SDK is responsible for refreshing.
- API key: Tenant admin generates and provides you with the key that you use in your configuration.
-
An environment variable: The
You can now access the APIs in the namespaces
Example using the APIs
OGX_URL="https://ogx.apps.cluster.example.com" TOKEN="<your-api-key-from-admin>" # List models curl -s -H "Authorization: Bearer $TOKEN" "$OGX_URL/v1/models" | python3 -m json.tool # Create a response curl -s -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ "$OGX_URL/v1/responses" \ -d '{"model":"vllm-inference/llama-3-2-3b","input":"Summarize quantum computing","store":true}' \ | python3 -m json.tool # List your responses curl -s -H "Authorization: Bearer $TOKEN" "$OGX_URL/v1/responses" | python3 -m json.tool # Upload a file (owned by you) curl -s -H "Authorization: Bearer $TOKEN" \ -F "file=@dataset.jsonl" -F "purpose=assistants" \ "$OGX_URL/v1/files" | python3 -m json.tool # Create a vector store (owned by you) curl -s -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ "$OGX_URL/v1/vector_stores" \ -d '{"name":"my-knowledge-base"}' | python3 -m json.toolExample using the Python SDK
import os from openai import OpenAI # Token and URL are provided by your platform admin # (typically pre-set as environment variables in your notebook/workspace) client = OpenAI( base_url=os.environ.get("OGX_URL", "https://ogx.apps.cluster.example.com/v1"), api_key=os.environ["OGX_API_KEY"], ) # Create a stored response — automatically owned by your identity response = client.responses.create( model="vllm-inference/llama-3-2-3b", input="Explain transformers", store=True, ) # List responses — only returns yours, other teams' responses are invisible my_responses = client.responses.list()
Chapter 9. Configuring OGX with OAuth authentication
You can configure OGX to use role-based access control (RBAC) for model access with OAuth authentication on OpenShift AI. The following example shows how to configure OGX so that all authenticated users can access a vLLM model, while only specific users can access an OpenAI model. This example uses Keycloak to issue and validate tokens.
This procedure assumes that the Keycloak server is available at https://my-keycloak-server.com.
When you access OGX APIs, the required base URL depends on the client that you use.
For OpenAI-compatible clients or raw HTTP requests, include the
/v1path suffix in the base URL.For example,
http://ogx-service:8321/v1For the
OGXClientSDK, do not include the/v1path suffix in the base URL.For example,
http://ogx-service:8321
If you use an incorrect base URL, requests fail.
Prerequisites
- You have installed OpenShift 4.19 or later.
- You have logged in to Red Hat OpenShift AI.
- You have cluster-admin privileges for your OpenShift cluster.
You have a Keycloak instance configured with the following settings:
-
Realm:
ogx-demo -
Client:
ogxwith direct access grants enabled -
Role:
inference_max -
A protocol mapper that adds realm roles to the access token under the
ogx_rolesclaim Two test users:
-
user1with no assigned roles -
user2assigned theinference_maxrole
-
-
Realm:
- You have saved the Keycloak client secret for token requests.
-
Your Keycloak server is reachable at
https://my-keycloak-server.com. You have installed the OpenShift CLI (
oc) as described in the documentation for your cluster:- Installing the OpenShift CLI for OpenShift Container Platform
- Installing the OpenShift CLI for Red Hat OpenShift Service on AWS
Procedure
To configure OGX to use role-based access control (RBAC) for model access, view and verify the OAuth provider token structure.
Generate a Keycloak test token by running the following command:
$ curl -d client_id=ogx -d client_secret=YOUR_CLIENT_SECRET -d username=user1 -d password=user-password -d grant_type=password https://my-keycloak-server.com/realms/ogx-demo/protocol/openid-connect/token | jq -r .access_token > test.token
View the token claims by running the following command:
$ cat test.token | cut -d . -f 2 | base64 -d 2>/dev/null | jq .
Example token structure from Keycloak
{ "iss": "https://my-keycloak-server.com/realms/ogx-demo", "aud": "account", "sub": "761cdc99-80e5-4506-9b9e-26a67a8566f7", "preferred_username": "user1", "ogx_roles": [ "inference_max" ] }Update your existing
run.yamlfile to add the OAuth parameters.Example OAuth parameters in the
run.yamlfileserver: port: 8321 auth: provider_config: type: "oauth2_token" jwks: uri: "https://my-keycloak-server.com/realms/ogx-demo/protocol/openid-connect/certs" 1 key_recheck_period: 3600 issuer: "https://my-keycloak-server.com/realms/ogx-demo" 2 audience: "account" verify_tls: true claims_mapping: ogx_roles: "roles" 3 access_policy: - permit: 4 actions: [read] resource: model::vllm-inference/llama-3-2-3b description: Allow all authenticated users to access the Llama 3.2 model - permit: 5 actions: [read] resource: model::openai/gpt-4o-mini when: user with inference_max in roles description: Allow only users with the inference_max role to access OpenAI modelsCreate a ConfigMap that uses the updated
run.yamlconfiguration by running the following command:$ oc create configmap ogx-custom-config --from-file=run.yaml=run.yaml -n redhat-ods-operator
Create a
ogx-server.yamlfile with the following content:apiVersion: ogx.io/v1beta1 kind: OGXServer metadata: name: ogx-server namespace: redhat-ods-operator spec: distribution: name: rh-dev workload: replicas: 1 overrides: env: # vLLM provider configuration - name: VLLM_URL value: "https://your-vllm-service:8000/v1" - name: VLLM_API_TOKEN value: "your-vllm-token" - name: VLLM_TLS_VERIFY value: "false" # OpenAI provider configuration - name: OPENAI_API_KEY value: "your-openai-api-key" - name: OPENAI_BASE_URL value: "https://api.openai.com/v1" userConfig: configMapName: ogx-custom-config configMapNamespace: redhat-ods-operatorApply the distribution by running the following command:
$ oc apply -f ogx-server.yaml
Wait for the distribution to be ready by running the following command:
$ oc wait --for=jsonpath='{.status.phase}'=Ready ogxserver/ogx-server -n redhat-ods-operator --timeout=300sGenerate OAuth tokens for each user account to authenticate API requests.
To request a basic access token and save it to a
user1.tokenfile, run the following command:$ curl -d client_id=ogx \ -d client_secret=YOUR_CLIENT_SECRET \ -d username=user1 \ -d password=user1-password \ -d grant_type=password \ https://my-keycloak-server.com/realms/ogx-demo/protocol/openid-connect/token \ | jq -r .access_token > user1.token
To request a token for the privileged user and save it to a
user2.tokenfile, run the following command:$ curl -d client_id=ogx \ -d client_secret=YOUR_CLIENT_SECRET \ -d username=user2 \ -d password=user2-password \ -d grant_type=password \ https://my-keycloak-server.com/realms/ogx-demo/protocol/openid-connect/token \ | jq -r .access_token > user2.token
Verify the token claims by running the following command:
$ cat user2.token | cut -d . -f 2 | base64 -d 2>/dev/null | jq .
Verification
Set the OGX service URL:
$ export OGX_HOST="http://<ogx-host>:8321"
Verify basic access for
user1, who has no privileged roles.Load the token:
$ USER1_TOKEN=$(cat user1.token)
Confirm that
user1can access the vLLM-served model:$ curl -s -o /dev/null -w "%{http_code}\n" \ -X POST "${OGX_HOST}/v1/openai/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${USER1_TOKEN}" \ -d '{"model":"vllm-inference/llama-3-2-3b","messages":[{"role":"user","content":"Hello!"}],"max_tokens":50}'Expected result: HTTP
200.Confirm that
user1is denied access to the restricted OpenAI model:$ curl -s -o /dev/null -w "%{http_code}\n" \ -X POST "${OGX_HOST}/v1/openai/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${USER1_TOKEN}" \ -d '{"model":"openai/gpt-4o-mini","messages":[{"role":"user","content":"Hello!"}],"max_tokens":50}'Expected result: HTTP
403.Verify privileged access for
user2, who is assigned theinference_maxrole.Load the token:
$ USER2_TOKEN=$(cat user2.token)
Confirm that
user2can access both models:$ curl -s -o /dev/null -w "%{http_code}\n" \ -X POST "${OGX_HOST}/v1/openai/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${USER2_TOKEN}" \ -d '{"model":"vllm-inference/llama-3-2-3b","messages":[{"role":"user","content":"Hello!"}],"max_tokens":50}'$ curl -s -o /dev/null -w "%{http_code}\n" \ -X POST "${OGX_HOST}/v1/openai/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${USER2_TOKEN}" \ -d '{"model":"openai/gpt-4o-mini","messages":[{"role":"user","content":"Hello!"}],"max_tokens":50}'Expected result: HTTP
200for both requests.Verify that requests without a Bearer token are denied.
$ curl -s -o /dev/null -w "%{http_code}\n" \ -X POST "${OGX_HOST}/v1/openai/chat/completions" \ -H "Content-Type: application/json" \ -d '{"model":"vllm-inference/llama-3-2-3b","messages":[{"role":"user","content":"Hello!"}],"max_tokens":50}'Expected result: HTTP
401.
Chapter 10. Configuring attribute-based access control (ABAC) on your OGX server
OGX supports OAuth 2.0/OIDC authentication with attribute-based access control (ABAC) for multi-tenant isolation. ABAC provides multi-tenant isolation by configuring access policies based on specific attributes, assigned to a user and the requested resource. When enabled, users can only access resources they own based on the attributes, and system resources are readable by all authenticated users.
The following procedure describes how to enable attribute-based access control (ABAC) policies in your OGX distribution.
Prerequisites
- You have installed OpenShift 4.19 or later.
- You have logged in to Red Hat OpenShift AI.
- You have cluster administrator privileges for your OpenShift cluster.
- You have access to an OAuth 2.0/OIDC identity provider, for example, a Keycloak provider.
Procedure
The
AUTH_*parameters also need to be set in theOGXServercustom resource. For example:Example OGXServer CR
spec: replicas: 1 server: containerSpec: env: ... - name: AUTH_ISSUER value: https://keycloak-redhat-ods-applications.apps.rosa.<user-cluster>.gm8d.p3.openshiftapps.com/realms/ogx-demo - name: AUTH_JWKS_URI value: http://keycloak:8080/realms/ogx-demo/protocol/openid-connect/certsThe
server.authsection of theconfig.yamlfile includes the authentication environment variables, these specifications uses OAuth2 token validation:server: auth: provider_config: type: ${env.AUTH_ISSUER:+oauth2_token} audience: ${env.AUTH_AUDIENCE:=ogx} issuer: ${env.AUTH_ISSUER:=} jwks: uri: ${env.AUTH_JWKS_URI:=} key_recheck_period: ${env.AUTH_JWKS_RECHECK_PERIOD:=3600} verify_tls: ${env.AUTH_VERIFY_TLS:=true}Table 10.1. Environment variables reference
Variable Description Default AUTH_ISSUEROpenID connect (OIDC) issuer URL. If unset, authentication is disabled
None
AUTH_AUDIENCEExpected token audience
ogxAUTH_JWKS_URIJSON Web key set (JWKS) endpoint for token validation
None
AUTH_JWKS_RECHECK_PERIODHow often, in seconds, to refresh JWKS keys
3600AUTH_VERIFY_TLSVerify TLS when fetching JWKS
trueThe client user must include a valid JWT bearer token in requests, for example:
$ curl -H "Authorization: Bearer <token>" \ https://ogx.example.com/v1/models
The OGX distribution ships with a default access policy:
access_policy: - permit: actions: [read] when: resource is unowned description: "All users can read system resources" - permit: actions: [create] description: "Authenticated users can create resources" - permit: actions: [read, update, delete] when: user is owner description: "Owners can manage their own resources"You can change these policies and create custom permissions for resource allocation.
The default policy describes the following behaviors for users:
- System resources are readable by all - Resources without an owner. Models, shields, benchmarks registered in configuration are readable by any authenticated user.
- Any authenticated user can create resources - Users can create their own vector databases, files, datasets, conversations, etc.
- Users can only manage their own resources - Read, update, and delete operations on owned resources are restricted to the resource owner.
This access policy applies to user-created resources including: Vector databases, Files, Datasets, Conversations, Responses, Agents. While system resources registered in the
config.yamlfile do not have an owner and are accessible by all user types.
Chapter 11. About using self-signed certificates with OGX
You can configure a OGXServer custom resource (CR) to trust certificates that are issued by self-signed or private Certificate Authorities (CAs). This configuration enables the OGX server to establish secure TLS connections to external inference, embedding, or vector store providers.
To configure a custom CA bundle, you reference a config map that contains the CA certificates from the spec.server.tlsConfig.caBundle field of the CR. The OGX Operator validates the certificates, mounts a concatenated bundle into the OGX server pod, and sets the SSL_CERT_FILE environment variable so that TLS clients in the server trust the bundle automatically.
When you configure or change the CA bundle for a OGXServer CR, the OGX Operator restarts the OGX server pod so that the new certificates take effect. Plan for a brief service interruption when you apply or update the CA bundle on a OGXServer CR that is serving production traffic.
For the procedure and the OGX Operator processing details, see Configuring a CA bundle for OGX in Installing and uninstalling Red Hat OpenShift AI.
Chapter 12. Enabling high availability and autoscaling for OGX
You can configure OGX servers to remain available if a pod restarts, an application crashes, or node maintenance occurs. You can also enable autoscaling to adjust server capacity automatically based on resource usage. This procedure shows how to configure high availability and autoscaling for OGX server pods by using the OGXServer custom resource.
Prerequisites
- You have installed OpenShift 4.19 or later.
- You have logged in to Red Hat OpenShift AI.
- You have cluster administrator privileges for your OpenShift cluster.
- You have activated the OGX Operator in OpenShift AI. For more information, see Activating the OGX Operator.
You have installed the OpenShift CLI (
oc) as described in the documentation for your cluster:- Installing the OpenShift CLI for OpenShift Container Platform
- Installing the OpenShift CLI for Red Hat OpenShift Service on AWS
Procedure
To enable high availability for your OGX server, add the following parameters to your
OGXServerCR:spec: replicas: 2 1 server: podDisruptionBudget: maxUnavailable: 1 2 topologySpreadConstraints: 3 - maxSkew: 1 4 topologyKey: topology.kubernetes.io/zone 5 whenUnsatisfiable: ScheduleAnyway 6 labelSelector: matchLabels: app.kubernetes.io/instance: ogxserver-sample 7
- 1
- Runs two OGX pods for high availability.
- 2
- Specifies voluntary disruption tolerance. This configuration keeps at least one server pod available during voluntary disruptions.
- 3
- Specifies how matching pods are spread across the cluster topology.
- 4
- Instructs the scheduler to minimize replica imbalance across zones. With two replicas, the scheduler attempts to place one pod per zone.
- 5
- Uses the node zone label as the failure domain for pod spreading.
- 6
- Allows scheduling to proceed even if spread constraints cannot be fully satisfied.
- 7
- Ensures that only pods from the same application instance are considered when calculating spread.
To enable autoscaling for your OGX server, add the following parameters to your
OGXServerCR:spec: server: autoscaling: 1 minReplicas: 1 2 maxReplicas: 5 3 targetCPUUtilizationPercentage: 75 4 targetMemoryUtilizationPercentage: 70 5