test(neuron): integration coverage + fixture for multi-runtime per-co… - #749
Open
spanaik wants to merge 2 commits into
Open
test(neuron): integration coverage + fixture for multi-runtime per-co…#749spanaik wants to merge 2 commits into
spanaik wants to merge 2 commits into
Conversation
…re data loss
The defect only appears with >=2 Neuron runtimes on one node, and the otel-neuron
fixture had one: neuron-burn-core is replicas:1 holding one of inf2.xlarge's two
cores, and its self-referential podAntiAffinity on neuron-test=true actively
prevents a second Neuron pod from joining it.
Adds neuron-burn-peer, taking the other core, co-located via podAffinity. Three
constraints, each of which breaks an existing test if changed:
- not named neuron-burn-core-*: TestNeuronBurnWorkloadLabels and
TestNeuronBurnCorePodColor match HasPrefix(pod, "neuron-burn-core")
- no neuron-test=true label: burn-core's antiAffinity targets it, which would
make the two mutually exclusive and push burn-core onto the idle node
- podAffinity not just nodeSelector: both node groups use var.instance_type, so
a nodeSelector alone could land it on the idle node
wait_neuron_monitor now waits for both deployments to be Available and fails if
they did not co-locate; a silent split would make every multi-runtime test vacuous.
Eight tests in test/otel/neuron/multi_runtime_test.go. The value-level one requires
>=2 busy cores from >=2 runtime tags; the structural one requires cores x tags
series, which catches the collapse even on an idle node.
Two things the pre-existing tests could not catch, both verified against a
deliberately reverted agent on a live 2-runtime cluster: TestNeuronRuntimeTagInResourceScope
passes on the broken code (the collapsed resource still carries one tag), and
TestNeuronNoDuplicateSeries passes because the collision happens in-agent, so the
surface shows too FEW series rather than duplicates. Cardinality is the signal.
Validated: 7/8 pass against a live 2-runtime cluster with the fix (the 8th is the fixture-name
guard, which needs this terraform cluster); all 8 fail with the fix reverted.
No assertion on distinct POD count -- two runtimes need not be two pods, and
the cluster under test runs both from one, so requiring it would encode this fixture's shape
rather than the invariant. That over-specification was caught by running against a
real cluster.
2 tasks
The invariants they illustrated hold regardless of which cluster measured them, and the names mean nothing outside the team.
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.
Description of the issue
Related: aws/amazon-cloudwatch-agent#2263
The Neuron per-core data-loss defect fixed in
aws/amazon-cloudwatch-agent# only appears on a node running two or more Neuron
runtimes, and no fixture in this repo produced that shape — so nothing here could have
caught it.
neuron-burn-coreisreplicas: 1holding one ofinf2.xlarge's two NeuronCores, so itsnode has exactly one runtime. It also carries a self-referential
requiredDuringSchedulingpodAntiAffinityonneuron-test=true, which activelyprevents a second Neuron pod from joining it. Raising
replicasto 2 does not help: theanti-affinity pushes the second replica onto the idle node, giving one runtime per node
again and destroying the idle-node fixture.
Worth noting the two existing tests that look like they should catch the defect and do
not:
TestNeuronRuntimeTagInResourceScopepasses on the broken agent — it asserts the tagexists, is non-empty, and is absent from the datapoint, and all three hold. The collapsed
resource still carries one (wrong) tag.
TestNeuronNoDuplicateSeriespasses because the collision happens in-agent: duplicateidentities are merged before export, so the surface shows too few series rather than
duplicated ones.
Cardinality is the signal, not duplication.
Description of changes
Fixture (
terraform/eks/daemon/otel-neuron/main.tf) — adds aneuron-burn-peerDeployment taking the second core, co-located with
neuron-burn-coreviapodAffinity, soone node runs two runtimes burning different cores.
Three constraints, each of which breaks an existing test if changed:
neuron-burn-core-*TestNeuronBurnWorkloadLabelsandTestNeuronBurnCorePodColormatchHasPrefix(pod, "neuron-burn-core")and assertworkload.name == "neuron-burn-core"/pod-color == orangeneuron-test: "true"labelneuron-burn-core'spodAntiAffinitytargets it, which would make the two mutually exclusive on a host and pushneuron-burn-coreonto the idle nodepodAffinity, not justnodeSelectorvar.instance_type, so anodeSelectoralone could land it on the idle node, breaking the uncorrelated-results fixturewait_neuron_monitornow waits for both burn deployments to beAvailableand fails ifthey did not co-locate — a silent split would make every multi-runtime test vacuously
skip.
Tests (
test/otel/neuron/multi_runtime_test.go) — 8 tests. The value-level one requires≥2 busy cores reported by ≥2 runtime tags; the structural one requires
cores × tagsseries, which catches a collapse even on an idle node where values cannot distinguish it.
Also included: a tripwire asserting no series carries
runtime_tag="DEFAULT", which is whatthe in-agent-aggregation alternative stamps — changing that trade-off should mean changing
the test, not a silent behaviour swap.
Deliberately no assertion on distinct pod count: two runtimes need not be two pods, and
one pod can host both, so requiring it would encode this fixture's shape rather than the
invariant. (That over-specification was caught by running against a real cluster.)
License
By submitting this pull request, I confirm that you can use, modify, copy, and
redistribute this contribution, under the terms of your choice.
Tests
Validated against a live 2-runtime
inf2.xlargenode in both directions:FixtureIsBothBurnWorkloads, whichasserts the
neuron-burn-core/neuron-burn-peerpod names and therefore needs thisterraform cluster; the validation cluster used a differently-named workload.
reproduced first — 2 series instead of 4, one surviving runtime tag, core 0 reporting 0
while pinned at ~75% — then restored and re-ran to green.
That negative control also exposed a diagnostic problem, now fixed: all 8 failed via the
shared fixture guard rather than their own assertions, because the collapse destroys the
runtime tag itself, so
>= 2 distinct tagsnever holds. The guard's message previouslyblamed the fixture only. It now names both causes — the defect and a missing fixture —
with the
kubectlcommand to tell them apart, because a collapsed node is structurallyindistinguishable from a genuine single-runtime node on the metrics surface.
gofmtclean,go vet -tags integration ./test/otel/neuron/clean,terraform fmt -checkand
terraform validateclean.Not yet run:
terraform apply. The fixture is validated byterraform validateand bythe assertions passing against an existing 2-runtime node, but the specific
neuron-burn-peerplacement — that the device plugin grants one core to each pod andpodAffinityco-locates them — has not been exercised on a fresh cluster. Thewait_neuron_monitorco-location check is there to fail loudly if it doesn't.