-
Notifications
You must be signed in to change notification settings - Fork 237
6. How to use Connection API
This guide provides detailed examples for using the Connection API across different workload types and connection protocols.
The Connection API allows you to manage connections to external data sources and services in OpenShift AI. Connections are stored as Kubernetes Secrets with standardized annotations that enable protocol-based validation and routing.
Supported Connection Types (as of 3.0):
- s3: S3-compatible object storage
- uri: Public HTTP/HTTPS URIs
- oci: OCI-compliant container registries
Supported Workloads (as of 3.0):
- Notebook (Workbenches)
- InferenceService (Model Serving)
- LLMInferenceService (LLM Model Serving)
All connections follow this basic structure:
apiVersion: v1
kind: Secret
metadata:
name: <connection-name>
namespace: <your-namespace>
annotations:
opendatahub.io/connection-type-protocol: "<protocol>" # Required: s3, uri, or oci
type: Opaque
data:
# Protocol-specific fields (base64-encoded)apiVersion: v1
kind: Secret
metadata:
name: my-s3-connection
namespace: my-project
annotations:
opendatahub.io/connection-type-protocol: "s3"
type: Opaque
stringData:
AWS_S3_ENDPOINT: "https://s3.example.com"
AWS_S3_BUCKET: "my-bucket"
AWS_ACCESS_KEY_ID: "my-access-key"
AWS_SECRET_ACCESS_KEY: "my-secret-key"Required Fields for S3:
-
AWS_S3_ENDPOINT: S3 endpoint URL (e.g., "https://s3.amazonaws.com", "https://minio.example.com") -
AWS_S3_BUCKET: Bucket name (mandatory for s3 type) -
AWS_ACCESS_KEY_ID: Access key ID -
AWS_SECRET_ACCESS_KEY: Secret access key
Optional Fields:
-
AWS_DEFAULT_REGION: AWS region (e.g., "us-east-1")
apiVersion: kubeflow.org/v1
kind: Notebook
metadata:
name: my-workbench
namespace: my-project
annotations:
# Notebooks support multiple connections via comma-separated list
opendatahub.io/connections: 'my-project/my-s3-connection'
spec:
template:
spec:
containers:
- name: notebook
image: quay.io/opendatahub/workbench-images:jupyter-minimal-ubi9-python-3.11
# Connection credentials are automatically mounted as environment variablesapiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: my-model
namespace: my-project
annotations:
opendatahub.io/connections: 'my-s3-connection'
opendatahub.io/connection-path: 'my-bucket-path' # Optional: specify path within S3 bucket
spec:
predictor:
model:
modelFormat:
name: pytorch
# .spec.predictor.model.storageUri is automatically injected by the operator based on the connection
# Example: .spec.predictor.model.storageUri: s3://my-bucket/my-bucket-pathapiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
name: my-llm-model
namespace: my-project
annotations:
opendatahub.io/connections: 'my-s3-connection'
opendatahub.io/connection-path: 'my-bucket-path' # Optional: specify path within S3 bucket
spec:
model:
# .spec.model.uri is automatically injected by the operator based on the connection
# Example: .spec.model.uri: s3://my-bucket/my-bucket-pathapiVersion: v1
kind: Secret
metadata:
name: my-uri-connection
namespace: my-project
annotations:
opendatahub.io/connection-type-protocol: "uri"
type: Opaque
stringData:
URI: "https://example.com/models/my-model.tar.gz"Required Fields for URI:
-
URI: HTTP/HTTPS URL to the resource
Note: HuggingFace URIs (hf://) are treated as URI protocol connections.
apiVersion: kubeflow.org/v1
kind: Notebook
metadata:
name: my-workbench
namespace: my-project
annotations:
# Multiple connections example
opendatahub.io/connections: 'my-project/my-s3-connection,my-project/my-uri-connection'
spec:
template:
spec:
containers:
- name: notebook
image: quay.io/opendatahub/workbench-images:jupyter-minimal-ubi9-python-3.11apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: my-model
namespace: my-project
annotations:
opendatahub.io/connections: 'my-uri-connection'
spec:
predictor:
model:
modelFormat:
name: sklearn
# .spec.predictor.model.storageUri is automatically injected by the operator based on the connection
# Example: .spec.predictor.model.storageUri: https://example.com/models/my-model.tar.gzapiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
name: my-llm-model
namespace: my-project
annotations:
opendatahub.io/connections: 'my-uri-connection'
spec:
model:
# .spec.model.uri is automatically injected by the operator based on the connection
# Example: .spec.model.uri: https://example.com/models/llm-modelapiVersion: v1
kind: Secret
metadata:
name: my-oci-connection
namespace: my-project
annotations:
opendatahub.io/connection-type-protocol: "oci"
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64-encoded-docker-config>
OCI_HOST: <base64-encoded-registry-url> # Example: http://quay.io/<org>Required Fields for OCI:
-
.dockerconfigjson: Docker config JSON with registry authentication (base64-encoded) -
OCI_HOST: Registry host URL with organization (base64-encoded, e.g., "http://quay.io/my-org")
Example .dockerconfigjson content (before base64 encoding):
{
"auths": {
"quay.io": {
"auth": "<base64-encoded-username:password>"
}
}
}apiVersion: kubeflow.org/v1
kind: Notebook
metadata:
name: my-workbench
namespace: my-project
annotations:
opendatahub.io/connections: 'my-project/my-oci-connection'
spec:
template:
spec:
containers:
- name: notebook
image: quay.io/opendatahub/workbench-images:jupyter-minimal-ubi9-python-3.11apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: my-model
namespace: my-project
annotations:
opendatahub.io/connections: 'my-oci-connection'
spec:
predictor:
model:
modelFormat:
name: pytorch
# .spec.predictor.model.storageUri is automatically injected by the operator based on the connection
# Example: .spec.predictor.model.storageUri: oci://quay.io/my-org/my-model:latest
# The operator webhook also creates and injects .spec.predictor.imagePullSecrets for OCI authenticationapiVersion: serving.kserve.io/v1alpha1
kind: LLMInferenceService
metadata:
name: my-llm-model
namespace: my-project
annotations:
opendatahub.io/connections: 'my-oci-connection'
spec:
# The operator webhook automatically injects imagePullSecrets for OCI authentication
# Example: .spec.template.imagePullSecrets[].name set to the connection secret name-
Format: Comma-separated list with
namespace/nameformat - Multiple Connections: ✅ Supported
-
Example:
opendatahub.io/connections: 'my-project/connection1,my-project/connection2'
- Format: Connection name as string
- Multiple Connections: ❌ Single connection only
-
Example:
opendatahub.io/connections: 'my-connection'
-
Optional Annotation (S3 connections only):
opendatahub.io/connection-path: 'my-bucket-path' # Specify path within S3 bucket
- Connections are scoped to their namespace
- Resources can only access connections in the same namespace
- Cross-namespace access is not supported
- Users need Secret read/write permissions in their namespace to create/manage connections
- Workload ServiceAccounts need Secret read permissions to consume connections
For S3 connections, the operator automatically creates and injects a ServiceAccount:
-
ServiceAccount Name: Connection Secret name with
-sasuffix (e.g.,my-s3-connection-sa) - Purpose: Used for accessing S3 storage with the connection credentials
- Automatic Creation: The ServiceAccount is created in the same namespace as the connection Secret
- Automatic Linking: The ServiceAccount is automatically linked to the S3 connection Secret
-
Automatic Injection: The operator webhook automatically injects this ServiceAccount into:
-
.spec.predictor.serviceAccountNamefor InferenceService -
.spec.template.serviceAccountNamefor LLMInferenceService
-
- Webhook validation is advisory, not restrictive
- Invalid connections won't block Secret creation
- Invalid connections will cause workload failures at runtime
- Always validate your connection credentials before deploying workloads
If you have existing connections using the 2.16 annotation format:
Old format (2.16, deprecated but still supported):
annotations:
opendatahub.io/connection-type-ref: "s3"New format (3.0, recommended):
annotations:
opendatahub.io/connection-type-protocol: "s3"Both annotations are supported in 3.0, with connection-type-protocol taking precedence. For new connections, always use connection-type-protocol.