Running Jobs

Direct Kubernetes Use and Session Events

Draft

This documentation is in draft and under active review. Figures for the Fall 2026 GPU reservation system are not yet published, and some pages describe behavior that has not been verified against a primary source. Confirm any figure with parasol@ucsd.edu before relying on it.

Direct use of the Kubernetes cluster beneath launch.sh suits cases the launcher does not handle, chiefly running more than one pod at a time and running something other than a notebook. This page assumes working knowledge of Kubernetes.

Scope of Support

launch.sh is the supported path for ordinary work. It sets up the home directory, the workspace, group membership, and resource limits correctly. A hand-written manifest gets the workspace's directories only by carrying the labels in Home Directories in Manifest Pods, and gets none of the rest. Use launch.sh wherever it can do the job.

ITS supports the platform, not arbitrary Kubernetes. Before substantial work on a set of hand-written manifests begins, describe to ITS what the manifests are meant to do. A supported route often exists. Administrative Requests describes requests to ITS.

The Namespace & kubectl

Each account has its own Kubernetes namespace. kubectl on the login node operates inside that namespace and can see and change its pods and nothing else.

kubectl get pods                    # list the pods in the namespace
kubectl describe pod <pod-name>     # show why a pod is Pending, or what stopped it
kubectl logs <pod-name>             # print a pod's output
kubectl logs <pod-name> -f          # follow a pod's output
kubectl get events                  # list what the cluster has done to the pods
kubectl delete pod <pod-name>       # stop a pod
kubesh <pod-name>                   # open a shell inside a pod

Diagnosing a Launch

kubectl describe pod is the first command to run when a launch misbehaves. Its output carries the scheduling messages that the launcher's own output summarizes away, and the events the reservation system writes about a GPU pod. A GPU pod waiting for the reservation system always shows a FailedScheduling event; the reservation event beside it gives the reason. See Missing or Misspelled Class Label and Reservation Events.

Shell Access to a Pod

kubectl exec -it <pod-name> bash is the general form of kubesh. It is the form to use for a pod that launch.sh did not create.

Running a Service From a Manifest

Some coursework requires a database rather than a notebook. The database is launched from a manifest on the login node and reached from a notebook by service name. The notebook and the service are separate pods in one namespace and reach each other over the cluster network.

The pattern is the same for each service. For Redis:

kubectl create -f launch/redis.yaml   # start it
kubectl get pods                      # wait for READY
kubectl delete -f launch/redis.yaml   # stop it when the work is done

Service Addresses

From a notebook spawned in the usual way, connect to the service by name.

Service Reached at
Redis my-redis, port 6379
PostgreSQL my-postgres
Neo4j bolt://my-neo4j:7687
MongoDB mongodb://my-mongo
Cassandra A 3-pod StatefulSet that takes 5-10 minutes to reach 3/3 ready

A Redis connection from Python:

import redis
r = redis.Redis(host='my-redis', port=6379, db=0)

Service Readiness

A pod can exist before it is serving. Connect after the pod reports READY, not a few seconds after kubectl create. Cassandra takes several minutes to become ready, and kubectl get statefulset and kubectl logs cassandra-0 -f report its progress.

Stopping a Service

Warning

Nothing created with kubectl create is cleaned up on logout. Anything started by hand must be stopped by hand.

kubectl delete -f <manifest> removes what a manifest created. Run kubectl get pods at the end of a session to see what is still running.

Home Directories in Manifest Pods

The cluster mounts the workspace home directory, public/, and private/ into a pod only when the pod carries two labels:

metadata:
  labels:
    dsmlp/course: <WORKSPACE>
    dsmlp/user: <username>

In a Job or Deployment, set them on the pod template, under spec.template.metadata.labels. The cluster checks both labels against the namespace: the user name must be the namespace's own, and the workspace must be one that user belongs to. A pod without both labels gets none of these directories. launch.sh -W sets both labels; see Workspace and GPU Charges.

Every pod gets /etc/podinfo/annotations, with or without the labels. See Reading the Warning From Inside a Container.

GPU Pods From a Manifest

A pod created from a manifest that requests a GPU is admitted, charged, and ended by the reservation system like a launched one. It needs:

  • An nvidia.com/gpu resource request.
  • The gpu-class label, naming the class.
  • The dsmlp/course label, naming the workspace, which launch.sh sets from -W. A pod without it is charged to ORG_ON_DEMAND and never claims a course booking; see Claiming a Booking.

The manifest sets no node selector for the class. The cluster's admission controller adds the class's node selection to any pod that carries the gpu-class label, whether the pod comes from launch.sh, from a hand-written manifest, or from a Job or Deployment, so a manifest pod with the label is routed like a launched one.

Resource Limits for Manifest Pods

Pods created from a manifest draw on the same limits as every other pod in the namespace. The namespace's totals cover everything running at once, so a database pod and a notebook pod share one allowance. A shared allowance is the usual reason the second pod does not schedule. Running Several Jobs at Once describes limits on concurrent pods.

Privileges in Manifest Pods

Containers started from a manifest are unprivileged, like every other container on the platform, so a manifest that expects to run as root or to mount a host path does not work (Root Access and System Packages).

Launch Templates

ITS maintains the launch templates for the courses that use them. Do not modify them without first checking with ITS. A locally edited copy is the usual reason a service that works for the rest of the class fails for one member.

Multi-Pod Topologies

A course may provide a cluster rather than a container. Spark is the standard example. The cluster is spawned by launching the course environment from datahub.ucsd.edu, not by running a script, and its pods are found with kubectl:

kubectl get pods                              # find spark-master-XXX-XXX
kubectl exec -it <spark-master-XXX-XXX> bash  # open a shell in the master pod

Work inside the master pod proceeds as in any other pod. A job is submitted to the cluster at its in-cluster address, for example spark://spark-master-svc:7077.

Stopping a Multi-Pod Cluster

Warning

Logging out does not stop the cluster. It keeps running and holding its resources until it is stopped with File → Hub Control Panel → Stop My Server.

See also: Stopping a Session

Reading Events

Events record what the cluster did to a pod and why.

kubectl get events                        # everything recent in the namespace
kubectl describe pod <pod-name>           # the events attached to one pod
kubectl get events --field-selector involvedObject.name=<pod-name>

kubectl describe pod is usually the most useful of the three. It lists the events at the bottom of the pod's own description, next to the resource requests and the node assignment.

Event Retention

Kubernetes keeps events for about an hour by default, so a session that ended overnight may have no events left to show by morning. For unattended work, a log file is the durable record, not the event stream. Checkpointing & Logging Long Runs covers logging.

Ordinary Pod Events

Most events are unrelated to reservations. The reason strings in this table are standard Kubernetes vocabulary and mean the same here as on any Kubernetes cluster.

Reason Meaning
Scheduled The scheduler picked a node. The pod is about to start.
FailedScheduling No node could take the pod. For a GPU pod, this event is normal until the reservation system admits the pod (Missing or Misspelled Class Label).
Pulling, Pulled The image is being fetched. A large custom image can spend minutes in this state.
Started, Killing Started: the container started. Killing: the container is being stopped.
OOMKilled (pod status) The memory limit was reached. Resource Requests and Limits describes memory requests and limits.
DeadlineExceeded (pod status) The runtime limit was reached. See The Runtime Limit.

Reservation Events

The reservation system writes 19 events of its own about GPU pods. Each is a full sentence that states what happened and what to do, and the From column of kubectl describe pod reads gpu-reservation-controller. Reservation Events defines all 19:

  • While a pod waits: WaitingForReservation, ReservationFull, ReservationTooSmall, OnDemandLeaseDenied, OnDemandLeaseRejected, OnDemandAdmissionPaused, UnknownGpuClass, NoReservation, NoGpuRequest, AnnotationIgnored, NoMatchingNode, WaitingForNode.
  • When a pod is admitted: RuntimeGuaranteed, ReservationRelinked, OverstayRelinked, BestEffortAdmitted.
  • When a pod is stopped: Preempted, ReservationCancelled, ReservationReassigned.

The three stopping events are type Normal and are written just before the pod is deleted. Read them with kubectl get events.

Reservation Annotations

The reservation system also writes annotations on each GPU pod it admits. kubectl describe pod lists them under Annotations. They are informational: the reservation system does not read them back.

Annotation Value
galends/booking-reference res- and the ID of the reservation the pod runs under
galends/reservation-kind booking or on_demand
galends/reservation-start, galends/reservation-end The reservation's own window
galends/reservation-gpu-count The number of GPUs the reservation holds, which can be more than the pod uses
galends/gpu-class-name The class's name in the reservation app
galends/admitted-at When the pod was first admitted
galends/guaranteed-until The end of the runtime guarantee. It moves later when a directly following booking is added
galends/guarantee-status guaranteed, or overstay once the guarantee has ended
galends/pod-runtime-limit-seconds The length of the guarantee in seconds, when it was last recorded. Nothing enforces it
galends/termination-warning-at, -risk, -message Present only while the pod is at risk of preemption. See The Termination Warning

Timestamps are UTC, in the form 2026-09-23T17:00:00Z; only the prose of termination-warning-message is in Pacific time. guaranteed-until and guarantee-status are refreshed about every 5 minutes. When the pod moves onto another reservation, the reservation annotations change with it.

Reading an Event Alongside the Session

Events are read together with the pod's status and the job's own logs.

Observation Interpretation
The session ended with no event and no error The session was most likely idle-culled. A warning comes first, saved work survives, and the ending is not a crash. See What Ends a Session.
The session never started The cause is a scheduling problem. The events at the bottom of the kubectl describe pod output show it.
The session ended mid-run with a reservation event Preempted is a capacity outcome rather than a fault; ReservationCancelled and ReservationReassigned mean the reservation was cancelled or given to someone else. See Events When a Pod Is Stopped.
The session ended mid-run with no event or error anywhere Report it to ITS with the pod name, the node from the launch output, and the approximate time. See Support Contacts.

Error Messages covers why a session ended without assuming Kubernetes knowledge.