Container¶
A container is a plain OCI container, created and run by containerd, that belongs to a specific cell. Containers are the only layer in the hierarchy that corresponds directly to something you would recognize from Docker.
What a container is¶
Creating a container materializes:
- An OCI container in containerd, in the realm's namespace (
kukeon-<realm>). - A cgroup leaf —
/sys/fs/cgroup/kukeon/<realm>/<space>/<stack>/<cell>/<container>_<role>— where<role>isrootfor the root container or the container id otherwise. - Metadata at
/opt/kukeon/<realm>/<space>/<stack>/<cell>/containers/<container>.yaml.
The rootfs, image layers, and image content all live in containerd — Kukeon does not re-implement any of it. You can inspect the containerd-level state at any time:
Container spec¶
apiVersion: v1beta1
kind: Container
metadata:
name: web
spec:
id: web
realmId: main
spaceId: default
stackId: default
cellId: hello-world
root: true
image: docker.io/library/nginx:alpine
command: /bin/sh
args:
- -c
- "exec nginx -g 'daemon off;'"
env:
- "NGINX_HOST=example.com"
ports: []
volumes:
- source: /srv/html
target: /usr/share/nginx/html
readOnly: true
networks: []
networksAliases: []
privileged: false
restartPolicy: ""
See Manifest Reference → Container for the complete schema and the semantics of every field.
Root vs. non-root containers¶
- Exactly one container in a cell is the root. Set
spec.root: truein the manifest, or let Kukeon pick the first container if none is explicit. - The root container's network namespace becomes the cell's network namespace.
- Non-root containers inherit the network namespace from the root. They do not get their own IP; they share the cell IP.
- If the root container exits, the cell's network namespace goes away. Non-root containers should be designed to exit too.
Lifecycle¶
| State | What it means |
|---|---|
Pending |
Container metadata exists; containerd container not yet created |
Ready |
Task is running |
Stopped |
Task record exists but its task is gone, with no exit info (e.g. reaped post-reboot) |
Exited |
Task exited 0 — a clean completion (#1267) |
Error |
Task exited non-zero — a crash (#1267) |
Paused |
Task is paused (cgroup-frozen) |
Pausing |
Task is in the process of being paused |
Failed |
A kukeon container bring-up fault (reserved for kukeon's own faults — a non-zero task exit is Error) |
NotCreated |
No containerd record at all |
Unknown |
Daemon can't determine state |
Operations¶
Containers are not CLI-managed subjects on their own — they are not addressable by the CRUD or lifecycle verbs (create, delete, purge, start, stop, kill, restart); those operate on cells. Containers are declared inside a cell manifest and materialised as a side effect of the cell's lifecycle:
- Declare containers inline under
spec.cell.containers[]in akind: Cell,kind: CellBlueprint, orkind: CellConfigmanifest. Apply withkuke apply -f cell.yamlor run withkuke run -f cell.yaml/kuke run --from-config <cfg>. - Inspect the resulting runtime containers with
kuke get container, tail logs withkuke log --container <name>, and open a session withkuke attach --container <name>. - Lifecycle is cell-level:
kuke start <cell>,kuke stop <cell>,kuke kill <cell>, andkuke restart <cell>bounce every container in the cell as a single unit. There is no per-container start/stop/kill verb. - Removal of a single container is done by editing the manifest and re-applying (or re-running) the cell —
kuke apply -freconciles container sets, and the cell-levelkuke delete celltears down the whole cell including its containers.
Related concepts¶
- Cell — the parent of a container
- containerd namespaces — where containers actually live
- cgroups — the resource-control side