Skip to content

Tutorial: hello-world cell

Walks through running a minimal cell that serves a static HTML page over HTTP, using the hello-world.yaml example in the repo.

Prerequisites

  • Kukeon installed and bootstrapped — see Getting Started.
  • curl on the host, for the verification step.

1. Inspect the manifest

The example lives at docs/examples/hello-world.yaml:

apiVersion: v1beta1
kind: Cell
metadata:
  name: hello-world
spec:
  id: hello-world
  realmId: default
  spaceId: default
  stackId: default
  containers:
    - id: web
      image: docker.io/library/busybox:latest
      command: /bin/sh
      args:
        - -c
        - |
          mkdir -p /www && \
          cat > /www/index.html <<'HTML'
          <!doctype html>
          <html>
            <head><meta charset="utf-8"><title>kukeon hello-world</title></head>
            <body style="font-family: sans-serif">
              <h1>Hello, world from kukeon!</h1>
              <p>Served by busybox httpd inside a cell in the <code>default</code> realm.</p>
            </body>
          </html>
          HTML
          exec busybox httpd -f -v -p 8080 -h /www

It's a single cell with a single container. The container bootstraps an index.html into a scratch dir, then executes busybox httpd bound to :8080. Because there's only one container, it's implicitly the root container and owns the cell's network namespace.

2. Apply it

sudo kuke apply -f docs/examples/hello-world.yaml

See Client and daemon for how kuke routes through kukeond by default, and the in-process escape hatch when the daemon is down.

3. Confirm the cell is Ready

$ sudo kuke get cells --realm default --space default --stack default
NAME         REALM    SPACE    STACK    STATE   ...
hello-world  default  default  default  Ready

If it's still Pending, give it a second and re-run. If it's Failed, check the container's log via ctr:

sudo ctr -n kukeon-default tasks attach hello-world_web

4. Find the cell IP and curl it

The default-default space bridge is 10.88.0.0/16. The cell gets one IP on that bridge. To find it, get the root container's pid from containerd, then peek into its network namespace:

ROOT_PID=$(sudo ctr -n kukeon.io task ls | awk '/hello-world_root/ {print $2}')
CELL_IP=$(sudo nsenter -t "${ROOT_PID}" -n ip -4 -o addr show eth0 | awk '{print $4}' | cut -d/ -f1)
curl http://${CELL_IP}:8080/

You should see the HTML from the manifest.

Containerd namespace

In the default bootstrap, the containerd namespace for realm=default is kukeon-default. If your realm is named differently, replace the namespace accordingly. Older layouts used kukeon.io as the default namespace.

5. Tear down

sudo kuke delete cell hello-world \
    --realm default --space default --stack default --cascade

--cascade removes every container in the cell along with the cell itself.

What you just did

  • Applied a YAML manifest — one cell, one container.
  • Watched Kukeon create a cgroup under /sys/fs/cgroup/kukeon/default/default/default/hello-world/, a network namespace, a veth into the default bridge, and a containerd container in the kukeon-default namespace.
  • Reached the container's IP from the host because your host shares the same layer-2 segment as the bridge.

Next steps