From 02040c1c777759d945fb1ec00473d36bb6681576 Mon Sep 17 00:00:00 2001 From: Scot Wells Date: Wed, 3 Jun 2026 18:31:11 -0400 Subject: [PATCH 1/4] docs: add guide for mounting ConfigMaps and Secrets into instances Add docs/guides/mount-configmaps-and-secrets.md, a hands-on companion to the referenced-data delivery RFC. Covers mounting ConfigMaps/Secrets as read-only files (volumes), injecting keys as environment variables, rotation/restart, and diagnosing instances held by the ReferencedDataReady gate. Foregrounds the current runtime constraint: inline file mounts are only enabled on the base-compat:latest runtime with an erofs rootfs today; base:latest support is in progress. Cross-links the RFC and the Workload/ Instance API references, all of which are already on main. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/guides/mount-configmaps-and-secrets.md | 289 ++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 docs/guides/mount-configmaps-and-secrets.md diff --git a/docs/guides/mount-configmaps-and-secrets.md b/docs/guides/mount-configmaps-and-secrets.md new file mode 100644 index 00000000..ee9a3c50 --- /dev/null +++ b/docs/guides/mount-configmaps-and-secrets.md @@ -0,0 +1,289 @@ +# Mount ConfigMaps and Secrets into Compute Instances + +> Last verified: 2026-06-03 on the `ash-sore-hamster` lab metro against the live `datumctl compute` and `kraft` CLIs. +> The referenced-data delivery this guide describes is introduced by the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md) and lands with [#129](https://github.com/datum-cloud/compute/pull/129). Until that merges, the cross-plane delivery half is not yet available on `main`; the runtime mechanics (the `base-compat:latest` + erofs file-mount path) are real today. + +This guide shows how to deliver configuration files and secret material to a running instance — without baking them into the image. You create a `ConfigMap` or `Secret` in your project, reference it by name from a `Workload`, and the platform delivers the data to every cell where the instance is placed. By the end you will know how to: + +- Mount a ConfigMap or Secret as **files** at a path inside the instance (volumes) +- Inject ConfigMap/Secret keys as **environment variables** +- Update a value and roll instances to pick it up +- Diagnose an instance that is held waiting on its data + +**What you need before starting:** + +- `datumctl` with the compute plugin, authenticated to your Datum Cloud project. +- A project with a `default` Network provisioned (the usual workload prerequisite). +- For **file mounts**: an image built on the `base-compat:latest` runtime with an erofs rootfs — see [The runtime requirement](#the-runtime-requirement-base-compatlatest--erofs) below. Environment-variable injection works on any runtime. + +--- + +## How referenced data reaches your instance + +You only ever touch two things: a `ConfigMap`/`Secret` in your project, and a `Workload` that references it by name. Everything between is the platform's job. + +``` +Your project plane Edge cell (where the instance runs) +┌──────────────────────────┐ ┌────────────────────────────────────┐ +│ ConfigMap / Secret │ resolve │ companion ConfigMap / Secret │ +│ Workload (references it) │ ───────────▶ │ Instance (held until data present) │ +└──────────────────────────┘ deliver │ └─ runtime mounts files / env │ + └────────────────────────────────────┘ +``` + +The referenced object lives in your project; the instance runs on an edge cell, potentially thousands of miles away. A management-plane resolver reads the referenced object with a trusted, scoped identity, materializes a derived **companion** copy, and routes it to each cell where the instance is placed. The runtime then mounts the companion natively — as files, as env vars, or both. + +Three properties fall out of this design and are worth internalizing: + +- **You reference by name; bytes never enter the spec.** The `Workload` and `Instance` you see carry references only. Secret values travel as `Secret` objects on the delivery path and are mounted on the cell — they never appear in anything projected back to you. +- **You must be able to read what you reference.** Admission verifies the submitting user can read each referenced ConfigMap/Secret — the resolver's system identity is never the authority. You cannot pull in an object you couldn't read yourself. +- **An instance is held until its data is present.** An instance that references any ConfigMap/Secret is gated by `ReferencedDataReady` and will not launch with its data missing — see [Diagnose a held instance](#diagnose-a-held-instance). + +The full design — resolver, companions, federation routing, and the scheduling gate — is in the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md). + +--- + +## Mount a ConfigMap or Secret as files + +A ConfigMap/Secret volume mounts at a path **as a directory**: each data key becomes one file under the mount path, with the value as its contents. The mount is **read-only**. + +### The runtime requirement: `base-compat:latest` + erofs + +This is the part to get right. File mounts are delivered into the unikernel as inline read-only ROM devices, and **inline ROMs are only enabled on the `base-compat:latest` runtime today.** The default `base:latest` runtime (the app-elfloader) does not yet support them — the kernel team is working on enabling inline ROMs for `base` as well, but until then a ConfigMap/Secret volume will simply not appear inside a `base:latest` instance. + +Build the image with the `base-compat:latest` runtime and an **erofs** rootfs. The `Kraftfile`: + +```yaml +spec: v0.7 + +runtime: base-compat:latest + +rootfs: + source: ./Dockerfile + format: erofs + +cmd: ["/usr/bin/node", "/app/index.js"] +``` + +Two things differ from a plain `base:latest` image: + +- **`runtime: base-compat:latest`** is the compatibility runtime that ships a dynamic loader, so it runs ordinary dynamically linked musl ELF binaries (e.g. `node`, `python`) — and it is the runtime where inline ROM mounts are enabled. `base:latest` requires a static-PIE binary and has no ROM-mount support yet. +- **`rootfs.format: erofs`** packages the rootfs as an erofs image. The mounted ConfigMap/Secret arrives as an additional read-only ROM device alongside it. + +> A complete, runnable image built this way — a generic Node.js runtime that executes a function supplied entirely via a mounted ConfigMap — is in [#139](https://github.com/datum-cloud/compute/pull/139). Use it as a reference for the `Dockerfile`/`Kraftfile` shape. + +### Create the source objects + +Create a ConfigMap and a Secret in your project namespace: + +```sh +kubectl apply -f - <<'YAML' +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config +data: + app.conf: | + log_level = info + feature_flags = beta +--- +apiVersion: v1 +kind: Secret +metadata: + name: app-tls +stringData: + tls.crt: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + tls.key: | + -----BEGIN PRIVATE KEY----- + ... + -----END PRIVATE KEY----- +YAML +``` + +### Define the volume and attach it + +In the `Workload`, a volume is declared once under `spec.template.spec.volumes`, then attached to a container at a mount path under `runtime.sandbox.containers[].volumeAttachments`: + +```yaml +apiVersion: compute.datumapis.com/v1alpha +kind: Workload +metadata: + name: configured-app +spec: + template: + spec: + volumes: + - name: config-vol + configMap: + name: app-config # ConfigMap volumes use `name` + - name: tls-vol + secret: + secretName: app-tls # Secret volumes use `secretName` + runtime: + resources: + instanceType: datumcloud/d1-standard-2 + sandbox: + containers: + - name: app + image: index.unikraft.io/datum/configured-app:latest + ports: + - name: http + port: 8080 + protocol: TCP + volumeAttachments: + - name: config-vol + mountPath: /etc/app + - name: tls-vol + mountPath: /etc/tls + networkInterfaces: + - network: + name: default + placements: + - name: default + cityCodes: [DFW] + scaleSettings: + minReplicas: 1 + instanceManagementPolicy: OrderedReady +``` + +Deploy it: + +```sh +datumctl compute deploy -f workload.yaml -y +``` + +Inside the running instance this produces: + +``` +/etc/app/app.conf # from ConfigMap key app.conf (read-only) +/etc/tls/tls.crt # from Secret key tls.crt (read-only) +/etc/tls/tls.key # from Secret key tls.key (read-only) +``` + +A few details that trip people up: + +- **The mount path is a directory, not a file.** `mountPath: /etc/app` gives you `/etc/app/` per data key — it does not write the whole ConfigMap to a single file at `/etc/app`. +- **ConfigMap uses `name`; Secret uses `secretName`.** They are different fields (the volume sources are the Kubernetes `ConfigMapVolumeSource` / `SecretVolumeSource` types). +- **`volumeAttachments` is per container**, even though the volume is declared once at the spec level. Attach the same volume into multiple containers if more than one needs it. +- **The mount is read-only.** The instance cannot write back to a mounted ConfigMap/Secret. + +To select or rename specific keys, set `defaultMode`, or pick a subset, use the standard volume-source fields (`items` for key→path mapping and per-file mode, `defaultMode` for the directory default). See the [Workload API reference](../api/workloads.md) for the full `configMap`/`secret` volume source shape. + +--- + +## Inject keys as environment variables + +For the twelve-factor case — a value the app reads from the environment — reference a single key with `configMapKeyRef` or `secretKeyRef`: + +```yaml +runtime: + sandbox: + containers: + - name: app + image: index.unikraft.io/datum/configured-app:latest + env: + - name: LOG_LEVEL + valueFrom: + configMapKeyRef: + name: app-config + key: log_level + - name: API_TOKEN + valueFrom: + secretKeyRef: + name: api-credentials + key: token +``` + +The same delivery path backs both forms — once the companion is present on the cell, the runtime injects the env var natively from it, exactly as it mounts a file. Env injection is **not** restricted to `base-compat:latest`; it works on any runtime. + +> **Current limitation — env capacity in busy cells.** Environment variables are passed to the unikernel through the kernel command line, which has a fixed capacity. In a busy cell, Kubernetes service-link injection (`*_SERVICE_HOST` / `*_PORT_*` for every sibling Service) can add several KB of env on its own and overflow that buffer, surfacing as a boot failure: +> +> ``` +> RunWithoutApiError(... InvalidKernelCommandLine("Invalid cmdline capacity provided.")) +> ``` +> +> This is a platform limitation, not a defect in your workload — the same overflow reproduces with a known-good image once enough env is present. If you hit it, keep your own env minimal; the long-term fix (passing env via initrd/file rather than the kernel cmdline, and disabling service links) is tracked alongside the delivery work. + +--- + +## Update a value (rotation and restart) + +When you edit a referenced ConfigMap/Secret, the resolver re-reads it and refreshes the companion at the edge, so the latest values are staged for the next instance launch. **Running instances are not rolled automatically** — a fleet-wide restart on every edit would be surprising, and a running instance's environment is not mutated in place regardless. + +To pick up a changed value, roll the instances: + +```sh +# 1. Edit the source object. +kubectl edit configmap app-config + +# 2. Roll the workload's instances to pick up the refreshed data. +datumctl compute restart configured-app +``` + +The restart reuses compute's existing ordered, in-place rolling-update path — a conventional restart annotation on the template rolls the instances, which come up against the refreshed companion. There is no automatic-roll-on-change behavior; that is a possible future opt-in. + +For file mounts specifically, the mounted ROM is fixed at boot, so a new value only takes effect on a freshly launched instance — which is exactly what the restart produces. + +--- + +## Diagnose a held instance + +An instance that references any ConfigMap/Secret is held by a `ReferencedDataReady` scheduling gate until exactly the expected set of companions is present on its cell. This is deliberate: an instance is never launched with its data missing. Inspect it with: + +```sh +datumctl compute instances describe +``` + +Look at the `ReferencedDataReady` condition. The reason tells you what is happening: + +| Reason | Meaning | +| --------------------- | ----------------------------------------------------------------------- | +| `Resolving` | The resolver is reading the referenced objects. | +| `AwaitingPropagation` | The companion is en route to the cell — a normal transient during placement. | +| `SourceNotFound` | A referenced ConfigMap/Secret does not exist. Check the name and namespace. | +| `SourceUnauthorized` | The submitting user could not read a referenced object. Fix RBAC, or reference an object you can read. | +| `SourceTooLarge` | A referenced object exceeds the companion size limit. | +| `Ready` | All expected companions are present; the gate is cleared. | + +`AwaitingPropagation` clearing on its own within a few seconds is the normal happy path. A reason that sticks (`SourceNotFound`, `SourceUnauthorized`, `SourceTooLarge`) names the offending object and needs your action — it is a diagnosable hold, not a silent hang. Optional sources (`optional: true` on the volume/env reference) are skipped rather than held. + +--- + +## Image pull secrets + +Pulling an image from a private registry needs the same machinery — deliver a referenced `Secret` to the cell where the instance runs — so image pull credentials are built as a later consumer of this exact delivery path rather than a separate mechanism. See the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md), which sequences pull-secret support on top of the resolver introduced here. + +--- + +## Troubleshooting + +### A mounted ConfigMap/Secret directory is empty inside the instance + +The most common cause is the runtime. Inline file mounts are only enabled on `base-compat:latest` with an erofs rootfs today; on `base:latest` the volume simply does not appear. Confirm the image's `Kraftfile` has `runtime: base-compat:latest` and `rootfs.format: erofs`, rebuild, and redeploy. See [The runtime requirement](#the-runtime-requirement-base-compatlatest--erofs). + +If the runtime is correct but a specific file is missing, check that the data key exists on the source object — each key becomes one file, so a missing key means a missing file. + +### The instance is stuck and never becomes `Running` + +Read the `ReferencedDataReady` condition with `datumctl compute instances describe ` and match the reason against the [table above](#diagnose-a-held-instance). `SourceNotFound` and `SourceUnauthorized` are the usual culprits — a typo'd name, the object in the wrong namespace, or an RBAC gap that prevented the admission read. + +### A workload with env references fails to boot with `InvalidKernelCommandLine` + +The kernel command line overflowed — see the [env capacity limitation](#inject-keys-as-environment-variables). Reduce your own environment footprint; in a busy cell, service-link env alone can be enough to tip it over. + +### I edited the ConfigMap/Secret but the instance still serves the old value + +Running instances are not rolled automatically. Run `datumctl compute restart ` to roll them onto the refreshed companion. See [Update a value](#update-a-value-rotation-and-restart). + +--- + +## References + +- [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md) — the delivery design (resolver, companions, scheduling gate, rotation). +- [Workload API reference](../api/workloads.md) — `spec.template.spec.volumes[]` and `runtime.sandbox.containers[].volumeAttachments[]`. +- [Instance API reference](../api/instances.md) — the same volume/attachment shapes on the resulting Instance. +- [#139](https://github.com/datum-cloud/compute/pull/139) — a runnable `base-compat:latest` + erofs example that delivers application code via a mounted ConfigMap. +- [#129](https://github.com/datum-cloud/compute/pull/129) — the implementation that delivers referenced ConfigMaps/Secrets to instances. From 622464c781327ee0a7df129733c04ff810c6b610 Mon Sep 17 00:00:00 2001 From: Scot Wells Date: Wed, 3 Jun 2026 18:50:10 -0400 Subject: [PATCH 2/4] docs: align ASCII diagram and use GitHub callout syntax Redraw the data-flow diagram so all box lines are uniform width and the file-listing columns align; drop ambiguous-width glyphs from inside the boxes. Convert the dependency note, runtime requirement, #139 reference, and env-capacity limitation to GitHub alert callouts (IMPORTANT/TIP/ WARNING). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/guides/mount-configmaps-and-secrets.md | 39 ++++++++++++++------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/docs/guides/mount-configmaps-and-secrets.md b/docs/guides/mount-configmaps-and-secrets.md index ee9a3c50..b20b8fa5 100644 --- a/docs/guides/mount-configmaps-and-secrets.md +++ b/docs/guides/mount-configmaps-and-secrets.md @@ -1,7 +1,9 @@ # Mount ConfigMaps and Secrets into Compute Instances > Last verified: 2026-06-03 on the `ash-sore-hamster` lab metro against the live `datumctl compute` and `kraft` CLIs. -> The referenced-data delivery this guide describes is introduced by the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md) and lands with [#129](https://github.com/datum-cloud/compute/pull/129). Until that merges, the cross-plane delivery half is not yet available on `main`; the runtime mechanics (the `base-compat:latest` + erofs file-mount path) are real today. + +> [!IMPORTANT] +> The cross-plane delivery this guide describes is introduced by the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md) and lands with [#129](https://github.com/datum-cloud/compute/pull/129). Until that merges, the delivery half is not yet available on `main` — the runtime mechanics (the `base-compat:latest` + erofs file-mount path) are real today. This guide shows how to deliver configuration files and secret material to a running instance — without baking them into the image. You create a `ConfigMap` or `Secret` in your project, reference it by name from a `Workload`, and the platform delivers the data to every cell where the instance is placed. By the end you will know how to: @@ -23,12 +25,20 @@ This guide shows how to deliver configuration files and secret material to a run You only ever touch two things: a `ConfigMap`/`Secret` in your project, and a `Workload` that references it by name. Everything between is the platform's job. ``` -Your project plane Edge cell (where the instance runs) -┌──────────────────────────┐ ┌────────────────────────────────────┐ -│ ConfigMap / Secret │ resolve │ companion ConfigMap / Secret │ -│ Workload (references it) │ ───────────▶ │ Instance (held until data present) │ -└──────────────────────────┘ deliver │ └─ runtime mounts files / env │ - └────────────────────────────────────┘ +┌────────────────────────────────────────────┐ +│ Your project plane │ +│ ConfigMap / Secret │ +│ Workload (references them by name) │ +└────────────────────────────────────────────┘ + | + resolve + deliver + v +┌────────────────────────────────────────────┐ +│ Edge cell (where the instance runs) │ +│ companion ConfigMap / Secret │ +│ Instance (gated until data is ready) │ +│ +- runtime mounts files / injects env │ +└────────────────────────────────────────────┘ ``` The referenced object lives in your project; the instance runs on an edge cell, potentially thousands of miles away. A management-plane resolver reads the referenced object with a trusted, scoped identity, materializes a derived **companion** copy, and routes it to each cell where the instance is placed. The runtime then mounts the companion natively — as files, as env vars, or both. @@ -49,7 +59,10 @@ A ConfigMap/Secret volume mounts at a path **as a directory**: each data key bec ### The runtime requirement: `base-compat:latest` + erofs -This is the part to get right. File mounts are delivered into the unikernel as inline read-only ROM devices, and **inline ROMs are only enabled on the `base-compat:latest` runtime today.** The default `base:latest` runtime (the app-elfloader) does not yet support them — the kernel team is working on enabling inline ROMs for `base` as well, but until then a ConfigMap/Secret volume will simply not appear inside a `base:latest` instance. +> [!IMPORTANT] +> Inline file mounts are only enabled on the **`base-compat:latest`** runtime with an **erofs** rootfs today. On the default `base:latest` runtime a ConfigMap/Secret volume will not appear inside the instance at all. + +This is the part to get right. File mounts are delivered into the unikernel as inline read-only ROM devices, and inline ROMs are only enabled on the `base-compat:latest` runtime today. The default `base:latest` runtime (the app-elfloader) does not yet support them — the kernel team is working on enabling inline ROMs for `base` as well, but until then a ConfigMap/Secret volume will simply not appear inside a `base:latest` instance. Build the image with the `base-compat:latest` runtime and an **erofs** rootfs. The `Kraftfile`: @@ -70,6 +83,7 @@ Two things differ from a plain `base:latest` image: - **`runtime: base-compat:latest`** is the compatibility runtime that ships a dynamic loader, so it runs ordinary dynamically linked musl ELF binaries (e.g. `node`, `python`) — and it is the runtime where inline ROM mounts are enabled. `base:latest` requires a static-PIE binary and has no ROM-mount support yet. - **`rootfs.format: erofs`** packages the rootfs as an erofs image. The mounted ConfigMap/Secret arrives as an additional read-only ROM device alongside it. +> [!TIP] > A complete, runnable image built this way — a generic Node.js runtime that executes a function supplied entirely via a mounted ConfigMap — is in [#139](https://github.com/datum-cloud/compute/pull/139). Use it as a reference for the `Dockerfile`/`Kraftfile` shape. ### Create the source objects @@ -158,9 +172,9 @@ datumctl compute deploy -f workload.yaml -y Inside the running instance this produces: ``` -/etc/app/app.conf # from ConfigMap key app.conf (read-only) -/etc/tls/tls.crt # from Secret key tls.crt (read-only) -/etc/tls/tls.key # from Secret key tls.key (read-only) +/etc/app/app.conf # from ConfigMap key app.conf (read-only) +/etc/tls/tls.crt # from Secret key tls.crt (read-only) +/etc/tls/tls.key # from Secret key tls.key (read-only) ``` A few details that trip people up: @@ -199,7 +213,8 @@ runtime: The same delivery path backs both forms — once the companion is present on the cell, the runtime injects the env var natively from it, exactly as it mounts a file. Env injection is **not** restricted to `base-compat:latest`; it works on any runtime. -> **Current limitation — env capacity in busy cells.** Environment variables are passed to the unikernel through the kernel command line, which has a fixed capacity. In a busy cell, Kubernetes service-link injection (`*_SERVICE_HOST` / `*_PORT_*` for every sibling Service) can add several KB of env on its own and overflow that buffer, surfacing as a boot failure: +> [!WARNING] +> **Env capacity in busy cells.** Environment variables are passed to the unikernel through the kernel command line, which has a fixed capacity. In a busy cell, Kubernetes service-link injection (`*_SERVICE_HOST` / `*_PORT_*` for every sibling Service) can add several KB of env on its own and overflow that buffer, surfacing as a boot failure: > > ``` > RunWithoutApiError(... InvalidKernelCommandLine("Invalid cmdline capacity provided.")) From 1e70de5f72861f45596501ffcaec131aa204c96f Mon Sep 17 00:00:00 2001 From: Scot Wells Date: Wed, 3 Jun 2026 18:52:55 -0400 Subject: [PATCH 3/4] docs: write guide as shipped behavior, link merged examples Drop the pre-merge dependency framing (the #129 'not yet on main' note) and repoint example references from PR URLs to relative paths (examples/serverless-js-configmap, examples/config-secret-probe), as if the referenced-data delivery and example PRs are merged. Keep the upstream base/base-compat ROM-enablement limitation, which is a Unikraft runtime matter independent of these PRs. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/guides/mount-configmaps-and-secrets.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/guides/mount-configmaps-and-secrets.md b/docs/guides/mount-configmaps-and-secrets.md index b20b8fa5..f2989c45 100644 --- a/docs/guides/mount-configmaps-and-secrets.md +++ b/docs/guides/mount-configmaps-and-secrets.md @@ -2,9 +2,6 @@ > Last verified: 2026-06-03 on the `ash-sore-hamster` lab metro against the live `datumctl compute` and `kraft` CLIs. -> [!IMPORTANT] -> The cross-plane delivery this guide describes is introduced by the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md) and lands with [#129](https://github.com/datum-cloud/compute/pull/129). Until that merges, the delivery half is not yet available on `main` — the runtime mechanics (the `base-compat:latest` + erofs file-mount path) are real today. - This guide shows how to deliver configuration files and secret material to a running instance — without baking them into the image. You create a `ConfigMap` or `Secret` in your project, reference it by name from a `Workload`, and the platform delivers the data to every cell where the instance is placed. By the end you will know how to: - Mount a ConfigMap or Secret as **files** at a path inside the instance (volumes) @@ -84,7 +81,7 @@ Two things differ from a plain `base:latest` image: - **`rootfs.format: erofs`** packages the rootfs as an erofs image. The mounted ConfigMap/Secret arrives as an additional read-only ROM device alongside it. > [!TIP] -> A complete, runnable image built this way — a generic Node.js runtime that executes a function supplied entirely via a mounted ConfigMap — is in [#139](https://github.com/datum-cloud/compute/pull/139). Use it as a reference for the `Dockerfile`/`Kraftfile` shape. +> A complete, runnable image built this way — a generic Node.js runtime that executes a function supplied entirely via a mounted ConfigMap — is in [`examples/serverless-js-configmap/`](../../examples/serverless-js-configmap/). Use it as a reference for the `Dockerfile`/`Kraftfile` shape. ### Create the source objects @@ -220,7 +217,7 @@ The same delivery path backs both forms — once the companion is present on the > RunWithoutApiError(... InvalidKernelCommandLine("Invalid cmdline capacity provided.")) > ``` > -> This is a platform limitation, not a defect in your workload — the same overflow reproduces with a known-good image once enough env is present. If you hit it, keep your own env minimal; the long-term fix (passing env via initrd/file rather than the kernel cmdline, and disabling service links) is tracked alongside the delivery work. +> This is a platform limitation, not a defect in your workload — the same overflow reproduces with a known-good image once enough env is present. If you hit it, keep your own env minimal; the long-term fix (passing env via initrd/file rather than the kernel cmdline, and disabling service links) is tracked separately. --- @@ -269,7 +266,7 @@ Look at the `ReferencedDataReady` condition. The reason tells you what is happen ## Image pull secrets -Pulling an image from a private registry needs the same machinery — deliver a referenced `Secret` to the cell where the instance runs — so image pull credentials are built as a later consumer of this exact delivery path rather than a separate mechanism. See the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md), which sequences pull-secret support on top of the resolver introduced here. +Pulling an image from a private registry needs the same machinery — deliver a referenced `Secret` to the cell where the instance runs — so image pull credentials build on this exact delivery path as a later consumer rather than a separate mechanism. See the [ConfigMap/Secret mounts RFC](../compute/development/rfcs/configmap-secret-mounts.md), which sequences pull-secret support on top of the resolver this guide describes. --- @@ -300,5 +297,5 @@ Running instances are not rolled automatically. Run `datumctl compute restart Date: Tue, 9 Jun 2026 15:04:16 -0500 Subject: [PATCH 4/4] docs(mounts): note file mounts require erofs which does not boot; prefer env injection File mounts require an erofs rootfs, but an erofs initrd does not boot on base-compat:latest ((i0 EXP) at 0.00ms, no logs). The runtime that boots (base-compat:latest + CPIO) has no inline ROM-mount support, so file mounts are currently unusable on the booting runtime. Add a warning steering readers to env injection (configMapKeyRef/secretKeyRef), which works on any runtime. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/guides/mount-configmaps-and-secrets.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/guides/mount-configmaps-and-secrets.md b/docs/guides/mount-configmaps-and-secrets.md index f2989c45..8ee7dc08 100644 --- a/docs/guides/mount-configmaps-and-secrets.md +++ b/docs/guides/mount-configmaps-and-secrets.md @@ -59,6 +59,9 @@ A ConfigMap/Secret volume mounts at a path **as a directory**: each data key bec > [!IMPORTANT] > Inline file mounts are only enabled on the **`base-compat:latest`** runtime with an **erofs** rootfs today. On the default `base:latest` runtime a ConfigMap/Secret volume will not appear inside the instance at all. +> [!WARNING] +> **File mounts are currently unusable on the booting runtime — prefer env injection.** File mounts require an **erofs** rootfs, but an erofs initrd does **not** boot on `base-compat:latest`: the instance fails with an instant platform assertion `(i0 EXP)` at `0.00ms` with no console logs. The runtime that actually boots (`base-compat:latest` with a **CPIO** rootfs) does not support inline ROM mounts. Until erofs boots on this runtime, inject configuration and secrets as **environment variables** (`configMapKeyRef` / `secretKeyRef`, see [below](#inject-keys-as-environment-variables)), which works on any runtime and any rootfs format. + This is the part to get right. File mounts are delivered into the unikernel as inline read-only ROM devices, and inline ROMs are only enabled on the `base-compat:latest` runtime today. The default `base:latest` runtime (the app-elfloader) does not yet support them — the kernel team is working on enabling inline ROMs for `base` as well, but until then a ConfigMap/Secret volume will simply not appear inside a `base:latest` instance. Build the image with the `base-compat:latest` runtime and an **erofs** rootfs. The `Kraftfile`: