Use DEDL standalone S3 object storage with KServe

This article explains how to make a model stored in DEDL standalone S3 object storage available to a KServe InferenceService.

What you will do

In this article, you perform the procedure. You need project administrator privileges in My DataLake Services and access to the target MLOps Studio namespace.

You will:

  • identify the existing DEDL standalone S3 credentials and model URI,

  • create and annotate a Kubernetes secret,

  • attach the secret to the service account,

  • deploy the InferenceService,

  • verify the result.

Two actions may require assistance:

  • The DEDL operator approves your access and quota role requests.

  • If you cannot create secrets or patch service accounts, ask the MLOps Studio platform administrator to grant the required permissions.

Prerequisites

No. 1 kubectl configured for MLOps Studio

Configure kubectl for the cluster and namespace in which the InferenceService will run.

See How to access a Kubernetes cluster post-deployment using kubectl.

No. 2 Namespace access and permissions

Confirm that you can access the namespace and can create secrets and patch service accounts in it.

No. 3 KServe service account name

Identify the service account used by the InferenceService. If spec.predictor.serviceAccountName is not set, this is normally default.

No. 4 DEDL standalone S3 credentials

Obtain the standalone S3 endpoint, region, access key, and secret key from the s3-object-storage service in My DataLake Services. Do not use EODATA or Islet/OpenStack object storage credentials.

Generate the credentials for the same DEDL site that hosts the bucket. For example, credentials generated for central, eumetsat, or leonardo must be used with the standalone S3 endpoint for that site.

Follow How to obtain S3 keys for standalone S3 object storage through My DataLake Services before continuing.

No. 5 Model stored in DEDL standalone S3 object storage

Ensure that the model is already stored at the selected DEDL site and record its complete S3 URI. The example used below assumes that the model is stored at s3://my-private-models/sklearn/model.joblib in the central service.

Use the standalone S3 endpoint published for that site. Do not use a bucket URL, an EODATA endpoint, or an Islet/OpenStack endpoint. The My DataLake Services portal manages access, quotas, accounts, keys, and usage, but it does not provide an interface for uploading model files.

If the model still needs to be uploaded, you can use an S3-compatible client. The linked articles are optional client examples; use the standalone S3 endpoint and credentials from Prerequisite No. 4 rather than the service values shown in another example.

For s3cmd instructions, see How to access object storage using s3cmd.

For AWS CLI instructions, see Using AWS CLI to access Fresh Data Pool (EODATA).

For boto3 instructions, see How to access private object storage using S3cmd or boto3.

For Cyberduck instructions, see Using Cyberduck with S3-compatible object storage.

Set the configuration values

Set the namespace, service account, secret, S3, and model values once before running the remaining commands:

export NAMESPACE="<namespace>"
export SERVICE_ACCOUNT="<service-account>"
export SECRET_NAME="s3-creds-private"
export AWS_ACCESS_KEY_ID="<access key generated for central>"
export AWS_SECRET_ACCESS_KEY="<secret key shown once for central>"
export S3_ENDPOINT="<standalone DEDL S3 endpoint for central>"
export S3_REGION="<region required by the central endpoint>"
export INFERENCE_SERVICE_NAME="private-s3-model"
export MODEL_FORMAT="<model-format>"
export STORAGE_URI="s3://my-private-models/sklearn/model.joblib"

Do not commit credentials, a rendered secret manifest, or a file containing these exported values to source control.

Create and annotate the secret

Create the secret with the credential keys expected by KServe:

kubectl create secret generic "$SECRET_NAME" \
  --namespace "$NAMESPACE" \
  --from-literal=AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" \
  --from-literal=AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY"

Annotate the secret for the selected standalone S3 service:

kubectl annotate secret "$SECRET_NAME" \
  --namespace "$NAMESPACE" \
  serving.kserve.io/s3-endpoint="$S3_ENDPOINT" \
  serving.kserve.io/s3-region="$S3_REGION" \
  serving.kserve.io/s3-usehttps="1" \
  serving.kserve.io/s3-useanoncredential="false" \
  --overwrite

Use serving.kserve.io/s3-usehttps="0" only when the endpoint does not support HTTPS. The endpoint value should use the format required by the platform’s KServe installation, normally a hostname with an optional port and without a bucket path.

Attach the secret to the service account

Attach the secret to the service account used by the InferenceService:

kubectl patch serviceaccount "$SERVICE_ACCOUNT" \
  --namespace "$NAMESPACE" \
  --type=strategic \
  --patch "{\"secrets\":[{\"name\":\"$SECRET_NAME\"}]}"

Deploy the InferenceService

Apply an InferenceService that uses the same namespace, service account, and model URI:

kubectl apply -f - <<EOF
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: ${INFERENCE_SERVICE_NAME}
  namespace: ${NAMESPACE}
spec:
  predictor:
    serviceAccountName: ${SERVICE_ACCOUNT}
    model:
      modelFormat:
        name: ${MODEL_FORMAT}
      storageUri: ${STORAGE_URI}
EOF

Verify the configuration

Confirm that the annotations and service-account secret reference are present without printing secret values:

kubectl describe secret "$SECRET_NAME" --namespace "$NAMESPACE"
kubectl get serviceaccount "$SERVICE_ACCOUNT" \
  --namespace "$NAMESPACE" \
  --output yaml

Inspect the status of the InferenceService and recent namespace events:

kubectl get inferenceservice "$INFERENCE_SERVICE_NAME" \
  --namespace "$NAMESPACE" \
  --output yaml
kubectl get events \
  --namespace "$NAMESPACE" \
  --sort-by=.lastTimestamp

Authentication failures, missing secret references, endpoint errors, and TLS errors normally appear in the InferenceService, pod, or namespace events.

Rotate or delete credentials

If a DEDL secret key is refreshed, the previous secret stops working immediately. Update the Kubernetes secret used by KServe and restart or redeploy the affected InferenceService.

Deleting a site-specific key pair similarly removes KServe’s access to models at that site without affecting key pairs for other DEDL sites.