{"version": 2, "width": 155, "height": 42, "timestamp": 1791319694, "idle_time_limit": 3.0, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
[0.756746, "o", "\r\n===========================================================================================================\r\n"]
[0.757113, "o", "   Ironvisor  --  a Type-1 hypervisor in Rust: one microVM per Kubernetes pod\r\n   iron-kernel is VM 0 (the node's management VM) and the kernel of every pod.\r\n   Real kube-apiserver + scheduler + kubelet + kube-proxy v1.35.9; containerd 2.3 with our runtime shim.\r\n\r\n"]
[0.757446, "o", "===========================================================================================================\r\n"]
[3.757745, "o", "\r\n>>> 1. The node: a real kubelet, registered with a real API server. Pods that ask for\r\n    runtimeClassName: ironvisor are handed to Ironvisor's containerd shim.\r\n\r\nhost$ kubectl get nodes\r\n"]
[3.77748, "o", "NAME          STATUS   ROLES    AGE   VERSION\r\nironvisor-1   Ready    <none>   8d    v1.35.9\r\n"]
[4.779419, "o", "\r\nhost$ kubectl get runtimeclass\r\n"]
[4.798999, "o", "NAME        HANDLER     AGE\r\nironvisor   ironvisor   8d\r\n"]
[7.801819, "o", "\r\n>>> 2. A Deployment (replicas=2) of stock nginx:alpine, and a ClusterIP Service in front of it.\r\n\r\nhost$ cat web.yaml\r\n"]
[7.801943, "o", "apiVersion: apps/v1\r\n"]
[7.802034, "o", "kind: Deployment\r\n"]
[7.802134, "o", "metadata: {name: web}\r\nspec:\r\n  replicas: 2\r\n"]
[7.802256, "o", "  selector: {matchLabels: {app: web}}\r\n  template:\r\n    metadata: {labels: {app: web}}\r\n    spec:\r\n      runtimeClassName: ironvisor\r\n      containers:\r\n      - name: nginx\r\n"]
[7.803117, "o", "        image: docker.io/library/nginx:alpine\r\n        command: [\"sh\", \"-c\", \"echo \\\"served by pod $(hostname)\\\" > /usr/share/nginx/html/index.html; exec nginx -g 'daemon off;'\"]\r\n        ports: [{containerPort: 80}]\r\n        readinessProbe: {httpGet: {path: /, port: 80}, periodSeconds: 2}\r\n        resources: {limits: {memory: 128Mi, cpu: \"1\"}}\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata: {name: web}\r\nspec:\r\n  selector: {app: web}\r\n"]
[7.804558, "o", "  ports: [{port: 80, targetPort: 80}]\r\n"]
[7.804715, "o", "\r\nhost$ kubectl apply -f web.yaml\r\n"]
[7.848202, "o", "deployment.apps/web created\r\n"]
[7.851075, "o", "service/web created\r\n"]
[7.852719, "o", "\r\nhost$ kubectl rollout status deploy/web\r\n"]
[7.876335, "o", "Waiting for deployment \"web\" rollout to finish: 0 of 2 updated replicas are available...\r\n"]
[10.921075, "o", "Waiting for deployment \"web\" rollout to finish: 1 of 2 updated replicas are available...\r\n"]
[10.922618, "o", "deployment \"web\" successfully rolled out\r\n"]
[10.923775, "o", "\r\n"]
[10.923999, "o", "host$ kubectl get pods -o wide\r\n"]
[10.943479, "o", "NAME                  READY   STATUS    RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES\r\nweb-5d448d4c6-7mgkz   1/1     Running   0          3s    10.77.0.139   ironvisor-1   <none>           <none>\r\nweb-5d448d4c6-vx4qp   1/1     Running   0          3s    10.77.0.140   ironvisor-1   <none>           <none>\r\n"]
[14.944336, "o", "\r\n>>> 3. Each pod is its own microVM. The hypervisor's own console, while those pods started:\r\n"]
[15.946548, "o", "    | VM 1: private window: gpa [0, 0x8000000) -> host [0x71e00000, 0x79e00000)\r\n    | MGMT: HC_VM_CREATE created pod VM 1 (iron-kernel, 128 MiB window, 1 vCPU, idle)\r\n    | VM 2: private window: gpa [0, 0x8000000) -> host [0x69c00000, 0x71c00000)\r\n    | MGMT: HC_VM_CREATE created pod VM 2 (iron-kernel, 128 MiB window, 1 vCPU, idle)\r\n"]
[15.947222, "o", "    | MGMT: HC_VM_START — pod VM 1 dedicated to host core 1; it begins running shortly (rootfs 1147640 bytes, block image 0 bytes)\r\n    | MGMT: HC_VM_START — pod VM 2 dedicated to host core 2; it begins running shortly (rootfs 1147640 bytes, block image 0 bytes)\r\n"]
[15.948033, "o", "    | [vm1] container 1 (boot): hostname web-5d448d4c6-7mgkz\r\n"]
[15.948087, "o", "    | [vm2] container 1 (boot): hostname web-5d448d4c6-vx4qp\r\n"]
[18.950893, "o", "\r\n    Inside each pod: its own kernel (iron-kernel, not the host's Linux), its own RAM and CPUs:\r\n"]
[18.978245, "o", "\r\nhost$ kubectl exec web-5d448d4c6-7mgkz -- sh -c 'uname -sv; nproc; grep MemTotal /proc/meminfo'\r\n"]
[19.043847, "o", "Linux #1 SMP iron-kernel\r\n1\r\nMemTotal:      130048 kB\r\n"]
[19.684274, "o", "\r\nhost$ kubectl exec web-5d448d4c6-vx4qp -- sh -c 'uname -sv; nproc; grep MemTotal /proc/meminfo'\r\n"]
[19.741329, "o", "Linux #1 SMP iron-kernel\r\n1\r\nMemTotal:      130048 kB\r\n"]
[24.76102, "o", "\r\n>>> 4. kube-proxy (nftables mode) programs the Service. 24 requests to ClusterIP 10.96.213.33 from the node:\r\n\r\nhost$ nft list table ip kube-proxy | grep -c 10.96.213.33\r\n"]
[24.766804, "o", "3\r\n"]
[24.766812, "o", "\r\n"]
[24.766866, "o", "host$ for i in $(seq 24); do curl -s -m 5 http://10.96.213.33/; done | sort | uniq -c\r\n"]
[30.697745, "o", "     11 served by pod web-5d448d4c6-7mgkz\r\n     13 served by pod web-5d448d4c6-vx4qp\r\n"]
[34.700391, "o", "\r\n>>> 5. Stock postgres:16-alpine (unmodified, its own entrypoint) in a pod, its data on a pod volume.\r\n\r\nhost$ cat pg.yaml\r\n"]
[34.700495, "o", "apiVersion: v1\r\nkind: Pod\r\nmetadata:\r\n  name: pg\r\n"]
[34.70055, "o", "  annotations:\r\n    io.ironvisor/image-mode: auto          # the stock image is ~370 MB: serve it from the image store\r\n    io.ironvisor/emptydir-sizes: pgdata=1Gi\r\nspec:\r\n"]
[34.701018, "o", "  runtimeClassName: ironvisor\r\n  containers:\r\n  - name: postgres\r\n    image: docker.io/library/postgres:16-alpine\r\n    env:\r\n    - {name: POSTGRES_PASSWORD, value: demo}\r\n    - {name: PGDATA, value: /var/lib/postgresql/data/pgdata}\r\n    # TCP only: a Unix-domain socket cannot be created in a pod's added container\r\n    # yet (an iron-kernel issue), and the stock entrypoint's temporary server\r\n    # listens on nothing else, so initdb runs first, then the stock entrypoint.\r\n    command: [sh, -c]\r\n    args:\r\n    - |\r\n      mkdir -p \"$PGDATA\" && chown postgres \"$PGDATA\" && chmod 700 \"$PGDATA\"\r\n      [ -s \"$PGDATA/PG_VERSION\" ] || gosu postgres initdb -D \"$PGDATA\" >/dev/null\r\n      exec docker-entrypoint.sh postgres -c unix_socket_directories=\r\n"]
[34.703457, "o", "    readinessProbe: {exec: {command: [pg_isready, -h, 127.0.0.1, -U, postgres]}, periodSeconds: 3}\r\n    resources: {limits: {memory: 512Mi, cpu: \"1\"}}\r\n    volumeMounts: [{name: pgdata, mountPath: /var/lib/postgresql/data}]\r\n  volumes:\r\n  - {name: pgdata, emptyDir: {}}                     # a disk emptyDir: a PV block volume\r\n"]
[34.70441, "o", "\r\nhost$ kubectl apply -f pg.yaml && kubectl wait --for=condition=Ready pod/pg\r\n"]
[34.753945, "o", "pod/pg created\r\n"]
[39.763753, "o", "pod/pg condition met\r\n"]
[39.764682, "o", "\r\nhost$ kubectl get pods -o wide\r\n"]
[39.788226, "o", "NAME                  READY   STATUS    RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES\r\npg                    1/1     Running   0          5s    10.77.0.141   ironvisor-1   <none>           <none>\r\nweb-5d448d4c6-7mgkz   1/1     Running   0          32s   10.77.0.139   ironvisor-1   <none>           <none>\r\nweb-5d448d4c6-vx4qp   1/1     Running   0          32s   10.77.0.140   ironvisor-1   <none>           <none>\r\n"]
[39.789409, "o", "\r\n"]
[39.789433, "o", "    The hypervisor and the pod's kernel, while it started:\r\n"]
[39.790538, "o", "    | MGMT: HC_VM_CREATE created pod VM 3 (iron-kernel, 512 MiB window, 1 vCPU, idle)\r\n"]
[39.79057, "o", "    | MGMT: HC_VM_START — pod VM 3 dedicated to host core 3; it begins running shortly (rootfs 1147624 bytes, block image 0 bytes)\r\n"]
[39.791489, "o", "    | [vm3] mounts: volume pgdata = /dev/pvblk2\r\n"]
[39.792622, "o", "    | [vm3] PVBLKQ: image device 0 (DEV_IMAGE, 361500 KiB, 90375 x 4096 B blocks): ext2 read-only through the queue, mounted once\r\n"]
[42.798647, "o", "\r\nhost$ kubectl exec pg -- df -h /var/lib/postgresql/data\r\n"]
[42.930339, "o", "Filesystem                Size      Used Available Use% Mounted on\r\nvolume:pgdata             1.0G    102.6M    870.2M  11% /var/lib/postgresql/data\r\n"]
[43.816937, "o", "\r\nhost$ kubectl exec pg -- psql -h 127.0.0.1 -U postgres -c '<create a table, insert 1000 rows, count them>'\r\n"]
[44.030682, "o", "CREATE TABLE\r\nINSERT 0 1000\r\n rows |  size  \r\n------+--------\r\n 1000 | 128 kB\r\n(1 row)\r\n\r\n      server      \r\n------------------\r\n PostgreSQL 16.15\r\n(1 row)\r\n\r\n"]
[47.867599, "o", "\r\n===========================================================================================================\r\n   Scoreboard (computed from what happened above)\r\n\r\n"]
[47.892054, "o", "   a real kubelet + API server: node Ready, RuntimeClass ironvisor                  PASS\r\n"]
[47.919409, "o", "   Deployment web: 2/2 replicas Running                                             PASS\r\n"]
[47.919508, "o", "   one microVM per pod: 2 pod VMs created for 2 web pods, 1 for pg                  PASS\r\n"]
[47.919735, "o", "   ClusterIP Service via kube-proxy: 24/24 answered, by 2 distinct pods             PASS\r\n"]
[47.920026, "o", "   stock postgres:16-alpine on a pod volume: 1000 rows written and read back        PASS\r\n"]
[47.920242, "o", "   no INVARIANT / ISOLATION line on the hypervisor console                          PASS\r\n\r\n"]
[47.920374, "o", "   3 pods, 3 microVMs, one iron-kernel each; VM 0 runs controld, which the shim drives.\r\n\r\n"]
[47.920611, "o", "===========================================================================================================\r\n"]
[51.921189, "o", "\r\n### DEMO COMPLETE ###\r\n"]
