Skip to content

feat(arc): keep a profile's work volume in memory, and refuse measured profiles that share nodes - #148

Merged
Mearman merged 2 commits into
mainfrom
feat/arc-profile-work-volume-medium
Oct 28, 2026
Merged

Mearman merged 2 commits into
mainfrom
feat/arc-profile-work-volume-medium

Conversation

@Mearman

@Mearman Mearman commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Two per-profile options for fleets that mix nodes whose disks sustain far less write throughput than their memory could absorb with nodes whose memory is the bound. Nothing here changes a profile that sets neither.

The work volume in memory. work_volume_medium: Memory with work_volume_size_limit: <quantity> puts the runner's work directory on a tmpfs (emptyDir with medium: Memory and sizeLimit), so a job's checkout, dependency installs and cache archives (which actions/cache writes under _work/_temp) write nothing to the node's disk. arc_work_volume runs last in render_scale_set_values.yml, after the registry cache's dind wiring adds its own work volume. A values volume named work is changed in place; the chart's dind mode is given one, which the chart keeps in place of its own (dind-work-volume in the 0.15 chart's _helpers.tpl); otherwise the volume is added and mounted on the runner at /home/runner/_work. The kubernetes container modes, a work volume that is not an emptyDir or already sets medium or sizeLimit, a missing or non-positive size, and a size without Memory are refused with their own messages. Validation follows #109's medium. The README says the pages count against the pod's memory and cannot be reclaimed, so the profile's runner memory request and limit, and its sizing's pod_memory_request_gib, must rise by the size; how to size it from a running pod; and that measured sizing then derives fewer pods, which is the point on a disk-bound node.

I left the tool cache and the Docker data root out. The capability store (#132) already writes the capabilities' copies once per node, and #109 measured that holding them in memory costs every pod the reservation. The data root is large only in image builds, so holding it in memory would charge a build's size to every job; a values file for a build-only profile can mount its own memory-backed /var/lib/docker, and the README says so.

Profiles on different nodes. A per-profile node_selector already existed and already applied to the runner pods and to measured sizing, so a pinned profile is sized from its own nodes; the gap was overlap. Measured sizing leaves every scale set's runner pods out of what it subtracts, so two measured profiles that may use the same node each count all of its room and together allow more pods than fit. Dividing one node between scale sets of different pod sizes is a policy choice the cluster's figures do not settle, so rather than guess, the role now refuses it before installing anything (check_measured_overlap.yml after node labelling, arc_measured_overlap_errors), naming the profiles and nodes. Only profiles the role measures are compared: an ordinary measured profile without max_runners, and the autoscaled pool's sized profile. A profile with its own max_runners is the existing way to split nodes on purpose. Like the measurement, the check reads node_selector and tolerations and not a values file's own affinity (#145). The autoscaler's ceiling (autoscaler-ceiling.jq) counts only nodes every pooled template fits, so autoscaled profiles must now share one node_selector and set of tolerations, which validation checks. Pod capacity (#88) needs no sharing logic once the node sets are disjoint, and the usual way to make them disjoint is a taint on the pinned nodes that only the pinned profile tolerates (#85).

The unit tests cover each validation message, the filter's branches, sizing of a pinned and an unpinned profile against the same nodes, the overlap and autoscaled-pool refusals, the check's place in main.yml, and the rendered values through the role's own tasks. I broke each behaviour once and watched its test fail. The repository's CI (yamllint, ansible-lint --profile production, every unit shard and the kind tests) passes on this head.

Release: feat makes the next semantic-release run a minor release, so a fleet repository consumes this by pinning the release that carries both commits. The overlap refusal is a fix, following the precedent of earlier refusals; an inventory that today has two measured profiles counting the same node will fail at the new check until one gets max_runners or the node sets are made disjoint.

Nothing is deployed anywhere by this PR.

A profile's work_volume_medium: Memory puts the runner's work directory on a
tmpfs of work_volume_size_limit, so a job's checkout, dependency installs and
cache archives write nothing to the node's disk. This suits nodes whose disk
sustains far less write throughput than their memory could absorb.

The values' own work volume is changed in place, the chart's dind mode is given
one it keeps in place of its own, and otherwise the volume is added and mounted
at the work directory. The kubernetes container modes, a work volume that is
not an emptyDir or already sets a medium or size, and a size limit without the
Memory medium are refused. The README says how to size it and that the
profile's memory request and limit, and its sizing, must rise by its size.
A measured ceiling counts the whole of every node its profile's runner pods may
use, leaving every scale set's runner pods out of what it subtracts, so two
measured profiles that may both use a node each count all of its room and
together let more runner pods start than it holds. Splitting one node between
scale sets of different pod sizes is a choice the cluster's figures do not
make, so the role now refuses the overlap before it installs anything, naming
the profiles and the nodes, and a profile pinned to some nodes with
node_selector, and kept off by a taint elsewhere, is sized from its own nodes.

Autoscaled profiles must also share one node_selector and one set of
tolerations, since their pool's ceiling counts only the nodes every pooled pod
can use.
@Mearman
Mearman marked this pull request as ready for review October 28, 2026 13:50
@Mearman

Mearman commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-10-28T13:53:23.230229Z bc13cea Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: bc13cea9b8

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@Mearman
Mearman merged commit c65cac9 into main Oct 28, 2026
41 checks passed
@Mearman
Mearman deleted the feat/arc-profile-work-volume-medium branch October 28, 2026 13:57
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant