gpustack / gpustack/gpustack-operator
todo: segment identity needs a working fabric rerun and the migration step
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 4
- Forks
- 7
- Avg merge
- 3h 9m
- Merged PRs (30d)
- 213
Description
What is left undone
Two things, after a second cluster run closed the TCP control.
-
The packaged image has been exercised only halfway. A host-network backend has now run under
gpustack/mirrored-mooncake:0.3.13.post1-cpu, so the tag gap on the identity and attribution
reading is filled. What that run does NOT support is the transport half: EFA itself did not come
up on it (the member could not reach the fabric), so "the EFA path works on the packaged image"
is still unread.What blocked that re-run has since changed, and this paragraph used to point at the wrong
thing. It cited #347 and #348 as two standing blockers. #347 has merged: it adds the EFA
device-resource request, so an EFA member is no longer deniedopen()on the device by the
device cgroup. #348 is still open but it covers the RDMA branch of that same function only —
applyMemberFabricreturns before the resource request whenever the protocol is notefa
(pkg/worker/kvcache/mooncake/member_workload.go, read 2026-09-12) — so it does not block an EFA
re-run.⚠️ What #347 has NOT got is a reading on real hardware. No EFA member has been observed
reaching the fabric since it merged, because the cluster it would run on was destroyed. So the
honest state of this item is "waiting on an environment", not "waiting on a fix" — and the
re-run is also the first evidence that #347 works. -
The upgrade/migration step was not run.
What has already been measured
On a cluster with two host-network EFA nodes:
-
Step 1. Both host-network member Pods came up Running, co-located on one node.
-
Steps 3 and 4, in part. The leader reported two
protocol: efasegments sharing the
host-network address, withsegment_idandclient_idboth non-empty and distinct. The controller
could not uniquely attribute either row to a Pod from a shared address and reported
MembersMounted=Falsewith reasonAmbiguousMemberIdentity.⚠️ Step 4's criterion has been restated and the reading above predates it. The original step
asked that both ambiguous rows leavenodeNameandmediumempty. That bound two separate things
into one sentence, and only the second is required: what must not happen is a Pod being guessed.
Since #345 an ambiguous row reports the node and the medium every candidate agrees on, which is
well defined because the candidates are on one node by construction. The criterion is now that
MembersMountedstaysFalsewith reasonAmbiguousMemberIdentityand that nosegmentIDor
clientIDis attributed to a Pod that was merely guessed. An emptynodeNameis no longer
evidence of anything, and a populated one is no longer a defect. -
Step 5. With the groups moved to separate nodes, the two rows gained distinct identities,
MembersMountedbecameTrue/Mounted, and the backendPhasebecame Ready. -
The TCP control (formerly step 6), now run. Two TCP groups pinned to one node took their own
Pod IPs,MembersMountedbecameTrue/Mounted,Phasebecame Ready, and both rows carried a
nodeNameand amedium. This is the positive baseline the ambiguity reading needed: it shows
the mechanism reports mounted when identity is unambiguous, rather than reporting ambiguity
unconditionally.
⚠️ The protocol: efa in that reading does not mean the members used EFA. That field reports what
the client declared when it registered the segment, not the transport it negotiated - see #341. It is
recorded here as the identity reading it is, not as transport evidence.
The "portless segment name" criterion was wrong twice, and both readings are now in
This issue was filed asking for rows whose segment_name is portless. It is not, on either
transport: the leader's actual output carries a dynamic port in both the host-network case and
the TCP case. The portless shape came from the fixture in PR #296, not from a live Mooncake v0.3.13,
and it was carried into this issue as though it had been observed. Anyone following the original
wording gets a mismatch on the first read and has every reason to file it as a segment-naming
defect. It is not one.
⛔ A third reading, which the fixture work has to account for: within a single row, the port in
segment_name and the port in te_endpoint are DIFFERENT. They are two independently assigned
values, not one value rendered twice. Correcting the fixture by copying te_endpoint's port onto
segment_name would produce a shape the leader never emits.
That fixture is a fidelity gap and not a masking one: the attribution and ambiguity decisions read
te_endpoint, never segment_name (hostOf(segment.TEEndpoint)), and the fixtures' te_endpoint
values already carry ports. segment_name bears weight only in the encoded-size budget, where the
boundary case uses a name four orders of magnitude longer than a real one.
How to verify what remains
- Re-run the co-located and separated host-network shapes under
gpustack/mirrored-mooncake:0.3.13.post1-cpuon members that actually reach the fabric,
asserting the same identity properties as steps 3-5 above, and recording the leader's
/get_segments_detailresponse verbatim - bothsegment_nameandte_endpoint, since their
ports differ and each is its own reading. - On a cluster at Kubernetes 1.23 or above - the lowest version this project supports, not that
exact version - install the pre-change CRD and controller, create a storedstatus.membersrow
withoutsegmentIDorclientID, then upgrade the CRD and controller while the leader's
/get_segments_detailrequest fails. Trigger both the backend listing path and the pool
controller's independentusedBystatus write. Both writes must succeed, the entire incompatible
member listing must be omitted, and the backend must be Degraded withMembersMounted=Falseand
reasonLegacyMemberStatus. Restore the leader response and verify that real IDs repopulate the
rows, the migration reason clears, and normal phase/condition reporting resumes.
⚠️ Step 2 must run last on any shared cluster: it downgrades the CRD and controller and upgrades
them again, which invalidates the premises of every other assertion on that cluster. And a green
result on a server that has CRD validation ratcheting should be recorded as holding on that version -
it does not establish the pre-ratcheting path, though a red result there would establish its failure.
What does NOT fill these
- Re-running the host-network path on the same upstream image. The gap is the tag, not the path.
- The identity reading that has already run under the packaged tag. It settles attribution on
that image and says nothing about whether the transport works there, which is the half still open. - Reading the migration logic from unit tests. Those pass, and what they do not prove is that
both API-server status transitions succeed against a real installed CRD.
/area kv-cache
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with pkg/worker/kvcache/mooncake/member_workload.go and the leader's /get_segments_detail response, then prepare a Kubernetes 1.23+ environment using the packaged image. Run the co-located and separated EFA cases on members that reach the fabric, followed last by the pre-change CRD/controller migration. Done means transport and identity evidence is recorded, incompatible legacy status is safely omitted with LegacyMemberStatus, and normal IDs and conditions return after recovery.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go, kubernetes
- Domain
- distributed-systems, infrastructure, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100