Conversation
A network now reaches the internet from a cell when a consumer asked for it. The egress intent projected onto NetworkContext.spec selects the egress shards serving the class, and the shards' SRv6 SIDs are rendered straight into the CNI conflist the node reads. Nothing new lands on VPCAttachment: the node never reads it, and the conflist is written in the same reconcile pass from the same inputs. Intent is a function of (VPC, cell) alone. The kernel VRF is shared by every attachment of a VPC on a node and the datapath route key has no per-attachment component, so divergent intent between two attachments of one VPC is undefined. Every attachment resolves the same NetworkContext and computes the same ordered list, so the install is idempotent by construction. The egress block is absent whenever intent is Disabled, absent, or no shard is bound, and a conflist rendered without it is byte-identical to what the renderer produced before the field existed. Key changes: - Add EgressShardParameters, the cluster-scoped parameters type an InternetEgressClass names in its parametersRef for this controller to serve. It holds the shard namespace and a label selector over the network.datumapis.com/egress-* labels - Select shards in NetworkInterfaceReconciler, requiring the IPv6 family label, in name order, skipping shards that report no SID - Give galactic's BGPPlugin an omitempty egress block carrying an ordered shardSIDs candidate list the node keeps the first resolvable entry from - Watch NetworkContext and EgressShard so intent and a shard's reported SID reach the conflist without waiting out a poll interval - Pin go.datum.net/network and go.datum.net/network-services-operator to local checkouts, because both halves of the contract this reads are on unpushed branches. Lab only; it cannot merge in this state Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A consumer can now read the address their traffic leaves the platform on, per interface. This controller is the only component that resolved which shard a network bound to, so it publishes the answer on VPCAttachment status, which NSO already reaches through the generic attachmentRef on a network interface and reads without a typed dependency on this module. Stability is derived here from the serving class's sharing rather than left to the consumer: Shared reports None, Dedicated reports Network. Sharing is an operator-side decision about the platform, and a consumer interpreting it would be deciding for themselves whether allow-listing an address is safe. Nothing is published unless the platform can state it. No shard, absent intent, Disabled, a shard that has reported no address, or a class whose sharing never projected all report no egress at all. An absent address is not an empty list and not a placeholder, and one that was published is withdrawn when the path is. Key changes: - Add egress.internet.sourceAddresses to VPCAttachment status, keyed by family, with an IPv6-only family enum while IPv4 reach stays refused - Resolve egress once per reconcile pass, so the conflist the node reads and the address the consumer reads are the same answer - Report the preferred shard's address only. The candidate list is a preference the node resolves to one entry; reporting every candidate would name addresses the traffic does not leave on - Keep whole-object Status().Update rather than moving to server-side apply. The new fields join a writer that already writes this status, so the writer count stays at two over disjoint field sets, and an update carrying a superseded resourceVersion is rejected rather than overwriting the other writer. A status half-written by SSA and half replaced wholesale is worse than either, so converting is a decision for the type, not a side effect of adding three fields - Record that shards live in galactic-system, in the field an operator fills in. shardNamespace stays required: it names the nodes every network on a class leaves through - Replace the committed replace directives with an untracked go.work. CI checks out this repo alone, so a committed replace to a sibling path fails its build outright Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI checks out this repo alone, so a module replace pointing at a local path cannot resolve. Point both at the pushed commits instead, which CI can fetch, so the build reflects the branches this depends on. Key changes: - Replace the network module with the pushed egress address commit - Replace the operator module with the pushed egress API commit - Drop the local workspace file in favour of resolvable versions Revert both replaces once those modules release the fields. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
A network declares whether its instances reach the internet, but nothing carries that decision to the machines running the workload. The node learns everything else about an interface from the configuration written when the interface is attached, and egress was missing from it.
This resolves which translating shard serves a network in this location and writes that into the same configuration, so a node installs an outbound route for a network that asked for one and none for a network that did not.
It also reports the address the network's traffic leaves from, with a note saying whether that address is shared with other networks and therefore unsafe to allow-list at a destination.
Architecture
sequenceDiagram participant NC as Network presence in this location participant C as Attachment controller participant P as Class parameters participant S as Egress shards participant N as Node participant A as Attachment status NC->>C: egress intent, resolved upstream C->>P: read what serves this class here C->>S: select by pool, location and address family C->>N: write the shard list into the interface config C->>A: report the source address and whether it is shared Note over C,A: no shard, or no address it can state, reports no egressTest plan
Related to datum-cloud/network-services-operator#475