Skip to content

Remove upsert_sled in favor of server versioned API and polling #11627

Open

Description

@andrewjstone

As we work towards multirack, we run into more and more problems with client-side versioned APIs. A particular one of note that is causing hardship right now is the application level upsert_sled driven by Nexus internal HTTP API endpoints: sled_agent_put and sled_agent_get.

The PUT is particularly problematic because it does not include the rack_id in the SledAgentInfo structure that sled-agent sends to Nexus. Nexus currently therefore uses it's own rack_id to fill out the sled table in CRDB. This works fine in single-rack scenarios, but is incorrect in multirack scenarios. The rack running a Nexus is not necessarily the same rack where the sled-agent is running.

In particular, we tried to gate the upsert of the sled on the rack_id, since it shouldn't be present in the sled table if the rack has not yet been adopted (#11580) . This was implemented in #11598 when @jgallagher noticed that we couldn't actually do this, because of the aforementioned issue of inserting the wrong rack_id.

Unfortunately, this is a major change to the control plane, and it has unknown rabbit holes. The only other alternative, namely: adding a rack_id field to the client side versioned API, requires smearing that change over two releases. Unfortunately, we need this change integrated to be able to continue multirack development and this means carrying along a patch that we issue to all development branches that includes this field in the client messages. That seems tedious and error prone.

Ideally we would just work on transitioning from a client side to server side API now. That's the rigorous thing to do. But urgency is steering us away from this path and towards maintaining the painful client side versioning. Perhaps there are other alternatives, but we haven't thought of them yet.

Activity

  1. self-assigned this
    on Oct 28, 2026
  2. bnaecker commented on Oct 29, 2026

    @bnaecker
    Collaborator

    Related #7980

  3. davepacheco commented on Oct 30, 2026

    @davepacheco
    Collaborator

    I gather from today's update watercooler that there's a plan in-progress to unblock multi-rack. That's all good but I wanted to jot down some notes here about longer-term fixes.


    I believe this API endpoint is from very early days, before sled lifecycle was much of a thing, before RSS, and before "sled add". This API serves a couple of different purposes:

    1. It's the first place Nexus learns about a sled and some of its static information, including its IP. The fact that Nexus doesn't know about sleds prior to their first attempted upsert is part of what makes fixing this tricky (since Nexus can't reach out to the sled until it knows this)
    2. It's the place where some dynamic state about the system is reported (e.g., reservoir size)
    3. It's the point where Nexus learns that Sled Agent has restarted (possibly as a result of a system reboot). This is an important signal for Nexus to go check that the sled is doing what it's supposed to be doing (e.g., running the instances that are expected).

    It may be helpful to consider these use cases separately.

    The static information (e.g., sled type, memory, IP address) ought to be known even before Sled Agent starts. In the single-rack case, RSS could know this (if it doesn't already) and could provide it in the handoff request. In the case of a sled being added to the control plane, similarly, this information could be inserted as part of the "sled add" process. I don't know enough about how multi-rack join works to suggest what the analogous thing would be but I would guess there's a similar point where this information can be told to Nexus.

    The dynamic information (e.g., reservoir size) seems like a good case for inventory, which already runs periodically and on-demand when we think it's changed.

    So in the longer term, maybe something like this:

    1. RSS, "sled add", and "multirack join" would be responsible for collecting the static information and providing it to Nexus for it to insert the initial sled record.
    2. Dynamic stuff like inventory and whether it's a scrimlet could move to inventory. (Note that we could still have something copy it from inventory to the sled table, if it makes sense to latch the last-seen state, or if it's too painful to migrate consumers of this data.)
    3. I assume we'd still keep a client-side-versioned upcall, but all it would do is activate some background tasks (like inventory collection, to catch any updated dynamic state, or instance_watcher, to make sure the instances are running).
  4. andrewjstone commented on Oct 30, 2026

    @andrewjstone
    ContributorAuthor

    I gather from today's update watercooler that there's a plan in-progress to unblock multi-rack. That's all good but I wanted to jot down some notes here about longer-term fixes.

    Indeed. I wrote this up before that discussion. The current plan is to continue to use the client-side upcall as a "doorbell" and then call down to sled-agent to fetch all this information. The code will actually use the current structure as a doorbell and ignore it once nexus is upgraded. That will be good enough for multirack since multirack won't be functional until after the upgrade. Then the upcall will be changed to be a pure doorbell and remove the existing info passed upwards. @sunshowers deserves all the credit for thinking of this solution.

    I believe this API endpoint is from very early days, before sled lifecycle was much of a thing, before RSS, and before "sled add". This API serves a couple of different purposes:

    1. It's the first place Nexus learns about a sled and some of its static information, including its IP.  The fact that Nexus doesn't know about sleds prior to their first attempted upsert is part of what makes fixing this tricky (since Nexus can't reach out to the sled until it knows this)
    

    Yep. I was calling this the "discovery" phase. When I wrote this issue my plan was to utilize a union of the sled_underlay_subnet_allocation table and existing sled table to find the the sled-agents. If we keep the doorbell, this is no longer necessary, which is quite nice.

    2. It's the place where some dynamic state about the system is reported (e.g., reservoir size)
    

    Indeed. We can still use the doorbell and poll for this.

    3. It's the point where Nexus learns that Sled Agent has restarted (possibly as a result of a system reboot).  This is an important signal for Nexus to go check that the sled is doing what it's supposed to be doing (e.g., running the instances that are expected).
    

    Same as above.

    It may be helpful to consider these use cases separately.

    The static information (e.g., sled type, memory, IP address) ought to be known even before Sled Agent starts. In the single-rack case, RSS could know this (if it doesn't already) and could provide it in the handoff request. In the case of a sled being added to the control plane, similarly, this information could be inserted as part of the "sled add" process. I don't know enough about how multi-rack join works to suggest what the analogous thing would be but I would guess there's a similar point where this information can be told to Nexus.

    The dynamic information (e.g., reservoir size) seems like a good case for inventory, which already runs periodically and on-demand when we think it's changed.

    So in the longer term, maybe something like this:

    1. RSS, "sled add", and "multirack join" would be responsible for collecting the static information and providing it to Nexus for it to insert the initial `sled` record.
    
    2. Dynamic stuff like inventory and whether it's a scrimlet could move to inventory.  (Note that we could still have something copy it from inventory to the `sled` table, if it makes sense to latch the last-seen state, or if it's too painful to migrate consumers of this data.)
    
    3. I assume we'd still keep a client-side-versioned upcall, but all it would do is activate some background tasks (like inventory collection, to catch any updated dynamic state, or instance_watcher, to make sure the instances are running).
    

    I think it would be useful to separate out the sled table from the inventory related information, but I'm no longer that concerned about it. The doorbell + polling seems like a good solution that can last us a long time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Sled AgentRelated to the Per-Sled Configuration and Managementmulti-racknexusRelated to nexus

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions