elmo

Labs that run in your cluster, isolated from everything else

Some of the people you need to train cannot install Docker, and some of them should not be allowed to. A lab gives them the same exercise in a browser tab: real tools, a real terminal, running on your own nodes for as long as the class lasts.

A lab is a group of pods, not one

Containers inside a single pod share one network namespace, so a client and a server placed together would talk to each other over the loopback interface. For a networking exercise that quietly destroys the thing being taught: the traffic the learner is supposed to capture never crosses a wire. So each component that should be a separate host gets its own pod, and only components that genuinely belong on one host share.

The exercise runs unchanged

Each lab gets its own name resolution, so a bare hostname in the exercise resolves to that learner's own server and never to somebody else's. The scripts a learner is told to run are the same scripts they would run on a laptop — which matters, because a hosted lab whose commands differ from the written exercise teaches the hosting, not the subject.

Default-deny, in both directions

Labs run in a namespace of their own where nothing may talk in and nothing may talk out. Outbound is opened only to name resolution and to the other pods of the same lab; a template may additionally allow public addresses, and that is a deliberate choice made per template rather than a default. One lab can reach another only on ports a template names — never its terminals.

Proven from inside, not read off a policy file

Network policy is only as real as the network plugin enforcing it, and a policy that reads correctly can still be enforcing nothing. So the isolation is checked by a script that runs inside a live lab and tries to reach the things it must not reach — the platform's own database, other namespaces, the cluster's internal services. Nineteen checks, and the result is a count of what was actually attempted.

The cluster says whether a lab is running

Not a status column in a database. Asking the cluster means the answer is never stale after a node reboots, a pod is evicted or somebody deletes one by hand — the three cases where a stored status is confidently wrong and a learner is told their lab is running when it is not.

It ends itself

Each lab carries its own deadline, set from the template's limit and clamped to whatever time the class has left. There is no scheduled job that has to survive for the cleanup to happen: a lab that nobody stops stops anyway, and a class that ends takes its labs with it.

One running lab per person

Somebody may hold several and run one. That single rule is what bounds the load on your cluster, because every lab belongs to exactly one person: a class can never run more labs than it has people, and an instructor who starts the whole class at once starts at most one each.

What this does not solve

A learner is root inside their own lab, and two consequences follow that no platform setting fixes. A connection already open when access is withdrawn survives until the pod is stopped. And a process that forks without limit is bounded by the node's own configuration, not by anything here — which is a setting your cluster administrator makes, and one we will tell you to check before a pilot rather than after it.

The learner is root inside their own lab. Every rule on this page assumes that and is written to hold anyway.