An image build node up 24 days had lost its running kernel's modules to a linux-lts upgrade, so tun could not load and every RUN line failed in pasta. mesh-build-image now proves the tun device and, whatever its look refuses, judges its node not eligible (capacity 0 with the reason), so the asks go to a node that can build them. The kernel module loads tun at boot and declares kernel-modules-hook, which keeps the running kernel's modules across an upgrade. Needs mesh-sdk fix/ace-tun (Puller.Eligible).
55 lines
4.6 KiB
Markdown
55 lines
4.6 KiB
Markdown
# mesh-build-image — the image build module
|
|
|
|
Design 47, release R4c-9 (novox/hq ADR 0487, ADR 0466 §1, ADR 0469; issue 1703). The module that builds a module's
|
|
`image` artifact from the Dockerfile in the module's own directory, on a build machine, as an account of its own
|
|
(`runs-as`, no login shell, home at mode 0700). It serves every module's image, whatever the base, so it is not a
|
|
build module for one module. It claims no seat: it is assigned to the build machines and runs dark until the builder
|
|
uses it.
|
|
|
|
## Rootless
|
|
|
|
The tool is `buildah`, which the `buildah` module installs and provides as `rootless-image-build` with the machine's
|
|
reach: a machine without it refuses this module at assignment, naming `buildah`. The build runs as the module's own
|
|
account in a user namespace (`--isolation oci`), with buildah's image store and runtime state in
|
|
`/var/lib/mesh-build-image-store` (outside the home), no mount of the host, no container runtime socket, no registry
|
|
credential and an environment built from scratch.
|
|
|
|
The account's subordinate user and group ranges are not declared anywhere: the node-engine makes every `user` account
|
|
with `useradd`, which allocates them. The module's health reads `/etc/subuid` and `/etc/subgid` and is unhealthy
|
|
without a range for the account, without buildah, when a user namespace cannot be made, or when `/dev/net/tun`
|
|
cannot be opened (buildah makes a RUN line's network with pasta, which needs the tun driver; on 2026-10-28 a build node had the
|
|
device node and no driver, so every image build there failed with "Failed to open() /dev/net/tun: No such device"). The
|
|
kernel module loads `tun` at boot. Whatever the health refuses, the node is **not eligible**: the seat's puller judges
|
|
by a capacity of 0 with that reason (`capacity.<node>`, which `build_usage` shows), so the asks go to a node that can
|
|
build them; a look that passes again wakes the puller.
|
|
|
|
The Dockerfile's steps may use the network (ADR 0487 §6); nothing a step can read holds a key.
|
|
|
|
## Steps
|
|
|
|
- `build_image_fetch` fetches a commit over SSH into a workspace (a base commit makes the merge preview, as the other
|
|
build modules' fetch). Long: answers a step id and ends on its key in `steps`.
|
|
- `build_image_build` builds one image artifact: `buildah bud` with the Dockerfile `from` names (in the module's
|
|
directory or a subdirectory of it) as file and the module's own directory as context, so a COPY names paths from the
|
|
module's root (issue 1703), `--target`, and the images `build.on` pins as `--build-arg`. Answers the image's digest. With
|
|
`publish: true` (a merged trunk commit only) the module's own process then pushes it to the registry under
|
|
`<module>/<artifact>:<tag of its own>` (the first 12 hex digits of the digest unless the call gives one), waiting out
|
|
a registry held still, and the key carries the digest the registry serves and the reference pinned by it. Without
|
|
`publish` (a pull request) nothing is pushed.
|
|
- `build_image_copy` copies an upstream artifact (`module`, `artifact`, `from`) registry to registry into the artifact store
|
|
over the registry API, the whole index and every blob, by the digest the manifest pins (ADR 0498 §4), and verifies the
|
|
store serves that digest. Answers the digest and the reference `<registry>/<module>/<artifact>@sha256:<digest>`. A
|
|
`from` without a digest fails `not pinned:`. It needs no workspace and no buildah.
|
|
- It refuses, naming why, an image whose build context is a whole repository (`context`) or whose `build.on` names
|
|
another module's artifact (`unsupportedImage` in `build.go`): those forms belong to the images build-agent builds
|
|
until it is removed at R4g.
|
|
- `build_image_release {workspace}` removes a workspace at once (no guard, no floor; one already gone is no error, one a
|
|
running step holds is refused); its caller calls it once its last step answered. A failed fetch removes its own
|
|
workspace, and one no caller released is removed two hours after its last use (ADR 0509).
|
|
- A fetch and a build are refused, `refused: <node> has N GiB free under the floor of 20 GiB (on <dir>)`, and the health
|
|
is unhealthy with that text, while the work directory's or the image store's filesystem has less than 20 GiB free
|
|
(issue 1839). A copy writes nothing to the disk and is not refused.
|
|
- `build_image_step`, `build_image_steps`, `build_image_status` and `build_image_health` read.
|
|
|
|
The registry's address is placed into `<home>/registry` as `${seat:mesh-artifact-store:reach}` (host:port): the provisioner's client fills a moved module's placement, and the artifact store has not moved, so a `${bound:artifact-store:...}` is refused at composition (issue 1703).
|