Chapter 4. Track experiments with MLflow in workbenches


You can track machine learning experiments in workbench notebooks with the MLflow SDK. OpenShift AI provides automatic MLflow SDK configuration for workbenches, which removes the need to manually set tracking URIs, configure authentication, or manage RBAC permissions.

To use MLflow experiment tracking, a cluster administrator must first enable the MLflow Operator component, and then a data scientist can enable and use the integration in individual workbenches.

4.1. MLflow workbench integration

You can enable automatic MLflow SDK configuration in your workbenches by annotating notebook resources with the opendatahub.io/mlflow-instance annotation. When this annotation is present, OpenShift AI automatically injects MLflow environment variables and provisions the required RBAC permissions, so that you can track experiments without manual SDK configuration.

The MLflow workbench integration removes the need to manually set tracking URIs, configure authentication tokens, or create Kubernetes RBAC resources. When an administrator enables the MLflow Operator component in the DataScienceCluster and creates an MLflow custom resource (CR), the platform handles the remaining configuration at the workbench level.

4.1.1. How the integration works

The integration uses two mechanisms in the notebook controller to configure MLflow access:

Environment variable injection

When a workbench notebook resource has the opendatahub.io/mlflow-instance annotation, the notebook controller’s mutating webhook injects three environment variables into the notebook container before the pod starts:

  • MLFLOW_TRACKING_URI: The URL of the MLflow tracking server, constructed from the GatewayAPI hostname and the MLflow instance name.
  • MLFLOW_K8S_INTEGRATION: Set to true to enable Kubernetes service account token authentication with the MLflow server.
  • MLFLOW_TRACKING_AUTH: Set to kubernetes-namespaced to configure namespace-scoped authentication.

These variables allow the MLflow Python SDK to connect to the tracking server without additional configuration in your notebook code.

RBAC provisioning
The notebook controller’s reconciler creates a namespace-scoped RoleBinding named __<notebook_name>__-mlflow that grants the workbench service account the permissions defined in the mlflow-operator-mlflow-integration ClusterRole. The RoleBinding uses a controller owner reference to the notebook resource, so it is automatically deleted when the notebook is deleted.

4.1.2. Configuration methods

You can enable MLflow integration for workbenches in two ways:

Dashboard-managed
If you use the OpenShift AI dashboard with the Dashboard, MLflow, and Workbenches components set to Managed in the DataScienceCluster, the dashboard automatically adds the opendatahub.io/mlflow-instance annotation when you create or update a workbench. No manual configuration is required.
Manual
If you manage workbenches through GitOps, Helm charts, or direct YAML manifests without the OpenShift AI dashboard, you must manually add the opendatahub.io/mlflow-instance annotation to the notebook resource.

4.1.3. Annotation lifecycle

The opendatahub.io/mlflow-instance annotation controls the MLflow integration for each workbench:

Adding the annotation
You can add the annotation to a stopped notebook or include it when you create a new notebook. The annotation value must be the name of the MLflow instance CR. Environment variables are injected on the next pod start, and the RoleBinding is created by the reconciler.
Removing the annotation
You must stop the workbench before removing the annotation. The RoleBinding is deleted immediately when the annotation is removed, but environment variables in the running pod persist until restart. This mismatch can cause authentication failures if the workbench continues to send requests to the MLflow tracking server after the RoleBinding is removed. A validating webhook checks that the kubeflow-resource-stopped annotation is present on the notebook resource before it allows removal of the MLflow annotation. The webhook validates the annotation state, not the actual pod state. If you try to remove the annotation without first stopping the workbench through the dashboard or by setting the stop annotation, the API request is rejected with a webhook error.

4.1.4. Non-blocking behavior

MLflow integration failures do not block workbench admission. If the tracking URI cannot be determined, for example because the GatewayAPI hostname is not yet available, the webhook skips the MLFLOW_TRACKING_URI injection but still allows the notebook to start. In this case, MLFLOW_K8S_INTEGRATION and MLFLOW_TRACKING_AUTH are still injected, which creates a degraded state in which the MLflow SDK is configured for Kubernetes authentication but has no tracking server to connect to. If MLflow operations such as mlflow.set_experiment() fail with a ConnectionError, verify that the MLFLOW_TRACKING_URI environment variable is set in your workbench pod.

Similarly, if the mlflow-operator-mlflow-integration ClusterRole does not yet exist, the reconciler requeues the RoleBinding creation with a warning event every 30 seconds until the ClusterRole becomes available.

4.1.5. Limitations

Artifact-serving configuration with S3 connection types is not supported. You can log parameters, metrics, and tags, but mlflow.log_artifact() functionality that relies on an S3-backed artifact store requires additional configuration that is outside the scope of the automatic integration.

4.2. Enable the MLflow operator component

You can enable the MLflow operator as a managed component in the DataScienceCluster so that the MLflow tracking server and workbench integration are available on the platform. When the MLflow operator component is enabled, workbench notebooks can use automatic MLflow SDK configuration.

Prerequisites

  • The Red Hat OpenShift AI Operator is installed on your OpenShift cluster.
  • A DataScienceCluster object exists.
  • You have cluster administrator privileges.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. Log in to your OpenShift cluster as a cluster administrator:

    $ oc login --token=__<token>__ --server=__<openshift_cluster_url>__
  2. Identify the name of the DataScienceCluster object:

    $ oc get datasciencecluster
  3. Edit the DataScienceCluster object to enable the MLflow operator component:

    $ oc edit datasciencecluster __<dsc_name>__
  4. In the spec.components section, add or update the mlflowoperator field and set managementState to Managed:

    spec:
      components:
        # ...
        mlflowoperator:
          managementState: Managed
        # ...
    Note

    The default managementState for the mlflowoperator component is Removed. You must explicitly set it to Managed to enable MLflow on the platform.

  5. Save and close the editor.

    When you set mlflowoperator to Managed, the Red Hat OpenShift AI Operator automatically configures the notebook controller with MLFLOW_ENABLED=true and sets the appropriate GATEWAY_URL for the cluster.

  6. Create an MLflow CR to deploy a tracking server instance. The MLflow CR structure and namespace requirements depend on the MLflow operator version. For more information, consult the MLflow operator documentation for the CR specification.

Verification

  1. Confirm that the MLflow operator pod is running:

    $ oc get pods -n redhat-ods-applications -l app=mlflow-operator --field-selector status.phase=Running

    The output shows one or more MLflow operator pods in Running status. If the command returns no results, verify that the mlflowoperator component managementState is set to Managed and wait for the operator pods to start.

  2. Confirm that the mlflowoperator component status is true in the DataScienceCluster:

    $ oc get datasciencecluster __<dsc_name>__ -o jsonpath='{.status.installedComponents.mlflowoperator}'

    The expected output is true.

4.2.1. MLflow dashboard feature flag deprecation

Starting with Red Hat OpenShift AI 3.4, the mlflow field in the OdhDashboardConfig CR is deprecated. MLflow availability in the dashboard is now determined by the mlflowoperator component state in the DataScienceCluster, and the dashboard feature flag is no longer required.

4.2.1.1. Deprecated field

The mlflow field in spec.dashboardConfig of the OdhDashboardConfig CR is deprecated and no longer controls MLflow visibility in the dashboard. You do not need to set this field to enable MLflow. The field has no effect on MLflow functionality.

4.2.1.2. Current behavior

MLflow features in the OpenShift AI dashboard are automatically available when the mlflowoperator component is set to Managed in the DataScienceCluster. No additional dashboard configuration is required.

4.2.1.3. mlflowPipelines field

The mlflowPipelines field in the OdhDashboardConfig CR is not deprecated and remains active. This field controls whether pipeline run tables display the MLflow experiment column. Do not confuse the deprecated mlflow field with the active mlflowPipelines field.

Expand
Table 4.1. Dashboard feature flag status
FieldStatusDescription

spec.dashboardConfig.mlflow

Deprecated

In earlier releases, this field controlled MLflow visibility in the dashboard. No longer required; MLflow is enabled automatically by the mlflowoperator component.

spec.dashboardConfig.mlflowPipelines

Active

Controls whether the MLflow experiment column is displayed in pipeline run tables.

4.3. Enable MLflow integration for a workbench

You can enable automatic MLflow SDK configuration for a workbench by adding the opendatahub.io/mlflow-instance annotation to the notebook resource. When the workbench starts, the platform injects MLflow environment variables and provisions the required RBAC resources.

When you create or update a workbench, the OpenShift AI dashboard automatically adds the MLflow annotation. For this to occur, the following components in the DataScienceCluster object must be set to Managed:

  • Dashboard
  • MLflow
  • Workbenches

The following procedure is for environments where you manage workbenches through GitOps, Helm charts, or direct YAML manifests without the OpenShift AI dashboard.

Prerequisites

  • A cluster administrator has enabled the MLflow Operator component in the DataScienceCluster object. For more information, see Enable the MLflow Operator component.
  • An MLflow CR has been created in the same namespace as the workbench.
  • The workbench is stopped.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. Log in to your OpenShift cluster:

    $ oc login --token=__<token>__ --server=__<openshift_cluster_url>__
  2. Add the opendatahub.io/mlflow-instance annotation to the notebook resource.

    In the following command, replace __<notebook_name>__ with the name of your workbench notebook and __<mlflow_instance_name>__ with the name of your MLflow instance CR:

    $ oc annotate notebook -n __<namespace>__ __<notebook_name>__ opendatahub.io/mlflow-instance=__<mlflow_instance_name>__

    If the MLflow instance name is mlflow, the tracking URI path is /mlflow. If the instance name is different, the path is /mlflow-__<mlflow_instance_name>__.

    Alternatively, you can add the annotation directly in the notebook resource YAML:

    apiVersion: kubeflow.org/v1
    kind: Notebook
    metadata:
      name: __<notebook_name>__
      namespace: __<namespace>__
      annotations:
        opendatahub.io/mlflow-instance: "__<mlflow_instance_name>__"
    spec:
      # ...
  3. Start or restart the workbench so that the environment variables are injected into the new pod.

Verification

  1. Verify that the MLflow environment variables are present in the running workbench pod.

    First, find the pod name for your notebook:

    $ oc get pods -n __<namespace>__ -l notebook-name=__<notebook_name>__

    Then verify that the MLflow environment variables are present, where __<notebook_pod_name>__ is the pod name from the previous command and __<notebook_name>__ is the notebook resource name:

    $ oc exec -n __<namespace>__ __<notebook_pod_name>__ -c __<notebook_name>__ -- env | grep MLFLOW

    The expected output shows the following environment variables:

    MLFLOW_TRACKING_URI=https://<gateway_hostname>/mlflow
    MLFLOW_K8S_INTEGRATION=true
    MLFLOW_TRACKING_AUTH=kubernetes-namespaced

    The <gateway_hostname> value is cluster-specific and matches the GatewayAPI public endpoint for your cluster.

  2. Verify that the MLflow RoleBinding exists in the namespace:

    $ oc get rolebinding -n __<namespace>__ __<notebook_name>__-mlflow

    The output shows a RoleBinding referencing the mlflow-operator-mlflow-integration ClusterRole.

4.4. Use the MLflow SDK in a workbench notebook

After MLflow integration is enabled for your workbench, you can use the MLflow Python SDK to create experiments, log parameters and metrics, and track runs. The required environment variables are already configured, so the SDK connects to the tracking server automatically.

Prerequisites

  • A cluster administrator has enabled the MLflow operator component in the DataScienceCluster. For more information, see Enable the MLflow operator component.
  • An MLflow CR has been created in the namespace.
  • The workbench notebook resource has the opendatahub.io/mlflow-instance annotation. For more information, see Enable MLflow integration for a workbench.
  • The workbench is started and the MLflow environment variables are injected.
  • The mlflow Python package is installed in the workbench. Starting with OpenShift AI 3.4, all workbench images except the minimal image include the MLflow SDK. For older images or custom images, install the package by running pip install mlflow in a notebook cell.

    Note

    If you need only basic tracking functionality, you can install the mlflow-skinny package instead for a smaller footprint. The mlflow-skinny package contains the core tracking and logging features but does not include model serving integrations or the full MLflow CLI.

Procedure

  1. Open a notebook in the workbench.
  2. Verify that the MLflow environment variables are available:

    import os
    print(os.environ.get("MLFLOW_TRACKING_URI"))
    print(os.environ.get("MLFLOW_K8S_INTEGRATION"))
    print(os.environ.get("MLFLOW_TRACKING_AUTH"))

    All three variables display their configured values.

  3. Import the MLflow SDK and set an experiment:

    import mlflow
    
    mlflow.set_experiment("my-experiment")

    The set_experiment() call returns an Experiment object and prints the experiment ID. If you see a ConnectionError, verify that the MLFLOW_TRACKING_URI environment variable is set correctly by re-running the check in step 2.

  4. Start a run and log parameters and metrics:

    with mlflow.start_run():
        mlflow.log_param("learning_rate", 0.01)
        mlflow.log_param("epochs", 10)
        mlflow.log_metric("accuracy", 0.95)
        mlflow.log_metric("loss", 0.05)

    You can log any number of parameters, metrics, and tags within a run. If start_run() raises a ConnectionError or an authentication or authorization error, verify that the MLflow tracking server is running and that the workbench RoleBinding exists.

  5. View the experiment results in the MLflow UI, which is accessible from the OpenShift AI dashboard.

Verification

  • Confirm that the experiment and run are displayed in the MLflow UI. Navigate to the MLflow tracking server URL in your browser or through the OpenShift AI dashboard and verify that the logged parameters and metrics are visible.
Note

Artifact-serving configuration with S3 connection types is not supported. You can log parameters, metrics, and tags, but mlflow.log_artifact() functionality that relies on an S3-backed artifact store requires additional configuration. For more information, see MLflow workbench integration.

4.5. Disable MLflow integration for a workbench

You can disable MLflow integration for a workbench by removing the opendatahub.io/mlflow-instance annotation from the notebook resource. You must stop the workbench before removing the annotation.

Important

When you remove the annotation, the platform deletes the associated RoleBinding resource immediately, but environment variables in the running pod persist until the pod restarts. If the workbench is running when you remove the annotation, the MLflow SDK continues to send requests to the tracking server without a valid RoleBinding resource in place, which causes authentication failures.

Prerequisites

  • Your workbench has the opendatahub.io/mlflow-instance annotation.
  • The workbench is stopped. The validating webhook requires the kubeflow-resource-stopped annotation to be present on the notebook resource before it allows removal of the MLflow annotation.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. Log in to your OpenShift cluster:

    $ oc login --token=__<token>__ --server=__<openshift_cluster_url>__
  2. Verify that the workbench pod has stopped:

    $ oc get pods -n __<namespace>__ -l notebook-name=__<notebook_name>__

    The command produces no output when the pod has stopped.

  3. Remove the opendatahub.io/mlflow-instance annotation from the notebook resource.

    In the following command, replace __<notebook_name>__ with the name of your workbench notebook:

    $ oc annotate notebook -n __<namespace>__ __<notebook_name>__ opendatahub.io/mlflow-instance-

    The trailing dash (-) removes the annotation.

Verification

  1. Start the workbench and verify that the MLflow environment variables are no longer present.

    First, find the pod name for your notebook:

    $ oc get pods -n __<namespace>__ -l notebook-name=__<notebook_name>__

    Then verify that the MLflow environment variables are no longer present, where __<notebook_pod_name>__ is the pod name from the previous command and __<notebook_name>__ is the notebook resource name:

    $ oc exec -n __<namespace>__ __<notebook_pod_name>__ -c __<notebook_name>__ -- env | grep MLFLOW

    The command produces no output, confirming that the MLflow variables have been removed.

  2. Verify that the MLflow RoleBinding resource has been removed:

    $ oc get rolebinding -n __<namespace>__ __<notebook_name>__-mlflow

    The expected output is:

    Error from server (NotFound): rolebindings.rbac.authorization.k8s.io "__<notebook_name>__-mlflow" not found

Troubleshooting

If the annotation removal is rejected with a webhook error, see Resolve MLflow annotation removal rejection.

4.6. Resolve MLflow annotation removal rejection

If you try to remove the opendatahub.io/mlflow-instance annotation from a running workbench, the API request is rejected by a validating webhook. You can resolve this issue by stopping the workbench before removing the annotation.

The validating webhook checks that the kubeflow-resource-stopped annotation is present on the notebook resource before it allows removal of the MLflow annotation. The webhook validates the annotation state, not the actual pod state. If the pod was stopped without setting the stop annotation, for example by deleting the pod directly, the webhook still rejects the annotation removal.

Prerequisites

  • The workbench has the opendatahub.io/mlflow-instance annotation.
  • You received a webhook error when trying to remove the annotation.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. Stop the workbench. You can stop the workbench from the OpenShift AI dashboard or by applying the stop annotation:

    $ oc annotate notebook -n __<namespace>__ __<notebook_name>__ kubeflow-resource-stopped=true

    The value of the kubeflow-resource-stopped annotation is not significant for this purpose. The validating webhook checks only for the presence of the annotation key.

  2. Wait for the notebook pod to stop fully:

    $ oc get pods -n __<namespace>__ -l notebook-name=__<notebook_name>__

    The command produces no output when the pod has stopped.

  3. Remove the MLflow annotation:

    $ oc annotate notebook -n __<namespace>__ __<notebook_name>__ opendatahub.io/mlflow-instance-

Verification

  • Confirm that the annotation has been removed:

    $ oc get notebook -n __<namespace>__ __<notebook_name>__ -o jsonpath='{.metadata.annotations.opendatahub\.io/mlflow-instance}'

    The command produces no output, confirming the annotation is removed.

When MLflow integration is enabled for a workbench, the notebook controller injects environment variables and creates RBAC resources automatically. You can use this reference to understand the annotation, environment variables, and RoleBinding that the platform manages on your behalf.

4.7.1. Annotation

Expand
Table 4.2. MLflow instance annotation
AnnotationDescription

opendatahub.io/mlflow-instance

Specifies the name of the MLflow instance CR to connect to. When this annotation is present and non-empty on a notebook resource, the notebook controller enables MLflow integration for the workbench. The annotation value determines the path segment in the tracking URI.

Expand
Table 4.3. Annotation value to tracking URI path mapping
Annotation valueTracking URI path

mlflow

/mlflow

__<custom_instance_name>__

/mlflow-__<custom_instance_name>__

4.7.2. Environment variables

The following environment variables are injected into the notebook container when the opendatahub.io/mlflow-instance annotation is present.

Expand
Table 4.4. MLflow environment variables
VariableValueDescription

MLFLOW_TRACKING_URI

\https://__<gateway_hostname>__/mlflow or \https://__<gateway_hostname>__/mlflow-__<instance_name>__

Specifies the URL of the MLflow tracking server. The hostname is derived from the GatewayAPI public endpoint. If the instance name is mlflow, the path is /mlflow. If the instance name differs from mlflow, the path is /mlflow-__<instance_name>__.

MLFLOW_K8S_INTEGRATION

true

Specifies that the MLflow client uses Kubernetes service account token authentication.

MLFLOW_TRACKING_AUTH

kubernetes-namespaced

Specifies the authentication method for the MLflow client. This value configures namespace-scoped authentication using the workbench service account.

4.7.3. RoleBinding

The notebook controller creates a namespace-scoped RoleBinding for each annotated workbench.

Expand
Table 4.5. MLflow RoleBinding details
PropertyValue

Name

__<notebook_name>__-mlflow

Namespace

Same as the notebook resource namespace

Subject

ServiceAccount with the name of the notebook, in the notebook namespace

RoleRef

ClusterRole named mlflow-operator-mlflow-integration

Controller owner reference

Set to the notebook resource, so the RoleBinding is automatically deleted when the notebook is deleted

Labels

notebook-name: __<notebook_name>__

4.7.4. ClusterRole availability

The RoleBinding references the mlflow-operator-mlflow-integration ClusterRole, which is created by the MLflow operator. If this ClusterRole does not yet exist when the reconciler attempts to create the RoleBinding, the reconciler requeues the request with a warning event every 30 seconds until the ClusterRole becomes available. These events are generated only when a notebook resource has the opendatahub.io/mlflow-instance annotation but the ClusterRole does not yet exist. If no annotated notebooks exist, no events are generated. You can observe these events by running the following command, where __<namespace>__ is the namespace containing your workbench notebook:

$ oc get events -n __<namespace>__ --field-selector reason=MLflowClusterRolePending

4.7.5. Controller environment variables

The Red Hat OpenShift AI Operator automatically configures the following environment variables on the notebook controller when the mlflowoperator component is set to Managed in the DataScienceCluster. You do not need to set these variables manually.

Expand
Table 4.6. Controller environment variables
VariableDescription

MLFLOW_ENABLED

Set to true when the mlflowoperator component is Managed in the DataScienceCluster. Enables the notebook controller to process MLflow annotations on workbench resources.

GATEWAY_URL

Set based on the cluster’s Gateway configuration. The notebook controller uses this value to construct the MLFLOW_TRACKING_URI for workbench pods.

Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top