Repository navigation
feat(arc): keep a profile's work volume in memory, and refuse measured profiles that share nodes - #148
Conversation
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.
|
@codex security review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
🎉 This PR is included in version 2.10.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
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: Memorywithwork_volume_size_limit: <quantity>puts the runner's work directory on a tmpfs (emptyDirwithmedium: MemoryandsizeLimit), so a job's checkout, dependency installs and cache archives (whichactions/cachewrites under_work/_temp) write nothing to the node's disk.arc_work_volumeruns last inrender_scale_set_values.yml, after the registry cache's dind wiring adds its own work volume. A values volume namedworkis changed in place; the chart's dind mode is given one, which the chart keeps in place of its own (dind-work-volumein 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, aworkvolume that is not anemptyDiror already setsmediumorsizeLimit, a missing or non-positive size, and a size withoutMemoryare 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'spod_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_selectoralready 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.ymlafter node labelling,arc_measured_overlap_errors), naming the profiles and nodes. Only profiles the role measures are compared: an ordinary measured profile withoutmax_runners, and the autoscaled pool's sized profile. A profile with its ownmax_runnersis the existing way to split nodes on purpose. Like the measurement, the check readsnode_selectorandtolerationsand 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 onenode_selectorand 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:
featmakes 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 afix, 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 getsmax_runnersor the node sets are made disjoint.Nothing is deployed anywhere by this PR.