Repository navigation
feat: the node is described, and its comings and goings recorded (ADR 0064) - #100
Merged
kfeofantov merged 1 commit intoSep 3, 2026
Merged
Conversation
… 0064)
`node_metadata` carried ten fields drawn for one job — turning a node name into
a zone. It now describes the machine: age, kubelet version, OS image, container
runtime, ephemeral storage and the pod ceiling, allow-listed accelerators, the
five standard conditions, and taints.
Adds `node_lifecycle`, a windowed journal of nodes joining and leaving. It is
the first payload that says what the fleet *was*: a departed node is absent from
every snapshot by definition, so the record carries its own size and devices.
Three bounded reductions, each following the discipline placement.go set for
operator-written strings: conditions allow-listed by type and never carrying
`message`, extended resources allow-listed by hardware-vendor prefix, taints
bounded at 128 bytes. What each refuses is counted in `collection_coverage`,
never named.
An arrival is reported only when the creation timestamp proves it — at cache
sync the add handler fires for every node, and counting those would report an
agent restart as the whole fleet arriving (ADR 0034's rule, applied to nodes).
A departure carries the agent's observation instant and says so.
go test ./... — all packages pass; golangci-lint run ./... — 0 issues
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011YRKuL97KRndaopfpixrhp
kfeofantov
deleted the
feat/the-node-is-described-and-its-comings-recorded
branch
September 3, 2026 18:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nine gaps in what the agent knows about a node, closed together. Eight are
fields on an informer the agent already runs; the ninth is a fact no snapshot
can hold.
node_metadatadescribes the machinemetadata.creationTimestampkubeletVersionosImage,operatingSystemcontainerRuntimeVersionpodswas not on the list asked for. It is one field from the same map asephemeral storage, and leaving it out makes "why won't this schedule" half
answerable, so it is here — flagged rather than slipped in.
node_lifecycle— the ninthA windowed journal of arrivals and departures, keyed and delivered exactly like
pod_disruptions. Each record repeats the node's instance type, capacity anddevices, and that repetition is the whole point: a node that left is gone from
node_metadataby definition, so without the size on the event, "twelve nodesleft this hour" can never become "and they were 96 cores of spot capacity".
Two honesty constraints, both with precedent in this repository:
creation timestamp against when this process started watching — at cache sync
the add handler fires for every node in the cluster, and counting those would
report an agent restart as the entire fleet arriving at once. ADR 0034's rule,
applied to nodes.
object has no deletion time to read, so
atmeans two different things andat_observedmarks which — rather than one field silently mixing provenances.What is filtered, and why there
Three reductions, each following the discipline
placement.goset foroperator-written strings (ADR 0019, ADR 0031):
messageis never read: it isfree text into which the kubelet and node-problem-detector write paths and
command output. The type allow-list is what makes
reasonsafe to carry.The last transition is kept, the heartbeat is not — it moves every few
seconds on every node and would make every node differ from its previous view
on every flush.
GPU and a MIG slice of it are the same fact, allow-list because the rest of
that namespace belongs to the customer, where a resource named for an internal
team or licence must not travel.
customer-written strings read from a node; the justification is symmetry, not
harmlessness — tolerations are already collected from every pod spec, and a
toleration without the taint it answers is half a fact.
What each refuses is counted in
collection_coverage.nodes. Aggregate only.Consequence worth naming
NodeInfois no longer comparable, so the informer's "report only when the viewchanged" test moved from
==to a deep equality. Affordable because node objectschange on the order of minutes — the kubelet heartbeats to a Lease, not to the
node — and the one sub-second field it does write is the condition heartbeat,
which is deliberately not collected.
One existing test asserted the old contract: it added a
Readycondition andcalled that "an update that changes nothing in the collected view". Under this
change a condition is the collected view, so the test now moves the heartbeat
instead — which makes it a regression test for the decision above.
Evidence
Goldens regenerated with
-update;node-metadata.golden.jsonnow carries anaccelerator node under memory pressure so the three reduced lists appear in the
bytes rather than only in unit tests.
Docs updated in the same PR: ADR 0064,
security.md§4 and the payload table,backend-requirements.mdingest rules for both kinds. Two prose ceilings moved,for the new payload kind and the wider node read.
🤖 Generated with Claude Code
https://claude.ai/code/session_011YRKuL97KRndaopfpixrhp