Skip to main content

Run marimo notebooks on CKS

Run reactive Python notebooks on CKS with persistent storage and AI Object Storage integration

marimo is an open-source Python notebook designed specifically for machine learning and AI.

This tutorial shows you how to develop with marimo notebooks on CKS, including connecting to CoreWeave Object Storage for data access.

In this tutorial, you will:

  1. Install the marimo operator on your CKS cluster (for cluster administrators)
  2. Run notebooks with the CLI plugin (recommended for researchers)
  3. Connect to CoreWeave Object Storage to access data from your notebooks
  4. Deploy with manifests for advanced configuration

Install the marimo operator

Note that this section is primary for cluster administrators who need to install the marimo operator on CKS clusters. If the operator is already installed on your cluster, skip to Install Kubernetes marimo CLI plugin.

To use marimo within a CKS cluster, install the marimo operator by running the following commands:

  1. Install the operator:

    Example
    $
    kubectl apply -f https://raw.githubusercontent.com/marimo-team/marimo-operator/main/deploy/install.yaml
  2. Verify the operator is running:

    Example
    $
    kubectl get pods -n marimo-operator-system

    The output should show the operator pod in a Running state:

    NAME READY STATUS RESTARTS AGE
    marimo-operator-controller-manager-xxxxx 1/1 Running 0 30s

Install the marimo CLI plugin

The CLI plugin is the fastest way to run notebooks. It handles manifest generation, port forwarding, and credential management automatically.

To install the marimo CLI plugin, run the following commands:

  1. Install kubectl-marimo:

    Example
    # With uv (recommended)
    $
    uv tool install kubectl-marimo
    # Or with pip
    $
    pip install kubectl-marimo

Run a marimo notebook on CKS

After installing the operator and CLI plugin, you can run marimo notebooks.

If you're new to marimo, you can use one of the pre-written CPU or GPU notebooks. For more information about these example notebooks, go to the marimo operator examples page.

CPU notebook

Example
$
curl -O https://raw.githubusercontent.com/marimo-team/marimo-operator/main/plugin/examples/getting-started.py
$
kubectl marimo edit getting-started.py

GPU notebook

Example
$
curl -O https://raw.githubusercontent.com/marimo-team/marimo-operator/main/plugin/examples/gpu-getting-started.py
$
kubectl marimo edit gpu-getting-started.py
  1. Run and edit a notebook interactively by running the following command:

    Example
    $
    kubectl marimo edit EXAMPLE_NOTEBOOK.py
    • Note: Replace EXAMPLE_NOTEBOOK.py with the path to a marimo notebook. If you don't have a marimo notebook, you can create a file with a .py extension to use as a starting point. You can also use one of the pre-written notebooks mentioned above, such as the CPU or GPU notebook.

    This command does the following:

    • Uploads your notebook to the cluster
    • Creates persistent storage for your changes
    • Starts the marimo server
    • Provides a URL where you can access your notebook. Your notebook opens at http://localhost:<port>, which runs until you close the connection with ctrl-C.

    After closing the connection with ctrl-C and selecting to delete the pod, the plugin:

    • Syncs changes you made to your notebook back to your local machine
    • Tears down your pod
  2. To edit a notebook without storage sync and management, run the following command:

    Example
    $
    kubectl marimo edit --headless notebook.py
    Tip

    To run a notebook as a read-only application (useful for dashboards), use kubectl marimo run --headless notebook.py instead.

Specifying resources

You can configure notebook resources directly in your notebook files using Python metadata and frontmatter.

Info

In addition to resource specification, marimo-operator will sandbox your environments through the marimo sandbox specification.

Python marimo notebooks (.py):

Example
# /// script
# dependencies = ["marimo", "pandas", "numpy"]
#
# [tool.marimo.k8s]
# image = "ghcr.io/marimo-team/marimo:latest"
# storage = "5Gi"
# mounts = ["cw://my-bucket/data"]
# [tool.marimo.k8s.env]
# DEBUG = "true"
# ///
#

Markdown marimo notebooks (.md):

Example
---
title: my-analysis
image: ghcr.io/marimo-team/marimo:latest
storage: 5Gi
mounts:
- cw://my-bucket/data
env:
DEBUG: "true"
---

Configuration fields

FieldDescriptionDefault
titleResource name in Kubernetesfilename
imageContainer imageghcr.io/marimo-team/marimo:latest
portServer port2718
storagePersistent volume sizenone (ephemeral)
resourcesCPU, memory, and GPU requests/limitsnone
authSet to "none" to disable authenticationtoken auth
envEnvironment variablesnone
mountsData source URIs to mountnone

Resource requests and limits

Specify CPU, memory, and GPU resources using Kubernetes resource quantity format.

Python notebooks (.py):

Example
# /// script
# [tool.marimo.k8s.resources]
# requests.cpu = "500m"
# requests.memory = "2Gi"
# limits.cpu = "2"
# limits.memory = "8Gi"
# limits."nvidia.com/gpu" = 1
# ///

Markdown notebooks (.md):

Example
---
resources:
requests:
cpu: "500m"
memory: "2Gi"
limits:
cpu: "2"
memory: "8Gi"
nvidia.com/gpu: 1
---
  • GPU workloads. For GPU workloads on CoreWeave, specifying nvidia.com/gpu in limits is typically sufficient. The scheduler will place your notebook on an appropriate GPU Node. For advanced scheduling (specific GPU types, Node affinity), use manifest-based deployment.

  • CRD information. For the full CRD specification including advanced features like podOverrides, sidecars, and custom authentication, see the marimo-operator documentation.

Mount URI schemes

SchemeDescriptionExample
cw://CoreWeave Object Storagecw://bucket/path
sshfs://SSH filesystem mountsshfs://user@host:/path
rsync://Local directory syncrsync://./data:/notebooks

Local and bi-directional syncing

Local rsync:// URIs (like rsync://./data) sync a local directory to the pod. Remote URIs (like rsync://user@host:/path) create continuous bi-directional sync.

Connect to CoreWeave AI Object Storage

Mount CoreWeave AI Object Storage buckets in your notebooks with automatic credential management.

  1. Login to the CoreWeave Intelligent CLI to use cwic commands:

    Example
    $
    cwic auth login

    The following prompt appears and a browser opens the CoreWeave Console:

    Example
    Opening browser for authentication...
    Please visit: https://console.coreweave.com/tokens
    Please enter the token from the browser:
  2. In the Console, create a new token by selecting Create Token and provide a name and expiration.

  3. Paste the token secret into the cwic prompt here:

    Example
    Please enter the token from the browser:
  4. Use cwic to create an access token for creating AI Object Storage buckets:

    Example
    $
    cwic cwobject token create --name TOKEN_NAME --duration Permanent
    • Note: Replace TOKEN_NAME with your token name, for example, marimo-bucket-token.
    • Save the Access Key ID and Secret Key from the output.
  5. Configure your local AI Object Storage credentials (one-time setup).

    We're creating an .s3cfg file because cwic uses S3cmd for creating buckets.

    Example
    $
    cat >> ~/.s3cfg << EOF
    [marimo]
    access_key = CWXXXXXXXXXX
    secret_key = cwXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    host_base = cwobject.com
    host_bucket = %(bucket)s.cwobject.com
    use_https = True
    bucket_location = AVAILABILITY_ZONE
    EOF
    • Note: Replace the access_key and secret_key values with your actual Access Key ID and Secret Key. Replace AVAILABILITY_ZONE with the your zone, for example, US-EAST-04A.
  6. Create a bucket.

    Example
    $
    cwic cwobject mb BUCKET_NAME
    • Note: Replace BUCKET_NAME with your bucket name, for example, my-notebook-data.
  7. Create a file and add it to the bucket:

    Example
    $
    touch some-data.txt
    $
    s3cmd put ./some-data.txt s3://BUCKET_NAME/
    • Note: Replace BUCKET_NAME with your bucket name.
  8. Deploy with storage mounted:

    Example
    $
    kubectl marimo edit --source=cw://BUCKET_NAME NOTEBOOK_NAME.py
    • Note: Replace BUCKET_NAME and NOTEBOOK_NAME.py with the names of your bucket and notebook.

    The plugin automatically creates the Kubernetes secret from your ~/.s3cfg file - no manual kubectl create secret required.

  9. Access your data in the notebook:

    Files are mounted at /home/marimo/notebooks/mounts/cw-0/:

    In the marimo notebook, access the mounted storage from the files menu under mounts > cw-0:

    You can also add this script to the notebook as an example of accessing the mounted storage:

    Example
    import os
    mount_path = "/home/marimo/notebooks/mounts/cw-0"
    # List files in the bucket
    files = os.listdir(mount_path)
    print(f"Files: {files}")
    Tip

    The mount supports full read/write access. Any files you create or modify in the mount directory are saved to your S3-compatible bucket.

Manually syncing and managing deployments

When you're done editing, sync your changes back to your local file without stopping the instance:

Example
$
kubectl marimo sync NOTEBOOK.py
  • Note: Replace NOTEBOOK.py with your notebook name.

Delete the deployment when finished:

Example
$
kubectl marimo delete NOTEBOOK.py
  • Note: Replace NOTEBOOK.py with your notebook name.

List all active notebook deployments:

Example
$
kubectl marimo status

CLI plugin reference

Commands

edit

Run a notebook and launch the marimo editor

Example
kubectl marimo edit [OPTIONS] FILE
OptionDescription
-n, --namespaceKubernetes namespace (default: "default")
--sourceData source URI to mount (cw://, sshfs://, rsync://)
--dry-runPrint the generated YAML without applying
--headlessDeploy without port-forward or browser (for CI/scripts)
-f, --forceOverwrite existing deployment without prompting

Examples:

Example
$
kubectl marimo edit notebook.py
$
kubectl marimo edit --source=cw://my-bucket/data notebook.py
$
kubectl marimo edit -n staging --headless notebook.py

run

Deploy a notebook as a read-only application (useful for dashboards).

Example
kubectl marimo run [OPTIONS] FILE

Options are the same as edit.

sync

Pull changes from the cluster back to your local file.

Example
kubectl marimo sync [OPTIONS] FILE
OptionDescription
-n, --namespaceKubernetes namespace
-f, --forceOverwrite local file without prompting

delete

Remove a notebook deployment from the cluster.

Example
kubectl marimo delete [OPTIONS] FILE
OptionDescription
-n, --namespaceKubernetes namespace
--delete-pvcRemove persistent storage after deletion
--no-syncDelete without syncing changes back first

status

List active notebook deployments.

Example
$
kubectl marimo status

Deploy with manifests

Info

For advanced users who need fine-grained control over deployments, you can create MarimoNotebook resources directly.

Basic manifest

  1. Create a file named notebook.yaml:

    notebook.yaml
    apiVersion: marimo.io/v1alpha1
    kind: MarimoNotebook
    metadata:
    name: my-notebook
    spec:
    source: https://github.com/marimo-team/examples.git
    Must be a valid .git repository path.
    storage:
    size: 1Gi
  2. Apply the manifest:

    Example
    $
    kubectl apply -f notebook.yaml
  3. Check the status:

    Example
    $
    kubectl get marimos

    The output shows your notebook and its status:

    NAME PHASE URL AGE
    my-notebook Running http://my-notebook:2718 45s
  4. To access the notebook, set up port forwarding:

    Example
    $
    kubectl port-forward service/my-notebook 2718:2718
  5. Get the URL with the access token by getting the Pod's logs:

    Example
    $
    kubectl logs MARIMO_NAME
    • Note: Replace MARIMO_NAME with the manifest name.
  6. Copy the URL with the access token and paste it into your browser. You should now see the notebook defined the manifest's source field.

With storage (manual setup)

To add manually add storage, complete the following steps:

  1. Create the credentials secret:

    Example
    $
    kubectl create secret generic cw-credentials \
    --from-literal=AWS_ACCESS_KEY_ID=CWXXXXXXXXXX \
    --from-literal=AWS_SECRET_ACCESS_KEY=cwXXXXXXXXXXXXXX
  2. Add mounts to your manifest:

    Example
    apiVersion: marimo.io/v1alpha1
    kind: MarimoNotebook
    metadata:
    name: my-notebook
    spec:
    source: https://github.com/marimo-team/examples.git
    Must be a valid .git repository path.
    storage:
    size: 5Gi
    mounts:
    - cw://my-notebook-data

With GPU resources

To run notebooks with GPU access, specify resource requests and limits:

Example
apiVersion: marimo.io/v1alpha1
kind: MarimoNotebook
metadata:
name: gpu-notebook
spec:
source: https://github.com/your-org/notebooks.git
Must be a valid .git repository path.
storage:
size: 5Gi
resources:
requests:
cpu: "500m"
memory: 4Gi
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1

For specific GPU types or node placement, use podOverrides:

Example
apiVersion: marimo.io/v1alpha1
kind: MarimoNotebook
metadata:
name: gpu-notebook
spec:
source: https://github.com/your-org/notebooks.git
Must be a valid .git repository path.
storage:
size: 5Gi
resources:
requests:
cpu: "500m"
memory: 4Gi
limits:
cpu: "4"
memory: 16Gi
nvidia.com/gpu: 1
podOverrides:
nodeSelector:
gpu.nvidia.com/class: Quadro_RTX_4000
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule

Clean up

Delete your notebook deployment:

Example
$
kubectl delete marimo MARIMO_NAME
  • Note: Replace MARIMO_NAME with the name in the manifest.
Info

Using kubectl delete directly will not sync your changes back to your local file.

  • Run kubectl marimo sync to sync local changes.
  • Run kubectl marimo delete to automatically sync before deletion.
  • Run kubectl marimo delete --delete-pvc to also delete the persistent data.

Additional resources