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:
- Install the marimo operator on your CKS cluster (for cluster administrators)
- Run notebooks with the CLI plugin (recommended for researchers)
- Connect to CoreWeave Object Storage to access data from your notebooks
- Deploy with manifests for advanced configuration
Before you start, you must have:
- A CKS cluster with available resources
kubectlinstalled and configured to access your cluster- Python 3.10+ with
piporuv - CoreWeave Intelligent CLI for storage setup
- S3cmd for storage setup
You'll use these tools:
- marimo-operator: Manages notebook deployments on Kubernetes
- kubectl-marimo: CLI plugin for running notebooks on Kubernetes
- CoreWeave AI Object Storage: S3-compatible storage for data access
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:
-
Install the operator:
Example$kubectl apply -f https://raw.githubusercontent.com/marimo-team/marimo-operator/main/deploy/install.yaml -
Verify the operator is running:
Example$kubectl get pods -n marimo-operator-systemThe output should show the operator pod in a
Runningstate:NAME READY STATUS RESTARTS AGEmarimo-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:
-
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.pyGPU 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
-
Run and edit a notebook interactively by running the following command:
Example$kubectl marimo edit EXAMPLE_NOTEBOOK.py- Note: Replace
EXAMPLE_NOTEBOOK.pywith the path to a marimo notebook. If you don't have a marimo notebook, you can create a file with a.pyextension 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 withctrl-C.
After closing the connection with
ctrl-Cand selecting to delete the pod, the plugin:- Syncs changes you made to your notebook back to your local machine
- Tears down your pod
- Note: Replace
-
To edit a notebook without storage sync and management, run the following command:
Example$kubectl marimo edit --headless notebook.pyTipTo run a notebook as a read-only application (useful for dashboards), use
kubectl marimo run --headless notebook.pyinstead.
Specifying resources
You can configure notebook resources directly in your notebook files using Python metadata and frontmatter.
In addition to resource specification, marimo-operator will sandbox your environments through the marimo sandbox specification.
Python marimo notebooks (.py):
# /// 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):
---title: my-analysisimage: ghcr.io/marimo-team/marimo:lateststorage: 5Gimounts:- cw://my-bucket/dataenv:DEBUG: "true"---
Configuration fields
| Field | Description | Default |
|---|---|---|
title | Resource name in Kubernetes | filename |
image | Container image | ghcr.io/marimo-team/marimo:latest |
port | Server port | 2718 |
storage | Persistent volume size | none (ephemeral) |
resources | CPU, memory, and GPU requests/limits | none |
auth | Set to "none" to disable authentication | token auth |
env | Environment variables | none |
mounts | Data source URIs to mount | none |
Resource requests and limits
Specify CPU, memory, and GPU resources using Kubernetes resource quantity format.
Python notebooks (.py):
# /// 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):
---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/gpuin 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
| Scheme | Description | Example |
|---|---|---|
cw:// | CoreWeave Object Storage | cw://bucket/path |
sshfs:// | SSH filesystem mount | sshfs://user@host:/path |
rsync:// | Local directory sync | rsync://./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.
-
Login to the CoreWeave Intelligent CLI to use
cwiccommands:Example$cwic auth loginThe following prompt appears and a browser opens the CoreWeave Console:
ExampleOpening browser for authentication...Please visit: https://console.coreweave.com/tokensPlease enter the token from the browser: -
In the Console, create a new token by selecting Create Token and provide a name and expiration.
-
Paste the token secret into the
cwicprompt here:ExamplePlease enter the token from the browser: -
Use
cwicto create an access token for creating AI Object Storage buckets:Example$cwic cwobject token create --name TOKEN_NAME --duration Permanent- Note: Replace
TOKEN_NAMEwith your token name, for example,marimo-bucket-token. - Save the Access Key ID and Secret Key from the output.
- Note: Replace
-
Configure your local AI Object Storage credentials (one-time setup).
We're creating an
.s3cfgfile becausecwicuses S3cmd for creating buckets.Example$cat >> ~/.s3cfg << EOF[marimo]access_key = CWXXXXXXXXXXsecret_key = cwXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXhost_base = cwobject.comhost_bucket = %(bucket)s.cwobject.comuse_https = Truebucket_location = AVAILABILITY_ZONEEOF- Note: Replace the
access_keyandsecret_keyvalues with your actual Access Key ID and Secret Key. ReplaceAVAILABILITY_ZONEwith the your zone, for example,US-EAST-04A.
- Note: Replace the
-
Create a bucket.
Example$cwic cwobject mb BUCKET_NAME- Note: Replace
BUCKET_NAMEwith your bucket name, for example,my-notebook-data.
- Note: Replace
-
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_NAMEwith your bucket name.
- Note: Replace
-
Deploy with storage mounted:
Example$kubectl marimo edit --source=cw://BUCKET_NAME NOTEBOOK_NAME.py- Note: Replace
BUCKET_NAMEandNOTEBOOK_NAME.pywith the names of your bucket and notebook.
The plugin automatically creates the Kubernetes secret from your
~/.s3cfgfile - no manualkubectl create secretrequired. - Note: Replace
-
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:
Exampleimport osmount_path = "/home/marimo/notebooks/mounts/cw-0"# List files in the bucketfiles = os.listdir(mount_path)print(f"Files: {files}")TipThe 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:
$kubectl marimo sync NOTEBOOK.py
- Note: Replace
NOTEBOOK.pywith your notebook name.
Delete the deployment when finished:
$kubectl marimo delete NOTEBOOK.py
- Note: Replace
NOTEBOOK.pywith your notebook name.
List all active notebook deployments:
$kubectl marimo status
CLI plugin reference
Commands
edit
Run a notebook and launch the marimo editor
kubectl marimo edit [OPTIONS] FILE
| Option | Description |
|---|---|
-n, --namespace | Kubernetes namespace (default: "default") |
--source | Data source URI to mount (cw://, sshfs://, rsync://) |
--dry-run | Print the generated YAML without applying |
--headless | Deploy without port-forward or browser (for CI/scripts) |
-f, --force | Overwrite existing deployment without prompting |
Examples:
$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).
kubectl marimo run [OPTIONS] FILE
Options are the same as edit.
sync
Pull changes from the cluster back to your local file.
kubectl marimo sync [OPTIONS] FILE
| Option | Description |
|---|---|
-n, --namespace | Kubernetes namespace |
-f, --force | Overwrite local file without prompting |
delete
Remove a notebook deployment from the cluster.
kubectl marimo delete [OPTIONS] FILE
| Option | Description |
|---|---|
-n, --namespace | Kubernetes namespace |
--delete-pvc | Remove persistent storage after deletion |
--no-sync | Delete without syncing changes back first |
status
List active notebook deployments.
$kubectl marimo status
Deploy with manifests
For advanced users who need fine-grained control over deployments, you can create MarimoNotebook resources directly.
Basic manifest
-
Create a file named
notebook.yaml:notebook.yamlapiVersion: marimo.io/v1alpha1kind: MarimoNotebookmetadata:name: my-notebookspec:source: https://github.com/marimo-team/examples.gitMust be a valid .git repository path.storage:size: 1Gi -
Apply the manifest:
Example$kubectl apply -f notebook.yaml -
Check the status:
Example$kubectl get marimosThe output shows your notebook and its status:
NAME PHASE URL AGEmy-notebook Running http://my-notebook:2718 45s -
To access the notebook, set up port forwarding:
Example$kubectl port-forward service/my-notebook 2718:2718 -
Get the URL with the access token by getting the Pod's logs:
Example$kubectl logs MARIMO_NAME- Note: Replace
MARIMO_NAMEwith the manifest name.
- Note: Replace
-
Copy the URL with the access token and paste it into your browser. You should now see the notebook defined the manifest's
sourcefield.
With storage (manual setup)
To add manually add storage, complete the following steps:
-
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 -
Add mounts to your manifest:
ExampleapiVersion: marimo.io/v1alpha1kind: MarimoNotebookmetadata:name: my-notebookspec:source: https://github.com/marimo-team/examples.gitMust be a valid .git repository path.storage:size: 5Gimounts:- cw://my-notebook-data
With GPU resources
To run notebooks with GPU access, specify resource requests and limits:
apiVersion: marimo.io/v1alpha1kind: MarimoNotebookmetadata:name: gpu-notebookspec:source: https://github.com/your-org/notebooks.gitMust be a valid .git repository path.storage:size: 5Giresources:requests:cpu: "500m"memory: 4Gilimits:cpu: "4"memory: 16Ginvidia.com/gpu: 1
For specific GPU types or node placement, use podOverrides:
apiVersion: marimo.io/v1alpha1kind: MarimoNotebookmetadata:name: gpu-notebookspec:source: https://github.com/your-org/notebooks.gitMust be a valid .git repository path.storage:size: 5Giresources:requests:cpu: "500m"memory: 4Gilimits:cpu: "4"memory: 16Ginvidia.com/gpu: 1podOverrides:nodeSelector:gpu.nvidia.com/class: Quadro_RTX_4000tolerations:- key: nvidia.com/gpuoperator: Existseffect: NoSchedule
Clean up
Delete your notebook deployment:
$kubectl delete marimo MARIMO_NAME
- Note: Replace
MARIMO_NAMEwith the name in the manifest.
Using kubectl delete directly will not sync your changes back to your local file.
- Run
kubectl marimo syncto sync local changes. - Run
kubectl marimo deleteto automatically sync before deletion. - Run
kubectl marimo delete --delete-pvcto also delete the persistent data.