Lab 6: CPU and memory¶
Objectives: see requests and limits applied to workspaces, feel CPU throttling and the OOM killer, and hit LimitRange and ResourceQuota on purpose.
1. What did the workspace get?¶
kubectl -n project-alpha get pod jupyter-researcher1 \
-o jsonpath='{.spec.containers[0].resources}{"\n"}'
kubectl -n project-alpha describe limitrange project-limits
kubectl -n project-alpha describe resourcequota project-quota
Where do 0.5 CPU and 1Gi memory come from? Follow the trail:
gitops/apps/values.yaml (sizes: [small]) → gitops/projects/chart/values.yaml
(sizeCatalogue.small) → namespace annotation k8tre.io/sizes → tre_config.py → the pod.
Units
KubeSpawner reads 1G as 1 GiB (1024³ bytes), so pods show 1Gi. CPU 0.5 is 500m
(millicores).
2. CPU: throttled, not killed¶
As researcher1, in a notebook:
import multiprocessing, os
def burn():
while True:
pass
procs = [multiprocessing.Process(target=burn, daemon=True) for _ in range(4)]
for p in procs:
p.start()
print("burning on", len(procs), "processes; os.cpu_count() says", os.cpu_count())
In the dev container, after about 30 seconds:
CPU sits at about 500m however many processes you start: the container is throttled to its
limit. os.cpu_count() still reports every core of the node, which confuses many data-science
libraries into starting too many threads. (Discuss: how would you tell researchers?)
Stop the burners with Kernel → Restart Kernel.
3. Memory: over the limit means killed¶
chunks = []
for i in range(40):
chunks.append(bytearray(100 * 1024 * 1024)) # 100 MiB at a time
print(f"{(i + 1) * 100} MiB allocated", flush=True)
Somewhere below 1000 MiB the container hits its memory limit. Here memory.oom.group=1, so the
cgroup OOM killer kills every process in the container: JupyterLab shows "Server unavailable
or unreachable" and the pod restarts.
If your environment uses memory.oom.group=0, only the Python kernel dies ("The kernel appears to
have died. It will restart automatically."), the Jupyter server survives and RESTARTS stays 0.
4. The LimitRange ceiling¶
No container can ask for more than the project LimitRange's max:
kubectl -n project-alpha run toobig --restart=Never \
--image=quay.io/jupyter/minimal-notebook:2026-08-10 --labels=k8tre.io/project=alpha \
--overrides='{"spec":{"containers":[{"name":"toobig","image":"quay.io/jupyter/minimal-notebook:2026-08-10","command":["sleep","3600"],"resources":{"limits":{"cpu":"4","memory":"8Gi"}}}]}}'
Error from server (Forbidden): pods "toobig" is forbidden: [maximum cpu usage per Container is 1,
but limit is 4, maximum memory usage per Container is 2Gi, but limit is 8Gi]
5. The project quota¶
Project beta has a quota of 4Gi of memory limits in total. First stop any beta
workspaces (researcher2, researcher3). Then fill the quota with two 2Gi "sleeper" pods:
for i in 1 2; do
kubectl -n project-beta run hog$i --restart=Never \
--image=quay.io/jupyter/minimal-notebook:2026-08-10 --labels=k8tre.io/project=beta \
--overrides='{"spec":{"containers":[{"name":"hog","image":"quay.io/jupyter/minimal-notebook:2026-08-10","command":["sleep","3600"],"resources":{"requests":{"cpu":"50m","memory":"64Mi"},"limits":{"cpu":"500m","memory":"2Gi"}}}]}}'
done
kubectl -n project-beta describe resourcequota project-quota
Notice two things:
- Pod Security prints warnings (
would violate PodSecurity "restricted:latest"). The namespace enforcesbaselinebut only warns aboutrestricted: a gentle way to roll out stricter rules. limits.memoryused is now4Giof4Gi.
Now log in as researcher2 and start a workspace in beta. It fails with something like:
Spawn failed: ... pods "jupyter-researcher2" is forbidden: exceeded quota: project-quota,
requested: limits.memory=1Gi, used: limits.memory=4Gi, limited: limits.memory=4Gi
The quota protects everyone else on the cluster from one project's appetite. Researchers see it as a failed launch, so a real TRE needs a clear message and a process for asking for more.
Clean up:
Check your understanding¶
- What is the difference between a request and a limit? Which one does the scheduler use?
- Why cap memory hard but only throttle CPU?
- The quota counts limits, not actual usage. What are the pros and cons for a TRE?
- How would you change project beta's quota properly? (Hint: lab 7.)