Repository navigation
fix(router): hold consumers whose interface is not ready yet - #1379
Merged
Merged
Conversation
A recreated instance can be selected before its new host interface exists or is registered. Programming it failed, and the first failure stopped the rest of the policy, so other new consumers on the node waited for a retry and the router kept reporting errors until the interface appeared. Hold such a consumer with nothing installed, as repair already does for an interface that disappears, and install it when the interface comes up: the router now watches the node's interfaces and requeues the policies that use one. Apply every intent of a policy even when one fails, and return the failures together.
The CNI registers an interface's attachment identity after the interface appears, and that write sends no interface event, so a consumer held for a missing identity waited for the 30 second resync. While the programmer holds any consumer, recheck after one second and log that it is holding. Exercise the in-place LocalSet replacement when every producer is gone.
Rechecking every policy each second while any consumer was held would keep the single worker busy for as long as one interface never returns. Recheck only a policy that holds one of its own consumers, starting at one second and doubling to the 30 second resync, and log when a policy starts holding.
privateip
approved these changes
Nov 10, 2026
ecv
approved these changes
Nov 10, 2026
ecv
left a comment
Contributor
There was a problem hiding this comment.
Approve. A failed Apply rolls back its own entries and only successes enter current, so going past a failing intent leaves nothing half-installed, and real failures still reach the programming alert. ErrNoAttachmentIdentity classifies through recoverableEntries, which apply, rebuild and repair all share.
Follow-ups:
- A held consumer counts as a successful apply, sets
Ready=trueand adds to the programmed gauge, whileGalacticServiceRouteProgrammingFailingfires only onresult="error". A consumer whose identity never arrives is held at the 30 s recheck forever with only the one "holding" log. Add a held-intents gauge with an alert for a hold longer than a few minutes, and leave held intents out of the programmed gauge. - When
Cleanupfails,replacePolicyLockedstill returns early and skips the remaining intents, contrary to its new comment.
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.
Requested by Scot Schuchert-Wells
Related: datum-cloud/enhancements#921, datum-cloud/compute#630.
Problem
When an instance is deleted and recreated under the same name, its new attachment can be selected by a service route policy before the new host interface exists, or before the CNI has registered its attachment identity. The router treated that as a programming error. It also stopped at the first error, so other new consumers of the same policy on that node weren't programmed until a retry succeeded. The router logged "resolve consumer interface ...: Link not found" or "lookup attachment identity ...: key does not exist" until the interface appeared, which can trip the service route programming alert.
Measured in a test cell: every same-name redeploy produced 10 to 14 such errors in the 0.3 to 0.7 s before the new interface came up. First deploys of a name produced none.
Change
EBPFRouteProgrammer.Applyholds a consumer whose interface is missing, or has no attachment identity, with nothing installed. This is what repair already does for an interface that disappears. The next repair installs it once the interface is ready.serviceroutemap.IdentityTokennow wrapsErrNoAttachmentIdentityso that case can be told apart.linkWatch. On a change, it requeues the policies whose applied intents use that interface.replacePolicyLockedtries every intent of a policy and returns the failures together.A held consumer counts as applied. For a frontend policy, the node's programming acknowledgment can then report ready while that one consumer's interface isn't there yet. Until the interface exists, that consumer has nothing to serve.
Testing
go build ./...,golangci-lint(0 issues) andgo test -racepass for./internal/serviceroute/,./internal/controller/,./internal/plumbing/ebpf/serviceroutemap/and./cmd/galactic-router/in a Linux build container.