Skip to main content
This page describes how to run workloads on a Together GPU cluster with Kubernetes: deploying pods with persistent storage, running GPU workloads in containers, and monitoring them with Grafana. Before you start, connect kubectl to your cluster. For background on Kubernetes and how it works on Together, see Concepts.

Deploy pods with storage

Together provides a static PersistentVolume (PV) with the same name as your shared volume. Data you write to the static PV persists across pod restarts, cluster operations, and, by default, cluster deletion. Kubernetes connects storage to your containers through three objects:
  • PersistentVolume (PV): The storage resource itself, managed by Together.
  • PersistentVolumeClaim (PVC): A request for storage that your pods can use. You create this.
  • Pod with volumeMounts: Mounts the PVC into your container at a specific path. You create this.
1

Create PVCs

For shared storage that multiple pods can read and write at the same time, create a PVC with ReadWriteMany access. Set volumeName to your shared volume’s name so the PVC binds to the static PV:
shared-pvc.yaml
The static PV uses your cluster’s shared storage class, which is also the cluster’s default storage class, so the PVC doesn’t need a storageClassName. If the shared PVC stays Pending, check the PV’s class with kubectl get pv <shared volume name> and add a matching storageClassName to the PVC.
For fast local NVMe storage that only one node can mount at a time, create a PVC with ReadWriteOnce access and the local storage class:
local-pvc.yaml
Data on local NVMe is ephemeral, so use the local PVC only for scratch files you can regenerate.Apply both PVCs and check their status:
The shared PVC shows Bound right away. The local PVC stays Pending until a pod that mounts it is scheduled, which is expected for the local storage class.
2

Define a pod that mounts the PVCs

Define a pod that mounts both PVCs as volumes. Each volumes entry references a PVC by its claimName, and each volumeMounts entry uses a volume’s name to mount it at a path inside the container:
pod-with-storage.yaml
3

Deploy and access the pod

Deploy the pod in the same namespace as its PVCs, then open a shell in it:
4

Verify mounted volumes

Inside the pod, check that both volumes are mounted and that you can write to the shared volume:

Access the shared volume from multiple pods

Because the shared PVC uses ReadWriteMany access, multiple pods can mount it at the same time. To read the file you wrote from test-pod, create a second pod that mounts the same PVC. It needs its own manifest, because kubectl run can’t attach a PVC:
test-pod-2.yaml
Create the second pod and read the file from it:

Run GPU workloads in containers

To run GPU workloads or work with your data volumes, deploy a pod with GPU and storage access, then exec into it. Use a CUDA-enabled base image, such as nvidia/cuda or pytorch/pytorch, instead of installing CUDA yourself. A pod gets the GPUs it requests with nvidia.com/gpu, so always request GPUs explicitly. On older clusters, a pod that requests none can still see every GPU on its node if its image sets NVIDIA_VISIBLE_DEVICES, as CUDA images do. The host provides the NVIDIA kernel driver, and your container image provides the CUDA libraries. In an image without CUDA, such as a debian or ubuntu base image, you can’t run CUDA workloads until you install CUDA. This pod mounts the shared-pvc claim from Deploy pods with storage, so create that PVC first:
gpu-pod.yaml
Deploy the pod and open a shell in it:

Monitor workloads with Grafana

The Observability add-on provides Grafana dashboards for cluster nodes and workloads. To open them:
  1. Enable the Observability add-on. When you create a cluster, it’s under Cluster add-ons. On a running cluster, it’s in the Add-ons section of the cluster’s Overview tab.
  2. On the cluster details page, select Open Grafana under Access.

Troubleshooting

  • Pods aren’t scheduled: Check node status with kubectl get nodes, confirm the pod’s resource requests don’t exceed available resources, and check for taints with kubectl describe node <node_name>.
  • Volumes don’t mount: Check that the PVC is bound with kubectl get pvc. For the shared PVC, check that volumeName matches your shared volume’s name. For the local PVC, check that its storage class exists.
  • GPU isn’t accessible in a container: Use a CUDA-enabled image such as pytorch/pytorch or nvidia/cuda.

Next steps

Cluster storage

Choose the right storage tier for datasets and checkpoints.

Manage clusters

Manage access, scale capacity, and monitor cluster health.

Volcano

Gang-schedule distributed GPU jobs with the Volcano scheduler.

Kueue

Queue and admit GPU jobs with Kueue quotas.

Preemptible compute

Schedule interruption-tolerant workloads onto discounted preemptible nodes.